blob: 1bb4e182d3c9eb73f1eff897f64705bf01722460 [file] [log] [blame]
/*
* Copyright (c) 2011-2019 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 <linux/wcnss_wlan.h>
#include <macTrace.h>
#include <wlan_hdd_includes.h>
#include <wlan_btc_svc.h>
#include <wlan_nlink_common.h>
#ifdef WLAN_BTAMP_FEATURE
#include <bap_hdd_main.h>
#endif
#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
#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_pal_trace.h"
#include "wlan_qct_tl.h"
#include "wlan_hdd_misc.h"
#include "bap_hdd_misc.h"
#include "wlan_hdd_dev_pwr.h"
#include "qc_sap_ioctl.h"
#include "sme_Api.h"
#include "vos_trace.h"
#include "wlan_hdd_assoc.h"
#include "vos_utils.h"
#include "sapInternal.h"
#include "wlan_hdd_request_manager.h"
#ifdef CONFIG_HAS_EARLYSUSPEND
extern void hdd_suspend_wlan(struct early_suspend *wlan_suspend);
extern void hdd_resume_wlan(struct early_suspend *wlan_suspend);
#endif
#ifdef FEATURE_OEM_DATA_SUPPORT
#define MAX_OEM_DATA_RSP_LEN 2047
#endif
#define HDD_FINISH_ULA_TIME_OUT 800
#define COUNTRY_CODE_LEN 2
// tdlsoffchan
#ifdef FEATURE_WLAN_TDLS
static int tdlsOffCh = 1;
static int tdlsOffChBwOffset = 0;
#endif
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}, {4920, 240}, {4940, 244}, {4960, 248}, {4980, 252},
{5040, 208}, {5060, 212}, {5080, 216}, {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} };
#define FREQ_CHAN_MAP_TABLE_SIZE (sizeof(freq_chan_map)/sizeof(freq_chan_map[0]))
/* 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_ENABLE_STRICT_FCC_REG 10
#define WE_SET_MAX_TX_POWER_2_4 11
#define WE_SET_MAX_TX_POWER_5_0 12
/* Private IOCTL for debug connection issues */
#define WE_SET_DEBUG_LOG 13
// tdlsoffchan
#ifdef FEATURE_WLAN_TDLS
#define WE_SET_TDLS_OFF_CHAN 14
#define WE_SET_TDLS_SEC_OFF_CHAN_OFFSET 15
#define WE_SET_TDLS_OFF_CHAN_MODE 16
#endif
#define WE_SET_SCAN_BAND_PREFERENCE 17
#define WE_SET_MIRACAST_VENDOR_CONFIG 18
#define WE_GET_FRAME_LOG 19
#ifdef FEATURE_WLAN_TDLS
#define WE_SET_TDLS_2040_BSS_COEXISTENCE 20
#endif
#define WE_SET_RTS_CTS_HTVHT 21
#define WE_SET_MONITOR_STATE 22
#define WE_SET_PKT_STATS_ENABLE_DISABLE 23
#define WE_SET_PROXIMITY_ENABLE 24
#define WE_CAP_TSF 25
#define WE_SET_MODULATED_DTIM 26
#define WLAN_SET_DYNNAMIC_AGGREGATION 27
/* 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_PMC_STATE 3
#define WE_GET_WLAN_DBG 4
#define WE_GET_MAX_ASSOC 6
#define WE_GET_WDI_DBG 7
#define WE_GET_SAP_AUTO_CHANNEL_SELECTION 8
#define WE_GET_CONCURRENCY_MODE 9
#define WE_GET_SCAN_BAND_PREFERENCE 10
#define WE_GET_ANTENA_DIVERSITY_SELECTION 11
/* 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
#define WE_SET_ENCRYPT_MSG 6
/* 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_WDI_DBG 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
#define WE_GET_ROAM_RSSI 7
#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
#ifdef WLAN_FEATURE_RMC
#define WE_GET_IBSS_STA_INFO 11
#endif
#define WE_GET_SNR 12
#ifdef FEATURE_OEM_DATA_SUPPORT
#define WE_GET_OEM_DATA_CAP 13
#endif
/* Private ioctls and their sub-ioctls */
#define WLAN_PRIV_SET_NONE_GET_NONE (SIOCIWFIRSTPRIV + 6)
#define WE_CLEAR_STATS 1
#define WE_INIT_AP 2
#define WE_STOP_AP 3
#ifdef WLAN_BTAMP_FEATURE
#define WE_ENABLE_AMP 4
#define WE_DISABLE_AMP 5
#endif /* WLAN_BTAMP_FEATURE */
#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
#ifdef WLAN_FEATURE_RMC
#define WE_IBSS_GET_PEER_INFO_ALL 10
#endif
#define WE_STOP_OBSS_SCAN 11
#define WE_DUMP_ROAM_TIMER_LOG 12
#define WE_RESET_ROAM_TIMER_LOG 13
#define WE_GET_FW_LOGS 14
#define WE_GET_FW_MEMDUMP 15
/* 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
#ifdef WLAN_FEATURE_RMC
#define WE_IBSS_GET_PEER_INFO 6
#endif
#define WE_MTRACE_DUMP_CMD 8
#define WE_MTRACE_SELECTIVE_MODULE_LOG_ENABLE_CMD 9
#define WE_CONFIGURE_MONITOR_MODE 10
#define WE_SET_MONITOR_MODE_FILTER 11
#ifdef FEATURE_WLAN_TDLS
#undef MAX_VAR_ARGS
#define MAX_VAR_ARGS 10
#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
#ifdef FEATURE_OEM_DATA_SUPPORT
/* Private ioctls for setting the measurement configuration */
#define WLAN_PRIV_SET_OEM_DATA_REQ (SIOCIWFIRSTPRIV + 17)
#define WLAN_PRIV_GET_OEM_DATA_RSP (SIOCIWFIRSTPRIV + 19)
#endif
#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)
#define WLAN_GET_LINK_SPEED (SIOCIWFIRSTPRIV + 31)
#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
#define TX_PWR_MIN 6
#define TX_PWR_MAX 22
#define TX_PWR_DEF 50
/* Dynamic Aggregation */
#define DISABLE_AGGREGATION 0
#define ENABLE_AGGREGATION 1
/*
* When supplicant sends SETBAND ioctl it queries for channels from
* cfg80211 layer by sending itself EVENT_CHANNEL_LIST_CHANGED command.
* This is not required if the return type from ioctl is
* DO_NOT_SEND_CHANNEL_CHANGE_EVENT as wiphy will send channel change
* event as part of regulatory_hint.
*/
enum {
SEND_CHANNEL_CHANGE_EVENT = 0,
DO_NOT_SEND_CHANNEL_CHANGE_EVENT,
};
/*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,
};
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_adapter_t *pAdapter, tpPacketFilterCfg pRequest);
#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 = kmalloc(len + 1, GFP_KERNEL);
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__);
kfree(ptr);
return NULL;
}
ptr[len] = '\0';
return ptr;
}
// Function to handle and get compatible struct iw_point passed to ioctl.
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 (is_compat_task())
{
struct compat_iw_point *p_compat_priv_data;
// Compat task: typecast to campat 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;
}//if(is_compat_task())
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
}//else of - if(is_compat_task())
#endif //#ifdef CONFIG_COMPAT
return 0;
}
/**---------------------------------------------------------------------------
\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)
{
VOS_STATUS status;
tSirVersionString wcnss_SW_version;
tSirVersionString wcnss_HW_version;
tSirVersionString iris_name;
char *pIRISversion;
char *pSWversion;
char *pHWversion;
tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
status = sme_GetWcnssSoftwareVersion(hHal, wcnss_SW_version,
sizeof(wcnss_SW_version));
if (VOS_IS_STATUS_SUCCESS(status))
{
pSWversion = wcnss_SW_version;
}
else
{
pSWversion = "Unknown";
}
status = sme_GetWcnssHardwareVersion(hHal, wcnss_HW_version,
sizeof(wcnss_HW_version));
if (VOS_IS_STATUS_SUCCESS(status))
{
pHWversion = wcnss_HW_version;
}
else
{
pHWversion = "Unknown";
}
status = wcnss_get_iris_name(iris_name);
if (!status) {
pIRISversion = iris_name;
} else {
pIRISversion = "Unknown";
}
wrqu->data.length = scnprintf(extra, WE_MAX_STR_LEN,
"Host SW:%s, FW:%s, HW:%s, IRIS_HW:%s",
QWLAN_VERSIONSTR,
pSWversion,
pHWversion, pIRISversion);
return;
}
#ifdef WLAN_FEATURE_RMC
void hdd_get_ibss_peer_info_cb(v_VOID_t *pUserData, v_VOID_t *pPeerInfoRsp)
{
hdd_adapter_t *pAdapter = (hdd_adapter_t *)pUserData;
tSirPeerInfoRspParams *pPeerInfo = (tSirPeerInfoRspParams *)pPeerInfoRsp;
hdd_station_ctx_t *pStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
v_U8_t i;
if (NULL != pPeerInfo && eHAL_STATUS_SUCCESS == pPeerInfo->status)
{
pStaCtx->ibss_peer_info.status = pPeerInfo->status;
pStaCtx->ibss_peer_info.numIBSSPeers = pPeerInfo->numPeers;
for (i = 0; i < pPeerInfo->numPeers; i++)
{
memcpy(&pStaCtx->ibss_peer_info.ibssPeerList[i],
&pPeerInfo->peerInfoParams[i], sizeof(hdd_ibss_peer_info_params_t));
}
}
else
{
hddLog(LOGE,
FL("PEER_INFO_CMD_STATUS is not SUCCESS"));
}
complete(&pAdapter->ibss_peer_info_comp);
}
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);
hdd_ibss_peer_info_t *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)
{
long ret;
ret = wait_for_completion_interruptible_timeout
(&pAdapter->ibss_peer_info_comp,
msecs_to_jiffies(IBSS_PEER_INFO_REQ_TIMOEUT));
if (ret <= 0)
{
hddLog(VOS_TRACE_LEVEL_ERROR,
FL("failed wait on ibss_peer_info_comp %ld"), ret);
return eHAL_STATUS_FAILURE;
}
/** Print the peer info */
pr_info("pPeerInfo->numIBSSPeers = %d ", pPeerInfo->numIBSSPeers);
pr_info("============================================================");
{
v_MACADDR_t *macAddr = hdd_wlan_get_ibss_mac_addr_from_staid(pAdapter,
staIdx);
v_U32_t txRateMbps = ((pPeerInfo->ibssPeerList[0].txRate)*500*1000)/1000000;
if (NULL != macAddr)
{
pr_info("PEER ADDR :" MAC_ADDRESS_STR " TxRate: %d Mbps RSSI: %d",
MAC_ADDR_ARRAY(macAddr->bytes),
(int)txRateMbps, (int)pPeerInfo->ibssPeerList[0].rssi);
}
else
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
" ERROR: PEER MAC ADDRESS NOT FOUND ");
}
}
}
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);
hdd_ibss_peer_info_t *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)
{
long ret;
ret = wait_for_completion_interruptible_timeout
(&pAdapter->ibss_peer_info_comp,
msecs_to_jiffies(IBSS_PEER_INFO_REQ_TIMOEUT));
if (ret <= 0)
{
hddLog(VOS_TRACE_LEVEL_ERROR,
FL("failed wait on ibss_peer_info_comp %ld"), ret);
return eHAL_STATUS_FAILURE;
}
/** Print the peer info */
pr_info("pPeerInfo->numIBSSPeers = %d ", (int)pPeerInfo->numIBSSPeers);
pr_info("============================================================");
for (i = 0; i < pPeerInfo->numIBSSPeers; i++)
{
v_U8_t staIdx = pPeerInfo->ibssPeerList[i].staIdx;
v_MACADDR_t *macAddr = hdd_wlan_get_ibss_mac_addr_from_staid(pAdapter,
staIdx);
v_U32_t txRateMbps = ((pPeerInfo->ibssPeerList[0].txRate)*500*1000)/1000000;
pr_info("STAIDX:%d ", (int)pPeerInfo->ibssPeerList[i].staIdx);
if (NULL != macAddr)
{
pr_info(" PEER ADDR :" MAC_ADDRESS_STR " TxRate: %d Mbps RSSI: %d",
MAC_ADDR_ARRAY(macAddr->bytes),
(int)txRateMbps, (int)pPeerInfo->ibssPeerList[i].rssi);
}
else
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
" ERROR: PEER MAC ADDRESS NOT FOUND ");
}
}
}
else
{
hddLog(VOS_TRACE_LEVEL_WARN,
"%s: Warning: sme_RequestIBSSPeerInfo Request failed", __func__);
}
return status;
}
#endif /* WLAN_FEATURE_RMC */
int hdd_wlan_get_rts_threshold(hdd_adapter_t *pAdapter, union iwreq_data *wrqu)
{
tHalHandle hHal;
hdd_context_t *pHddCtx;
v_U32_t threshold = 0;
int ret = 0;
ENTER();
if (NULL == pAdapter)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: Adapter is NULL",__func__);
return -EINVAL;
}
pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
ret = wlan_hdd_validate_context(pHddCtx);
if (0 != ret)
{
return ret;
}
hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
if (NULL == hHal)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: Hal Context is NULL",__func__);
return -EINVAL;
}
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;
hdd_context_t *pHddCtx;
v_U32_t threshold = 0, status = 0;
ENTER();
if (NULL == pAdapter)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: Adapter is NULL",__func__);
return -EINVAL;
}
pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
status = wlan_hdd_validate_context(pHddCtx);
if (0 != status)
{
return status;
}
hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
if (NULL == hHal)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: Hal Context is NULL",__func__);
return -EINVAL;
}
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 0;
}
}
}
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;
}
struct snr_priv {
int8_t snr;
};
/**
* hdd_get_snr_cb() - "Get SNR" callback function
* @snr: Current SNR of the station
* @sta_id: ID of the station
* @context: opaque context originally passed to SME. HDD always passes
* a cookie for the request context
*
* Return: None
*/
static void hdd_get_snr_cb(tANI_S8 snr, tANI_U32 staId, void *context)
{
struct hdd_request *request;
struct snr_priv *priv;
request = hdd_request_get(context);
if (!request) {
hddLog(VOS_TRACE_LEVEL_ERROR, FL("Obsolete request"));
return;
}
/* propagate response back to requesting thread */
priv = hdd_request_priv(request);
priv->snr = snr;
hdd_request_complete(request);
hdd_request_put(request);
}
struct rssi_priv {
v_S7_t rssi;
};
static void hdd_get_rssi_cb( v_S7_t rssi, tANI_U32 staId, void *context )
{
struct hdd_request *request;
struct rssi_priv *priv;
if (ioctl_debug) {
pr_info("%s: rssi [%d] STA [%d] context [%pK]\n",
__func__, (int)rssi, (int)staId, context);
}
request = hdd_request_get(context);
if (!request) {
hddLog(VOS_TRACE_LEVEL_ERROR, FL("Obsolete request"));
return;
}
priv = hdd_request_priv(request);
priv->rssi = rssi;
hdd_request_complete(request);
hdd_request_put(request);
}
VOS_STATUS wlan_hdd_get_rssi(hdd_adapter_t *pAdapter, v_S7_t *rssi_value)
{
hdd_context_t *pHddCtx;
hdd_station_ctx_t *pHddStaCtx;
eHalStatus hstatus;
int ret;
void *cookie;
struct hdd_request *request;
struct rssi_priv *priv;
static const struct hdd_request_params params = {
.priv_size = sizeof(*priv),
.timeout_ms = WLAN_WAIT_TIME_STATS,
};
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)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%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, hence return last cached RSSI", __func__);
*rssi_value = pAdapter->rssi;
return VOS_STATUS_SUCCESS;
}
request = hdd_request_alloc(&params);
if (!request) {
hddLog(VOS_TRACE_LEVEL_ERROR, FL("Request allocation failure"));
return VOS_STATUS_E_NOMEM;
}
cookie = hdd_request_cookie(request);
hstatus = sme_GetRssi(pHddCtx->hHal, hdd_get_rssi_cb,
pHddStaCtx->conn_info.staId[ 0 ],
pHddStaCtx->conn_info.bssId,
cookie, 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 */
ret = hdd_request_wait_for_response(request);
if (ret)
{
hddLog(VOS_TRACE_LEVEL_ERROR,
FL("SME timeout while retrieving RSSI"));
/* we'll now returned a cached value below */
}
else
{
priv = hdd_request_priv(request);
pAdapter->rssi = priv->rssi;
/*
* copy over the rssi.FW will return RSSI as -100 if
* there are no samples to calculate the averag RSSI
*/
if (priv->rssi != -100)
pAdapter->rssi = priv->rssi;
if (pAdapter->rssi > 0)
pAdapter->rssi = 0;
}
}
*rssi_value = pAdapter->rssi;
hddLog(VOS_TRACE_LEVEL_INFO,
"%s: RSSI = %d", __func__, *rssi_value);
/*
* either we never sent a request, we sent a request and received a
* response or we sent a request and timed out. Regardless we are
* done with the request.
*/
hdd_request_put(request);
return VOS_STATUS_SUCCESS;
}
/**---------------------------------------------------------------------------
\brief wlan_hdd_get_frame_logs() -
This function use to get Frames log.
\param - pAdapter Pointer to the adapter.
flag - Specify type of request. Clear and Send request are
supported.
\return - none
--------------------------------------------------------------------------*/
VOS_STATUS wlan_hdd_get_frame_logs(hdd_adapter_t *pAdapter, v_U8_t flag)
{
hdd_context_t *pHddCtx;
eHalStatus hstatus;
if (NULL == pAdapter)
{
hddLog(VOS_TRACE_LEVEL_WARN,
"%s: Invalid context, pAdapter", __func__);
return VOS_STATUS_E_FAULT;
}
pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
if (!pHddCtx->mgmt_frame_logging)
{
hddLog(LOGW, FL("Frame Logging not init!"));
return VOS_STATUS_E_AGAIN;
}
if ((flag != WLAN_HDD_GET_FRAME_LOG_CMD_CLEAR) &&
(flag != WLAN_HDD_GET_FRAME_LOG_CMD_SEND_AND_CLEAR) &&
(flag != WLAN_HDD_GET_FRAME_LOG_CMD_BMU_TRACING))
{
hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Incorrect getFrame params!", __func__);
return VOS_STATUS_E_INVAL;
}
if ((flag == WLAN_HDD_GET_FRAME_LOG_CMD_BMU_TRACING) &&
(!pHddCtx->cfg_ini->enableBMUHWtracing))
{
hddLog(VOS_TRACE_LEVEL_ERROR,"%s: BMUHW Tracing not enabled!", __func__);
return VOS_STATUS_E_INVAL;
}
hstatus = sme_GetFramesLog(pHddCtx->hHal, flag);
if (eHAL_STATUS_SUCCESS != hstatus)
{
hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Unable to get Frame Logs", __func__);
return VOS_STATUS_E_FAILURE;
}
return VOS_STATUS_SUCCESS;
}
VOS_STATUS wlan_hdd_get_snr(hdd_adapter_t *pAdapter, v_S7_t *snr)
{
hdd_context_t *pHddCtx;
hdd_station_ctx_t *pHddStaCtx;
eHalStatus hstatus;
int ret;
void *cookie;
struct hdd_request *request;
struct snr_priv *priv;
static const struct hdd_request_params params = {
.priv_size = sizeof(*priv),
.timeout_ms = WLAN_WAIT_TIME_STATS,
};
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);
ret = wlan_hdd_validate_context(pHddCtx);
if (0 != ret)
{
return VOS_STATUS_E_FAULT;
}
pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
if (NULL == pHddStaCtx)
{
hddLog(VOS_TRACE_LEVEL_ERROR, FL("HDD STA context is not valid"));
return VOS_STATUS_E_FAULT;
}
request = hdd_request_alloc(&params);
if (!request) {
hddLog(VOS_TRACE_LEVEL_ERROR, FL("Request allocation failure"));
return VOS_STATUS_E_FAULT;
}
cookie = hdd_request_cookie(request);
hstatus = sme_GetSnr(pHddCtx->hHal, hdd_get_snr_cb,
pHddStaCtx->conn_info.staId[ 0 ],
pHddStaCtx->conn_info.bssId,
cookie);
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 */
ret = hdd_request_wait_for_response(request);
if (ret) {
hddLog(VOS_TRACE_LEVEL_ERROR,
FL("SME timed out while retrieving SNR"));
/* we'll now returned a cached value below */
} else {
/* update the adapter with the fresh results */
priv = hdd_request_priv(request);
pAdapter->snr = priv->snr;
}
}
/*
* either we never sent a request, we sent a request and
* received a response or we sent a request and timed out.
* regardless we are done with the request.
*/
hdd_request_put(request);
*snr = pAdapter->snr;
EXIT();
return VOS_STATUS_SUCCESS;
}
#if defined WLAN_FEATURE_VOWIFI_11R || defined FEATURE_WLAN_ESE || defined(FEATURE_WLAN_LFR)
VOS_STATUS wlan_hdd_get_roam_rssi(hdd_adapter_t *pAdapter, v_S7_t *rssi_value)
{
hdd_context_t *pHddCtx = NULL;
hdd_station_ctx_t *pHddStaCtx = NULL;
eHalStatus hstatus;
int ret;
void *cookie;
struct hdd_request *request;
struct rssi_priv *priv;
static const struct hdd_request_params params = {
.priv_size = sizeof(*priv),
.timeout_ms = WLAN_WAIT_TIME_STATS,
};
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)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
/* return a cached value */
*rssi_value = 0;
return VOS_STATUS_SUCCESS;
}
if (VOS_TRUE == pHddStaCtx->hdd_ReassocScenario)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
"%s: Roaming in progress, hence return last cached RSSI", __func__);
*rssi_value = pAdapter->rssi;
return VOS_STATUS_SUCCESS;
}
request = hdd_request_alloc(&params);
if (!request) {
hddLog(VOS_TRACE_LEVEL_ERROR, FL("Request allocation failure"));
return VOS_STATUS_E_NOMEM;
}
cookie = hdd_request_cookie(request);
hstatus = sme_GetRoamRssi(pHddCtx->hHal, hdd_get_rssi_cb,
pHddStaCtx->conn_info.staId[ 0 ],
pHddStaCtx->conn_info.bssId,
cookie, 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
{
ret = hdd_request_wait_for_response(request);
if(ret)
/* request was sent -- wait for the response */
{
hddLog(VOS_TRACE_LEVEL_ERROR,
FL(" SME timeout while retrieving RSSI"));
/* we'll now returned a cached value below */
}
else
{
priv = hdd_request_priv(request);
pAdapter->rssi = priv->rssi;
}
}
/*
* either we never sent a request, we sent a request and received a
* response or we sent a request and timed out. Regardless we are
* done with the request.
*/
hdd_request_put(request);
*rssi_value = pAdapter->rssi;
return VOS_STATUS_SUCCESS;
}
#endif
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);
if(pWextState)
{
vos_status = vos_event_set(&pWextState->vosevent);
if (!VOS_IS_STATUS_SUCCESS(vos_status))
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: vos_event_set failed", __func__);
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();
}
void hdd_clearRoamProfileIe( hdd_adapter_t *pAdapter)
{
hdd_wext_state_t *pWextState= WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
/* 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.nAddIEScanLength = 0;
memset(pWextState->roamProfile.addIEScan, 0 , SIR_MAC_MAX_ADD_IE_LENGTH+2);
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), WNI_CFG_BSSID_LEN);
#ifdef WLAN_FEATURE_11W
pWextState->roamProfile.MFPEnabled = eANI_BOOLEAN_FALSE;
pWextState->roamProfile.MFPRequired = 0;
pWextState->roamProfile.MFPCapable = 0;
#endif
pWextState->authKeyMgmt = 0;
vos_mem_zero(&pWextState->roamProfile.Keys,
sizeof(pWextState->roamProfile.Keys));
#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), WNI_CFG_BSSID_LEN);
}
void wlan_hdd_ula_done_cb(v_VOID_t *callbackContext)
{
hdd_adapter_t *pAdapter = (hdd_adapter_t*)callbackContext;
if ( (pAdapter == NULL) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic))
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: Invalid pAdapter magic/ pAdapter is NULL", __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;
}
static int __iw_set_commit(struct net_device *dev, struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
hdd_adapter_t *pAdapter;
hdd_context_t *pHddCtx;
int ret = 0;
ENTER();
pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
if (NULL == pAdapter)
{
VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: pAdapter is NULL\n", __func__);
return -EINVAL;
}
pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
ret = wlan_hdd_validate_context(pHddCtx);
if (0 != ret)
{
return ret;
}
/* Do nothing for now */
EXIT();
return ret;
}
static 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;
}
static int __iw_get_name(struct net_device *dev,
struct iw_request_info *info,
char *wrqu, char *extra)
{
hdd_adapter_t *pAdapter;
hdd_context_t *pHddCtx;
int ret = 0;
ENTER();
pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
if (NULL == pAdapter)
{
VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: pAdapter is NULL\n", __func__);
return -EINVAL;
}
pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
ret = wlan_hdd_validate_context(pHddCtx);
if (0 != ret)
{
return ret;
}
strlcpy(wrqu, "Qcom:802.11n", IFNAMSIZ);
EXIT();
return ret;
}
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;
}
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;
v_U32_t status = 0;
hdd_wext_state_t *pWextState;
hdd_adapter_t *pAdapter;
hdd_context_t *pHddCtx;
tHalHandle hHal;
hdd_station_ctx_t *pHddStaCtx;
tCsrRoamProfile * pRoamProfile;
ENTER();
pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
if (NULL == pAdapter)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s:Invalid Adapter",__func__);
return -EINVAL;
}
pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
status = wlan_hdd_validate_context(pHddCtx);
if (0 != status)
{
return status;
}
hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
if (NULL == hHal)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: Hal Context is NULL",__func__);
return -EINVAL;
}
pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
if (NULL == pHddStaCtx)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s:STA context is NULL",__func__);
return -EINVAL;
}
pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
if (NULL == pWextState)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: pWextState is NULL",__func__);
return -EINVAL;
}
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 status;
}
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;
}
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;
tHalHandle hHal;
hdd_wext_state_t *pWextState;
tCsrRoamProfile * pRoamProfile;
hdd_station_ctx_t *pHddStaCtx;
hdd_context_t *pHddCtx;
int ret = 0;
ENTER();
pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
if (NULL == pAdapter)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: Adapter is NULL", __func__);
return -EINVAL;
}
pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
ret = wlan_hdd_validate_context(pHddCtx);
if (0 != ret)
{
return ret;
}
hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
if (NULL == hHal)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: Hal Context is NULL",__func__);
return -EINVAL;
}
pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
if (NULL == pHddStaCtx)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: HddStaCtx is NULL", __func__);
return -EINVAL;
}
pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
if (NULL == pWextState)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: pWextState is NULL",__func__);
return -EINVAL;
}
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( 0 == 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;
}
EXIT();
return ret;
}
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;
}
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;
hdd_context_t *pHddCtx;
hdd_station_ctx_t *pHddStaCtx;
int ret = 0;
ENTER();
pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
if (NULL == pAdapter)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: Adapter is NULL",__func__);
return -EINVAL;
}
pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
ret = wlan_hdd_validate_context(pHddCtx);
if (0 != ret)
{
return ret;
}
pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
if (NULL == pHddStaCtx)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: STA Context is NULL",__func__);
return -EINVAL;
}
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;
EXIT();
return 0;
}
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;
}
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;
tHalHandle hHal;
hdd_context_t *pHddCtx;
int ret = 0;
ENTER();
pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
if (NULL == pAdapter)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: Adapter is NULL",__func__);
return -EINVAL;
}
pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
ret = wlan_hdd_validate_context(pHddCtx);
if (0 != ret)
{
return ret;
}
hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
if (NULL == hHal)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: Hal Context is NULL",__func__);
return -EINVAL;
}
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;
}
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;
}
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;
hdd_context_t *pHddCtx;
hdd_station_ctx_t *pHddStaCtx;
int ret = 0;
ENTER();
pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
if (NULL == pAdapter)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: Adapter is NULL",__func__);
return -EINVAL;
}
pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
ret = wlan_hdd_validate_context(pHddCtx);
if (0 != ret)
{
return ret;
}
pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
if (NULL == pHddStaCtx)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: STA Context is NULL",__func__);
return -EINVAL;
}
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 );
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);
if (NULL == pWextState)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: pWextState is NULL",__func__);
return -EINVAL;
}
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;
}
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;
}
/* ccm call back function */
static int __iw_set_bitrate(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu,
char *extra)
{
hdd_adapter_t *pAdapter;
hdd_wext_state_t *pWextState;
hdd_station_ctx_t *pHddStaCtx;
hdd_context_t *pHddCtx;
v_U8_t supp_rates[WNI_CFG_SUPPORTED_RATES_11A_LEN +
WNI_CFG_SUPPORTED_RATES_11B_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;
int ret = 0;
ENTER();
pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
if (NULL == pAdapter)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: Adapter is NULL",__func__);
return -EINVAL;
}
pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
ret = wlan_hdd_validate_context(pHddCtx);
if (0 != ret)
{
return ret;
}
pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
if (NULL == pHddStaCtx)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: STA Context is NULL",__func__);
return -EINVAL;
}
pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
if (NULL == pWextState)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: pWextState is NULL",__func__);
return -EINVAL;
}
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 + a_len, &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;
}
EXIT();
return 0;
}
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;
}
static int __iw_set_genie(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu,
char *extra)
{
hdd_adapter_t *pAdapter;
hdd_context_t *pHddCtx;
hdd_wext_state_t *pWextState;
u_int8_t *genie = NULL;
u_int8_t *base_genie = NULL;
v_U16_t remLen;
int ret = 0;
ENTER();
pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
if (NULL == pAdapter)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: Adapter is NULL",__func__);
return -EINVAL;
}
pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
ret = wlan_hdd_validate_context(pHddCtx);
if (0 != ret)
{
return ret;
}
pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
if (NULL == pWextState)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: pWextState is NULL",__func__);
return -EINVAL;
}
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();
kfree(base_genie);
return ret;
}
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;
}
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_context_t *pHddCtx;
hdd_adapter_t *pAdapter;
hdd_station_ctx_t *pHddStaCtx;
eHalStatus status;
v_U32_t length = DOT11F_IE_RSN_MAX_LEN;
v_U8_t genIeBytes[DOT11F_IE_RSN_MAX_LEN];
ENTER();
pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
if (NULL == pAdapter)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: Adapter is NULL",__func__);
return -EINVAL;
}
pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
status = wlan_hdd_validate_context(pHddCtx);
if (0 != status)
{
return status;
}
pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
if (NULL == pWextState)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: pWextState is NULL",__func__);
return -EINVAL;
}
pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
if (NULL == pHddStaCtx)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: STA Context is NULL",__func__);
return -EINVAL;
}
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;
}
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;
}
static int __iw_get_encode(struct net_device *dev,
struct iw_request_info *info,
struct iw_point *dwrq, char *extra)
{
hdd_adapter_t *pAdapter;
hdd_context_t *pHddCtx;
hdd_wext_state_t *pWextState;
tCsrRoamProfile *pRoamProfile;
int keyId, i, ret = 0;
eCsrAuthType authType = eCSR_AUTH_TYPE_NONE;
ENTER();
pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
if (NULL == pAdapter)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: Adapter is NULL",__func__);
return -EINVAL;
}
pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
ret = wlan_hdd_validate_context(pHddCtx);
if (0 != ret)
{
return ret;
}
pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
if (NULL == pWextState)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: pWextState is NULL",__func__);
return -EINVAL;
}
pRoamProfile = &(pWextState->roamProfile);
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.KeyMaterial[i] == NULL)
{
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;
}
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.
*/
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;
}
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;
}
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;
hdd_context_t *pHddCtx;
tHalHandle hHal;
int ret = 0;
ENTER();
pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
if (NULL == pAdapter)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: Adapter is NULL",__func__);
return -EINVAL;
}
pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
ret = wlan_hdd_validate_context(pHddCtx);
if (0 != ret)
{
return ret;
}
hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
if (NULL == hHal)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: Hal Context is NULL",__func__);
return -EINVAL;
}
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;
}
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;
}
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);
v_U32_t status = 0;
status = hdd_wlan_get_frag_threshold(pAdapter,wrqu);
return status;
}
static int iw_get_frag_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_frag_threshold(dev, info, wrqu, extra);
vos_ssr_unprotect(__func__);
return ret;
}
static int __iw_set_frag_threshold(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
hdd_adapter_t *pAdapter;
hdd_context_t *pHddCtx;
tHalHandle hHal;
int ret = 0;
ENTER();
pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
if (NULL == pAdapter)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: Adapter is NULL",__func__);
return -EINVAL;
}
pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
ret = wlan_hdd_validate_context(pHddCtx);
if (0 != ret)
{
return ret;
}
hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
if (NULL == hHal)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: Hal Context is NULL",__func__);
return -EINVAL;
}
if ( wrqu->frag.value < WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN || wrqu->frag.value > WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX )
{
return -EINVAL;
}
if ( ccmCfgSetInt(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD, wrqu->frag.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_FRAGMENTATION_THRESHOLD"));
return -EIO;
}
EXIT();
return 0;
}
static int iw_set_frag_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_frag_threshold(dev, info, wrqu, extra);
vos_ssr_unprotect(__func__);
return ret;
}
static int __iw_get_power_mode(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
hdd_adapter_t *pAdapter;
hdd_context_t *pHddCtx;
int ret = 0;
ENTER();
pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
if (NULL == pAdapter)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: Adapter is NULL",__func__);
return -EINVAL;
}
pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
ret = wlan_hdd_validate_context(pHddCtx);
if (0 != ret)
{
return ret;
}
EXIT();
return -EOPNOTSUPP;
}
static int iw_get_power_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_power_mode(dev, info, wrqu, extra);
vos_ssr_unprotect(__func__);
return ret;
}
static int __iw_set_power_mode(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
hdd_adapter_t *pAdapter;
hdd_context_t *pHddCtx;
int ret = 0;
ENTER();
pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
if (NULL == pAdapter)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: Adapter is NULL",__func__);
return -EINVAL;
}
pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
ret = wlan_hdd_validate_context(pHddCtx);
if (0 != ret)
{
return ret;
}
EXIT();
return -EOPNOTSUPP;
}
static int iw_set_power_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_power_mode(dev, info, wrqu, extra);
vos_ssr_unprotect(__func__);
return ret;
}
static int __iw_get_range(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
hdd_adapter_t *pAdapter;
tHalHandle hHal;
hdd_context_t *pHddCtx;
int ret = 0;
struct iw_range *range = (struct iw_range *) extra;
v_U8_t channels[WNI_CFG_VALID_CHANNEL_LIST_LEN];
v_U32_t num_channels = sizeof(channels);
v_U8_t supp_rates[WNI_CFG_SUPPORTED_RATES_11A_LEN];
v_U32_t a_len;
v_U32_t b_len;
v_U32_t active_phy_mode = 0;
v_U8_t index = 0, i;
ENTER();
pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
if (NULL == pAdapter)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: pAdapter is NULL", __func__);
return -EINVAL;
}
pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
ret = wlan_hdd_validate_context(pHddCtx);
if (0 != ret)
{
return ret;
}
hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
if (NULL == hHal)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: pAdapter is NULL", __func__);
return -EINVAL;
}
wrqu->data.length = sizeof(struct iw_range);
memset(range, 0, sizeof(struct iw_range));
/*Get the phy mode*/
if (ccmCfgGetInt(hHal,
WNI_CFG_DOT11_MODE, &active_phy_mode) == eHAL_STATUS_SUCCESS)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
"active_phy_mode = %d", active_phy_mode);
if (active_phy_mode == WNI_CFG_DOT11_MODE_11A || active_phy_mode == WNI_CFG_DOT11_MODE_11G)
{
/*Get the supported rates for 11G band*/
a_len = WNI_CFG_SUPPORTED_RATES_11A_LEN;
if (ccmCfgGetStr(hHal,
WNI_CFG_SUPPORTED_RATES_11A,
supp_rates, &a_len) == eHAL_STATUS_SUCCESS)
{
if (a_len > WNI_CFG_SUPPORTED_RATES_11A_LEN)
{
a_len = WNI_CFG_SUPPORTED_RATES_11A_LEN;
}
for (i = 0; i < a_len; i++)
{
range->bitrate[i] = ((supp_rates[i] & 0x7F) / 2) * 1000000;
}
range->num_bitrates = a_len;
}
else
{
return -EIO;
}
}
else if (active_phy_mode == WNI_CFG_DOT11_MODE_11B)
{
/*Get the supported rates for 11B band*/
b_len = WNI_CFG_SUPPORTED_RATES_11B_LEN;
if (ccmCfgGetStr(hHal,
WNI_CFG_SUPPORTED_RATES_11B,
supp_rates, &b_len) == eHAL_STATUS_SUCCESS)
{
if (b_len > WNI_CFG_SUPPORTED_RATES_11B_LEN)
{
b_len = WNI_CFG_SUPPORTED_RATES_11B_LEN;
}
for (i = 0; i < b_len; i++)
{
range->bitrate[i] = ((supp_rates[i] & 0x7F) / 2) * 1000000;
}
range->num_bitrates = b_len;
}
else
{
return -EIO;
}
}
}
range->max_rts = WNI_CFG_RTS_THRESHOLD_STAMAX;
range->min_frag = WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN;
range->max_frag = WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX;
range->encoding_size[0] = 5;
range->encoding_size[1] = 13;
range->num_encoding_sizes = 2;
range->max_encoding_tokens = MAX_WEP_KEYS;
// we support through Wireless Extensions 22
range->we_version_compiled = WIRELESS_EXT;
range->we_version_source = 22;
/*Supported Channels and Frequencies*/
if (ccmCfgGetStr((hHal), WNI_CFG_VALID_CHANNEL_LIST, channels, &num_channels) != 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;
}
if (num_channels > IW_MAX_FREQUENCIES)
{
num_channels = IW_MAX_FREQUENCIES;
}
range->num_channels = num_channels;
range->num_frequency = num_channels;
for (index=0; index < num_channels; index++)
{
v_U32_t frq_indx = 0;
range->freq[index].i = channels[index];
while (frq_indx < FREQ_CHAN_MAP_TABLE_SIZE)
{
if(channels[index] == freq_chan_map[frq_indx].chan)
{
range->freq[index].m = freq_chan_map[frq_indx].freq * 100000;
range->freq[index].e = 1;
break;
}
frq_indx++;
}
}
/* Event capability (kernel + driver) */
range->event_capa[0] = (IW_EVENT_CAPA_K_0 |
IW_EVENT_CAPA_MASK(SIOCGIWAP) |
IW_EVENT_CAPA_MASK(SIOCGIWSCAN));
range->event_capa[1] = IW_EVENT_CAPA_K_1;
/*Encryption capability*/
range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP;
/* Txpower capability */
range->txpower_capa = IW_TXPOW_MWATT;
/*Scanning capability*/
#if WIRELESS_EXT >= 22
range->scan_capa = IW_SCAN_CAPA_ESSID | IW_SCAN_CAPA_TYPE | IW_SCAN_CAPA_CHANNEL;
#endif
EXIT();
return 0;
}
static int iw_get_range(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
int ret;
vos_ssr_protect(__func__);
ret = __iw_get_range(dev, info, wrqu, extra);
vos_ssr_unprotect(__func__);
return ret;
}
/* Callback function for tx per hit */
void hdd_tx_per_hit_cb (void *pCallbackContext)
{
hdd_adapter_t *pAdapter = (hdd_adapter_t *)pCallbackContext;
unsigned char tx_fail[16];
union iwreq_data wrqu;
if (NULL == pAdapter || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic))
{
hddLog(LOGE, "hdd_tx_per_hit_cb: pAdapter is NULL");
return;
}
memset(&wrqu, 0, sizeof(wrqu));
wrqu.data.length = strlcpy(tx_fail, "TX_FAIL", sizeof(tx_fail));
wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu, tx_fail);
}
void hdd_get_class_a_statistics_cb(void *stats, void *context)
{
struct hdd_request *request;
struct stats_class_a_ctx *priv;
if (ioctl_debug) {
pr_info("%s: stats [%pK] context [%pK]\n",
__func__, stats, context);
}
if (NULL == stats) {
hddLog(VOS_TRACE_LEVEL_ERROR,
"%s: Bad param, stats [%pK]",
__func__, stats);
return;
}
request = hdd_request_get(context);
if (!request) {
hddLog(VOS_TRACE_LEVEL_ERROR, FL("Obsolete request"));
return;
}
priv = hdd_request_priv(request);
/* copy over the stats. do so as a struct copy */
priv->class_a_stats = *(tCsrGlobalClassAStatsInfo *)stats;
hdd_request_complete(request);
hdd_request_put(request);
}
VOS_STATUS wlan_hdd_get_classAstats(hdd_adapter_t *pAdapter)
{
hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
eHalStatus hstatus;
int ret;
void *cookie;
struct hdd_request *request;
struct stats_class_a_ctx *priv;
static const struct hdd_request_params params = {
.priv_size = sizeof(*priv),
.timeout_ms = WLAN_WAIT_TIME_STATS,
};
if (NULL == pAdapter)
{
hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Padapter is NULL", __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 VOS_STATUS_SUCCESS;
}
request = hdd_request_alloc(&params);
if (!request) {
hddLog(VOS_TRACE_LEVEL_ERROR, FL("Request allocation failure"));
return VOS_STATUS_E_NOMEM;
}
cookie = hdd_request_cookie(request);
/* query only for Class A statistics (which include link speed) */
hstatus = sme_GetStatistics( WLAN_HDD_GET_HAL_CTX(pAdapter),
eCSR_HDD,
SME_GLOBAL_CLASSA_STATS,
hdd_get_class_a_statistics_cb,
0, // not periodic
FALSE, //non-cached results
pHddStaCtx->conn_info.staId[0],
cookie);
if (eHAL_STATUS_SUCCESS != hstatus)
{
hddLog(VOS_TRACE_LEVEL_ERROR,
"%s: Unable to retrieve Class A statistics",
__func__);
/* we'll returned a cached value below */
}
else
{
/* request was sent -- wait for the response */
ret = hdd_request_wait_for_response(request);
if (ret)
{
hddLog(VOS_TRACE_LEVEL_ERROR,
FL("SME timeout while retrieving Class A statistics"));
}
else
{
priv = hdd_request_priv(request);
pAdapter->hdd_stats.ClassA_stat = priv->class_a_stats;
}
}
/*
* either we never sent a request, we sent a request and received a
* response or we sent a request and timed out. Regardless we are
* done with the request.
*/
hdd_request_put(request);
/* either callback updated pAdapter stats or it has cached data */
return VOS_STATUS_SUCCESS;
}
struct stats_ctx {
tCsrSummaryStatsInfo summary_stats;
tCsrGlobalClassAStatsInfo class_a_stats;
};
static void hdd_get_station_statistics_cb(void *stats, void *context)
{
tCsrSummaryStatsInfo *summary_stats;
tCsrGlobalClassAStatsInfo *class_a_stats;
struct hdd_request *request;
struct stats_ctx *priv;
if (ioctl_debug) {
pr_info("%s: stats [%pK] context [%pK]\n",
__func__, stats, context);
}
if (NULL == stats) {
hddLog(VOS_TRACE_LEVEL_ERROR,
"%s: Bad param, stats [%pK]",
__func__, stats);
return;
}
request = hdd_request_get(context);
if (!request) {
hddLog(VOS_TRACE_LEVEL_ERROR, FL("Obsolete request"));
return;
}
summary_stats = (tCsrSummaryStatsInfo *)stats;
class_a_stats = (tCsrGlobalClassAStatsInfo *)(summary_stats + 1);
priv = hdd_request_priv(request);
/* copy over the stats. do so as a struct copy */
priv->summary_stats = *summary_stats;
priv->class_a_stats = *class_a_stats;
hdd_request_complete(request);
hdd_request_put(request);
}
VOS_STATUS wlan_hdd_get_station_stats(hdd_adapter_t *pAdapter)
{
hdd_station_ctx_t *pHddStaCtx;
hdd_ap_ctx_t *sap_ctx;
eHalStatus hstatus;
tANI_U8 sta_id;
int ret;
void *cookie;
struct hdd_request *request;
struct stats_ctx *priv;
static const struct hdd_request_params params = {
.priv_size = sizeof(*priv),
.timeout_ms = WLAN_WAIT_TIME_STATS,
};
if (NULL == pAdapter)
{
hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Padapter is NULL", __func__);
return VOS_STATUS_SUCCESS;
}
if (pAdapter->device_mode == WLAN_HDD_SOFTAP) {
sap_ctx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
sta_id = sap_ctx->uBCStaId;
} else {
pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
sta_id = pHddStaCtx->conn_info.staId[0];
}
request = hdd_request_alloc(&params);
if (!request) {
hddLog(VOS_TRACE_LEVEL_ERROR, FL("Request allocation failure"));
return VOS_STATUS_E_NOMEM;
}
cookie = hdd_request_cookie(request);
/* query only for Summary & Class A statistics */
hstatus = sme_GetStatistics(WLAN_HDD_GET_HAL_CTX(pAdapter),
eCSR_HDD,
SME_SUMMARY_STATS |
SME_GLOBAL_CLASSA_STATS |
SME_PER_PKT_STATS,
hdd_get_station_statistics_cb,
0, // not periodic
FALSE, //non-cached results
sta_id,
cookie);
if (eHAL_STATUS_SUCCESS != hstatus)
{
hddLog(VOS_TRACE_LEVEL_ERROR,
"%s: Unable to retrieve statistics",
__func__);
/* we'll return with cached values */
}
else
{
/* request was sent -- wait for the response */
ret = hdd_request_wait_for_response(request);
if (ret)
{
hddLog(VOS_TRACE_LEVEL_ERROR,
FL("SME timeout while retrieving statistics"));
}
else
{
priv = hdd_request_priv(request);
pAdapter->hdd_stats.summary_stat = priv->summary_stats;
pAdapter->hdd_stats.ClassA_stat = priv->class_a_stats;
}
}
/*
* either we never sent a request, we sent a request and received a
* response or we sent a request and timed out. Regardless we are
* done with the request.
*/
hdd_request_put(request);
/* either callback updated pAdapter stats or it has cached data */
return VOS_STATUS_SUCCESS;
}
/*
* Support for the LINKSPEED private command
* Per the WiFi framework the response must be of the form
* "LinkSpeed xx"
*/
static int iw_get_linkspeed(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
hdd_adapter_t *pAdapter;
hdd_context_t *pHddCtx;
char *pLinkSpeed = (char*)extra;
int len = sizeof(v_U32_t) + 1;
v_U32_t link_speed;
hdd_station_ctx_t *pHddStaCtx;
VOS_STATUS status;
int rc, valid = 0;
ENTER();
pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
if (NULL == pAdapter)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: Adapter is NULL",__func__);
return -EINVAL;
}
pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
valid = wlan_hdd_validate_context(pHddCtx);
if (0 != valid)
{
return valid;
}
pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
if (NULL == pHddStaCtx)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: STA Context is NULL",__func__);
return -EINVAL;
}
if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
{
/* we are not connected so we don't have a classAstats */
link_speed = 0;
}
else
{
status = wlan_hdd_get_classAstats(pAdapter);
if (!VOS_IS_STATUS_SUCCESS(status ))
{
hddLog(VOS_TRACE_LEVEL_ERROR, FL("Unable to retrieve SME statistics"));
return -EINVAL;
}
/* Unit of link capacity is obtained from the TL API is MbpsX10 */
WLANTL_GetSTALinkCapacity(WLAN_HDD_GET_CTX(pAdapter)->pvosContext,
(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[0],
&link_speed);
link_speed = link_speed / 10;
if (0 == link_speed)
{
/* The linkspeed returned by HAL is in units of 500kbps.
* converting it to mbps.
* This is required to support legacy firmware which does
* not return link capacity.
*/
link_speed = pAdapter->hdd_stats.ClassA_stat.tx_rate/2;
}
}
wrqu->data.length = len;
// return the linkspeed in the format required by the WiFi Framework
rc = snprintf(pLinkSpeed, len, "%u", link_speed);
if ((rc < 0) || (rc >= len))
{
// encoding or length error?
hddLog(VOS_TRACE_LEVEL_ERROR,FL("Unable to encode link speed"));
return -EIO;
}
EXIT();
/* a value is being successfully returned */
return rc;
}
/*
* Helper function to return correct value for WLAN_GET_LINK_SPEED
*
*/
static int __iw_get_linkspeed_priv(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
int rc;
rc = iw_get_linkspeed(dev, info, wrqu, extra);
if (rc < 0)
return rc;
/* a value is being successfully returned */
return 0;
}
static int iw_get_linkspeed_priv(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
int ret;
vos_ssr_protect(__func__);
ret = __iw_get_linkspeed_priv(dev, info, wrqu, extra);
vos_ssr_unprotect(__func__);
return ret;
}
/*
* Support for the RSSI & RSSI-APPROX private commands
* Per the WiFi framework the response must be of the form
* "<ssid> rssi <xx>"
* unless we are not associated, in which case the response is
* "OK"
*/
static int iw_get_rssi(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);
char *cmd = extra;
int len = wrqu->data.length;
v_S7_t s7Rssi = 0;
hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
int ssidlen = pHddStaCtx->conn_info.SSID.SSID.length;
VOS_STATUS vosStatus;
int rc;
if ((eConnectionState_Associated != pHddStaCtx->conn_info.connState) ||
(0 == ssidlen) || (ssidlen >= len))
{
/* we are not connected or our SSID is too long
so we cannot report an rssi */
rc = scnprintf(cmd, len, "OK");
}
else
{
/* we are connected with a valid SSID
so we can write the SSID into the return buffer
(note that it is not NUL-terminated) */
memcpy(cmd, pHddStaCtx->conn_info.SSID.SSID.ssId, ssidlen );
wlan_hdd_get_station_stats(pAdapter);
vosStatus = wlan_hdd_get_rssi(pAdapter, &s7Rssi);
if (VOS_STATUS_SUCCESS == vosStatus)
{
/* append the rssi to the ssid in the format required by
the WiFI Framework */
rc = scnprintf(&cmd[ssidlen], len - ssidlen, " rssi %d", s7Rssi);
rc += ssidlen;
}
else
{
rc = -1;
}
}
/* verify that we wrote a valid response */
if ((rc < 0) || (rc >= len))
{
// encoding or length error?
hddLog(VOS_TRACE_LEVEL_ERROR,
"%s: Unable to encode RSSI, got [%s]",
__func__, cmd);
return -EIO;
}
/* a value is being successfully returned */
return rc;
}
/*
* Support for SoftAP channel range private command
*/
static int iw_softap_set_channel_range( struct net_device *dev,
int startChannel,
int endChannel,
int band)
{
VOS_STATUS status;
int ret = 0;
hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev));
tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pHostapdAdapter);
hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
status = WLANSAP_SetChannelRange(hHal, startChannel, endChannel, band);
if (VOS_STATUS_SUCCESS != status)
{
ret = -EINVAL;
}
pHddCtx->is_dynamic_channel_range_set = 1;
return ret;
}
static uint8 chartohex(char c)
{
uint8 val = 0;
if (c >= '0' && c <= '9')
val = c - '0';
else if (c >= 'a' && c <= 'f')
val = c - 'a' + 10;
else if (c >= 'A' && c <= 'F')
val = c - 'A' + 10;
else
hddLog(VOS_TRACE_LEVEL_ERROR, "Not a valid hex char");
return val;
}
uint8 getByte(char **buf)
{
uint8 byte = 0;
char *temp = *buf;
byte = chartohex(*temp) * 16;
temp++;
byte += chartohex(*temp);
temp++;
*buf = temp;
return byte;
}
static void parse_Bufferforpkt(tSirpkt80211 *pkt, u8 *pBuffer, u16 len)
{
tSir80211Header *macHeader;
int i = 0, j = 0, length = 0;
uint8 byte = 0;
char *temp = pBuffer;
uint16 fragNum = 0;
char *pHeader;
tSir80211Header header;
macHeader = &pkt->macHeader;
pkt->encParams.keyParams.key[0].keyId = *temp - '0';
temp++;
hddLog(VOS_TRACE_LEVEL_ERROR, "Input Message to encrypt");
hddLog(VOS_TRACE_LEVEL_ERROR, "Key Id : %d",
pkt->encParams.keyParams.key[0].keyId);
for (i = 0; i< 16; i++) {
pkt->encParams.keyParams.key[0].key[i]
= getByte(&temp);
}
print_hex_dump(KERN_INFO, "Key : ", DUMP_PREFIX_NONE, 16, 1,
&pkt->encParams.keyParams.key[0].key[0], 16, 0);
for (i = 0; i< 6; i++) {
pkt->encParams.pn[i]
= getByte(&temp);
}
print_hex_dump(KERN_INFO, "PN : ", DUMP_PREFIX_NONE, 16, 1,
&pkt->encParams.pn[0], 6, 0);
for (i = 0, j= 5; i< 3; i++, j--) {
byte = pkt->encParams.pn[i];
pkt->encParams.pn[i] = pkt->encParams.pn[j];
pkt->encParams.pn[j] = byte;
}
length = getByte(&temp);
if (length > sizeof(tSir80211Header))
length = sizeof(tSir80211Header);
pHeader = temp;
vos_mem_zero(&header, sizeof(tSir80211Header));
for (i = 0; i < length; i++) {
*((uint8 *)&header + i) = getByte(&pHeader);
}
print_hex_dump(KERN_INFO, "Header : ", DUMP_PREFIX_NONE, 16, 1,
(char *)&header, length, 0);
byte = getByte(&temp);
macHeader->frameCtrl.protVer = byte & 0x3;
macHeader->frameCtrl.type = (byte >> 2) & 0x3;
macHeader->frameCtrl.subType = (byte >> 4) & 0xF;
byte = getByte(&temp);
macHeader->frameCtrl.toDS = (byte) & 0x1;
macHeader->frameCtrl.fromDS = (byte >> 1) & 0x1;
macHeader->frameCtrl.moreFrag = (byte >> 2) & 0x1;
macHeader->frameCtrl.retry = (byte >> 3) & 0x1;
macHeader->frameCtrl.powerMgmt = (byte >> 4) & 0x1;
macHeader->frameCtrl.moreData = (byte >> 5) & 0x1;
macHeader->frameCtrl.wep = (byte >> 6) & 0x1;
macHeader->frameCtrl.order = (byte >> 7) & 0x1;
hddLog(VOS_TRACE_LEVEL_INFO, "macHeader->frameCtrl.protVer : %x "
"macHeader->frameCtrl.type : %x "
"macHeader->frameCtrl.subType : %x "
"macHeader->frameCtrl.toDS : %x "
"macHeader->frameCtrl.fromDS : %x "
"macHeader->frameCtrl.moreFrag : %x "
"macHeader->frameCtrl.retry : %x "
"macHeader->frameCtrl.powerMgmt : %x "
"macHeader->frameCtrl.MoreData : %x "
"macHeader->frameCtrl.wep : %x "
"macHeader->frameCtrl.order : %x "
, macHeader->frameCtrl.protVer
, macHeader->frameCtrl.type
, macHeader->frameCtrl.subType
, macHeader->frameCtrl.toDS
, macHeader->frameCtrl.fromDS
, macHeader->frameCtrl.moreFrag
, macHeader->frameCtrl.retry
, macHeader->frameCtrl.powerMgmt
, macHeader->frameCtrl.moreData
, macHeader->frameCtrl.wep
, macHeader->frameCtrl.order);
macHeader->usDurationId = getByte(&temp);
macHeader->usDurationId += getByte(&temp) << 8;
macHeader->vA1[0] = getByte(&temp);
macHeader->vA1[1] = getByte(&temp);
macHeader->vA1[2] = getByte(&temp);
macHeader->vA1[3] = getByte(&temp);
macHeader->vA1[4] = getByte(&temp);
macHeader->vA1[5] = getByte(&temp);
macHeader->vA2[0] = getByte(&temp);
macHeader->vA2[1] = getByte(&temp);
macHeader->vA2[2] = getByte(&temp);
macHeader->vA2[3] = getByte(&temp);
macHeader->vA2[4] = getByte(&temp);
macHeader->vA2[5] = getByte(&temp);
macHeader->vA3[0] = getByte(&temp);
macHeader->vA3[1] = getByte(&temp);
macHeader->vA3[2] = getByte(&temp);
macHeader->vA3[3] = getByte(&temp);
macHeader->vA3[4] = getByte(&temp);
macHeader->vA3[5] = getByte(&temp);
macHeader->sSeqCtrl = getByte(&temp);
fragNum = macHeader->sSeqCtrl & 0xF;
macHeader->sSeqCtrl >>= 4;
macHeader->sSeqCtrl += getByte(&temp) << 4;
macHeader->sSeqCtrl |= fragNum << 12;
if (length == 30 || length == 32) {
macHeader->optvA4[0] = getByte(&temp);
macHeader->optvA4[1] = getByte(&temp);
macHeader->optvA4[2] = getByte(&temp);
macHeader->optvA4[3] = getByte(&temp);
macHeader->optvA4[4] = getByte(&temp);
macHeader->optvA4[5] = getByte(&temp);
}
if (length == 26 || length == 32) {
macHeader->usQosCtrl = getByte(&temp);
macHeader->usQosCtrl += getByte(&temp) << 8;
}
//parse payload
length = getByte(&temp);
length += getByte(&temp) << 8;
hddLog(VOS_TRACE_LEVEL_INFO,"Payload length : %d", length);
if (length >= WLAN_DISA_MAX_PAYLOAD_SIZE)
length = WLAN_DISA_MAX_PAYLOAD_SIZE;
pkt->data.length = length;
for (i = 0; i< length; i++) {
pkt->data.data[i] = getByte(&temp);
}
print_hex_dump(KERN_INFO, "Data : ", DUMP_PREFIX_NONE, 16, 1,
&pkt->data.data[0], pkt->data.length, 0);
}
/**---------------------------------------------------------------------------
\brief hdd_encrypt_msg_cb() - Callback function for DISA
encrypt message request
This is an asynchronous callback function from SME when the encrypted data
is received
\pEncInfoRsp -> Encrypted data info
\return - 0 for success non-zero for failure
--------------------------------------------------------------------------*/
static void
hdd_encrypt_msg_cb(v_VOID_t *pUserData, v_VOID_t *pEncInfoRsp)
{
tpSetEncryptedDataRspParams pEncryptedDataRsp;
pEncryptedDataRsp = (tpSetEncryptedDataRspParams)pEncInfoRsp;
hddLog(VOS_TRACE_LEVEL_ERROR, "Encrypted Message");
hddLog(VOS_TRACE_LEVEL_ERROR, "Length : %d",
pEncryptedDataRsp->encryptedPayload.length);
hddLog(VOS_TRACE_LEVEL_ERROR, " Encrypted Data: ");
print_hex_dump(KERN_INFO, "", DUMP_PREFIX_NONE, 16, 1,
pEncryptedDataRsp->encryptedPayload.data,
pEncryptedDataRsp->encryptedPayload.length, 0);
}
/**
* iw_power_callback_func() - Callback function registered with PMC
* @context: cookie originally registered with PMC
* @status: status code indicated by PMC state machine
*
* Return: None
*/
static void iw_power_callback_func(void *context, eHalStatus status)
{
struct hdd_request *request = hdd_request_get(context);
if (!request) {
hddLog(VOS_TRACE_LEVEL_ERROR,
"%s: Obsolete request", __func__);
return;
}
hdd_request_complete(request);
hdd_request_put(request);
}
VOS_STATUS wlan_hdd_enter_bmps(hdd_adapter_t *pAdapter, int mode)
{
eHalStatus status;
hdd_context_t *pHddCtx;
hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
int ret;
void *cookie;
struct hdd_request *request;
static const struct hdd_request_params params = {
.priv_size = 0,
.timeout_ms = WLAN_WAIT_TIME_STATS,
};
if (NULL == pAdapter)
{
hddLog(VOS_TRACE_LEVEL_FATAL, "Adapter NULL");
return VOS_STATUS_E_FAULT;
}
hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "power mode=%d", mode);
pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
if (pHddCtx->isLogpInProgress) {
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s:LOGP in Progress. Ignore!!!", __func__);
return VOS_STATUS_E_FAILURE;
}
request = hdd_request_alloc(&params);
if (!request) {
hddLog(VOS_TRACE_LEVEL_ERROR, FL("Request allocation failure"));
return VOS_STATUS_E_NOMEM;
}
cookie = hdd_request_cookie(request);
if (DRIVER_POWER_MODE_ACTIVE == mode)
{
hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s:Wlan driver Entering "
"Full Power", __func__);
status = sme_RequestFullPower(WLAN_HDD_GET_HAL_CTX(pAdapter),
iw_power_callback_func, cookie,
eSME_FULL_PWR_NEEDED_BY_HDD);
// Enter Full power command received from GUI this means we are disconnected
// Set PMC remainInPowerActiveTillDHCP flag to disable auto BMPS entry by PMC
sme_SetDHCPTillPowerActiveFlag(pHddCtx->hHal, TRUE);
if (eHAL_STATUS_PMC_PENDING == status)
{
ret = hdd_request_wait_for_response(request);
if (ret)
{
hddLog(VOS_TRACE_LEVEL_ERROR,
FL("SME timeout while requesting fullpower"));
}
}
}
else if (DRIVER_POWER_MODE_AUTO == mode)
{
/* If this is called by hdd_suspend_wlan or hdd_resume_wlan, driver
* was already in BMPS state and thus either STA or P2P-CLI is in
* associated state and authenticated, so even if STA connState is
* not associated it can be assumed that P2P-CLI is associated and
* authenticated. Thus driver can enter BMPS. And even if we try to enter
* BMPS with no adaptor in associated state, pmcRequestBmps will check
* if all condition are satisfied for entering BMPS.
*/
if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
(VOS_FALSE == pHddStaCtx->conn_info.uIsAuthenticated))
{
hddLog(LOGE,
FL("Station is associated but, still not Authenticated ignore "
"power save mode"));
return VOS_STATUS_E_AGAIN;
}
if (pHddCtx->cfg_ini->fIsBmpsEnabled)
{
hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s:Wlan driver Entering Bmps ",
__func__);
// Enter BMPS command received from GUI this means DHCP is completed
// Clear PMC remainInPowerActiveTillDHCP flag to enable auto BMPS entry
sme_SetDHCPTillPowerActiveFlag(WLAN_HDD_GET_HAL_CTX(pAdapter),
FALSE);
status = sme_RequestBmps(WLAN_HDD_GET_HAL_CTX(pAdapter),
iw_power_callback_func, cookie);
if (eHAL_STATUS_PMC_PENDING == status)
{
/* request was sent -- wait for the response */
ret = hdd_request_wait_for_response(request);
if (ret)
{
hddLog(VOS_TRACE_LEVEL_ERROR,
FL("SME timeout while requesting bmps"));
}
}
}
else
{
hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "BMPS is not "
"enabled in the cfg");
}
}
/*
* either we never sent a request, we sent a request and received a
* response or we sent a request and timed out. Regardless we are
* done with the request.
*/
hdd_request_put(request);
return VOS_STATUS_SUCCESS;
}
VOS_STATUS wlan_hdd_exit_lowpower(hdd_context_t *pHddCtx,
hdd_adapter_t *pAdapter)
{
VOS_STATUS vos_Status;
if ((NULL == pAdapter) || (NULL == pHddCtx))
{
hddLog(VOS_TRACE_LEVEL_FATAL, "Invalid pointer");
return VOS_STATUS_E_FAULT;
}
/**Exit from Deep sleep or standby if we get the driver
START cmd from android GUI
*/
if (WLAN_MAP_DRIVER_STOP_TO_STANDBY == pHddCtx->cfg_ini->nEnableDriverStop)
{
hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: WLAN being exit "
"from Stand by",__func__);
vos_Status = hdd_exit_standby(pHddCtx);
}
else if (eHDD_SUSPEND_DEEP_SLEEP == pHddCtx->hdd_ps_state)
{
hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: WLAN being exit "
"from deep sleep",__func__);
vos_Status = hdd_exit_deep_sleep(pHddCtx, pAdapter);
}
else
{
hddLog(VOS_TRACE_LEVEL_WARN, "%s: Not in standby or deep sleep. "
"Ignore start cmd %d", __func__, pHddCtx->hdd_ps_state);
vos_Status = VOS_STATUS_SUCCESS;
}
return vos_Status;
}
VOS_STATUS wlan_hdd_enter_lowpower(hdd_context_t *pHddCtx)
{
VOS_STATUS vos_Status = VOS_STATUS_E_FAILURE;
if (NULL == pHddCtx)
{
hddLog(VOS_TRACE_LEVEL_ERROR, "HDD context NULL");
return VOS_STATUS_E_FAULT;
}
if (WLAN_MAP_DRIVER_STOP_TO_STANDBY == pHddCtx->cfg_ini->nEnableDriverStop)
{
//Execute standby procedure.
//Executing standby procedure will cause the STA to
//disassociate first and then the chip will be put into standby.
hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "Wlan driver entering Stand by mode");
vos_Status = hdd_enter_standby(pHddCtx);
}
else if (WLAN_MAP_DRIVER_STOP_TO_DEEP_SLEEP ==
pHddCtx->cfg_ini->nEnableDriverStop)
{
//Execute deep sleep procedure
hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "Wlan driver entering "
"deep sleep mode");
//Deep sleep not supported
vos_Status = hdd_enter_standby(pHddCtx);
}
else
{
hddLog(VOS_TRACE_LEVEL_INFO_LOW, "%s: Driver stop is not enabled %d",
__func__, pHddCtx->cfg_ini->nEnableDriverStop);
vos_Status = VOS_STATUS_SUCCESS;
}
return vos_Status;
}
void* wlan_hdd_change_country_code_callback(void *pAdapter)
{
hdd_adapter_t *call_back_pAdapter = pAdapter;
complete(&call_back_pAdapter->change_country_code);
return NULL;
}
static int __iw_set_priv(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
hdd_adapter_t *pAdapter;
char *cmd = NULL;
int cmd_len = wrqu->data.length;
int rc = 0, ret = 0;
VOS_STATUS vos_status = VOS_STATUS_SUCCESS;
hdd_context_t *pHddCtx;
ENTER();
pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
if (NULL == pAdapter)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"mem_alloc_copy_from_user_helper fail");
return -EINVAL;
}
pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
rc = wlan_hdd_validate_context(pHddCtx);
if (0 != rc)
{
return rc;
}
cmd = mem_alloc_copy_from_user_helper(wrqu->data.pointer,
wrqu->data.length);
if (NULL == cmd)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"mem_alloc_copy_from_user_helper fail");
return -ENOMEM;
}
if (ioctl_debug)
{
pr_info("%s: req [%s] len [%d]\n", __func__, cmd, cmd_len);
}
hddLog(VOS_TRACE_LEVEL_INFO_MED,
"%s: ***Received %s cmd from Wi-Fi GUI***", __func__, cmd);
if (strncmp(cmd, "CSCAN", 5) == 0 )
{
if (eHAL_STATUS_SUCCESS != iw_set_cscan(dev, info, wrqu, cmd)) {
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: Error in iw_set_scan!", __func__);
rc = -EINVAL;
}
}
else if( strcasecmp(cmd, "start") == 0 ) {
hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "Start command");
/*Exit from Deep sleep or standby if we get the driver START cmd from android GUI*/
vos_status = wlan_hdd_exit_lowpower(pHddCtx, pAdapter);
if (vos_status == VOS_STATUS_SUCCESS)
{
union iwreq_data wrqu;
char buf[10];
memset(&wrqu, 0, sizeof(wrqu));
wrqu.data.length = strlcpy(buf, "START", sizeof(buf));
wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu, buf);
}
else
{
hddLog(VOS_TRACE_LEVEL_ERROR, "%s: START CMD Status %d", __func__, vos_status);
rc = -EIO;
}
goto done;
}
else if( strcasecmp(cmd, "stop") == 0 )
{
union iwreq_data wrqu;
char buf[10];
hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "Stop command");
wlan_hdd_enter_lowpower(pHddCtx);
memset(&wrqu, 0, sizeof(wrqu));
wrqu.data.length = strlcpy(buf, "STOP", sizeof(buf));
wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu, buf);
goto done;
}
else if (strcasecmp(cmd, "macaddr") == 0)
{
ret = snprintf(cmd, cmd_len, "Macaddr = " MAC_ADDRESS_STR,
MAC_ADDR_ARRAY(pAdapter->macAddressCurrent.bytes));
}
else if (strcasecmp(cmd, "scan-active") == 0)
{
hddLog(LOG1,
FL("making default scan to active"));
pHddCtx->scan_info.scan_mode = eSIR_ACTIVE_SCAN;
ret = snprintf(cmd, cmd_len, "OK");
}
else if (strcasecmp(cmd, "scan-passive") == 0)
{
hddLog(LOG1,
FL("making default scan to passive"));
pHddCtx->scan_info.scan_mode = eSIR_PASSIVE_SCAN;
ret = snprintf(cmd, cmd_len, "OK");
}
else if( strcasecmp(cmd, "scan-mode") == 0 )
{
ret = snprintf(cmd, cmd_len, "ScanMode = %u", pHddCtx->scan_info.scan_mode);
}
else if( strcasecmp(cmd, "linkspeed") == 0 )
{
ret = iw_get_linkspeed(dev, info, wrqu, cmd);
}
else if( strncasecmp(cmd, "rssi", 4) == 0 )
{
ret = iw_get_rssi(dev, info, wrqu, cmd);
}
else if( strncasecmp(cmd, "powermode", 9) == 0 ) {
int mode;
char *ptr;
if (9 < cmd_len)
{
ptr = (char*)(cmd + 9);
}else{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"CMD LENGTH %d is not correct",cmd_len);
kfree(cmd);
return -EINVAL;
}
if (1 != sscanf(ptr,"%d",&mode))
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"powermode input %s is not correct",ptr);
kfree(cmd);
return -EIO;
}
wlan_hdd_enter_bmps(pAdapter, mode);
/*TODO:Set the power mode*/
}
else if (strncasecmp(cmd, "getpower", 8) == 0 ) {
v_U32_t pmc_state;
v_U16_t value;
pmc_state = pmcGetPmcState(WLAN_HDD_GET_HAL_CTX(pAdapter));
if(pmc_state == BMPS) {
value = DRIVER_POWER_MODE_AUTO;
}
else {
value = DRIVER_POWER_MODE_ACTIVE;
}
ret = snprintf(cmd, cmd_len, "powermode = %u", value);
}
else if( strncasecmp(cmd, "btcoexmode", 10) == 0 ) {
hddLog( VOS_TRACE_LEVEL_INFO, "btcoexmode");
/*TODO: set the btcoexmode*/
}
else if( strcasecmp(cmd, "btcoexstat") == 0 ) {
hddLog(VOS_TRACE_LEVEL_INFO, "BtCoex Status");
/*TODO: Return the btcoex status*/
}
else if( strcasecmp(cmd, "rxfilter-start") == 0 ) {
hddLog(VOS_TRACE_LEVEL_INFO, "Rx Data Filter Start command");
/*TODO: Enable Rx data Filter*/
}
else if( strcasecmp(cmd, "rxfilter-stop") == 0 ) {
hddLog(VOS_TRACE_LEVEL_INFO, "Rx Data Filter Stop command");
/*TODO: Disable Rx data Filter*/
}
else if( strcasecmp(cmd, "rxfilter-statistics") == 0 ) {
hddLog( VOS_TRACE_LEVEL_INFO, "Rx Data Filter Statistics command");
/*TODO: rxfilter-statistics*/
}
else if( strncasecmp(cmd, "rxfilter-add", 12) == 0 ) {
hddLog( VOS_TRACE_LEVEL_INFO, "rxfilter-add");
/*TODO: rxfilter-add*/
}
else if( strncasecmp(cmd, "rxfilter-remove",15) == 0 ) {
hddLog( VOS_TRACE_LEVEL_INFO, "rxfilter-remove");
/*TODO: rxfilter-remove*/
}
#ifdef FEATURE_WLAN_SCAN_PNO
else if( strncasecmp(cmd, "pnosetup", 8) == 0 ) {
hddLog( VOS_TRACE_LEVEL_INFO, "pnosetup");
/*TODO: support pnosetup*/
}
else if( strncasecmp(cmd, "pnoforce", 8) == 0 ) {
hddLog( VOS_TRACE_LEVEL_INFO, "pnoforce");
/*TODO: support pnoforce*/
}
else if( strncasecmp(cmd, "rssifilter",10) == 0 ) {
hddLog( VOS_TRACE_LEVEL_INFO, "rssifilter");
vos_status = iw_set_rssi_filter(dev, info, wrqu, cmd, 10);
kfree(cmd);
return (vos_status == VOS_STATUS_SUCCESS) ? 0 : -EINVAL;
}
#endif /*FEATURE_WLAN_SCAN_PNO*/
else if( strncasecmp(cmd, "powerparams",11) == 0 ) {
hddLog( VOS_TRACE_LEVEL_INFO, "powerparams");
vos_status = iw_set_power_params(dev, info, wrqu, cmd, 11);
kfree(cmd);
return (vos_status == VOS_STATUS_SUCCESS) ? 0 : -EINVAL;
}
else if( 0 == strncasecmp(cmd, "CONFIG-TX-TRACKING", 18) ) {
tSirTxPerTrackingParam tTxPerTrackingParam;
char *ptr;
if (18 < cmd_len)
{
ptr = (char*)(cmd + 18);
}else{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"CMD LENGTH %d is not correct",cmd_len);
kfree(cmd);
return -EINVAL;
}
if (4 != sscanf(ptr,"%hhu %hhu %hhu %u",
&(tTxPerTrackingParam.ucTxPerTrackingEnable),
&(tTxPerTrackingParam.ucTxPerTrackingPeriod),
&(tTxPerTrackingParam.ucTxPerTrackingRatio),
&(tTxPerTrackingParam.uTxPerTrackingWatermark)))
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"CONFIG-TX-TRACKING %s input is not correct",ptr);
kfree(cmd);
return -EIO;
}
// parameters checking
// period has to be larger than 0
if (0 == tTxPerTrackingParam.ucTxPerTrackingPeriod)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, "Period input is not correct");
kfree(cmd);
return -EIO;
}
// use default value 5 is the input is not reasonable. in unit of 10%
if ((tTxPerTrackingParam.ucTxPerTrackingRatio > TX_PER_TRACKING_MAX_RATIO) || (0 == tTxPerTrackingParam.ucTxPerTrackingRatio))
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, "Ratio input is not good. use default 5");
tTxPerTrackingParam.ucTxPerTrackingRatio = TX_PER_TRACKING_DEFAULT_RATIO;
}
// default is 5
if (0 == tTxPerTrackingParam.uTxPerTrackingWatermark)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, "Tx Packet number input is not good. use default 5");
tTxPerTrackingParam.uTxPerTrackingWatermark = TX_PER_TRACKING_DEFAULT_WATERMARK;
}
if (eHAL_STATUS_SUCCESS !=
sme_SetTxPerTracking(pHddCtx->hHal,
hdd_tx_per_hit_cb,
(void*)pAdapter, &tTxPerTrackingParam)) {
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, "Set Tx PER Tracking Failed!");
rc = -EIO;
}
}
else {
hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s",
__func__, cmd);
}
done:
/* many of the commands write information back into the command
string using snprintf(). check the return value here in one
place */
if ((ret < 0) || (ret >= cmd_len))
{
/* there was an encoding error or overflow */
rc = -EINVAL;
}
else if (ret > 0)
{
if (copy_to_user(wrqu->data.pointer, cmd, ret))
{
hddLog(VOS_TRACE_LEVEL_ERROR,
"%s: failed to copy data to user buffer", __func__);
kfree(cmd);
return -EFAULT;
}
wrqu->data.length = ret;
}
if (ioctl_debug)
{
pr_info("%s: rsp [%s] len [%d] status %d\n",
__func__, cmd, wrqu->data.length, rc);
}
kfree(cmd);
EXIT();
return rc;
}
static int iw_set_priv(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
int ret;
vos_ssr_protect(__func__);
ret = __iw_set_priv(dev, info, wrqu, extra);
vos_ssr_unprotect(__func__);
return ret;
}
static int __iw_set_nick(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
hdd_adapter_t *pAdapter;
hdd_context_t *pHddCtx;
int ret = 0;
ENTER();
pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
if (NULL == pAdapter)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: Adapter is NULL",__func__);
return -EINVAL;
}
pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
ret = wlan_hdd_validate_context(pHddCtx);
if (0 != ret)
{
return ret;
}
EXIT();
return 0;
}
static int iw_set_nick(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
int ret;
vos_ssr_protect(__func__);
ret = __iw_set_nick(dev, info, wrqu, extra);
vos_ssr_unprotect(__func__);
return ret;
}
static int __iw_get_nick(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
hdd_adapter_t *pAdapter;
hdd_context_t *pHddCtx;
int ret = 0;
ENTER();
pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
if (NULL == pAdapter)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: Adapter is NULL",__func__);
return -EINVAL;
}
pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
ret = wlan_hdd_validate_context(pHddCtx);
if (0 != ret)
{
return ret;
}
EXIT();
return 0;
}
static int iw_get_nick(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
int ret;
vos_ssr_protect(__func__);
ret = __iw_get_nick(dev, info, wrqu, extra);
vos_ssr_unprotect(__func__);
return ret;
}
/* cat /proc/net/wireless invokes this function to get wireless stats */
static struct iw_statistics * __get_wireless_stats(struct net_device *dev)
{
hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
hdd_context_t *pHddCtx;
hdd_station_ctx_t *pHddStaCtx;
v_S7_t snr = 0, rssi = 0;
eHalStatus status = eHAL_STATUS_SUCCESS;
ENTER();
if (NULL == pAdapter)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: Adapter is NULL",__func__);
return NULL;
}
pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
status = wlan_hdd_validate_context(pHddCtx);
if (0 != status)
{
return NULL;
}
pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
if (NULL == pHddStaCtx)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: STA Context is NULL",__func__);
return NULL;
}
if (eConnectionState_Associated == pHddStaCtx->conn_info.connState)
{
wlan_hdd_get_station_stats(pAdapter);
wlan_hdd_get_snr(pAdapter, &snr);
wlan_hdd_get_rssi(pAdapter, &rssi);
vos_mem_zero(&pAdapter->iwStats, sizeof(pAdapter->iwStats));
pAdapter->iwStats.status = 0;
pAdapter->iwStats.qual.qual = snr;
pAdapter->iwStats.qual.level = rssi;
pAdapter->iwStats.qual.noise = rssi - snr;
pAdapter->iwStats.discard.code = 0;
pAdapter->iwStats.discard.retries= 0;
pAdapter->iwStats.miss.beacon = 0;
pAdapter->iwStats.qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
}
else
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
FL("not in associated state: %d"), pHddStaCtx->conn_info.connState);
return NULL;
}
EXIT();
return &(pAdapter->iwStats);
}
static struct iw_statistics *get_wireless_stats(struct net_device *dev)
{
struct iw_statistics *stats;
vos_ssr_protect(__func__);
stats = __get_wireless_stats(dev);
vos_ssr_unprotect(__func__);
return stats;
}
static int __iw_set_encode(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu,char *extra)
{
hdd_adapter_t *pAdapter;
hdd_station_ctx_t *pHddStaCtx;
hdd_wext_state_t *pWextState;
hdd_context_t *pHddCtx;
struct iw_point *encoderq = &(wrqu->encoding);
v_U32_t keyId;
v_U8_t key_length;
eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
v_BOOL_t fKeyPresent = 0;
int i;
eHalStatus status = eHAL_STATUS_SUCCESS;
ENTER();
pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
if (NULL == pAdapter)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: Adapter is NULL",__func__);
return -EINVAL;
}
pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
status = wlan_hdd_validate_context(pHddCtx);
if (0 != status)
{
return status;
}
pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
if (NULL == pWextState)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: pWextState is NULL ",__func__);
return -EINVAL;
}
pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
if (NULL == pHddStaCtx)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: STA Context is NULL",__func__);
return -EINVAL;
}
keyId = encoderq->flags & IW_ENCODE_INDEX;
if(keyId)
{
if(keyId > MAX_WEP_KEYS)
{
return -EINVAL;
}
fKeyPresent = 1;
keyId--;
}
else
{
fKeyPresent = 0;
}
if(wrqu->data.flags & IW_ENCODE_DISABLED)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "****iwconfig wlan0 key off*****");
if(!fKeyPresent) {
for(i=0;i < CSR_MAX_NUM_KEY; i++) {
if(pWextState->roamProfile.Keys.KeyMaterial[i])
pWextState->roamProfile.Keys.KeyLength[i] = 0;
}
}
pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
pWextState->roamProfile.EncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_NONE;
pWextState->roamProfile.mcEncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_NONE;
pHddStaCtx->conn_info.ucEncryptionType = eCSR_ENCRYPT_TYPE_NONE;
pHddStaCtx->conn_info.mcEncryptionType = eCSR_ENCRYPT_TYPE_NONE;
if(eConnectionState_Associated == pHddStaCtx->conn_info.connState)
{
INIT_COMPLETION(pAdapter->disconnect_comp_var);
status = sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId, eCSR_DISCONNECT_REASON_UNSPECIFIED );
if(eHAL_STATUS_SUCCESS == status)
{
long ret;
ret = wait_for_completion_interruptible_timeout(
&pAdapter->disconnect_comp_var,
msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
if (ret <= 0)
hddLog(VOS_TRACE_LEVEL_ERROR,
FL("failed wait on disconnect_comp_var %ld"), ret);
}
}
return status;
}
if (wrqu->data.flags & (IW_ENCODE_OPEN | IW_ENCODE_RESTRICTED))
{
hddLog(VOS_TRACE_LEVEL_INFO, "iwconfig wlan0 key on");
pHddStaCtx->conn_info.authType = (encoderq->flags & IW_ENCODE_RESTRICTED) ? eCSR_AUTH_TYPE_SHARED_KEY : eCSR_AUTH_TYPE_OPEN_SYSTEM;
}
if(wrqu->data.length > 0)
{
hddLog(VOS_TRACE_LEVEL_INFO, "%s : wrqu->data.length : %d",__func__,wrqu->data.length);
key_length = wrqu->data.length;
/* IW_ENCODING_TOKEN_MAX is the value that is set for wrqu->data.length by iwconfig.c when 'iwconfig wlan0 key on' is issued.*/
if(5 == key_length)
{
hddLog(VOS_TRACE_LEVEL_INFO, "%s: Call with WEP40,key_len=%d",__func__,key_length);
if((IW_AUTH_KEY_MGMT_802_1X == pWextState->authKeyMgmt) && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType))
{
encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
}
else
{
encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
}
}
else if(13 == key_length)
{
hddLog(VOS_TRACE_LEVEL_INFO, "%s:Call with WEP104,key_len:%d",__func__,key_length);
if((IW_AUTH_KEY_MGMT_802_1X == pWextState->authKeyMgmt) && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType))
{
encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
}
else
{
encryptionType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
}
}
else
{
hddLog(VOS_TRACE_LEVEL_WARN, "%s: Invalid WEP key length :%d",
__func__, key_length);
return -EINVAL;
}
pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
pWextState->roamProfile.EncryptionType.numEntries = 1;
pWextState->roamProfile.EncryptionType.encryptionType[0] = encryptionType;
pWextState->roamProfile.mcEncryptionType.numEntries = 1;
pWextState->roamProfile.mcEncryptionType.encryptionType[0] = encryptionType;
if((eConnectionState_NotConnected == pHddStaCtx->conn_info.connState) &&
((eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType) ||
(eCSR_AUTH_TYPE_SHARED_KEY == pHddStaCtx->conn_info.authType)))
{
vos_mem_copy(&pWextState->roamProfile.Keys.KeyMaterial[keyId][0],extra,key_length);
pWextState->roamProfile.Keys.KeyLength[keyId] = (v_U8_t)key_length;
pWextState->roamProfile.Keys.defaultIndex = (v_U8_t)keyId;
return status;
}
}
EXIT();
return 0;
}
static int iw_set_encode(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu,char *extra)
{
int ret;
vos_ssr_protect(__func__);
ret = __iw_set_encode(dev, info, wrqu, extra);
vos_ssr_unprotect(__func__);
return ret;
}
static int __iw_get_encodeext(struct net_device *dev,
struct iw_request_info *info,
struct iw_point *dwrq,
char *extra)
{
hdd_adapter_t *pAdapter;
hdd_wext_state_t *pWextState;
tCsrRoamProfile *pRoamProfile;
int keyId;
eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
eCsrAuthType authType = eCSR_AUTH_TYPE_NONE;
int i, ret = 0;
hdd_context_t *pHddCtx;
ENTER();
pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
if (NULL == pAdapter)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: Adapter is NULL",__func__);
return -EINVAL;
}
pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
ret = wlan_hdd_validate_context(pHddCtx);
if (0 != ret)
{
return ret;
}
pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
if (NULL == pWextState)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: pWextState is NULL",__func__);
return -EINVAL;
}
pRoamProfile = &(pWextState->roamProfile);
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]);
}
else
{
dwrq->flags |= IW_ENCODE_DISABLED;
}
for(i=0; i < MAX_WEP_KEYS; i++)
{
if(pRoamProfile->Keys.KeyMaterial[i] == NULL)
{
continue;
}
else
{
break;
}
}
if(MAX_WEP_KEYS == i)
{
dwrq->flags |= IW_ENCODE_NOKEY;
}
else
{
dwrq->flags |= IW_ENCODE_ENABLED;
}
encryptionType = pRoamProfile->EncryptionType.encryptionType[0];
if(eCSR_ENCRYPT_TYPE_NONE == encryptionType)
{
dwrq->flags |= IW_ENCODE_DISABLED;
}
authType = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.authType;
if(IW_AUTH_ALG_OPEN_SYSTEM == authType)
{
dwrq->flags |= IW_ENCODE_OPEN;
}
else
{
dwrq->flags |= IW_ENCODE_RESTRICTED;
}
EXIT();
return 0;
}
static int iw_get_encodeext(struct net_device *dev,
struct iw_request_info *info,
struct iw_point *dwrq,
char *extra)
{
int ret;
vos_ssr_protect(__func__);
ret = __iw_get_encodeext(dev, info, dwrq, extra);
vos_ssr_unprotect(__func__);
return ret;
}
static int __iw_set_encodeext(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
hdd_adapter_t *pAdapter;
hdd_station_ctx_t *pHddStaCtx;
hdd_wext_state_t *pWextState;
hdd_context_t *pHddCtx;
eHalStatus halStatus = eHAL_STATUS_SUCCESS;
tCsrRoamProfile *pRoamProfile;
v_U32_t status = 0;
struct iw_encode_ext *ext = (struct iw_encode_ext*)extra;
v_U8_t groupmacaddr[WNI_CFG_BSSID_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
int key_index;
struct iw_point *encoding = &wrqu->encoding;
tCsrRoamSetKey setKey;
v_U32_t roamId= 0xFF;
VOS_STATUS vos_status;
ENTER();
pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
if (NULL == pAdapter)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: Adapter is NULL",__func__);
return -EINVAL;
}
pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
status = wlan_hdd_validate_context(pHddCtx);
if (0 != status)
{
return status;
}
pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
if (NULL == pHddStaCtx)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: STA Context is NULL",__func__);
return -EINVAL;
}
pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
if (NULL == pWextState)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: pWextState is NULL",__func__);
return -EINVAL;
}
pRoamProfile = &pWextState->roamProfile;
key_index = encoding->flags & IW_ENCODE_INDEX;
if(key_index > 0) {
/*Convert from 1-based to 0-based keying*/
key_index--;
}
if(!ext->key_len) {
/*Set the encrytion type to NONE*/
pRoamProfile->EncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_NONE;
return status;
}
if(eConnectionState_NotConnected == pHddStaCtx->conn_info.connState &&
(IW_ENCODE_ALG_WEP == ext->alg))
{
if(IW_AUTH_KEY_MGMT_802_1X == pWextState->authKeyMgmt) {
VOS_TRACE (VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
("Invalid Configuration:%s"),__func__);
return -EINVAL;
}
else {
/*Static wep, update the roam profile with the keys */
if(ext->key && (ext->key_len <= eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES) &&
key_index < CSR_MAX_NUM_KEY) {
vos_mem_copy(&pRoamProfile->Keys.KeyMaterial[key_index][0],ext->key,ext->key_len);
pRoamProfile->Keys.KeyLength[key_index] = (v_U8_t)ext->key_len;
if(ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
pRoamProfile->Keys.defaultIndex = (v_U8_t)key_index;
}
}
return status;
}
vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
setKey.keyId = key_index;
setKey.keyLength = ext->key_len;
if(ext->key_len <= CSR_MAX_KEY_LEN) {
vos_mem_copy(&setKey.Key[0],ext->key,ext->key_len);
}
if(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
/*Key direction for group is RX only*/
setKey.keyDirection = eSIR_RX_ONLY;
vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
}
else {
setKey.keyDirection = eSIR_TX_RX;
vos_mem_copy(setKey.peerMac,ext->addr.sa_data,WNI_CFG_BSSID_LEN);
}
/*For supplicant pae role is zero*/
setKey.paeRole = 0;
switch(ext->alg)
{
case IW_ENCODE_ALG_NONE:
setKey.encType = eCSR_ENCRYPT_TYPE_NONE;
break;
case IW_ENCODE_ALG_WEP:
setKey.encType = (ext->key_len== 5) ? eCSR_ENCRYPT_TYPE_WEP40:eCSR_ENCRYPT_TYPE_WEP104;
break;
case IW_ENCODE_ALG_TKIP:
{
v_U8_t *pKey = &setKey.Key[0];
setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
vos_mem_zero(pKey, CSR_MAX_KEY_LEN);
/*Supplicant sends the 32bytes key in this order
|--------------|----------|----------|
| Tk1 |TX-MIC | RX Mic |
|--------------|----------|----------|
<---16bytes---><--8bytes--><--8bytes-->
*/
/*Sme expects the 32 bytes key to be in the below order
|--------------|----------|----------|
| Tk1 |RX-MIC | TX Mic |
|--------------|----------|----------|
<---16bytes---><--8bytes--><--8bytes-->
*/
/* Copy the Temporal Key 1 (TK1) */
vos_mem_copy(pKey,ext->key,16);
/*Copy the rx mic first*/
vos_mem_copy(&pKey[16],&ext->key[24],8);
/*Copy the tx mic */
vos_mem_copy(&pKey[24],&ext->key[16],8);
}
break;
case IW_ENCODE_ALG_CCMP:
setKey.encType = eCSR_ENCRYPT_TYPE_AES;
break;
#ifdef FEATURE_WLAN_ESE
#define IW_ENCODE_ALG_KRK 6
case IW_ENCODE_ALG_KRK:
setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
break;
#endif /* FEATURE_WLAN_ESE */
default:
setKey.encType = eCSR_ENCRYPT_TYPE_NONE;
break;
}
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
("%s:cipher_alg:%d key_len[%d] *pEncryptionType :%d"),__func__,(int)ext->alg,(int)ext->key_len,setKey.encType);
#ifdef WLAN_FEATURE_VOWIFI_11R
/* The supplicant may attempt to set the PTK once pre-authentication
is done. Save the key in the UMAC and include it in the ADD
BSS request */
halStatus = sme_FTUpdateKey( WLAN_HDD_GET_HAL_CTX(pAdapter), &setKey);
if ( halStatus == eHAL_STATUS_FT_PREAUTH_KEY_SUCCESS )
{
hddLog(VOS_TRACE_LEVEL_INFO_MED,
"%s: Update PreAuth Key success", __func__);
return 0;
}
else if ( halStatus == eHAL_STATUS_FT_PREAUTH_KEY_FAILED )
{
hddLog(VOS_TRACE_LEVEL_ERROR,
"%s: Update PreAuth Key failed", __func__);
return -EINVAL;
}
#endif /* WLAN_FEATURE_VOWIFI_11R */
pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
vos_status = wlan_hdd_check_ula_done(pAdapter);
if ( vos_status != VOS_STATUS_SUCCESS )
{
VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"[%4d] wlan_hdd_check_ula_done returned ERROR status= %d",
__LINE__, vos_status );
pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
}
halStatus = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),pAdapter->sessionId, &setKey, &roamId );
if ( halStatus != eHAL_STATUS_SUCCESS )
{
VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"[%4d] sme_RoamSetKey returned ERROR status= %d",
__LINE__, halStatus );
pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
}
EXIT();
return halStatus;
}
static int iw_set_encodeext(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
int ret;
vos_ssr_protect(__func__);
ret = __iw_set_encodeext(dev, info, wrqu, extra);
vos_ssr_unprotect(__func__);
return ret;
}
static int __iw_set_retry(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
hdd_adapter_t *pAdapter;
tHalHandle hHal;
hdd_context_t *pHddCtx;
int ret = 0;
ENTER();
pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
if (NULL == pAdapter)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: Adapter is NULL",__func__);
return -EINVAL;
}
pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
ret = wlan_hdd_validate_context(pHddCtx);
if (0 != ret)
{
return ret;
}
hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
if (NULL == hHal)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: Hal Context is NULL",__func__);
return -EINVAL;
}
if(wrqu->retry.value < WNI_CFG_LONG_RETRY_LIMIT_STAMIN ||
wrqu->retry.value > WNI_CFG_LONG_RETRY_LIMIT_STAMAX) {
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, ("Invalid Retry-Limit=%d!!"),wrqu->retry.value);
return -EINVAL;
}
if(wrqu->retry.flags & IW_RETRY_LIMIT) {
if((wrqu->retry.flags & IW_RETRY_LONG))
{
if ( ccmCfgSetInt(hHal, WNI_CFG_LONG_RETRY_LIMIT, wrqu->retry.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_LONG_RETRY_LIMIT"));
return -EIO;
}
}
else if((wrqu->retry.flags & IW_RETRY_SHORT))
{
if ( ccmCfgSetInt(hHal, WNI_CFG_SHORT_RETRY_LIMIT, wrqu->retry.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_SHORT_RETRY_LIMIT"));
return -EIO;
}
}
}
else
{
return -EOPNOTSUPP;
}
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, ("Set Retry-Limit=%d!!"),wrqu->retry.value);
EXIT();
return 0;
}
static int iw_set_retry(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
int ret;
vos_ssr_protect(__func__);
ret = __iw_set_retry(dev, info, wrqu, extra);
vos_ssr_unprotect(__func__);
return ret;
}
static int __iw_get_retry(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
hdd_adapter_t *pAdapter;
hdd_context_t *pHddCtx;
tHalHandle hHal;
v_U32_t retry = 0;
int ret = 0;
ENTER();
pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
if (NULL == pAdapter)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: Adapter is NULL",__func__);
return -EINVAL;
}
pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
ret = wlan_hdd_validate_context(pHddCtx);
if (0 != ret)
{
return ret;
}
hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
if (NULL == hHal)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: Hal Context is NULL",__func__);
return -EINVAL;
}
if((wrqu->retry.flags & IW_RETRY_LONG))
{
wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_LONG;
if ( ccmCfgGetInt(hHal, WNI_CFG_LONG_RETRY_LIMIT, &retry) != eHAL_STATUS_SUCCESS )
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
FL("failed to get ini parameter, WNI_CFG_LONG_RETRY_LIMIT"));
return -EIO;
}
wrqu->retry.value = retry;
}
else if ((wrqu->retry.flags & IW_RETRY_SHORT))
{
wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_SHORT;
if ( ccmCfgGetInt(hHal, WNI_CFG_SHORT_RETRY_LIMIT, &retry) != eHAL_STATUS_SUCCESS )
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
FL("failed to get ini parameter, WNI_CFG_SHORT_RETRY_LIMIT"));
return -EIO;
}
wrqu->retry.value = retry;
}
else {
return -EOPNOTSUPP;
}
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, ("Retry-Limit=%d!!"),retry);
EXIT();
return 0;
}
static int iw_get_retry(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
int ret;
vos_ssr_protect(__func__);
ret = __iw_get_retry(dev, info, wrqu, extra);
vos_ssr_unprotect(__func__);
return ret;
}
static int __iw_set_mlme(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu,
char *extra)
{
hdd_adapter_t *pAdapter;
hdd_context_t *pHddCtx;
hdd_station_ctx_t *pHddStaCtx;
struct iw_mlme *mlme = (struct iw_mlme *)extra;
eHalStatus status = eHAL_STATUS_SUCCESS;
int ret = 0;
ENTER();
pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
if (NULL == pAdapter)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s:Adapter is NULL",__func__);
return -EINVAL;
}
pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
ret = wlan_hdd_validate_context(pHddCtx);
if (0 != ret)
{
return ret;
}
pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
if (NULL == pHddStaCtx)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s:STA context is NULL",__func__);
return -EINVAL;
}
//reason_code is unused. By default it is set to eCSR_DISCONNECT_REASON_UNSPECIFIED
switch (mlme->cmd) {
case IW_MLME_DISASSOC:
case IW_MLME_DEAUTH:
if( pHddStaCtx->conn_info.connState == eConnectionState_Associated )
{
eCsrRoamDisconnectReason reason = eCSR_DISCONNECT_REASON_UNSPECIFIED;
if( mlme->reason_code == HDD_REASON_MICHAEL_MIC_FAILURE )
reason = eCSR_DISCONNECT_REASON_MIC_ERROR;
INIT_COMPLETION(pAdapter->disconnect_comp_var);
status = sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,reason);
if(eHAL_STATUS_SUCCESS == status)
{
long ret;
ret = wait_for_completion_interruptible_timeout(
&pAdapter->disconnect_comp_var,
msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
if (ret <= 0)
hddLog(VOS_TRACE_LEVEL_ERROR,
FL("failed wait on disconnect_comp_var %ld"), ret);
}
else
hddLog(LOGE,"%s %d Command Disassociate/Deauthenticate : csrRoamDisconnect failure returned %d",
__func__, (int)mlme->cmd, (int)status );
/* Resetting authKeyMgmt */
(WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter))->authKeyMgmt = 0;
hddLog(VOS_TRACE_LEVEL_INFO, FL("Disabling queues"));
netif_tx_disable(dev);
netif_carrier_off(dev);
}
else
{
hddLog(LOGE,"%s %d Command Disassociate/Deauthenticate called but station is not in associated state", __func__, (int)mlme->cmd );
}
break;
default:
hddLog(LOGE,"%s %d Command should be Disassociate/Deauthenticate", __func__, (int)mlme->cmd );
return -EINVAL;
}//end of switch
EXIT();
return status;
}
static int iw_set_mlme(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu,
char *extra)
{
int ret;
vos_ssr_protect(__func__);
ret = __iw_set_mlme(dev, info, wrqu, extra);
vos_ssr_unprotect(__func__);
return ret;
}
int wlan_hdd_set_proximity(int set_value, tHalHandle hal)
{
sHwCalValues hwCalValues;
uint16 hwCalTxPower;
uint8 txPwr = TX_PWR_DEF;
hddLog(LOG1, FL("WE_SET_PROXIMITY_ENABLE: %d"), set_value);
if (TRUE == set_value) {
if(vos_nv_read( VNV_HW_CAL_VALUES, &hwCalValues,
NULL, sizeof(sHwCalValues) )
!= VOS_STATUS_SUCCESS) {
return -EINVAL;
}
hwCalTxPower = (uint16)(hwCalValues.calData.hwParam7 >> 16);
hddLog(LOG1, FL("hwCalTxPower:%x nv_data:%x"),
hwCalTxPower, hwCalValues.calData.hwParam7);
txPwr = (int8)(hwCalTxPower & 0x00FF);
txPwr = txPwr/10;
if (txPwr == 0)
txPwr = TX_PWR_DEF;
else if (txPwr < TX_PWR_MIN)
txPwr = TX_PWR_MIN;
else if (txPwr > TX_PWR_MAX)
txPwr = TX_PWR_MAX;
if (sme_SetMaxTxPowerPerBand(eCSR_BAND_24, txPwr, hal) !=
eHAL_STATUS_SUCCESS) {
hddLog(VOS_TRACE_LEVEL_ERROR,
FL("Setting tx power failed for 2.4GHz band %d"), txPwr);
return -EIO;
}
txPwr = (int8)((hwCalTxPower >> 8) & 0x00FF);
txPwr /= 10;
if (txPwr == 0)
txPwr = TX_PWR_DEF;
else if (txPwr < TX_PWR_MIN)
txPwr = TX_PWR_MIN;
else if (txPwr > TX_PWR_MAX)
txPwr = TX_PWR_MAX;
if (sme_SetMaxTxPowerPerBand(eCSR_BAND_5G, txPwr, hal) !=
eHAL_STATUS_SUCCESS) {
hddLog(VOS_TRACE_LEVEL_ERROR,
FL("setting tx power failed for 5GHz band %d"), txPwr);
return -EIO;
}
}
else if(FALSE == set_value) {
if (sme_SetMaxTxPowerPerBand(eCSR_BAND_24, txPwr, hal) !=
eHAL_STATUS_SUCCESS) {
hddLog(VOS_TRACE_LEVEL_ERROR,
FL("Setting tx power failed for 2.4GHz band %d"), txPwr);
return -EIO;
}
if (sme_SetMaxTxPowerPerBand(eCSR_BAND_5G, txPwr, hal) !=
eHAL_STATUS_SUCCESS) {
hddLog(VOS_TRACE_LEVEL_ERROR,
FL("setting tx power failed for 5GHz band %d"), txPwr);
return -EIO;
}
}
else {
return -EINVAL;
}
return eHAL_STATUS_SUCCESS;
}
static int hdd_set_dynamic_aggregation(int value, hdd_adapter_t *adapter)
{
int ret = 0;
tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
tDelBaParams del_session;
del_session.session_id = adapter->sessionId;
hddLog(LOG1, FL("WLAN_SET_DYNNAMIC_AGGREGATION: %d"), value);
if ((value == DISABLE_AGGREGATION) || (value == ENABLE_AGGREGATION))
{
ret = ccmCfgSetInt(hal, WNI_CFG_ENABLE_TX_RX_AGGREGATION,
value,NULL, eANI_BOOLEAN_FALSE);
if (ret != eHAL_STATUS_SUCCESS)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
FL("failed to set ini parameter, WNI_CFG_ENABLE_TX_RX_AGGREGATION"));
return -EIO;
}
} else {
hddLog(VOS_TRACE_LEVEL_ERROR,
FL("Invalid command input"));
return -EINVAL;
}
ret = sme_del_sta_ba_session_req(hal, del_session);
if (ret != VOS_STATUS_SUCCESS) {
hddLog(VOS_TRACE_LEVEL_ERROR, FL("send ba session req fail"));
return -EINVAL;
}
EXIT();
return ret;
}
static int
wlan_hdd_sta_mon_op(hdd_context_t *hdd_ctx, uint32_t set_value,
hdd_adapter_t *mon_adapter, hdd_mon_ctx_t *mon_ctx)
{
hdd_station_ctx_t *sta_ctx;
VOS_STATUS disable_bmps_status;
hdd_adapter_t *sta_adapter;
v_CONTEXT_t vos_ctx = (WLAN_HDD_GET_CTX(mon_adapter))->pvosContext;
if (!test_bit(DEVICE_IFACE_OPENED, &mon_adapter->event_flags)) {
hddLog(LOGE, FL("Monitor Interface is not OPENED"));
return -EINVAL;
}
if (set_value == MON_MODE_STOP) {
if (wlan_hdd_check_monitor_state(hdd_ctx))
return 0;
return -EINVAL;
}
sta_adapter = hdd_get_adapter(hdd_ctx, WLAN_HDD_INFRA_STATION);
if (!sta_adapter) {
hddLog(LOGE, FL("No Station adapter"));
return -EINVAL;
}
sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(sta_adapter);
if (!sta_ctx || !hdd_connIsConnected(sta_ctx)) {
hddLog(LOGE, FL("STA is not connected"));
return -EINVAL;
}
if (hdd_isConnectionInProgress(hdd_ctx, NULL, NULL)) {
hddLog(LOGE, FL("Roaming or set-key is in progress"));
return -EBUSY;
}
hdd_disable_roaming(hdd_ctx);
hddLog(LOG1, FL("Disable BMPS"));
disable_bmps_status = hdd_disable_bmps_imps(hdd_ctx,
WLAN_HDD_INFRA_STATION);
if (disable_bmps_status != VOS_STATUS_SUCCESS) {
hddLog(LOGE, FL("Cannot start monitor mode"));
hdd_restore_roaming(hdd_ctx);
return -EINVAL;
}
mon_ctx->ChannelNo = sta_ctx->conn_info.operationChannel;
/*
* In STA + Mon mode, firmware should not consider ChannelBW
*/
mon_ctx->ChannelBW = 0;
mon_ctx->crcCheckEnabled = 0;
wlan_hdd_mon_set_typesubtype(mon_ctx, 100);
mon_ctx->is80211to803ConReq = 0;
WLANTL_SetIsConversionReq(vos_ctx, 0);
mon_adapter->dev->type = ARPHRD_IEEE80211_RADIOTAP;
mon_ctx->state = MON_MODE_START;
return 0;
}
/* set param sub-ioctls */
static int __iw_mon_setint_getnone(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
hdd_adapter_t *adapter;
hdd_context_t *hdd_ctx;
hdd_mon_ctx_t *mon_ctx;
int *value = (int *)extra;
int sub_cmd = value[0];
int set_value = value[1];
int ret = 0; /* success */
tVOS_CONCURRENCY_MODE concurrency_mode;
ENTER();
adapter = WLAN_HDD_GET_PRIV_PTR(dev);
if (!adapter || adapter->device_mode != WLAN_HDD_MONITOR)
return -EINVAL;
hdd_ctx = WLAN_HDD_GET_CTX(adapter);
ret = wlan_hdd_validate_context(hdd_ctx);
if (ret)
return ret;
concurrency_mode = hdd_ctx->concurrency_mode;
if (concurrency_mode != VOS_STA_MON) {
hddLog(LOGE, "invalid concurrency mode %d", concurrency_mode);
return -EINVAL;
}
switch(sub_cmd) {
case WE_SET_MONITOR_STATE:
{
void *cookie;
struct hdd_request *request;
static const struct hdd_request_params params = {
.priv_size = 0,
.timeout_ms = MON_MODE_MSG_TIMEOUT,
};
mon_ctx = WLAN_HDD_GET_MONITOR_CTX_PTR(adapter);
if(!mon_ctx) {
hddLog(LOGE, "Monitor Context NULL");
ret = -EIO;
break;
}
if (mon_ctx->state == set_value) {
hddLog(LOGE, FL("already in same mode curr_mode:%d req_mode: %d"),
mon_ctx->state, set_value);
break;
}
ret = wlan_hdd_sta_mon_op(hdd_ctx, set_value,
adapter,mon_ctx);
if (ret)
break;
mon_ctx->state = set_value;
request = hdd_request_alloc(&params);
if (!request) {
hddLog(VOS_TRACE_LEVEL_ERROR, FL("Request allocation failure"));
ret = -ENOMEM;
break;
}
cookie = hdd_request_cookie(request);
if (wlan_hdd_mon_postMsg(cookie, mon_ctx,
hdd_mon_post_msg_cb)
!= VOS_STATUS_SUCCESS) {
hddLog(LOGE, FL("failed to post MON MODE REQ"));
mon_ctx->state =
(mon_ctx->state==MON_MODE_START) ?
MON_MODE_STOP : MON_MODE_START;
ret = -EIO;
} else {
ret = hdd_request_wait_for_response(request);
if (ret){
hddLog(LOGE, FL("failed to wait on monitor mode completion %d"),
ret);
} else if (mon_ctx->state == MON_MODE_STOP) {
hddLog(LOG1, FL("Enable BMPS"));
hdd_enable_bmps_imps(hdd_ctx);
hdd_restore_roaming(hdd_ctx);
}
}
hdd_request_put(request);
}
break;
default:
{
hddLog(LOGE, "Invalid IOCTL setvalue command %d value %d",
sub_cmd, set_value);
}
break;
}
EXIT();
return ret;
}
/* set param sub-ioctls */
static int __iw_setint_getnone(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
hdd_adapter_t *pAdapter;
tHalHandle hHal = NULL;
hdd_wext_state_t *pWextState;
hdd_context_t *pHddCtx;
hdd_mon_ctx_t *pMonCtx = NULL;
int *value = (int *)extra;
int sub_cmd = value[0];
int set_value = value[1];
int ret = 0; /* success */
int enable_pbm, enable_mp;
#ifdef CONFIG_HAS_EARLYSUSPEND
v_U8_t nEnableSuspendOld;
#endif
void *cookie;
struct hdd_request *request;
ENTER();
pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
if (NULL == pAdapter)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: Adapter is NULL",__func__);
return -EINVAL;
}
pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
ret = wlan_hdd_validate_context(pHddCtx);
if (0 != ret)
{
return ret;
}
if ( VOS_MONITOR_MODE != hdd_get_conparam())
{
/* In monitor mode hHal is NULL */
hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
if (NULL == hHal)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: Hal Context is NULL",__func__);
return -EINVAL;
}
pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
if (NULL == pWextState)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: pWextState is NULL",__func__);
return -EINVAL;
}
INIT_COMPLETION(pWextState->completion_var);
}
switch(sub_cmd)
{
case WE_SET_11D_STATE:
{
tSmeConfigParams smeConfig;
memset(&smeConfig, 0x00, sizeof(smeConfig));
if(((ENABLE_11D == set_value) || (DISABLE_11D == set_value)) &&
(hHal)) {
sme_GetConfigParam(hHal,&smeConfig);
smeConfig.csrConfig.Is11dSupportEnabled = (v_BOOL_t)set_value;
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, ("11D state=%d!!"),smeConfig.csrConfig.Is11dSupportEnabled);
sme_UpdateConfig(hHal,&smeConfig);
}
else {
return -EINVAL;
}
break;
}
case WE_WOWL:
{
switch (set_value)
{
case 0x00:
hdd_exit_wowl(pAdapter, eWOWL_EXIT_USER);
break;
case 0x01:
case 0x02:
case 0x03:
enable_mp = (set_value & 0x01) ? 1 : 0;
enable_pbm = (set_value & 0x02) ? 1 : 0;
hddLog(LOGE, "magic packet ? = %s pattern byte matching ? = %s",
(enable_mp ? "YES":"NO"), (enable_pbm ? "YES":"NO"));
hdd_enter_wowl(pAdapter, enable_mp, enable_pbm);
break;
default:
hddLog(LOGE, "Invalid arg %d in WE_WOWL IOCTL", set_value);
ret = -EINVAL;
break;
}
break;
}
case WE_SET_POWER:
{
if (wlan_hdd_check_monitor_state(pHddCtx)) {
hddLog(LOGE, FL("setPower not allowed in STA + MON"));
ret = -EOPNOTSUPP;
break;
}
switch (set_value)
{
case 0: //Full Power
{
eHalStatus status = eHAL_STATUS_FAILURE;
static const struct hdd_request_params params = {
.priv_size = 0,
.timeout_ms = WLAN_WAIT_TIME_POWER,
};
if (NULL == hHal)
return -EINVAL;
request = hdd_request_alloc(&params);
if (!request) {
hddLog(VOS_TRACE_LEVEL_ERROR,
FL("Request allocation failure"));
return VOS_STATUS_E_NOMEM;
}
cookie = hdd_request_cookie(request);
status = sme_RequestFullPower(WLAN_HDD_GET_HAL_CTX(pAdapter),
iw_power_callback_func, cookie,
eSME_FULL_PWR_NEEDED_BY_HDD);
if (eHAL_STATUS_PMC_PENDING == status)
{
ret = hdd_request_wait_for_response(request);
if (ret) {
hddLog(VOS_TRACE_LEVEL_ERROR,
FL("SME timeout while requesting bmps"));
}
}
/*
* either we never sent a request, we sent a request and
* received a response or we sent a request and timed out.
* Regardless we are done with the request.
*/
hdd_request_put(request);
hddLog(LOGE, "iwpriv Full Power completed");
break;
}
case 1: //Enable BMPS
if (hHal)
sme_EnablePowerSave(hHal, ePMC_BEACON_MODE_POWER_SAVE);
else
ret = -EINVAL;
break;
case 2: //Disable BMPS
if (hHal)
sme_DisablePowerSave(hHal, ePMC_BEACON_MODE_POWER_SAVE);
else
ret = -EINVAL;
break;
case 3: //Request Bmps
{
eHalStatus status = eHAL_STATUS_FAILURE;
static const struct hdd_request_params params = {
.priv_size = 0,
.timeout_ms = WLAN_WAIT_TIME_POWER,
};
if (NULL == hHal)
return -EINVAL;
request = hdd_request_alloc(&params);
if (!request) {
hddLog(VOS_TRACE_LEVEL_ERROR,
FL("Request allocation failure"));
return VOS_STATUS_E_NOMEM;
}
cookie = hdd_request_cookie(request);
status = sme_RequestBmps(WLAN_HDD_GET_HAL_CTX(pAdapter),
iw_power_callback_func, cookie);
if (eHAL_STATUS_PMC_PENDING == status)
{
ret = hdd_request_wait_for_response(request);
if (ret) {
hddLog(VOS_TRACE_LEVEL_ERROR,
FL("SME timeout while requesting fullpower"));
}
}
/*
* either we never sent a request, we sent a request and
* received a response or we sent a request and timed out.
* Regardless we are done with the request.
*/
hdd_request_put(request);
hddLog(LOGE, "iwpriv Request BMPS completed");
break;
}
case 4: //Enable IMPS
if (hHal)
sme_EnablePowerSave(hHal, ePMC_IDLE_MODE_POWER_SAVE);
else
ret = -EINVAL;
break;
case 5: //Disable IMPS
if (hHal)
sme_DisablePowerSave(hHal, ePMC_IDLE_MODE_POWER_SAVE);
else
ret = -EINVAL;
break;
case 6: //Enable Standby
if (hHal)
sme_EnablePowerSave(hHal, ePMC_STANDBY_MODE_POWER_SAVE);
else
ret = -EINVAL;
break;
case 7: //Disable Standby
if (hHal)
sme_DisablePowerSave(hHal, ePMC_STANDBY_MODE_POWER_SAVE);
else
ret = -EINVAL;
break;
case 8: //Request Standby
#ifdef CONFIG_HAS_EARLYSUSPEND
#endif
break;
case 9: //Start Auto Bmps Timer
if (hHal)
sme_StartAutoBmpsTimer(hHal);
else
ret = -EINVAL;
break;
case 10://Stop Auto BMPS Timer
if (hHal)
sme_StopAutoBmpsTimer(hHal);
else
ret = -EINVAL;
break;
#ifdef CONFIG_HAS_EARLYSUSPEND
case 11://suspend to standby
#ifdef CONFIG_HAS_EARLYSUSPEND
nEnableSuspendOld = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->nEnableSuspend;
(WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->nEnableSuspend = 1;
(WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->nEnableSuspend = nEnableSuspendOld;
#endif
break;
case 12://suspend to deep sleep
#ifdef CONFIG_HAS_EARLYSUSPEND
nEnableSuspendOld = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->nEnableSuspend;
(WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->nEnableSuspend = 2;
(WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->nEnableSuspend = nEnableSuspendOld;
#endif
break;
case 13://resume from suspend
#ifdef CONFIG_HAS_EARLYSUSPEND
#endif
break;
#endif
default:
hddLog(LOGE, "Invalid arg %d in WE_SET_POWER IOCTL", set_value);
ret = -EINVAL;
break;
}
break;
}
case WE_SET_MAX_ASSOC:
{
if ((WNI_CFG_ASSOC_STA_LIMIT_STAMIN > set_value) ||
(WNI_CFG_ASSOC_STA_LIMIT_STAMAX < set_value) ||
(NULL == hHal))
{
ret = -EINVAL;
}
else if ( ccmCfgSetInt(hHal, WNI_CFG_ASSOC_STA_LIMIT,
set_value, NULL, eANI_BOOLEAN_FALSE)
!= eHAL_STATUS_SUCCESS )
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
FL("failed to set ini parameter, WNI_CFG_ASSOC_STA_LIMIT"));
ret = -EIO;
}
break;
}
case WE_SET_SAP_AUTO_CHANNEL_SELECTION:
{
if( 0 == set_value )
{
(WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->apAutoChannelSelection = 0;
}
else if ( 1 == set_value )
{
(WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->apAutoChannelSelection = 1;
}
else
{
hddLog(LOGE, "Invalid arg %d in WE_SET_SAP_AUTO_CHANNEL_SELECTION IOCTL", set_value);
ret = -EINVAL;
}
break;
}
case WE_SET_DATA_INACTIVITY_TO:
{
if (NULL == hHal)
return -EINVAL;
if ((set_value < CFG_DATA_INACTIVITY_TIMEOUT_MIN) ||
(set_value > CFG_DATA_INACTIVITY_TIMEOUT_MAX) ||
(ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
WNI_CFG_PS_DATA_INACTIVITY_TIMEOUT,
set_value,
NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE))
{
hddLog(LOGE,"Failure: Could not pass on "
"WNI_CFG_PS_DATA_INACTIVITY_TIMEOUT configuration info "
"to CCM");
ret = -EINVAL;
}
break;
}
case WE_SET_MAX_TX_POWER:
{
tSirMacAddr bssid = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
tSirMacAddr selfMac = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
if (NULL == hHal)
return -EINVAL;
hddLog(VOS_TRACE_LEVEL_INFO, "%s: Setting maximum tx power %d dBm",
__func__, set_value);
if( sme_SetMaxTxPower(hHal, bssid, selfMac, set_value) !=
eHAL_STATUS_SUCCESS )
{
hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Setting maximum tx power failed",
__func__);
return -EIO;
}
break;
}
case WE_SET_MAX_TX_POWER_2_4:
{
if (NULL == hHal)
return -EINVAL;
hddLog(VOS_TRACE_LEVEL_INFO,
"%s: Setting maximum tx power %d dBm for 2.4 GHz band",
__func__, set_value);
if (sme_SetMaxTxPowerPerBand(eCSR_BAND_24, set_value, hHal) !=
eHAL_STATUS_SUCCESS)
{
hddLog(VOS_TRACE_LEVEL_ERROR,
"%s: Setting maximum tx power failed for 2.4 GHz band",
__func__);
return -EIO;
}
break;
}
case WE_SET_MAX_TX_POWER_5_0:
{
if (NULL == hHal)
return -EINVAL;
hddLog(VOS_TRACE_LEVEL_INFO,
"%s: Setting maximum tx power %d dBm for 5.0 GHz band",
__func__, set_value);
if (sme_SetMaxTxPowerPerBand(eCSR_BAND_5G, set_value, hHal) !=
eHAL_STATUS_SUCCESS)
{
hddLog(VOS_TRACE_LEVEL_ERROR,
"%s: Setting maximum tx power failed for 5.0 GHz band",
__func__);
return -EIO;
}
break;
}
case WE_SET_HIGHER_DTIM_TRANSITION:
{
if(!((set_value == eANI_BOOLEAN_FALSE) ||
(set_value == eANI_BOOLEAN_TRUE)))
{
hddLog(LOGE, "Dynamic DTIM Incorrect data:%d", set_value);
ret = -EINVAL;
}
else
{
if(pAdapter->higherDtimTransition != set_value)
{
pAdapter->higherDtimTransition = set_value;
hddLog(LOG1, "%s: higherDtimTransition set to :%d", __func__, pAdapter->higherDtimTransition);
}
}
break;
}
case WE_SET_TM_LEVEL:
{
hdd_context_t *hddCtxt = WLAN_HDD_GET_CTX(pAdapter);
hddLog(VOS_TRACE_LEVEL_INFO, "Set Thermal Mitigation Level %d", (int)set_value);
hddDevTmLevelChangedHandler(hddCtxt->parent_dev, set_value);
break;
}
case WE_ENABLE_STRICT_FCC_REG:
{
hdd_context_t *hddCtxt = WLAN_HDD_GET_CTX(pAdapter);
struct wiphy *wiphy = NULL;
long lrc;
int status;
wiphy = hddCtxt->wiphy;
if(wiphy == NULL)
{
hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy is NULL ", __func__);
break;
}
init_completion(&hddCtxt->wiphy_channel_update_event);
hddCtxt->nEnableStrictRegulatoryForFCC = set_value;
status = regulatory_hint(wiphy, "00");
if(status < 0)
{
hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failure in setting regulatory rule ", __func__);
break;
}
/* Wait for completion */
lrc = wait_for_completion_interruptible_timeout(&hddCtxt->wiphy_channel_update_event,
msecs_to_jiffies(WLAN_WAIT_TIME_CHANNEL_UPDATE));
if (lrc <= 0)
{
hddLog(VOS_TRACE_LEVEL_ERROR,"%s: SME %s while setting strict FCC regulatory rule ",
__func__, (0 == lrc) ? "Timeout" : "Interrupt");
return (0 == lrc) ? -ETIMEDOUT : -EINTR;
}
hddLog(VOS_TRACE_LEVEL_INFO,"%s: SUCCESS in setting strict FCC regulatory rule", __func__);
break;
}
case WE_SET_DEBUG_LOG:
{
hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
pHddCtx->cfg_ini->gEnableDebugLog = set_value;
if (hHal)
sme_UpdateConnectDebug(pHddCtx->hHal, set_value);
else
ret = -1;
break;
}
#ifdef FEATURE_WLAN_TDLS
case WE_SET_TDLS_OFF_CHAN:
{
hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: Tdls offchannel num %d",
__func__, set_value);
ret = iw_set_tdlsoffchannel(pHddCtx, set_value);
break;
}
case WE_SET_TDLS_SEC_OFF_CHAN_OFFSET:
{
hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: Tdls sec offchan offset %d",
__func__, set_value);
ret = iw_set_tdlssecoffchanneloffset(pHddCtx, set_value);
break;
}
case WE_SET_TDLS_OFF_CHAN_MODE:
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: Tdls offchannel mode %d",
__func__, set_value);
ret = iw_set_tdlsoffchannelmode(pAdapter, set_value);
break;
}
#endif
case WE_SET_SCAN_BAND_PREFERENCE:
{
tSmeConfigParams smeConfig;
memset(&smeConfig, 0x00, sizeof(smeConfig));
if(pAdapter->device_mode != WLAN_HDD_INFRA_STATION) {
ret = -EINVAL;
break;
}
hddLog(LOG1, "WE_SET_BAND_PREFERRENCE val %d ", set_value);
if ((eCSR_BAND_ALL == set_value ||
eCSR_BAND_24 == set_value || eCSR_BAND_5G == set_value) &&
(hHal)) {
sme_GetConfigParam(hHal, &smeConfig);
smeConfig.csrConfig.scanBandPreference = set_value;
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
"set band scan preference = %d\n",
smeConfig.csrConfig.scanBandPreference);
sme_UpdateConfig(hHal, &smeConfig);
}
else {
ret = -EINVAL;
}
break;
}
/* The WE_SET_MIRACAST_VENDOR_CONFIG IOCTL should be set before the
* connection happens so that the params can take effect during
* association. Also this should not be used in STA+p2p concurrency
* as the param will also effect the STA mode.
*/
case WE_SET_MIRACAST_VENDOR_CONFIG:
{
hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
hddLog(LOG1, FL(
"Set Miracast vendor tuning %d"), set_value);
if (NULL == hHal)
return -EINVAL;
if (1 == set_value || 0 == set_value)
{
if (eHAL_STATUS_SUCCESS != sme_SetMiracastVendorConfig(pHddCtx->hHal,
pHddCtx->cfg_ini->numBuffAdvert, set_value))
{
hddLog( LOGE, FL("set vendor miracast config failed"));
ret = -EIO;
}
}
else
{
hddLog(LOGE,
FL("Invalid value %d in WE_SET_MIRACAST_VENDOR_CONFIG IOCTL"), set_value);
ret = -EINVAL;
}
break;
}
case WE_GET_FRAME_LOG:
{
if (wlan_hdd_get_frame_logs(pAdapter, set_value)
!= VOS_STATUS_SUCCESS)
{
ret = -EINVAL;
}
break;
}
case WE_SET_TDLS_2040_BSS_COEXISTENCE:
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
"%s: TDLS_2040_BSS_COEXISTENCE %d", __func__, set_value);
if ((set_value == 0 || set_value == 1) && (hHal))
{
sme_SetTdls2040BSSCoexistence(WLAN_HDD_GET_HAL_CTX(pAdapter),
set_value);
}
else
ret = -EINVAL;
break;
}
/* Bit mask value to enable RTS/CTS for different modes
* for 2.4 GHz, HT20 - 0x0001, for 2.4 GHz, HT40 - 0x0002
* for 2.4 GHz, VHT20 - 0x0004, for 2.4 GHz, VHT40 - 0x0008
* for 5 GHz, HT20 - 0x0100, for 5 GHz, HT40 - 0x0200
* for 5 GHz, VHT20 - 0x0400, for 5 GHz, VHT40 - 0x0800
* for 5 GHz, VHT80 - 0x1000
*/
case WE_SET_RTS_CTS_HTVHT:
{
hddLog( LOG1, FL("WE_SET_RTS_CTS_HTVHT set value %d"), set_value);
if (NULL == hHal)
return -EINVAL;
if (eHAL_STATUS_SUCCESS !=
sme_SetRtsCtsHtVht( pHddCtx->hHal, set_value))
{
hddLog( LOGE, FL("set WE_SET_RTS_CTS_HTVHT failed"));
ret = -EINVAL;
}
break;
}
case WE_SET_MONITOR_STATE:
{
tVOS_CON_MODE mode = hdd_get_conparam();
int ret;
void *cookie;
struct hdd_request *request;
static const struct hdd_request_params params = {
.priv_size = 0,
.timeout_ms = MON_MODE_MSG_TIMEOUT,
};
if( VOS_MONITOR_MODE != mode)
{
hddLog(LOGE, "invalid mode %d", mode);
ret = -EIO;
break;
}
pMonCtx = WLAN_HDD_GET_MONITOR_CTX_PTR(pAdapter);
if( pMonCtx == NULL )
{
hddLog(LOGE, "Monitor Context NULL");
ret = -EIO;
break;
}
if (pMonCtx->state == set_value)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
FL("already in same mode curr_mode:%d req_mode: %d"),
pMonCtx->state, set_value);
break;
}
pMonCtx->state = set_value;
request = hdd_request_alloc(&params);
if (!request) {
hddLog(VOS_TRACE_LEVEL_ERROR, FL("Request allocation failure"));
ret = -ENOMEM;
break;
}
cookie = hdd_request_cookie(request);
if (VOS_STATUS_SUCCESS !=
wlan_hdd_mon_postMsg(cookie, pMonCtx,
hdd_mon_post_msg_cb)) {
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
FL("failed to post MON MODE REQ"));
pMonCtx->state = (pMonCtx->state==MON_MODE_START)?
MON_MODE_STOP : MON_MODE_START;
ret = -EIO;
} else {
ret = hdd_request_wait_for_response(request);
if (ret) {
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
FL("failed to wait on monitor mode completion %d"),
ret);
}
}
hdd_request_put(request);
break;
}
case WE_SET_PKT_STATS_ENABLE_DISABLE:
{
hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
tAniWifiStartLog start_log;
if (!pHddCtx->cfg_ini->wlanPerPktStatsLogEnable ||
!vos_isPktStatsEnabled())
{
hddLog(LOGE, FL("per pkt stats not enabled"));
return -EINVAL;
}
hddLog(LOG1, FL("Set Pkt Stats %d"), set_value);
if (1 == set_value || 0 == set_value)
{
start_log.ringId = RING_ID_PER_PACKET_STATS;
start_log.flag = 0;
if (set_value)
start_log.verboseLevel = WLAN_LOG_LEVEL_ACTIVE;
else
start_log.verboseLevel = WLAN_LOG_LEVEL_OFF;
vos_set_ring_log_level(start_log.ringId, start_log.verboseLevel);
}
else
{
hddLog(LOGE,
FL("Invalid value %d in WE_SET_PKT_STATS_ENABLE_DISABLE IOCTL"),
set_value);
ret = -EINVAL;
}
break;
}
case WE_SET_PROXIMITY_ENABLE:
{
if (NULL == hHal)
return -EINVAL;
ret = wlan_hdd_set_proximity(set_value, hHal);
break;
}
case WE_CAP_TSF:
{
if (NULL == hHal)
return -EINVAL;
ret = hdd_capture_tsf(pAdapter, (uint32_t *)&set_value, 1);
break;
}
case WE_SET_MODULATED_DTIM:
{
if ((set_value < CFG_ENABLE_MODULATED_DTIM_MIN) ||
(set_value > CFG_ENABLE_MODULATED_DTIM_MAX)) {
hddLog(LOGE, FL("Invalid value %d in gEnableModuleDTIM"),
set_value);
return -EINVAL;
} else {
ret = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->
enableModulatedDTIM = set_value;
}
}
case WLAN_SET_DYNNAMIC_AGGREGATION:
{
if (NULL == hHal)
return -EINVAL;
ret = hdd_set_dynamic_aggregation(set_value, pAdapter);
break;
}
default:
{
hddLog(LOGE, "Invalid IOCTL setvalue command %d value %d",
sub_cmd, set_value);
break;
}
}
EXIT();
return ret;
}
static int iw_setint_getnone(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
int ret;
vos_ssr_protect(__func__);
ret = __iw_setint_getnone(dev, info, wrqu, extra);
vos_ssr_unprotect(__func__);
return 0;
}
static
int iw_mon_setint_getnone(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
int ret;
vos_ssr_protect(__func__);
ret = __iw_mon_setint_getnone(dev, info, wrqu, extra);
vos_ssr_unprotect(__func__);
return 0;
}
/* set param sub-ioctls */
static int __iw_setchar_getnone(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
VOS_STATUS vstatus;
int sub_cmd;
int ret = 0; /* success */
char *pBuffer = NULL;
hdd_adapter_t *pAdapter;
hdd_context_t *pHddCtx;
#ifdef WLAN_FEATURE_VOWIFI
hdd_config_t *pConfig;
#endif /* WLAN_FEATURE_VOWIFI */
struct iw_point s_priv_data;
tSirpkt80211 *pkt;
ENTER();
if (!capable(CAP_NET_ADMIN))
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
FL("permission check failed"));
return -EPERM;
}
pAdapter = (netdev_priv(dev));
if (NULL == pAdapter)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: Adapter is NULL",__func__);
return -EINVAL;
}
pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
ret = wlan_hdd_validate_context(pHddCtx);
if (0 != ret)
{
return ret;
}
#ifdef WLAN_FEATURE_VOWIFI
pConfig = pHddCtx->cfg_ini;
#endif
/* helper function to get iwreq_data with compat handling. */
if (hdd_priv_get_data(&s_priv_data, wrqu))
{
return -EINVAL;
}
/* make sure all params are correctly passed to function */
if ((NULL == s_priv_data.pointer) || (0 == s_priv_data.length))
{
return -EINVAL;
}
sub_cmd = s_priv_data.flags;
/* ODD number is used for set, copy data using copy_from_user */
pBuffer = mem_alloc_copy_from_user_helper(s_priv_data.pointer,
s_priv_data.length);
if (NULL == pBuffer)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"mem_alloc_copy_from_user_helper fail");
return -ENOMEM;
}
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
"%s: Received length %d", __func__, s_priv_data.length);
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
"%s: Received data %s", __func__, pBuffer);
switch(sub_cmd)
{
case WE_WOWL_ADD_PTRN:
if (wlan_hdd_check_monitor_state(pHddCtx)) {
hddLog(LOGE, FL("wowlAddPtrn not allowed in STA + MON"));
ret = -EOPNOTSUPP;
break;
}
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "ADD_PTRN");
hdd_add_wowl_ptrn(pAdapter, pBuffer);
break;
case WE_WOWL_DEL_PTRN:
if (wlan_hdd_check_monitor_state(pHddCtx)) {
hddLog(LOGE, FL("wowlDelPtrn not allowed in STA + MON"));
ret = -EOPNOTSUPP;
break;
}
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "DEL_PTRN");
hdd_del_wowl_ptrn(pAdapter, pBuffer);
break;
#if defined WLAN_FEATURE_VOWIFI
case WE_NEIGHBOR_REPORT_REQUEST:
{
tRrmNeighborReq neighborReq;
tRrmNeighborRspCallbackInfo callbackInfo;
if (pConfig->fRrmEnable)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "Neighbor Request");
neighborReq.no_ssid = (s_priv_data.length - 1) ? false : true ;
if( !neighborReq.no_ssid )
{
neighborReq.ssid.length = (s_priv_data.length - 1) > 32 ? 32 : (s_priv_data.length - 1) ;
vos_mem_copy( neighborReq.ssid.ssId, pBuffer, neighborReq.ssid.length );
}
callbackInfo.neighborRspCallback = NULL;
callbackInfo.neighborRspCallbackContext = NULL;
callbackInfo.timeout = 5000; //5 seconds
sme_NeighborReportRequest( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId, &neighborReq, &callbackInfo );
}
else
{
hddLog(LOGE, "%s: Ignoring neighbor request as RRM is not enabled", __func__);
ret = -EINVAL;
}
}
break;
#endif
case WE_SET_AP_WPS_IE:
hddLog( LOGE, "Received WE_SET_AP_WPS_IE" );
sme_updateP2pIe( WLAN_HDD_GET_HAL_CTX(pAdapter), pBuffer, s_priv_data.length );
break;
case WE_SET_CONFIG:
vstatus = hdd_execute_config_command(pHddCtx, pBuffer);
if (VOS_STATUS_SUCCESS != vstatus)
{
ret = -EINVAL;
}
break;
case WE_SET_ENCRYPT_MSG:
pkt = vos_mem_malloc(sizeof(tSirpkt80211));
if (NULL == pkt)
{
hddLog(VOS_TRACE_LEVEL_ERROR,
"%s: vos_mem_alloc failed", __func__);
ret = -ENOMEM;
break;
}
memset(pkt, 0, sizeof(tSirpkt80211));
if (FALSE == sme_IsFeatureSupportedByFW(DISA)) {
hddLog(VOS_TRACE_LEVEL_ERROR,
FL("Firmware is not DISA capable"));
ret = -EINVAL;
vos_mem_free(pkt);
break;
}
parse_Bufferforpkt(pkt, pBuffer, wrqu->data.length);
ret = sme_Encryptmsgsend(pHddCtx->hHal, (u8 *)pkt,
sizeof(tSirpkt80211), hdd_encrypt_msg_cb);
if (eHAL_STATUS_SUCCESS != ret) {
hddLog(VOS_TRACE_LEVEL_ERROR,
FL("SENDEncryptMSG: fail to post WDA cmd"));
ret = -EINVAL;
}
vos_mem_free(pkt);
break;
default:
{
hddLog(LOGE, "%s: Invalid sub command %d",__func__, sub_cmd);
ret = -EINVAL;
break;
}
}
kfree(pBuffer);
EXIT();
return ret;
}
static int iw_setchar_getnone(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
int ret;
vos_ssr_protect(__func__);
ret = __iw_setchar_getnone(dev, info, wrqu, extra);
vos_ssr_unprotect(__func__);
return ret;
}
struct get_antenna_idx_priv {
int antenna_id;
};
static void hdd_get_current_antenna_index_cb(int antenna_id, void *context)
{
struct hdd_request *request;
struct get_antenna_idx_priv *priv;
request = hdd_request_get(context);
if (!request) {
hddLog(VOS_TRACE_LEVEL_ERROR, FL("Obsolete request"));
return;
}
priv = hdd_request_priv(request);
priv->antenna_id = antenna_id;
hdd_request_complete(request);
hdd_request_put(request);
}
static VOS_STATUS wlan_hdd_get_current_antenna_index(hdd_adapter_t *pAdapter,
int *antennaIndex)
{
hdd_context_t *pHddCtx;
eHalStatus halStatus;
int ret;
void *cookie;
struct hdd_request *request;
struct get_antenna_idx_priv *priv;
static const struct hdd_request_params params = {
.priv_size = sizeof(*priv),
.timeout_ms = WLAN_WAIT_TIME_STATS,
};
ENTER();
if (NULL == pAdapter)
{
hddLog(VOS_TRACE_LEVEL_WARN,
"%s: Invalid context, pAdapter", __func__);
return VOS_STATUS_E_FAULT;
}
pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
if (0 != (wlan_hdd_validate_context(pHddCtx)))
{
return VOS_STATUS_E_FAULT;
}
if (TRUE != sme_IsFeatureSupportedByFW(ANTENNA_DIVERSITY_SELECTION))
{
hddLog(VOS_TRACE_LEVEL_ERROR,
"%s: ANTENNA_DIVERSITY_SELECTION is not supported by Firwmare",
__func__);
return VOS_STATUS_E_NOSUPPORT;
}
request = hdd_request_alloc(&params);
if (!request) {
hddLog(VOS_TRACE_LEVEL_ERROR, FL("Request allocation failure"));
return VOS_STATUS_E_NOMEM;
}
cookie = hdd_request_cookie(request);
halStatus = sme_GetCurrentAntennaIndex(pHddCtx->hHal,
hdd_get_current_antenna_index_cb,
cookie, pAdapter->sessionId);
if (eHAL_STATUS_SUCCESS != halStatus)
{
hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Unable to retrieve Antenna Index",
__func__);
/* we'll returned a cached value below */
*antennaIndex = -1;
}
else
{
/* request was sent -- wait for the response */
ret = hdd_request_wait_for_response(request);
if (ret)
{
hddLog(VOS_TRACE_LEVEL_ERROR,
FL("SME timeout while retrieving Antenna Index"));
*antennaIndex = -1;
}
else
{
priv = hdd_request_priv(request);
pAdapter->antennaIndex = priv->antenna_id;
}
}
if (*antennaIndex != -1)
*antennaIndex = pAdapter->antennaIndex;
/*
* either we never sent a request, we sent a request and received a
* response or we sent a request and timed out. Regardless we are
* done with the request.
*/
hdd_request_put(request);
EXIT();
return VOS_STATUS_SUCCESS;
}
/* get param sub-ioctls */
static int __iw_setnone_getint(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
hdd_adapter_t *pAdapter;
tHalHandle hHal;
hdd_context_t *pHddCtx;
int *value = (int *)extra;
int ret = 0; /* success */
ENTER();
pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
if (NULL == pAdapter)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: Adapter is NULL",__func__);
return -EINVAL;
}
pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
ret = wlan_hdd_validate_context(pHddCtx);
if (0 != ret)
{
return ret;
}
hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
if (NULL == hHal)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: Hal Context is NULL",__func__);
return -EINVAL;
}
switch (value[0])
{
case WE_GET_11D_STATE:
{
tSmeConfigParams smeConfig;
sme_GetConfigParam(hHal,&smeConfig);
*value = smeConfig.csrConfig.Is11dSupportEnabled;
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, ("11D state=%d!!"),*value);
break;
}
case WE_IBSS_STATUS:
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "****Return IBSS Status*****");
break;
case WE_PMC_STATE:
{
*value = pmcGetPmcState(hHal);
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, ("PMC state=%d!!"),*value);
break;
}
case WE_GET_WLAN_DBG:
{
vos_trace_display();
*value = 0;
break;
}
case WE_GET_MAX_ASSOC:
{
if (ccmCfgGetInt(hHal, WNI_CFG_ASSOC_STA_LIMIT, (tANI_U32 *)value) != eHAL_STATUS_SUCCESS)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
FL("failed to get ini parameter, WNI_CFG_ASSOC_STA_LIMIT"));
ret = -EIO;
}
#ifdef WLAN_SOFTAP_VSTA_FEATURE
if (pHddCtx->cfg_ini->fEnableVSTASupport)
{
if (*value > VSTA_NUM_ASSOC_STA)
{
*value = VSTA_NUM_ASSOC_STA;
}
if ((pHddCtx->hddAdapters.count > VSTA_NUM_RESV_SELFSTA) &&
(*value > (VSTA_NUM_ASSOC_STA -
(pHddCtx->hddAdapters.count - VSTA_NUM_RESV_SELFSTA))))
{
*value = (VSTA_NUM_ASSOC_STA -
(pHddCtx->hddAdapters.count - VSTA_NUM_RESV_SELFSTA));
}
}
else
#endif
{
if (*value > NUM_ASSOC_STA)
{
*value = NUM_ASSOC_STA;
}
if ((pHddCtx->hddAdapters.count > NUM_RESV_SELFSTA) &&
(*value > (NUM_ASSOC_STA -
(pHddCtx->hddAdapters.count - NUM_RESV_SELFSTA))))
{
*value = (NUM_ASSOC_STA -
(pHddCtx->hddAdapters.count - NUM_RESV_SELFSTA));
}
}
break;
}
case WE_GET_WDI_DBG:
{
wpalTraceDisplay();
*value = 0;
break;
}
case WE_GET_SAP_AUTO_CHANNEL_SELECTION:
{
*value = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->apAutoChannelSelection;
break;
}
case WE_GET_CONCURRENCY_MODE:
{
*value = hdd_get_concurrency_mode ( );
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, ("concurrency mode=%d"),*value);
break;
}
case WE_GET_SCAN_BAND_PREFERENCE:
{
tSmeConfigParams smeConfig;
sme_GetConfigParam(hHal, &smeConfig);
*value = smeConfig.csrConfig.scanBandPreference;
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
"scanBandPreference = %d\n", *value);
break;
}
case WE_GET_ANTENA_DIVERSITY_SELECTION:
{
wlan_hdd_get_current_antenna_index(pAdapter, value);
break;
}
default:
{
hddLog(LOGE, "Invalid IOCTL get_value command %d ",value[0]);
break;
}
}
EXIT();
return ret;
}
static int iw_setnone_getint(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
int ret;
vos_ssr_protect(__func__);
ret = __iw_setnone_getint(dev, info, wrqu, extra);
vos_ssr_unprotect(__func__);
return ret;
}
/* set param sub-ioctls */
int __iw_set_three_ints_getnone(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
hdd_adapter_t *pAdapter;
hdd_context_t *pHddCtx;
int *value = (int *)extra;
int sub_cmd = value[0];
int ret = 0;
ENTER();
if (!capable(CAP_NET_ADMIN))
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
FL("permission check failed"));
return -EPERM;
}
pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
if (NULL == pAdapter)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: Adapter is NULL",__func__);
return -EINVAL;
}
pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
ret = wlan_hdd_validate_context(pHddCtx);
if (0 != ret)
{
return ret;
}
switch(sub_cmd)
{
case WE_SET_WLAN_DBG:
{
vos_trace_setValue( value[1], value[2], value[3]);
break;
}
case WE_SET_WDI_DBG:
{
wpalTraceSetLevel( value[1], value[2], value[3]);
break;
}
case WE_SET_SAP_CHANNELS:
{
ret = iw_softap_set_channel_range( dev, value[1], value[2], value[3]);
break;
}
default:
{
hddLog(LOGE, "%s: Invalid IOCTL command %d", __func__, sub_cmd );
break;
}
}
EXIT();
return ret;
}
int iw_set_three_ints_getnone(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
int ret;
vos_ssr_protect(__func__);
ret = __iw_set_three_ints_getnone(dev, info, wrqu, extra);
vos_ssr_unprotect(__func__);
return ret;
}
static int __iw_get_char_setnone(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
hdd_adapter_t *pAdapter;
int sub_cmd = wrqu->data.flags;
hdd_context_t *pHddCtx;
int ret = 0;
#ifdef WLAN_FEATURE_11W
hdd_wext_state_t *pWextState;
#endif
ENTER();
pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
if (pAdapter == NULL)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: pAdapter is NULL!", __func__);
return -EINVAL;
}
if (WLAN_HDD_MONITOR == pAdapter->device_mode ||
WLAN_HDD_FTM == pAdapter->device_mode)
return ret;
pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
ret = wlan_hdd_validate_context(pHddCtx);
if (0 != ret)
{
return ret;
}
#ifdef WLAN_FEATURE_11W
pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
if (NULL == pWextState)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: pWextState is NULL",__func__);
return -EINVAL;
}
#endif
switch(sub_cmd)
{
case WE_WLAN_VERSION:
{
hdd_wlan_get_version(pAdapter, wrqu, extra);
break;
}
case WE_GET_STATS:
{
tHalHandle hHal = NULL;
tpAniSirGlobal pMac = NULL;
hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
hdd_tx_rx_stats_t *pStats = &pAdapter->hdd_stats.hddTxRxStats;
hdd_chip_reset_stats_t *pResetStats = &pHddCtx->hddChipResetStats;
hdd_arp_stats_t *parpStats = &pAdapter->hdd_stats.hddArpStats;
snprintf(extra, WE_MAX_STR_LEN,
"\nTransmit"
"\ncalled %u, dropped %u, backpressured %u, queued %u"
"\n dropped BK %u, BE %u, VI %u, VO %u"
"\n classified BK %u, BE %u, VI %u, VO %u"
"\nbackpressured BK %u, BE %u, VI %u, VO %u"
"\n queued BK %u, BE %u, VI %u, VO %u"
"\nfetched %u, empty %u, lowres %u, deqerr %u"
"\ndequeued %u, depressured %u, deque-depressured %u, completed %u, flushed %u"
"\n fetched BK %u, BE %u, VI %u, VO %u"
"\n dequeued BK %u, BE %u, VI %u, VO %u"
"\n depressured BK %u, BE %u, VI %u, VO %u"
"\nDeque depressured BK %u, BE %u, VI %u, VO %u"
"\n flushed BK %u, BE %u, VI %u, VO %u"
"\n\nReceive"
"\nchains %u, packets %u, dropped %u, delivered %u, refused %u"
"\n\nResetsStats"
"\n TotalLogp %u Cmd53 %u MutexRead %u MIF-Error %u FW-Heartbeat %u Others %u"
"\n"
"\n\nARP Transmit"
"\nTransmit Count %u, dropped %u"
"\n\nARP Receive"
"\nReceive Count %u, dropped %u, Delivered %u, Refused %u, Drop Reason %u"
"\n",
pStats->txXmitCalled,
pStats->txXmitDropped,
pStats->txXmitBackPressured,
pStats->txXmitQueued,
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->txXmitBackPressuredAC[WLANTL_AC_BK],
pStats->txXmitBackPressuredAC[WLANTL_AC_BE],
pStats->txXmitBackPressuredAC[WLANTL_AC_VI],
pStats->txXmitBackPressuredAC[WLANTL_AC_VO],
pStats->txXmitQueuedAC[WLANTL_AC_BK],
pStats->txXmitQueuedAC[WLANTL_AC_BE],
pStats->txXmitQueuedAC[WLANTL_AC_VI],
pStats->txXmitQueuedAC[WLANTL_AC_VO],
pStats->txFetched,
pStats->txFetchEmpty,
pStats->txFetchLowResources,
pStats->txFetchDequeueError,
pStats->txFetchDequeued,
pStats->txFetchDePressured,
pStats->txDequeDePressured,
pStats->txCompleted,
pStats->txFlushed,
pStats->txFetchedAC[WLANTL_AC_BK],
pStats->txFetchedAC[WLANTL_AC_BE],
pStats->txFetchedAC[WLANTL_AC_VI],
pStats->txFetchedAC[WLANTL_AC_VO],
pStats->txFetchDequeuedAC[WLANTL_AC_BK],
pStats->txFetchDequeuedAC[WLANTL_AC_BE],
pStats->txFetchDequeuedAC[WLANTL_AC_VI],
pStats->txFetchDequeuedAC[WLANTL_AC_VO],
pStats->txFetchDePressuredAC[WLANTL_AC_BK],
pStats->txFetchDePressuredAC[WLANTL_AC_BE],
pStats->txFetchDePressuredAC[WLANTL_AC_VI],
pStats->txFetchDePressuredAC[WLANTL_AC_VO],
pStats->txDequeDePressuredAC[WLANTL_AC_BK],
pStats->txDequeDePressuredAC[WLANTL_AC_BE],
pStats->txDequeDePressuredAC[WLANTL_AC_VI],
pStats->txDequeDePressuredAC[WLANTL_AC_VO],
pStats->txFlushedAC[WLANTL_AC_BK],
pStats->txFlushedAC[WLANTL_AC_BE],
pStats->txFlushedAC[WLANTL_AC_VI],
pStats->txFlushedAC[WLANTL_AC_VO],
pStats->rxChains,
pStats->rxPackets,
pStats->rxDropped,
pStats->rxDelivered,
pStats->rxRefused,
pResetStats->totalLogpResets,
pResetStats->totalCMD53Failures,
pResetStats->totalMutexReadFailures,
pResetStats->totalMIFErrorFailures,
pResetStats->totalFWHearbeatFailures,
pResetStats->totalUnknownExceptions,
parpStats->txCount,
parpStats->txDropped,
parpStats->rxCount,
parpStats->rxDropped,
parpStats->rxDelivered,
parpStats->rxRefused,
parpStats->reason
);
wrqu->data.length = strlen(extra);
hHal = WLAN_HDD_GET_HAL_CTX( pAdapter );
if (hHal)
pMac = PMAC_STRUCT( hHal );
if (pMac && (wrqu->data.length < WE_MAX_STR_LEN)) {
__u32 pmmStatsLength = WE_MAX_STR_LEN - wrqu->data.length;
snprintf(extra+wrqu->data.length, pmmStatsLength,
"\n BMPS sleepcnt %lld, BMPS awakecnt %lld"
"\n BMPS sleepreqfailcnt %lld, BMPS wakeupreqfailcnt %lld"
"\n IMPS sleepcnt %lld, IMPS awakecnt %lld"
"\n IMPS sleepreqfailcnt %lld, IMPS wakeupreqfailcnt %lld, IMPS lasterr %lld"
"\n",
pMac->pmm.BmpscntSleep,
pMac->pmm.BmpscntAwake,
pMac->pmm.BmpsSleeReqFailCnt,
pMac->pmm.BmpsWakeupReqFailCnt,
pMac->pmm.ImpsCntSleep,
pMac->pmm.ImpsCntAwake,
pMac->pmm.ImpsSleepErrCnt,
pMac->pmm.ImpsWakeupErrCnt,
pMac->pmm.ImpsLastErr
);
}
wrqu->data.length = strlen(extra)+1;
break;
}
/* The case prints the current state of the HDD, SME, CSR, PE, TL
*it can be extended for WDI Global State as well.
*And currently it only checks P2P_CLIENT adapter.
*P2P_DEVICE and P2P_GO have not been added as of now.
*/
case WE_GET_STATES:
{
int buf = 0, len = 0;
int adapter_num = 0;
int count = 0, check = 1;
tANI_U16 tlState;
tHalHandle hHal = NULL;
tpAniSirGlobal pMac = NULL;
hdd_station_ctx_t *pHddStaCtx = NULL;
hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
hdd_adapter_t *useAdapter = NULL;
/* Print wlan0 or p2p0 states based on the adapter_num
*by using the correct adapter
*/
while ( adapter_num < 2 )
{
if ( WLAN_ADAPTER == adapter_num )
{
useAdapter = pAdapter;
buf = scnprintf(extra + len, WE_MAX_STR_LEN - len,
"\n\n wlan0 States:-");
len += buf;
}
else if ( P2P_ADAPTER == adapter_num )
{
buf = scnprintf(extra + len, WE_MAX_STR_LEN - len,
"\n\n p2p0 States:-");
len += buf;
if( !pHddCtx )
{
buf = scnprintf(extra + len, WE_MAX_STR_LEN - len,
"\n pHddCtx is NULL");
len += buf;
break;
}
/*Printing p2p0 states only in the case when the device is
configured as a p2p_client*/
useAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
if ( !useAdapter )
{
buf = scnprintf(extra + len, WE_MAX_STR_LEN - len,
"\n Device not configured as P2P_CLIENT.");
len += buf;
break;
}
}
hHal = WLAN_HDD_GET_HAL_CTX( useAdapter );
if (!hHal) {
buf = scnprintf(extra + len, WE_MAX_STR_LEN - len,
"\n pMac is NULL");
len += buf;
break;
}
pMac = PMAC_STRUCT( hHal );
if (!pMac) {
buf = scnprintf(extra + len, WE_MAX_STR_LEN - len,
"\n pMac is NULL");
len += buf;
break;
}
pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR( useAdapter );
if( !pHddStaCtx )
{
buf = scnprintf(extra + len, WE_MAX_STR_LEN - len,
"\n pHddStaCtx is NULL");
len += buf;
break;
}
tlState = smeGetTLSTAState(hHal, pHddStaCtx->conn_info.staId[0]);
buf = scnprintf(extra + len, WE_MAX_STR_LEN - len,
"\n HDD Conn State - %s "
"\n \n SME State:"
"\n Neighbour Roam State - %s"
"\n CSR State - %s"
"\n CSR Substate - %s"
"\n \n TL STA %d State: %s",
macTraceGetHDDWlanConnState(
pHddStaCtx->conn_info.connState),
macTraceGetNeighbourRoamState(
pMac->roam.neighborRoamInfo.neighborRoamState),
macTraceGetcsrRoamState(
pMac->roam.curState[useAdapter->sessionId]),
macTraceGetcsrRoamSubState(
pMac->roam.curSubState[useAdapter->sessionId]),
pHddStaCtx->conn_info.staId[0],
macTraceGetTLState(tlState)
);
len += buf;
adapter_num++;
}
if (pMac) {
/* Printing Lim State starting with global lim states */
buf = scnprintf(extra + len, WE_MAX_STR_LEN - len,
"\n \n LIM STATES:-"
"\n Global Sme State - %s "\
"\n Global mlm State - %s "\
"\n",
macTraceGetLimSmeState(pMac->lim.gLimSmeState),
macTraceGetLimMlmState(pMac->lim.gLimMlmState)
);
len += buf;
/*printing the PE Sme and Mlm states for valid lim sessions*/
while ( check < 3 && count < pMac->lim.maxBssId)
{
if ( pMac->lim.gpSession[count].valid )
{
buf = scnprintf(extra + len, WE_MAX_STR_LEN - len,
"\n Lim Valid Session %d:-"
"\n PE Sme State - %s "
"\n PE Mlm State - %s "
"\n",
check,
macTraceGetLimSmeState(pMac->lim.gpSession[count].limSmeState),
macTraceGetLimMlmState(pMac->lim.gpSession[count].limMlmState)
);
len += buf;
check++;
}
count++;
}
}
wrqu->data.length = strlen(extra)+1;
break;
}
case WE_GET_CFG:
{
hdd_cfg_get_config(WLAN_HDD_GET_CTX(pAdapter), extra, WE_MAX_STR_LEN);
wrqu->data.length = strlen(extra)+1;
break;
}
#ifdef WLAN_FEATURE_11AC
case WE_GET_RSSI:
{
v_S7_t s7Rssi = 0;
wlan_hdd_get_station_stats(pAdapter);
wlan_hdd_get_rssi(pAdapter, &s7Rssi);
snprintf(extra, WE_MAX_STR_LEN, "rssi=%d",s7Rssi);
wrqu->data.length = strlen(extra)+1;
break;
}
#endif
#if defined WLAN_FEATURE_VOWIFI_11R || defined FEATURE_WLAN_ESE || defined(FEATURE_WLAN_LFR)
case WE_GET_ROAM_RSSI:
{
v_S7_t s7Rssi = 0;
wlan_hdd_get_roam_rssi(pAdapter, &s7Rssi);
snprintf(extra, WE_MAX_STR_LEN, "rssi=%d", s7Rssi);
wrqu->data.length = strlen(extra)+1;
break;
}
#endif
case WE_GET_WMM_STATUS:
{
snprintf(extra, WE_MAX_STR_LEN,
"\nDir: 0=up, 1=down, 3=both\n"
"|------------------------|\n"
"|AC | ACM |Admitted| Dir |\n"
"|------------------------|\n"
"|VO | %d | %3s | %d |\n"
"|VI | %d | %3s | %d |\n"
"|BE | %d | %3s | %d |\n"
"|BK | %d | %3s | %d |\n"
"|------------------------|\n",
pAdapter->hddWmmStatus.wmmAcStatus[WLANTL_AC_VO].wmmAcAccessRequired,
pAdapter->hddWmmStatus.wmmAcStatus[WLANTL_AC_VO].wmmAcAccessAllowed?"YES":"NO",
pAdapter->hddWmmStatus.wmmAcStatus[WLANTL_AC_VO].wmmAcTspecInfo.ts_info.direction,
pAdapter->hddWmmStatus.wmmAcStatus[WLANTL_AC_VI].wmmAcAccessRequired,
pAdapter->hddWmmStatus.wmmAcStatus[WLANTL_AC_VI].wmmAcAccessAllowed?"YES":"NO",
pAdapter->hddWmmStatus.wmmAcStatus[WLANTL_AC_VI].wmmAcTspecInfo.ts_info.direction,
pAdapter->hddWmmStatus.wmmAcStatus[WLANTL_AC_BE].wmmAcAccessRequired,
pAdapter->hddWmmStatus.wmmAcStatus[WLANTL_AC_BE].wmmAcAccessAllowed?"YES":"NO",
pAdapter->hddWmmStatus.wmmAcStatus[WLANTL_AC_BE].wmmAcTspecInfo.ts_info.direction,
pAdapter->hddWmmStatus.wmmAcStatus[WLANTL_AC_BK].wmmAcAccessRequired,
pAdapter->hddWmmStatus.wmmAcStatus[WLANTL_AC_BK].wmmAcAccessAllowed?"YES":"NO",
pAdapter->hddWmmStatus.wmmAcStatus[WLANTL_AC_BK].wmmAcTspecInfo.ts_info.direction);
wrqu->data.length = strlen(extra)+1;
break;
}
case WE_GET_CHANNEL_LIST:
{
VOS_STATUS status;
v_U8_t i, len;
char* buf ;
tANI_U8 pBuf[COUNTRY_CODE_LEN];
tANI_U8 uBufLen = COUNTRY_CODE_LEN;
hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
tChannelListInfo channel_list;
memset(&channel_list, 0, sizeof(channel_list));
status = iw_softap_get_channel_list(dev, info, wrqu, (char *)&channel_list);
if ( !VOS_IS_STATUS_SUCCESS( status ) )
{
hddLog(VOS_TRACE_LEVEL_ERROR, "%s GetChannelList Failed!!!",__func__);
return -EINVAL;
}
buf = extra;
/**
* Maximum channels = WNI_CFG_VALID_CHANNEL_LIST_LEN. Maximum buffer
* needed = 5 * number of channels. Check ifsufficient
* buffer is available and then proceed to fill the buffer.
*/
if(WE_MAX_STR_LEN < (5 * WNI_CFG_VALID_CHANNEL_LIST_LEN))
{
hddLog(VOS_TRACE_LEVEL_ERROR,
"%s Insufficient Buffer to populate channel list",
__func__);
return -EINVAL;
}
len = scnprintf(buf, WE_MAX_STR_LEN, "%u ",
channel_list.num_channels);
if( eHAL_STATUS_SUCCESS == sme_GetCountryCode(pHddCtx->hHal, pBuf, &uBufLen))
{
//Printing Country code in getChannelList
for(i= 0; i < COUNTRY_CODE_LEN; i++)
{
len += scnprintf(buf + len, WE_MAX_STR_LEN - len,
"%c ", pBuf[i]);
}
}
for(i = 0 ; i < channel_list.num_channels; i++)
{
len += scnprintf(buf + len, WE_MAX_STR_LEN - len,
"%u ", channel_list.channels[i]);
}
wrqu->data.length = strlen(extra)+1;
break;
}
#ifdef FEATURE_WLAN_TDLS
case WE_GET_TDLS_PEERS:
{
wrqu->data.length = wlan_hdd_tdls_get_all_peers(pAdapter, extra, WE_MAX_STR_LEN)+1;
break;
}
#endif
#ifdef WLAN_FEATURE_11W
case WE_GET_11W_INFO:
{
hddLog(LOGE, "WE_GET_11W_ENABLED = %d", pWextState->roamProfile.MFPEnabled );
snprintf(extra, WE_MAX_STR_LEN,
"\n BSSID %02X:%02X:%02X:%02X:%02X:%02X, Is PMF Assoc? %d"
"\n Number of Unprotected Disassocs %d"
"\n Number of Unprotected Deauths %d",
(*pWextState->roamProfile.BSSIDs.bssid)[0], (*pWextState->roamProfile.BSSIDs.bssid)[1],
(*pWextState->roamProfile.BSSIDs.bssid)[2], (*pWextState->roamProfile.BSSIDs.bssid)[3],
(*pWextState->roamProfile.BSSIDs.bssid)[4], (*pWextState->roamProfile.BSSIDs.bssid)[5],
pWextState->roamProfile.MFPEnabled, pAdapter->hdd_stats.hddPmfStats.numUnprotDisassocRx,
pAdapter->hdd_stats.hddPmfStats.numUnprotDeauthRx);
wrqu->data.length = strlen(extra)+1;
break;
}
#endif
#ifdef WLAN_FEATURE_RMC
case WE_GET_IBSS_STA_INFO:
{
hdd_station_ctx_t *pHddStaCtx =
WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
int idx = 0;
int length = 0, buf = 0;
for (idx = 0; idx < HDD_MAX_NUM_IBSS_STA; idx++)
{
if (0 != pHddStaCtx->conn_info.staId[ idx ])
{
buf = snprintf
(
(extra + length), WE_MAX_STR_LEN - length,
"\n%d .%02x:%02x:%02x:%02x:%02x:%02x\n",
pHddStaCtx->conn_info.staId[ idx ],
pHddStaCtx->conn_info.peerMacAddress[idx].bytes[0],
pHddStaCtx->conn_info.peerMacAddress[idx].bytes[1],
pHddStaCtx->conn_info.peerMacAddress[idx].bytes[2],
pHddStaCtx->conn_info.peerMacAddress[idx].bytes[3],
pHddStaCtx->conn_info.peerMacAddress[idx].bytes[4],
pHddStaCtx->conn_info.peerMacAddress[idx].bytes[5]
);
length += buf;
}
}
wrqu->data.length = strlen(extra)+1;
break;
}
#endif
case WE_GET_SNR:
{
v_S7_t s7snr = 0;
int status = 0;
hdd_context_t *pHddCtx;
hdd_station_ctx_t *pHddStaCtx;
pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
status = wlan_hdd_validate_context(pHddCtx);
if (0 != status)
{
return status;
}
pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
if (0 == pHddCtx->cfg_ini->fEnableSNRMonitoring ||
eConnectionState_Associated != pHddStaCtx->conn_info.connState)
{
hddLog(LOGE, "%s: getSNR failed: Enable SNR Monitoring-%d,"
" ConnectionState-%d", __func__,
pHddCtx->cfg_ini->fEnableSNRMonitoring,
pHddStaCtx->conn_info.connState);
return -ENONET;
}
/*update the stats in TL*/
wlan_hdd_get_station_stats(pAdapter);
wlan_hdd_get_snr(pAdapter, &s7snr);
snprintf(extra, WE_MAX_STR_LEN, "snr=%d",s7snr);
wrqu->data.length = strlen(extra) + 1;
break;
}
#ifdef FEATURE_OEM_DATA_SUPPORT
case WE_GET_OEM_DATA_CAP:
{
return iw_get_oem_data_cap(dev, info, wrqu, extra);
}
#endif /* FEATURE_OEM_DATA_SUPPORT */
default:
{
hddLog(LOGE, "%s: Invalid IOCTL command %d", __func__, sub_cmd );
break;
}
}
EXIT();
return 0;
}
static int iw_get_char_setnone(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
int ret;
vos_ssr_protect(__func__);
ret = __iw_get_char_setnone(dev, info, wrqu, extra);
vos_ssr_unprotect(__func__);
return ret;
}
/* action sub-ioctls */
static int __iw_setnone_getnone(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
hdd_adapter_t *pAdapter;
hdd_context_t *pHddCtx;
int sub_cmd;
int ret = 0; /* success */
struct iw_point s_priv_data;
ENTER();
pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
if (NULL == pAdapter)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: Adapter is NULL",__func__);
return -EINVAL;
}
pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
ret = wlan_hdd_validate_context(pHddCtx);
if (0 != ret)
{
return ret;
}
/* helper function to get iwreq_data with compat handling. */
if (hdd_priv_get_data(&s_priv_data, wrqu))
{
return -EINVAL;
}
sub_cmd = s_priv_data.flags;
switch (sub_cmd)
{
case WE_CLEAR_STATS:
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"%s: clearing", __func__);
memset(&pAdapter->stats, 0, sizeof(pAdapter->stats));
memset(&pAdapter->hdd_stats, 0, sizeof(pAdapter->hdd_stats));
break;
}
case WE_INIT_AP:
{
/*FIX ME: Need to be revisited if multiple SAPs to be supported */
/* As Soft AP mode might been changed to STA already with
* killing of Hostapd, need to find the adpater by name
* rather than mode */
hdd_adapter_t* pAdapter_to_stop =
hdd_get_adapter_by_name(WLAN_HDD_GET_CTX(pAdapter), "softap.0");
if( pAdapter_to_stop )
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"Adapter with name softap.0 already "
"exist, ignoring the request.\nRemove the "
"adapter and try again\n");
break;
}
if (wlan_hdd_check_monitor_state(pHddCtx)) {
hddLog(LOGE, FL("initAP not allowed in STA + MON"));
ret = -EOPNOTSUPP;
break;
}
pr_info("Init AP trigger\n");
hdd_open_adapter( WLAN_HDD_GET_CTX(pAdapter), WLAN_HDD_SOFTAP, "softap.%d",
wlan_hdd_get_intf_addr( WLAN_HDD_GET_CTX(pAdapter) ),TRUE);
break;
}
#ifdef WLAN_FEATURE_RMC
case WE_IBSS_GET_PEER_INFO_ALL:
{
hdd_wlan_get_ibss_peer_info_all(pAdapter);
break;
}
#endif
case WE_STOP_AP:
{
/*FIX ME: Need to be revisited if multiple SAPs to be supported */
/* As Soft AP mode has been changed to STA already with killing of Hostapd,
* this is a dead code and need to find the adpater by name rather than mode */
hdd_adapter_t* pAdapter_to_stop =
hdd_get_adapter_by_name(WLAN_HDD_GET_CTX(pAdapter), "softap.0");
if( pAdapter_to_stop )
{
hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
pr_info("Stopping AP mode\n");
if (TRUE == sme_IsPmcBmps(WLAN_HDD_GET_HAL_CTX(pAdapter)))
{
/* EXIT BMPS as fw cannot handle DEL_STA when its in BMPS */
wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_ACTIVE);
}
/*Make sure that pAdapter cleaned properly*/
hdd_stop_adapter( pHddCtx, pAdapter_to_stop, VOS_TRUE );
hdd_deinit_adapter( pHddCtx, pAdapter_to_stop, TRUE);
memset(&pAdapter_to_stop->sessionCtx, 0, sizeof(pAdapter_to_stop->sessionCtx));
wlan_hdd_release_intf_addr(WLAN_HDD_GET_CTX(pAdapter),
pAdapter_to_stop->macAddressCurrent.bytes);
hdd_close_adapter(WLAN_HDD_GET_CTX(pAdapter), pAdapter_to_stop,
TRUE);
if (FALSE == sme_IsPmcBmps(WLAN_HDD_GET_HAL_CTX(pAdapter)))
{
/* put the device back into BMPS */
wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_AUTO);
}
}
else
{
printk(KERN_ERR"SAP adapter not found to stop it!\n");
}
break;
}
#ifdef WLAN_BTAMP_FEATURE
case WE_ENABLE_AMP:
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"%s: enabling AMP", __func__);
WLANBAP_RegisterWithHCI(pAdapter);
break;
}
case WE_DISABLE_AMP:
{
hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
VOS_STATUS status;
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"%s: disabling AMP", __func__);
pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
status = WLANBAP_StopAmp();
if(VOS_STATUS_SUCCESS != status )
{
pHddCtx->isAmpAllowed = VOS_TRUE;
hddLog(VOS_TRACE_LEVEL_FATAL,
"%s: Failed to stop AMP", __func__);
}
else
{
//a state m/c implementation in PAL is TBD to avoid this delay
msleep(500);
pHddCtx->isAmpAllowed = VOS_FALSE;
WLANBAP_DeregisterFromHCI();
}
break;
}
#endif
case WE_ENABLE_DXE_STALL_DETECT:
{
tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
sme_transportDebug(hHal, VOS_FALSE, VOS_TRUE);
break;
}
case WE_DISPLAY_DXE_SNAP_SHOT:
{
tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
sme_transportDebug(hHal, VOS_TRUE, VOS_FALSE);
break;
}
case WE_DISPLAY_DATAPATH_SNAP_SHOT:
{
hddLog(LOGE, "%s: called %d",__func__, sub_cmd);
hdd_wmm_tx_snapshot(pAdapter);
WLANTL_TLDebugMessage(WLANTL_DEBUG_TX_SNAPSHOT);
break;
}
case WE_SET_REASSOC_TRIGGER:
{
hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
tpAniSirGlobal pMac = WLAN_HDD_GET_HAL_CTX(pAdapter);
v_U32_t roamId = 0;
tCsrRoamModifyProfileFields modProfileFields;
sme_GetModifyProfileFields(pMac, pAdapter->sessionId, &modProfileFields);
sme_RoamReassoc(pMac, pAdapter->sessionId, NULL, modProfileFields, &roamId, 1);
return 0;
}
case WE_STOP_OBSS_SCAN:
{
/* 1.OBSS Scan is mandatory while operating in 2.4GHz
2.OBSS scan is stopped by Firmware during the disassociation
3.OBSS stop comamnd is added for debugging purpose*/
hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
tpAniSirGlobal pMac;
if (pAdapter == NULL)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
" pAdapter is NULL ");
return -EINVAL;
}
pMac = WLAN_HDD_GET_HAL_CTX(pAdapter);
if (pMac == NULL)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
" pMac is NULL ");
return -EINVAL;
}
sme_HT40StopOBSSScan(pMac, pAdapter->sessionId);
}
break;
case WE_DUMP_ROAM_TIMER_LOG:
{
vos_dump_roam_time_log_service();
break;
}
case WE_RESET_ROAM_TIMER_LOG:
{
vos_reset_roam_timer_log();
break;
}
case WE_GET_FW_LOGS:
{
vos_fatal_event_logs_req(WLAN_LOG_TYPE_NON_FATAL,
WLAN_LOG_INDICATOR_IOCTL,
WLAN_LOG_REASON_IOCTL,
TRUE, TRUE);
break;
}
default:
{
hddLog(LOGE, "%s: unknown ioctl %d", __func__, sub_cmd);
break;
}
}
EXIT();
return ret;
}
static int iw_setnone_getnone(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
int ret;
vos_ssr_protect(__func__);
ret = __iw_setnone_getnone(dev, info, wrqu, extra);
vos_ssr_unprotect(__func__);
return ret;
}
void hdd_wmm_tx_snapshot(hdd_adapter_t *pAdapter)
{
/*
* Function to display HDD WMM information
* for Tx Queues.
* Prints globala as well as per client depending
* whether the clients are registered or not.
*/
int i = 0, j = 0;
v_CONTEXT_t pVosContext = ( WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
ptSapContext pSapCtx = VOS_GET_SAP_CB(pVosContext);
hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
hdd_ibss_peer_info_t *pPeerInfo;
v_SIZE_t tx_queue_count[NUM_TX_QUEUES];
for ( i=0; i< NUM_TX_QUEUES; i++)
{
spin_lock_bh(&pAdapter->wmm_tx_queue[i].lock);
tx_queue_count[i] = pAdapter->wmm_tx_queue[i].count;
spin_unlock_bh(&pAdapter->wmm_tx_queue[i].lock);
}
for ( i=0; i< NUM_TX_QUEUES; i++) {
if (tx_queue_count[i]) {
hddLog(LOGE, "HDD WMM TxQueue Info For AC: %d Count: %d",
i, tx_queue_count[i]);
}
}
if(pSapCtx == NULL){
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
FL("psapCtx is NULL"));
return;
}
spin_lock_bh(&pSapCtx->staInfo_lock);
for(i =0; i<WLAN_MAX_STA_COUNT; i++)
{
if(pSapCtx->aStaInfo[i].isUsed)
{
hddLog(LOGE, "******STAIndex: %d*********", i);
for ( j=0; j< NUM_TX_QUEUES; j++)
{
if( pSapCtx->aStaInfo[i].wmm_tx_queue[j].count )
{
spin_lock_bh(&pSapCtx->aStaInfo[i].wmm_tx_queue[j].lock);
hddLog(LOGE, "HDD TxQueue Info For AC: %d Count: %d",
j, pSapCtx->aStaInfo[i].wmm_tx_queue[j].count);
spin_unlock_bh(&pSapCtx->aStaInfo[i].wmm_tx_queue[j].lock);
}
}
}
}
spin_unlock_bh(&pSapCtx->staInfo_lock);
if(pHddStaCtx == NULL){
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
FL("pHddStaCtx is NULL"));
return;
}
pPeerInfo = &pHddStaCtx->ibss_peer_info;
if(pPeerInfo == NULL){
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
FL("ppeerinfo is NULL"));
return;
}
for (i = 0; i < HDD_MAX_NUM_IBSS_STA; i++) {
if (pPeerInfo->ibssStaInfo[i].isUsed) {
hddLog(LOGE, "******IBSS STAIndex: %d*********", i);
for (j = 0; j < NUM_TX_QUEUES; j++) {
if (pPeerInfo->ibssStaInfo[i].wmm_tx_queue[j].count) {
spin_lock_bh(
&pPeerInfo->ibssStaInfo[i].wmm_tx_queue[j].lock);
hddLog(LOGE,
"HDD TxQueue Info For AC: %d Count: %d PrevAdress:%pK, NextAddress:%pK",
j, pPeerInfo->ibssStaInfo[i].wmm_tx_queue[j].count,
pPeerInfo->ibssStaInfo[i].wmm_tx_queue[j].anchor.prev,
pPeerInfo->ibssStaInfo[i].wmm_tx_queue[j].anchor.next);
spin_unlock_bh(
&pPeerInfo->ibssStaInfo[i].wmm_tx_queue[j].lock);
}
}
}
}
}
static int __iw_set_var_ints_getnone(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
hdd_adapter_t *pAdapter;
tHalHandle hHal = NULL;
int sub_cmd;
int *apps_args = (int *) extra;
hdd_station_ctx_t *pStaCtx = NULL ;
hdd_mon_ctx_t *pMonCtx = NULL;
hdd_context_t *pHddCtx = NULL;
hdd_ap_ctx_t *pAPCtx = NULL;
v_CONTEXT_t pVosContext;
int cmd = 0;
int staId = 0;
int ret = 0;
ENTER();
if (extra == NULL)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: NULL extra buffer pointer", __func__);
return -EINVAL;
}
pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
if (NULL == pAdapter)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: Adapter is NULL",__func__);
return -EINVAL;
}
pVosContext = ( WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
ret = wlan_hdd_validate_context(pHddCtx);
if (0 != ret)
{
return ret;
}
if( VOS_MONITOR_MODE != hdd_get_conparam())
{
hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
if (NULL == hHal)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: Hal Context is NULL",__func__);
return -EINVAL;
}
}
sub_cmd = wrqu->data.flags;
hddLog(LOG1, "%s: Received length %d", __func__, wrqu->data.length);
if(( sub_cmd == WE_MCC_CONFIG_CREDENTIAL ) ||
(sub_cmd == WE_MCC_CONFIG_PARAMS ))
{
if(( pAdapter->device_mode == WLAN_HDD_INFRA_STATION )||
( pAdapter->device_mode == WLAN_HDD_P2P_CLIENT ))
{
pStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
staId = pStaCtx->conn_info.staId[0];
}
else if (( pAdapter->device_mode == WLAN_HDD_P2P_GO ) ||
( pAdapter->device_mode == WLAN_HDD_SOFTAP ))
{
pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
staId = pAPCtx->uBCStaId;
}
else
{
hddLog(LOGE, "%s: Device mode %d not recognised", __FUNCTION__, pAdapter->device_mode);
return 0;
}
}
switch (sub_cmd)
{
case WE_LOG_DUMP_CMD:
{
if(apps_args[0] == 26) {
if (!pHddCtx->cfg_ini->crash_inject_enabled) {
hddLog(LOGE, "Crash Inject ini disabled, Ignore Crash Inject");
return 0;
}
}
hddLog(LOG1, "%s: LOG_DUMP %d arg1 %d arg2 %d arg3 %d arg4 %d",
__func__, apps_args[0], apps_args[1], apps_args[2],
apps_args[3], apps_args[4]);
if (hHal)
logPrintf(hHal, apps_args[0], apps_args[1], apps_args[2],
apps_args[3], apps_args[4]);
}
break;
#ifdef WLAN_FEATURE_RMC
case WE_IBSS_GET_PEER_INFO:
{
pr_info ( "Station ID = %d\n",apps_args[0]);
hdd_wlan_get_ibss_peer_info(pAdapter, apps_args[0]);
}
break;
#endif
case WE_P2P_NOA_CMD:
{
p2p_app_setP2pPs_t p2pNoA;
if (pAdapter->device_mode != WLAN_HDD_P2P_GO) {
hddLog(LOGE,
FL("Setting NoA is not allowed in Device mode:%d"),
pAdapter->device_mode);
return -EINVAL;
}
p2pNoA.opp_ps = apps_args[0];
p2pNoA.ctWindow = apps_args[1];
p2pNoA.duration = apps_args[2];
p2pNoA.interval = apps_args[3];
p2pNoA.count = apps_args[4];
p2pNoA.single_noa_duration = apps_args[5];
p2pNoA.psSelection = apps_args[6];
hddLog(LOG1, "%s: P2P_NOA_ATTR:oppPS %d ctWindow %d duration %d "
"interval %d count %d single noa duration %d PsSelection %x",
__func__, apps_args[0], apps_args[1], apps_args[2],
apps_args[3], apps_args[4], apps_args[5], apps_args[6]);
hdd_setP2pPs(dev, &p2pNoA);
}
break;
case WE_MTRACE_SELECTIVE_MODULE_LOG_ENABLE_CMD:
{
hddLog(LOG1, "%s: SELECTIVE_MODULE_LOG %d arg1 %d arg2",
__func__, apps_args[0], apps_args[1]);
vosTraceEnable(apps_args[0], apps_args[1]);
}
break;
case WE_MTRACE_DUMP_CMD:
{
hddLog(LOG1, "%s: MTRACE_DUMP code %d session %d count %d "
"bitmask_of_module %d ",
__func__, apps_args[0], apps_args[1], apps_args[2],
apps_args[3]);
if (hHal)
vosTraceDumpAll((void*)hHal , apps_args[0], apps_args[1],
apps_args[2], apps_args[3]);
}
break;
case WE_MCC_CONFIG_CREDENTIAL :
{
cmd = 287; //Command should be updated if there is any change
// in the Riva dump command
if((apps_args[0] >= 40 ) && (apps_args[0] <= 160 ))
{
if (hHal)
logPrintf(hHal, cmd, staId, apps_args[0], apps_args[1],
apps_args[2]);
}
else
{
hddLog(LOGE, "%s : Enter valid MccCredential value between MIN :40 and MAX:160", __func__);
return 0;
}
}
break;
case WE_MCC_CONFIG_PARAMS :
{
cmd = 288; //command Should be updated if there is any change
// in the Riva dump command
hdd_validate_mcc_config(pAdapter, staId, apps_args[0], apps_args[1],apps_args[2]);
}
break;
#ifdef FEATURE_WLAN_TDLS
case WE_TDLS_CONFIG_PARAMS :
{
tdls_config_params_t tdlsParams;
tdlsParams.tdls = apps_args[0];
tdlsParams.tx_period_t = apps_args[1];
tdlsParams.tx_packet_n = apps_args[2];
tdlsParams.discovery_period_t = apps_args[3];
tdlsParams.discovery_tries_n = apps_args[4];
tdlsParams.idle_timeout_t = apps_args[5];
tdlsParams.idle_packet_n = apps_args[6];
tdlsParams.rssi_hysteresis = apps_args[7];
tdlsParams.rssi_trigger_threshold = apps_args[8];
tdlsParams.rssi_teardown_threshold = apps_args[9];
wlan_hdd_tdls_set_params(dev, &tdlsParams);
}
break;
#endif
case WE_CONFIGURE_MONITOR_MODE:
{
tVOS_CON_MODE mode = hdd_get_conparam();
int ret;
void *cookie;
struct hdd_request *request;
static const struct hdd_request_params params = {
.priv_size = 0,
.timeout_ms = MON_MODE_MSG_TIMEOUT,
};
if (VOS_MONITOR_MODE != mode) {
hddLog(LOGE, FL("invalid mode %d"), mode);
return -EIO;
}
pMonCtx = WLAN_HDD_GET_MONITOR_CTX_PTR(pAdapter);
if( pMonCtx == NULL )
{
hddLog(LOGE, "Monitor Context NULL");
return -EIO;
}
hddLog(LOG1, "%s: Monitor MOde Configuration: ChNo=%d ChBW=%d CRCCheck=%d type=%d ConversionBit=%d",
__func__, apps_args[0], apps_args[1], apps_args[2],
apps_args[3], apps_args[4]);
/* Input Validation part of FW */
pMonCtx->ChannelNo = apps_args[0];
pMonCtx->ChannelBW = apps_args[1];
pMonCtx->crcCheckEnabled = apps_args[2];
wlan_hdd_mon_set_typesubtype( pMonCtx,apps_args[3]);
pMonCtx->is80211to803ConReq = apps_args[4];
WLANTL_SetIsConversionReq(pVosContext,apps_args[4]);
if( pMonCtx->is80211to803ConReq )
pAdapter->dev->type = ARPHRD_ETHER;
else
pAdapter->dev->type = ARPHRD_IEEE80211_RADIOTAP;
if( (apps_args[3]!= 100 && apps_args[3]!= 0) && apps_args[4] )
{
hddLog(LOGE, "%s: Filtering data packets as management and control"
" cannot be converted to 802.3 ",__func__);
pMonCtx->typeSubtypeBitmap = 0xFFFF00000000;
}
if (MON_MODE_START == pMonCtx->state) {
request = hdd_request_alloc(&params);
if (!request) {
hddLog(VOS_TRACE_LEVEL_ERROR, FL("Request allocation failure"));
return -ENOMEM;
}
cookie = hdd_request_cookie(request);
if (VOS_STATUS_SUCCESS !=
wlan_hdd_mon_postMsg(cookie, pMonCtx,
hdd_mon_post_msg_cb)) {
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
FL("failed to post MON MODE REQ"));
ret = -EIO;
} else {
ret = hdd_request_wait_for_response(request);
if (ret)
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
FL("failed to wait on monitor mode completion %d"),
ret);
}
hdd_request_put(request);
}
}
break;
case WE_SET_MONITOR_MODE_FILTER:
{
tVOS_CON_MODE mode = hdd_get_conparam();
int ret;
void *cookie;
struct hdd_request *request;
static const struct hdd_request_params params = {
.priv_size = 0,
.timeout_ms = MON_MODE_MSG_TIMEOUT,
};
if (VOS_MONITOR_MODE != mode) {
hddLog(LOGE, FL("invalid mode %d"), mode);
return -EIO;
}
pMonCtx = WLAN_HDD_GET_MONITOR_CTX_PTR(pAdapter);
if( pMonCtx == NULL )
{
hddLog(LOGE, "Monitor Context NULL");
return -EIO;
}
/* Input Validation Part of FW */
pMonCtx->numOfMacFilters=1;
pMonCtx->mmFilters[0].macAddr.bytes[0]=apps_args[0];
pMonCtx->mmFilters[0].macAddr.bytes[1]=apps_args[1];
pMonCtx->mmFilters[0].macAddr.bytes[2]=apps_args[2];
pMonCtx->mmFilters[0].macAddr.bytes[3]=apps_args[3];
pMonCtx->mmFilters[0].macAddr.bytes[4]=apps_args[4];
pMonCtx->mmFilters[0].macAddr.bytes[5]=apps_args[5];
pMonCtx->mmFilters[0].isA1filter = apps_args[6];
pMonCtx->mmFilters[0].isA2filter = apps_args[7];
pMonCtx->mmFilters[0].isA3filter = apps_args[8];
hddLog(LOG1, "%s: Monitor Filter: %pM A1=%d A2=%d A3=%d ",
__func__, pMonCtx->mmFilters[0].macAddr.bytes,
apps_args[6], apps_args[7], apps_args[8]);
if (MON_MODE_START == pMonCtx->state) {
request = hdd_request_alloc(&params);
if (!request) {
hddLog(VOS_TRACE_LEVEL_ERROR, FL("Request allocation failure"));
return -ENOMEM;
}
cookie = hdd_request_cookie(request);
if (VOS_STATUS_SUCCESS ==
wlan_hdd_mon_postMsg(cookie, pMonCtx,
hdd_mon_post_msg_cb)) {
ret = hdd_request_wait_for_response(request);
if (ret)
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
FL("failed to wait on monitor mode completion %d"),
ret);
}
hdd_request_put(request);
}
}
break;
default:
{
hddLog(LOGE, "%s: Invalid IOCTL command %d",
__func__, sub_cmd );
}
break;
}
EXIT();
return ret;
}
static int iw_hdd_set_var_ints_getnone(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
int ret;
union iwreq_data u_priv_wrqu;
int apps_args[MAX_VAR_ARGS] = {0};
int num_args;
if (!capable(CAP_NET_ADMIN))
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
FL("permission check failed"));
return -EPERM;
}
/* helper function to get iwreq_data with compat handling. */
if (hdd_priv_get_data(&u_priv_wrqu.data, wrqu))
{
return -EINVAL;
}
if (NULL == u_priv_wrqu.data.pointer)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: NULL data pointer", __func__);
return -EINVAL;
}
num_args = u_priv_wrqu.data.length;
if (num_args > MAX_VAR_ARGS)
{
num_args = MAX_VAR_ARGS;
}
if (copy_from_user(apps_args, u_priv_wrqu.data.pointer,
(sizeof(int)) * num_args))
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: failed to copy data from user buffer", __func__);
return -EFAULT;
}
vos_ssr_protect(__func__);
ret = __iw_set_var_ints_getnone(dev, info, &u_priv_wrqu,
(char *)&apps_args);
vos_ssr_unprotect(__func__);
return ret;
}
int iw_set_var_ints_getnone(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
int ret;
vos_ssr_protect(__func__);
ret = __iw_set_var_ints_getnone(dev, info, wrqu, extra);
vos_ssr_unprotect(__func__);
return ret;
}
static int __iw_add_tspec(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
hdd_adapter_t *pAdapter;
hdd_station_ctx_t *pHddStaCtx;
hdd_context_t *pHddCtx;
hdd_wlan_wmm_status_e *pStatus = (hdd_wlan_wmm_status_e *)extra;
int params[HDD_WLAN_WMM_PARAM_COUNT];
sme_QosWmmTspecInfo tSpec;
v_U32_t handle;
struct iw_point s_priv_data;
int ret = 0;
ENTER();
pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
if (NULL == pAdapter)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: Adapter is NULL",__func__);
return -EINVAL;
}
pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
ret = wlan_hdd_validate_context(pHddCtx);
if (0 != ret)
{
return ret;
}
pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
if (NULL == pHddStaCtx)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: STA Context is NULL",__func__);
return -EINVAL;
}
// make sure the application is sufficiently priviledged
// note that the kernel will do this for "set" ioctls, but since
// this ioctl wants to return status to user space it must be
// defined as a "get" ioctl
if (!capable(CAP_NET_ADMIN))
{
return -EPERM;
}
// we must be associated in order to add a tspec
if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
{
*pStatus = HDD_WLAN_WMM_STATUS_SETUP_FAILED_BAD_PARAM;
return 0;
}
// since we are defined to be a "get" ioctl, and since the number
// of params exceeds the number of params that wireless extensions
// will pass down in the iwreq_data, we must copy the "set" params.
// We must handle the compat for iwreq_data in 32U/64K environment.
// helper fucntion to get iwreq_data with compat handling.
if (hdd_priv_get_data(&s_priv_data, wrqu))
{
*pStatus = HDD_WLAN_WMM_STATUS_SETUP_FAILED_BAD_PARAM;
return 0;
}
// make sure all params are correctly passed to function
if ((NULL == s_priv_data.pointer) ||
(HDD_WLAN_WMM_PARAM_COUNT != s_priv_data.length))
{
*pStatus = HDD_WLAN_WMM_STATUS_SETUP_FAILED_BAD_PARAM;
return 0;
}
// from user space ourselves
if (copy_from_user(&params, s_priv_data.pointer, sizeof(params)))
{
// hmmm, can't get them
return -EIO;
}
// clear the tspec
memset(&tSpec, 0, sizeof(tSpec));
// validate the handle
handle = params[HDD_WLAN_WMM_PARAM_HANDLE];
if (HDD_WMM_HANDLE_IMPLICIT == handle)
{
// that one is reserved
*pStatus = HDD_WLAN_WMM_STATUS_SETUP_FAILED_BAD_PARAM;
return 0;
}
// validate the TID
if (params[HDD_WLAN_WMM_PARAM_TID] > 7)
{
// out of range
*pStatus = HDD_WLAN_WMM_STATUS_SETUP_FAILED_BAD_PARAM;
return 0;
}
tSpec.ts_info.tid = params[HDD_WLAN_WMM_PARAM_TID];
// validate the direction
switch (params[HDD_WLAN_WMM_PARAM_DIRECTION])
{
case HDD_WLAN_WMM_DIRECTION_UPSTREAM:
tSpec.ts_info.direction = SME_QOS_WMM_TS_DIR_UPLINK;
break;
case HDD_WLAN_WMM_DIRECTION_DOWNSTREAM:
tSpec.ts_info.direction = SME_QOS_WMM_TS_DIR_DOWNLINK;
break;
case HDD_WLAN_WMM_DIRECTION_BIDIRECTIONAL:
tSpec.ts_info.direction = SME_QOS_WMM_TS_DIR_BOTH;
break;
default:
// unknown
*pStatus = HDD_WLAN_WMM_STATUS_SETUP_FAILED_BAD_PARAM;
return 0;
}
tSpec.ts_info.psb = params[HDD_WLAN_WMM_PARAM_APSD];
// validate the user priority
if (params[HDD_WLAN_WMM_PARAM_USER_PRIORITY] >= SME_QOS_WMM_UP_MAX)
{
// out of range
*pStatus = HDD_WLAN_WMM_STATUS_SETUP_FAILED_BAD_PARAM;
return 0;
}
tSpec.ts_info.up = params[HDD_WLAN_WMM_PARAM_USER_PRIORITY];
if(0 > tSpec.ts_info.up || SME_QOS_WMM_UP_MAX < tSpec.ts_info.up)
{
hddLog(VOS_TRACE_LEVEL_ERROR,"***ts_info.up out of bounds***");
return 0;
}
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
"%s:TS_INFO PSB %d UP %d !!!", __func__,
tSpec.ts_info.psb, tSpec.ts_info.up);
tSpec.nominal_msdu_size = params[HDD_WLAN_WMM_PARAM_NOMINAL_MSDU_SIZE];
tSpec.maximum_msdu_size = params[HDD_WLAN_WMM_PARAM_MAXIMUM_MSDU_SIZE];
tSpec.min_data_rate = params[HDD_WLAN_WMM_PARAM_MINIMUM_DATA_RATE];
tSpec.mean_data_rate = params[HDD_WLAN_WMM_PARAM_MEAN_DATA_RATE];
tSpec.peak_data_rate = params[HDD_WLAN_WMM_PARAM_PEAK_DATA_RATE];
tSpec.max_burst_size = params[HDD_WLAN_WMM_PARAM_MAX_BURST_SIZE];
tSpec.min_phy_rate = params[HDD_WLAN_WMM_PARAM_MINIMUM_PHY_RATE];
tSpec.surplus_bw_allowance = params[HDD_WLAN_WMM_PARAM_SURPLUS_BANDWIDTH_ALLOWANCE];
tSpec.min_service_interval = params[HDD_WLAN_WMM_PARAM_SERVICE_INTERVAL];
tSpec.max_service_interval = params[HDD_WLAN_WMM_PARAM_MAX_SERVICE_INTERVAL];
tSpec.suspension_interval = params[HDD_WLAN_WMM_PARAM_SUSPENSION_INTERVAL];
tSpec.inactivity_interval = params[HDD_WLAN_WMM_PARAM_INACTIVITY_INTERVAL];
tSpec.ts_info.burst_size_defn = params[HDD_WLAN_WMM_PARAM_BURST_SIZE_DEFN];
// Save the expected UAPSD settings by application, this will be needed
// when re-negotiating UAPSD settings during BT Coex cases.
tSpec.expec_psb_byapp = params[HDD_WLAN_WMM_PARAM_APSD];
// validate the ts info ack policy
switch (params[HDD_WLAN_WMM_PARAM_ACK_POLICY])
{
case HDD_WLAN_WMM_TS_INFO_ACK_POLICY_NORMAL_ACK:
tSpec.ts_info.ack_policy = SME_QOS_WMM_TS_ACK_POLICY_NORMAL_ACK;
break;
case HDD_WLAN_WMM_TS_INFO_ACK_POLICY_HT_IMMEDIATE_BLOCK_ACK:
tSpec.ts_info.ack_policy = SME_QOS_WMM_TS_ACK_POLICY_HT_IMMEDIATE_BLOCK_ACK;
break;
default:
// unknown
*pStatus = HDD_WLAN_WMM_STATUS_SETUP_FAILED_BAD_PARAM;
return 0;
}
*pStatus = hdd_wmm_addts(pAdapter, handle, &tSpec);
EXIT();
return 0;
}
static int iw_add_tspec(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
int ret;
vos_ssr_protect(__func__);
ret = __iw_add_tspec(dev, info, wrqu, extra);
vos_ssr_unprotect(__func__);
return ret;
}
static int __iw_del_tspec(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
hdd_adapter_t *pAdapter;
hdd_context_t *pHddCtx;
int *params = (int *)extra;
hdd_wlan_wmm_status_e *pStatus = (hdd_wlan_wmm_status_e *)extra;
v_U32_t handle;
int ret = 0;
ENTER();
pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
if (NULL == pAdapter)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: Adapter is NULL",__func__);
return -EINVAL;
}
pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
ret = wlan_hdd_validate_context(pHddCtx);
if (0 != ret)
{
return ret;
}
// make sure the application is sufficiently priviledged
// note that the kernel will do this for "set" ioctls, but since
// this ioctl wants to return status to user space it must be
// defined as a "get" ioctl
if (!capable(CAP_NET_ADMIN))
{
return -EPERM;
}
// although we are defined to be a "get" ioctl, the params we require
// will fit in the iwreq_data, therefore unlike iw_add_tspec() there
// is no need to copy the params from user space
// validate the handle
handle = params[HDD_WLAN_WMM_PARAM_HANDLE];
if (HDD_WMM_HANDLE_IMPLICIT == handle)
{
// that one is reserved
*pStatus = HDD_WLAN_WMM_STATUS_SETUP_FAILED_BAD_PARAM;
return 0;
}
*pStatus = hdd_wmm_delts(pAdapter, handle);
EXIT();
return 0;
}
static int iw_del_tspec(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
int ret;
vos_ssr_protect(__func__);
ret = __iw_del_tspec(dev, info, wrqu, extra);
vos_ssr_unprotect(__func__);
return ret;
}
static int __iw_get_tspec(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
hdd_adapter_t *pAdapter;
hdd_context_t *pHddCtx;
int *params = (int *)extra;
hdd_wlan_wmm_status_e *pStatus = (hdd_wlan_wmm_status_e *)extra;
v_U32_t handle;
int ret = 0;
ENTER();
// although we are defined to be a "get" ioctl, the params we require
// will fit in the iwreq_data, therefore unlike iw_add_tspec() there
// is no need to copy the params from user space
pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
if (NULL == pAdapter)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: Adapter is NULL",__func__);
return -EINVAL;
}
pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
ret = wlan_hdd_validate_context(pHddCtx);
if (0 != ret)
{
return ret;
}
// validate the handle
handle = params[HDD_WLAN_WMM_PARAM_HANDLE];
if (HDD_WMM_HANDLE_IMPLICIT == handle)
{
// that one is reserved
*pStatus = HDD_WLAN_WMM_STATUS_SETUP_FAILED_BAD_PARAM;
return 0;
}
*pStatus = hdd_wmm_checkts(pAdapter, handle);
EXIT();
return 0;
}
static int iw_get_tspec(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
int ret;
vos_ssr_protect(__func__);
ret = __iw_get_tspec(dev, info, wrqu, extra);
vos_ssr_unprotect(__func__);
return ret;
}
/**
* __iw_setnone_get_threeint() - return three value to up layer.
*
* @dev: pointer of net_device of this wireless card
* @info: meta data about Request sent
* @wrqu: include request info
* @extra: buf used for in/Output
*
* Return: execute result
*/
static int __iw_setnone_get_threeint(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
int ret = 0; /* success */
uint32_t *value = (int *)extra;
hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
hddLog(VOS_TRACE_LEVEL_INFO, FL("param = %d"), value[0]);
switch (value[0]) {
case WE_GET_TSF:
ret = hdd_indicate_tsf(adapter, value, 3);
break;
default:
hddLog(VOS_TRACE_LEVEL_ERROR,
FL("Invalid IOCTL get_value command %d"),
value[0]);
break;
}
return ret;
}
/**
* iw_setnone_get_threeint() - return three value to up layer.
*
* @dev: pointer of net_device of this wireless card
* @info: meta data about Request sent
* @wrqu: include request info
* @extra: buf used for in/Output
*
* Return: execute result
*/
static int iw_setnone_get_threeint(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
int ret;
vos_ssr_protect(__func__);
ret = __iw_setnone_get_threeint(dev, info, wrqu, extra);
vos_ssr_unprotect(__func__);
return ret;
}
#ifdef WLAN_FEATURE_VOWIFI_11R
//
//
// Each time the supplicant has the auth_request or reassoc request
// IEs ready. This is pushed to the driver. The driver will inturn use
// it to send out the auth req and reassoc req for 11r FT Assoc.
//
static int __iw_set_fties(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
hdd_adapter_t *pAdapter;
hdd_station_ctx_t *pHddStaCtx;
hdd_context_t *pHddCtx;
int ret = 0;
//v_CONTEXT_t pVosContext;
ENTER();
pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
if (NULL == pAdapter)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: Adapter is NULL",__func__);
return -EINVAL;
}
pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
ret = wlan_hdd_validate_context(pHddCtx);
if (0 != ret)
{
return ret;
}
pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
if (NULL == pHddStaCtx)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: STA Context is NULL",__func__);
return -EINVAL;
}
if (!wrqu->data.length)
{
hddLog(LOGE, FL("called with 0 length IEs"));
return -EINVAL;
}
if (wrqu->data.pointer == NULL)
{
hddLog(LOGE, FL("called with NULL IE"));
return -EINVAL;
}
// Added for debug on reception of Re-assoc Req.
if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
{
hddLog(LOGE, FL("Called with Ie of length = %d when not associated"),
wrqu->data.length);
hddLog(LOGE, FL("Should be Re-assoc Req IEs"));
}
#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG
hddLog(LOGE, FL("%s called with Ie of length = %d"), __func__, wrqu->data.length);
#endif
// Pass the received FT IEs to SME
sme_SetFTIEs( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId, extra,
wrqu->data.length);
EXIT();
return 0;
}
static int iw_set_fties(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
int ret;
vos_ssr_protect(__func__);
ret = __iw_set_fties(dev, info, wrqu, extra);
vos_ssr_unprotect(__func__);
return ret;
}
#endif
static int __iw_set_dynamic_mcbc_filter(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
hdd_adapter_t *pAdapter;
tpRcvFltMcAddrList pRequest = (tpRcvFltMcAddrList)extra;
hdd_context_t *pHddCtx;
tpSirWlanSetRxpFilters wlanRxpFilterParam;
tHalHandle hHal;
tpSirRcvFltMcAddrList mc_addr_list_ptr;
int idx;
eHalStatus ret_val;
ENTER();
pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
if (NULL == pAdapter)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: Adapter is NULL",__func__);
return -EINVAL;
}
pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
ret_val = wlan_hdd_validate_context(pHddCtx);
if (0 != ret_val)
{
return ret_val;
}
hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
if (NULL == hHal)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: Hal Context is NULL",__func__);
return -EINVAL;
}
if (HDD_MULTICAST_FILTER_LIST == pRequest->mcastBcastFilterSetting)
{
#ifdef WLAN_FEATURE_PACKET_FILTERING
mc_addr_list_ptr = vos_mem_malloc(sizeof(tSirRcvFltMcAddrList));
if (NULL == mc_addr_list_ptr)
{
hddLog(VOS_TRACE_LEVEL_ERROR,
"%s: vos_mem_alloc failed", __func__);
return -ENOMEM;
}
mc_addr_list_ptr->ulMulticastAddrCnt = pRequest->mcast_addr_cnt;
if (mc_addr_list_ptr->ulMulticastAddrCnt > HDD_MAX_NUM_MULTICAST_ADDRESS)
mc_addr_list_ptr->ulMulticastAddrCnt = HDD_MAX_NUM_MULTICAST_ADDRESS;
hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s MC Addr List Cnt %d", __func__,
mc_addr_list_ptr->ulMulticastAddrCnt);
for (idx = 0; idx < mc_addr_list_ptr->ulMulticastAddrCnt; idx++)
{
memcpy(&mc_addr_list_ptr->multicastAddr[idx],
pRequest->multicastAddr[idx], HDD_WLAN_MAC_ADDR_LEN);
hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s MC Addr for Idx %d ="MAC_ADDRESS_STR, __func__,
idx, MAC_ADDR_ARRAY(mc_addr_list_ptr->multicastAddr[idx]));
}
ret_val = sme_8023MulticastList(hHal, pAdapter->sessionId, mc_addr_list_ptr);
vos_mem_free(mc_addr_list_ptr);
if (eHAL_STATUS_SUCCESS != ret_val)
{
hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failure to Set MC Address List",
__func__);
return -EINVAL;
}
#endif //WLAN_FEATURE_PACKET_FILTERING
}
else
{
hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
"%s: Set MC BC Filter Config request: %d suspend %d",
__func__, pRequest->mcastBcastFilterSetting,
pHddCtx->hdd_wlan_suspended);
spin_lock(&pHddCtx->filter_lock);
pHddCtx->configuredMcastBcastFilter = pRequest->mcastBcastFilterSetting;
spin_unlock(&pHddCtx->filter_lock);
if (pHddCtx->hdd_wlan_suspended)
{
wlanRxpFilterParam = vos_mem_malloc(sizeof(tSirWlanSetRxpFilters));
if (NULL == wlanRxpFilterParam)
{
hddLog(VOS_TRACE_LEVEL_ERROR,
"%s: vos_mem_alloc failed", __func__);
return -EINVAL;
}
wlanRxpFilterParam->configuredMcstBcstFilterSetting =
pRequest->mcastBcastFilterSetting;
wlanRxpFilterParam->setMcstBcstFilter = TRUE;
/* Fwr expect offload needs to clear before set */
hdd_conf_hostoffload(pAdapter, FALSE);
spin_lock(&pHddCtx->filter_lock);
pHddCtx->configuredMcastBcastFilter = pRequest->mcastBcastFilterSetting;
spin_unlock(&pHddCtx->filter_lock);
if (VOS_TRUE == pHddCtx->sus_res_mcastbcast_filter_valid)
{
hddLog(VOS_TRACE_LEVEL_INFO, "%s: pRequest->mcastBcastFilterSetting ", __func__);
pHddCtx->sus_res_mcastbcast_filter =
pRequest->mcastBcastFilterSetting;
}
hdd_conf_hostoffload(pAdapter, TRUE);
wlanRxpFilterParam->configuredMcstBcstFilterSetting =
pHddCtx->configuredMcastBcastFilter;
hddLog(VOS_TRACE_LEVEL_INFO, "%s:MC/BC changed Req %d Set %d En %d",
__func__,
pHddCtx->configuredMcastBcastFilter,
wlanRxpFilterParam->configuredMcstBcstFilterSetting,
wlanRxpFilterParam->setMcstBcstFilter);
if (eHAL_STATUS_SUCCESS !=
sme_ConfigureRxpFilter(WLAN_HDD_GET_HAL_CTX(pAdapter),
wlanRxpFilterParam))
{
hddLog(VOS_TRACE_LEVEL_ERROR,
"%s: Failure to execute set HW MC/BC Filter request",
__func__);
vos_mem_free(wlanRxpFilterParam);
return -EINVAL;
}
/* mc add list cfg item configuration in fwr */
hdd_mc_addr_list_cfg_config(pHddCtx, true);
}
}
EXIT();
return 0;
}
static int iw_set_dynamic_mcbc_filter(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
int ret;
vos_ssr_protect(__func__);
ret = __iw_set_dynamic_mcbc_filter(dev, info, wrqu, extra);
vos_ssr_unprotect(__func__);
return ret;
}
static int __iw_clear_dynamic_mcbc_filter(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
hdd_adapter_t *pAdapter;
hdd_context_t *pHddCtx;
tpSirWlanSetRxpFilters wlanRxpFilterParam;
int ret = 0;
ENTER();
if (!capable(CAP_NET_ADMIN))
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
FL("permission check failed"));
return -EPERM;
}
pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
if (NULL == pAdapter)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: Adapter is NULL",__func__);
return -EINVAL;
}
pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
ret = wlan_hdd_validate_context(pHddCtx);
if (0 != ret)
{
return ret;
}
spin_lock(&pHddCtx->filter_lock);
//Reset the filter to INI value as we have to clear the dynamic filter
pHddCtx->configuredMcastBcastFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting;
spin_unlock(&pHddCtx->filter_lock);
//Configure FW with new setting
if (pHddCtx->hdd_wlan_suspended)
{
wlanRxpFilterParam = vos_mem_malloc(sizeof(tSirWlanSetRxpFilters));
if (NULL == wlanRxpFilterParam)
{
hddLog(VOS_TRACE_LEVEL_ERROR,
"%s: vos_mem_alloc failed", __func__);
return -EINVAL;
}
wlanRxpFilterParam->configuredMcstBcstFilterSetting =
pHddCtx->configuredMcastBcastFilter;
wlanRxpFilterParam->setMcstBcstFilter = TRUE;
/* Fwr expect offload needs to clear before set */
hdd_conf_hostoffload(pAdapter, FALSE);
spin_lock(&pHddCtx->filter_lock);
pHddCtx->configuredMcastBcastFilter =
pHddCtx->cfg_ini->mcastBcastFilterSetting;
spin_unlock(&pHddCtx->filter_lock);
if (VOS_TRUE == pHddCtx->sus_res_mcastbcast_filter_valid)
{
pHddCtx->sus_res_mcastbcast_filter =
pHddCtx->cfg_ini->mcastBcastFilterSetting;
}
hdd_conf_hostoffload(pAdapter, TRUE);
wlanRxpFilterParam->configuredMcstBcstFilterSetting =
pHddCtx->configuredMcastBcastFilter;
if (eHAL_STATUS_SUCCESS !=
sme_ConfigureRxpFilter(WLAN_HDD_GET_HAL_CTX(pAdapter),
wlanRxpFilterParam))
{
hddLog(VOS_TRACE_LEVEL_ERROR,
"%s: Failure to execute set HW MC/BC Filter request",
__func__);
vos_mem_free(wlanRxpFilterParam);
return -EINVAL;
}
/* mc add list cfg item configuration in fwr */
hdd_mc_addr_list_cfg_config(pHddCtx, true);
}
EXIT();
return 0;
}
static int iw_clear_dynamic_mcbc_filter(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
int ret;
vos_ssr_protect(__func__);
ret = __iw_clear_dynamic_mcbc_filter(dev, info, wrqu, extra);
vos_ssr_unprotect(__func__);
return ret;
}
static int __iw_set_host_offload(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
hdd_adapter_t *pAdapter;
hdd_context_t *pHddCtx;
tpHostOffloadRequest pRequest = (tpHostOffloadRequest) extra;
tSirHostOffloadReq offloadRequest;
int ret = 0;
ENTER();
pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
if (NULL == pAdapter)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: Adapter is NULL",__func__);
return -EINVAL;
}
pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
ret = wlan_hdd_validate_context(pHddCtx);
if (0 != ret)
{
return ret;
}
/* Debug display of request components. */
switch (pRequest->offloadType)
{
case WLAN_IPV4_ARP_REPLY_OFFLOAD:
hddLog(VOS_TRACE_LEVEL_WARN, "%s: Host offload request: ARP reply", __func__);
switch (pRequest->enableOrDisable)
{
case WLAN_OFFLOAD_DISABLE:
hddLog(VOS_TRACE_LEVEL_WARN, " disable");
break;
case WLAN_OFFLOAD_ARP_AND_BC_FILTER_ENABLE:
hddLog(VOS_TRACE_LEVEL_WARN, " BC Filtering enable");
case WLAN_OFFLOAD_ENABLE:
hddLog(VOS_TRACE_LEVEL_WARN, " ARP offload enable");
hddLog(VOS_TRACE_LEVEL_WARN, " IP address: %d.%d.%d.%d",
pRequest->params.hostIpv4Addr[0], pRequest->params.hostIpv4Addr[1],
pRequest->params.hostIpv4Addr[2], pRequest->params.hostIpv4Addr[3]);
}
break;
case WLAN_IPV6_NEIGHBOR_DISCOVERY_OFFLOAD:
hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: Host offload request: neighbor discovery",
__func__);
switch (pRequest->enableOrDisable)
{
case WLAN_OFFLOAD_DISABLE:
hddLog(VOS_TRACE_LEVEL_INFO_HIGH, " disable");
break;
case WLAN_OFFLOAD_ENABLE:
hddLog(VOS_TRACE_LEVEL_INFO_HIGH, " enable");
hddLog(VOS_TRACE_LEVEL_INFO_HIGH, " IP address: %x:%x:%x:%x:%x:%x:%x:%x",
*(v_U16_t *)(pRequest->params.hostIpv6Addr),
*(v_U16_t *)(pRequest->params.hostIpv6Addr + 2),
*(v_U16_t *)(pRequest->params.hostIpv6Addr + 4),
*(v_U16_t *)(pRequest->params.hostIpv6Addr + 6),
*(v_U16_t *)(pRequest->params.hostIpv6Addr + 8),
*(v_U16_t *)(pRequest->params.hostIpv6Addr + 10),
*(v_U16_t *)(pRequest->params.hostIpv6Addr + 12),
*(v_U16_t *)(pRequest->params.hostIpv6Addr + 14));
}
}
vos_mem_zero(&offloadRequest, sizeof(offloadRequest));
offloadRequest.offloadType = pRequest->offloadType;
offloadRequest.enableOrDisable = pRequest->enableOrDisable;
vos_mem_copy(&offloadRequest.params, &pRequest->params,
sizeof(pRequest->params));
vos_mem_copy(&offloadRequest.bssId, &pRequest->bssId.bytes,
VOS_MAC_ADDRESS_LEN);
if (eHAL_STATUS_SUCCESS != sme_SetHostOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
pAdapter->sessionId, &offloadRequest))
{
hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failure to execute host offload request",
__func__);
return -EINVAL;
}
EXIT();
return 0;
}
static int iw_set_host_offload(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
int ret;
vos_ssr_protect(__func__);
ret = __iw_set_host_offload(dev, info, wrqu, extra);
vos_ssr_unprotect(__func__);
return ret;
}
static int __iw_set_keepalive_params(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
hdd_adapter_t *pAdapter;
hdd_context_t *pHddCtx;
tpKeepAliveRequest pRequest = (tpKeepAliveRequest) extra;
tSirKeepAliveReq keepaliveRequest;
int ret = 0;
ENTER();
pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
if (NULL == pAdapter)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: Adapter is NULL",__func__);
return -EINVAL;
}
pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
ret = wlan_hdd_validate_context(pHddCtx);
if (0 != ret)
{
return ret;
}
/* Debug display of request components. */
hddLog(VOS_TRACE_LEVEL_INFO,
"%s: Set Keep Alive Request : TimePeriod %d size %zu",
__func__, pRequest->timePeriod, sizeof(tKeepAliveRequest));
switch (pRequest->packetType)
{
case WLAN_KEEP_ALIVE_NULL_PKT:
hddLog(VOS_TRACE_LEVEL_WARN, "%s: Keep Alive Request: Tx NULL", __func__);
break;
case WLAN_KEEP_ALIVE_UNSOLICIT_ARP_RSP:
hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: Keep Alive Request: Tx UnSolicited ARP RSP",
__func__);
hddLog(VOS_TRACE_LEVEL_WARN, " Host IP address: %d.%d.%d.%d",
pRequest->hostIpv4Addr[0], pRequest->hostIpv4Addr[1],
pRequest->hostIpv4Addr[2], pRequest->hostIpv4Addr[3]);
hddLog(VOS_TRACE_LEVEL_WARN, " Dest IP address: %d.%d.%d.%d",
pRequest->destIpv4Addr[0], pRequest->destIpv4Addr[1],
pRequest->destIpv4Addr[2], pRequest->destIpv4Addr[3]);
hddLog(VOS_TRACE_LEVEL_WARN, " Dest MAC address: %d:%d:%d:%d:%d:%d",
pRequest->destMacAddr[0], pRequest->destMacAddr[1],
pRequest->destMacAddr[2], pRequest->destMacAddr[3],
pRequest->destMacAddr[4], pRequest->destMacAddr[5]);
break;
}
/* Execute keep alive request. The reason that we can copy the request information
from the ioctl structure to the SME structure is that they are laid out
exactly the same. Otherwise, each piece of information would have to be
copied individually. */
memcpy(&keepaliveRequest, pRequest, wrqu->data.length);
hddLog(VOS_TRACE_LEVEL_INFO, "set Keep: TP before SME %d",
keepaliveRequest.timePeriod);
if (eHAL_STATUS_SUCCESS != sme_SetKeepAlive(WLAN_HDD_GET_HAL_CTX(pAdapter),
pAdapter->sessionId, &keepaliveRequest))
{
hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failure to execute Keep Alive",
__func__);
return -EINVAL;
}
EXIT();
return 0;
}
static int iw_set_keepalive_params(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
int ret;
vos_ssr_protect(__func__);
ret = __iw_set_keepalive_params(dev, info, wrqu, extra);
vos_ssr_unprotect(__func__);
return ret;
}
#ifdef WLAN_FEATURE_PACKET_FILTERING
/**-----------------------------------------------------------------
\brief hdd_pkt_filter_done - callback to be executed on completion
successful/failure) for clear filter request.
\return - None
--------------------------------------------------------------------------*/
static void hdd_pkt_filter_done(void *data, v_U32_t status)
{
struct hdd_request *request;
hddLog(VOS_TRACE_LEVEL_INFO,
FL("Pkt Filter Clear Status : %d"), status);
request = hdd_request_get(data);
if (!request) {
hddLog(VOS_TRACE_LEVEL_ERROR, FL("Obsolete request"));
if (ioctl_debug)
pr_info("%s: Obsolete request", __func__);
return;
}
hdd_request_complete(request);
hdd_request_put(request);
}
int wlan_hdd_set_filter(hdd_adapter_t *pAdapter, tpPacketFilterCfg pRequest)
{
hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
tSirRcvPktFilterCfgType packetFilterSetReq = {0};
tSirRcvFltPktClearParam packetFilterClrReq = {0};
int i=0, status;
void *cookie;
struct hdd_request *request;
static const struct hdd_request_params params = {
.priv_size = 0,
.timeout_ms = PKT_FILTER_TIMEOUT,
};
status = wlan_hdd_validate_context(pHddCtx);
if (0 != status)
return status;
if (pHddCtx->cfg_ini->disablePacketFilter)
{
hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Packet Filtering Disabled. Returning ",
__func__ );
return 0;
}
if (pHddCtx->isLogpInProgress)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s:LOGP in Progress. Ignore!!!", __func__);
return -EBUSY;
}
/* Debug display of request components. */
hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Packet Filter Request : FA %d params %d",
__func__, pRequest->filterAction, pRequest->numParams);
switch (pRequest->filterAction)
{
case HDD_RCV_FILTER_SET:
hddLog(VOS_TRACE_LEVEL_INFO, "%s: Set Packet Filter Request for Id: %d",
__func__, pRequest->filterId);
packetFilterSetReq.filterId = pRequest->filterId;
if ( pRequest->numParams >= HDD_MAX_CMP_PER_PACKET_FILTER)
{
hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Number of Params exceed Max limit %d",
__func__, pRequest->numParams);
return -EINVAL;
}
packetFilterSetReq.numFieldParams = pRequest->numParams;
packetFilterSetReq.coalesceTime = 0;
packetFilterSetReq.filterType = 1;
for (i=0; i < pRequest->numParams; i++)
{
packetFilterSetReq.paramsData[i].protocolLayer = pRequest->paramsData[i].protocolLayer;
packetFilterSetReq.paramsData[i].cmpFlag = pRequest->paramsData[i].cmpFlag;
packetFilterSetReq.paramsData[i].dataOffset = pRequest->paramsData[i].dataOffset;
packetFilterSetReq.paramsData[i].dataLength = pRequest->paramsData[i].dataLength;
packetFilterSetReq.paramsData[i].reserved = 0;
hddLog(VOS_TRACE_LEVEL_INFO, "Proto %d Comp Flag %d Filter Type %d",
pRequest->paramsData[i].protocolLayer, pRequest->paramsData[i].cmpFlag,
packetFilterSetReq.filterType);
hddLog(VOS_TRACE_LEVEL_INFO, "Data Offset %d Data Len %d",
pRequest->paramsData[i].dataOffset, pRequest->paramsData[i].dataLength);
if ((sizeof(packetFilterSetReq.paramsData[i].compareData)) <
(pRequest->paramsData[i].dataLength))
return -EINVAL;
memcpy(&packetFilterSetReq.paramsData[i].compareData,
pRequest->paramsData[i].compareData, pRequest->paramsData[i].dataLength);
memcpy(&packetFilterSetReq.paramsData[i].dataMask,
pRequest->paramsData[i].dataMask, pRequest->paramsData[i].dataLength);
hddLog(VOS_TRACE_LEVEL_INFO, "CData %d CData %d CData %d CData %d CData %d CData %d",
pRequest->paramsData[i].compareData[0], pRequest->paramsData[i].compareData[1],
pRequest->paramsData[i].compareData[2], pRequest->paramsData[i].compareData[3],
pRequest->paramsData[i].compareData[4], pRequest->paramsData[i].compareData[5]);
hddLog(VOS_TRACE_LEVEL_INFO, "MData %d MData %d MData %d MData %d MData %d MData %d",
pRequest->paramsData[i].dataMask[0], pRequest->paramsData[i].dataMask[1],
pRequest->paramsData[i].dataMask[2], pRequest->paramsData[i].dataMask[3],
pRequest->paramsData[i].dataMask[4], pRequest->paramsData[i].dataMask[5]);
}
if (eHAL_STATUS_SUCCESS != sme_ReceiveFilterSetFilter(pHddCtx->hHal, &packetFilterSetReq, pAdapter->sessionId))
{
hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failure to execute Set Filter",
__func__);
return -EINVAL;
}
WLANTL_SetDataPktFilter((WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
pHddStaCtx->conn_info.staId[0], true);
break;
case HDD_RCV_FILTER_CLEAR:
hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: Clear Packet Filter Request for Id: %d",
__func__, pRequest->filterId);
if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
(WLAN_HDD_P2P_CLIENT == pAdapter->device_mode)) {
WLANTL_ResetRxSSN((WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
pHddStaCtx->conn_info.staId[0]);
}
request = hdd_request_alloc(&params);
if (!request) {
hddLog(VOS_TRACE_LEVEL_ERROR, FL("Request allocation failure"));
return VOS_STATUS_E_NOMEM;
}
cookie = hdd_request_cookie(request);
packetFilterClrReq.cbCtx = cookie;
packetFilterClrReq.filterId = pRequest->filterId;
packetFilterClrReq.pktFilterCallback = hdd_pkt_filter_done;
if (eHAL_STATUS_SUCCESS != sme_ReceiveFilterClearFilter(
pHddCtx->hHal,
&packetFilterClrReq,
pAdapter->sessionId))
{
hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failure to execute Clear Filter",
__func__);
hdd_request_put(request);
return -EINVAL;
}
status = hdd_request_wait_for_response(request);
hdd_request_put(request);
if (status)
{
hddLog(LOGE, FL("failure waiting for pkt_filter_comp_var %d"),
status);
return -EINVAL;
}
WLANTL_SetDataPktFilter((WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
pHddStaCtx->conn_info.staId[0], false);
break;
default :
hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: Packet Filter Request: Invalid %d",
__func__, pRequest->filterAction);
return -EINVAL;
}
return 0;
}
int wlan_hdd_setIPv6Filter(hdd_context_t *pHddCtx, tANI_U8 filterType,
tANI_U8 sessionId)
{
tSirRcvPktFilterCfgType packetFilterSetReq = {0};
tSirRcvFltPktClearParam packetFilterClrReq = {0};
if (NULL == pHddCtx)
{
hddLog(VOS_TRACE_LEVEL_ERROR, FL(" NULL HDD Context Passed"));
return -EINVAL;
}
if (pHddCtx->isLogpInProgress)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
"%s:LOGP in Progress. Ignore!!!", __func__);
return -EBUSY;
}
if (pHddCtx->cfg_ini->disablePacketFilter)
{
hddLog(VOS_TRACE_LEVEL_ERROR,
"%s: Packet Filtering Disabled. Returning ",
__func__ );
return -EINVAL;
}
switch (filterType)
{
/* For setting IPV6 MC and UC Filter we need to configure
* 2 filters, one for MC and one for UC.
* The Filter ID shouldn't be swapped, which results in making
* UC Filter ineffective.
* We have Hardcode all the values
*
* Reason for a seperate UC filter is because, driver need to
* specify the FW that the specific filter is for unicast
* otherwise FW will not pass the unicast frames by default
* through the filter. This is required to avoid any performance
* hits when no unicast filter is set and only MC/BC are set.
* The way driver informs host is by using the MAC protocol
* layer, CMP flag set to MAX, CMP Data set to 1.
*/
case HDD_FILTER_IPV6_MC_UC:
/* Setting IPV6 MC Filter below
*/
packetFilterSetReq.filterType = HDD_RCV_FILTER_SET;
packetFilterSetReq.filterId = HDD_FILTER_ID_IPV6_MC;
packetFilterSetReq.numFieldParams = 2;
packetFilterSetReq.paramsData[0].protocolLayer =
HDD_FILTER_PROTO_TYPE_MAC;
packetFilterSetReq.paramsData[0].cmpFlag =
HDD_FILTER_CMP_TYPE_NOT_EQUAL;
packetFilterSetReq.paramsData[0].dataOffset =
WLAN_HDD_80211_FRM_DA_OFFSET;
packetFilterSetReq.paramsData[0].dataLength = 1;
packetFilterSetReq.paramsData[0].compareData[0] =
HDD_IPV6_MC_CMP_DATA;
packetFilterSetReq.paramsData[1].protocolLayer =
HDD_FILTER_PROTO_TYPE_ARP;
packetFilterSetReq.paramsData[1].cmpFlag =
HDD_FILTER_CMP_TYPE_NOT_EQUAL;
packetFilterSetReq.paramsData[1].dataOffset = ETH_ALEN;
packetFilterSetReq.paramsData[1].dataLength = 2;
packetFilterSetReq.paramsData[1].compareData[0] =
HDD_IPV6_CMP_DATA_0;
packetFilterSetReq.paramsData[1].compareData[1] =
HDD_IPV6_CMP_DATA_1;
if (eHAL_STATUS_SUCCESS != sme_ReceiveFilterSetFilter(pHddCtx->hHal,
&packetFilterSetReq, sessionId))
{
hddLog(VOS_TRACE_LEVEL_ERROR,
"%s: Failure to execute Set IPv6 Mulicast Filter",
__func__);
return -EINVAL;
}
memset( &packetFilterSetReq, 0, sizeof(tSirRcvPktFilterCfgType));
/*
* Setting IPV6 UC Filter below
*/
packetFilterSetReq.filterType = HDD_RCV_FILTER_SET;
packetFilterSetReq.filterId = HDD_FILTER_ID_IPV6_UC;
packetFilterSetReq.numFieldParams = 2;
packetFilterSetReq.paramsData[0].protocolLayer =
HDD_FILTER_PROTO_TYPE_MAC;
packetFilterSetReq.paramsData[0].cmpFlag =
HDD_FILTER_CMP_TYPE_MAX;
packetFilterSetReq.paramsData[0].dataOffset = 0;
packetFilterSetReq.paramsData[0].dataLength = 1;
packetFilterSetReq.paramsData[0].compareData[0] =
HDD_IPV6_UC_CMP_DATA;
packetFilterSetReq.paramsData[1].protocolLayer =
HDD_FILTER_PROTO_TYPE_ARP;
packetFilterSetReq.paramsData[1].cmpFlag =
HDD_FILTER_CMP_TYPE_NOT_EQUAL;
packetFilterSetReq.paramsData[1].dataOffset = ETH_ALEN;
packetFilterSetReq.paramsData[1].dataLength = 2;
packetFilterSetReq.paramsData[1].compareData[0] =
HDD_IPV6_CMP_DATA_0;
packetFilterSetReq.paramsData[1].compareData[1] =
HDD_IPV6_CMP_DATA_1;
if (eHAL_STATUS_SUCCESS != sme_ReceiveFilterSetFilter(pHddCtx->hHal,
&packetFilterSetReq, sessionId))
{
hddLog(VOS_TRACE_LEVEL_ERROR,
"%s: Failure to execute Set IPv6 Unicast Filter",
__func__);
return -EINVAL;
}
break;
case HDD_FILTER_IPV6_MC:
/*
* IPV6 UC Filter might be already set,
* clear the UC Filter. As the Filter
* IDs are static, we can directly clear it.
*/
packetFilterSetReq.filterType = HDD_RCV_FILTER_SET;
packetFilterClrReq.filterId = HDD_FILTER_ID_IPV6_UC;
if (eHAL_STATUS_SUCCESS != sme_ReceiveFilterClearFilter(pHddCtx->hHal,
&packetFilterClrReq, sessionId))
{
hddLog(VOS_TRACE_LEVEL_ERROR,
"%s: Failure to execute Clear IPv6 Unicast Filter",
__func__);
return -EINVAL;
}
/*
* Setting IPV6 MC Filter below
*/
packetFilterSetReq.filterId = HDD_FILTER_ID_IPV6_MC;
packetFilterSetReq.numFieldParams = 2;
packetFilterSetReq.paramsData[0].protocolLayer =
HDD_FILTER_PROTO_TYPE_MAC;
packetFilterSetReq.paramsData[0].cmpFlag =
HDD_FILTER_CMP_TYPE_NOT_EQUAL;
packetFilterSetReq.paramsData[0].dataOffset =
WLAN_HDD_80211_FRM_DA_OFFSET;
packetFilterSetReq.paramsData[0].dataLength = 1;
packetFilterSetReq.paramsData[0].compareData[0] =
HDD_IPV6_MC_CMP_DATA;
packetFilterSetReq.paramsData[1].protocolLayer =
HDD_FILTER_PROTO_TYPE_ARP;
packetFilterSetReq.paramsData[1].cmpFlag =
HDD_FILTER_CMP_TYPE_NOT_EQUAL;
packetFilterSetReq.paramsData[1].dataOffset = ETH_ALEN;
packetFilterSetReq.paramsData[1].dataLength = 2;
packetFilterSetReq.paramsData[1].compareData[0] =
HDD_IPV6_CMP_DATA_0;
packetFilterSetReq.paramsData[1].compareData[1] =
HDD_IPV6_CMP_DATA_1;
if (eHAL_STATUS_SUCCESS != sme_ReceiveFilterSetFilter(pHddCtx->hHal,
&packetFilterSetReq, sessionId))
{
hddLog(VOS_TRACE_LEVEL_ERROR,
"%s: Failure to execute Set IPv6 Multicast Filter",
__func__);
return -EINVAL;
}
break;
default :
hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
"%s: Packet Filter Request: Invalid",
__func__);
return -EINVAL;
}
return 0;
}
void wlan_hdd_set_mc_addr_list(hdd_adapter_t *pAdapter, v_U8_t set)
{
v_U8_t i;
tpSirRcvFltMcAddrList pMulticastAddrs = NULL;
tHalHandle hHal = NULL;
hdd_context_t* pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
if (NULL == pHddCtx)
{
hddLog(VOS_TRACE_LEVEL_ERROR, FL("HDD CTX is NULL"));
return;
}
hHal = pHddCtx->hHal;
if (NULL == hHal)
{
hddLog(VOS_TRACE_LEVEL_ERROR, FL("HAL Handle is NULL"));
return;
}
/* Check if INI is enabled or not, other wise just return
*/
if (pHddCtx->cfg_ini->fEnableMCAddrList)
{
pMulticastAddrs = vos_mem_malloc(sizeof(tSirRcvFltMcAddrList));
if (NULL == pMulticastAddrs)
{
hddLog(VOS_TRACE_LEVEL_ERROR, FL("Could not allocate Memory"));
return;
}
if (set)
{
/* Following pre-conditions should be satisfied before wei
* configure the MC address list.
*/
if (((pAdapter->device_mode == WLAN_HDD_INFRA_STATION) ||
(pAdapter->device_mode == WLAN_HDD_P2P_CLIENT))
&& pAdapter->mc_addr_list.mc_cnt
&& (eConnectionState_Associated ==
(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState))
{
pMulticastAddrs->ulMulticastAddrCnt =
pAdapter->mc_addr_list.mc_cnt;
for (i = 0; i < pAdapter->mc_addr_list.mc_cnt; i++)
{
memcpy(pMulticastAddrs->multicastAddr[i],
pAdapter->mc_addr_list.addr[i],
sizeof(pAdapter->mc_addr_list.addr[i]));
hddLog(VOS_TRACE_LEVEL_INFO,
"%s: %s multicast filter: addr ="
MAC_ADDRESS_STR,
__func__, set ? "setting" : "clearing",
MAC_ADDR_ARRAY(pMulticastAddrs->multicastAddr[i]));
}
/* Set multicast filter */
sme_8023MulticastList(hHal, pAdapter->sessionId,
pMulticastAddrs);
}
}
else
{
/* Need to clear only if it was previously configured
*/
if (pAdapter->mc_addr_list.isFilterApplied)
{
pMulticastAddrs->ulMulticastAddrCnt = 0;
sme_8023MulticastList(hHal, pAdapter->sessionId,
pMulticastAddrs);
}
}
pAdapter->mc_addr_list.isFilterApplied = set ? TRUE : FALSE;
vos_mem_free(pMulticastAddrs);
}
else
{
hddLog(VOS_TRACE_LEVEL_INFO,
FL("gMCAddrListEnable is not enabled in INI"));
}
return;
}
static int __iw_set_packet_filter_params(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
hdd_adapter_t *pAdapter;
hdd_context_t *pHddCtx;
tpPacketFilterCfg pRequest = NULL;
int ret = 0;
struct iw_point s_priv_data;
ENTER();
if (!capable(CAP_NET_ADMIN))
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
FL("permission check failed"));
return -EPERM;
}
pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
if (NULL == pAdapter)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: Adapter is NULL",__func__);
return -EINVAL;
}
pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
ret = wlan_hdd_validate_context(pHddCtx);
if (0 != ret)
{
return ret;
}
if (hdd_priv_get_data(&s_priv_data, wrqu))
{
return -EINVAL;
}
if ((NULL == s_priv_data.pointer) || (0 == s_priv_data.length))
{
return -EINVAL;
}
/* ODD number is used for set, copy data using copy_from_user */
pRequest = mem_alloc_copy_from_user_helper(s_priv_data.pointer,
s_priv_data.length);
if (NULL == pRequest)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"mem_alloc_copy_from_user_helper fail");
return -ENOMEM;
}
ret = wlan_hdd_set_filter(pAdapter, pRequest);
kfree(pRequest);
EXIT();
return ret;
}
static int iw_set_packet_filter_params(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
int ret;
vos_ssr_protect(__func__);
ret = __iw_set_packet_filter_params(dev, info, wrqu, extra);
vos_ssr_unprotect(__func__);
return ret;
}
#endif
static int __iw_get_statistics(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;
hdd_context_t *pHddCtx;
char *p = extra;
int tlen = 0, ret = 0;
tCsrSummaryStatsInfo *pStats;
tCsrGlobalClassAStatsInfo *aStats;
tCsrGlobalClassDStatsInfo *dStats;
ENTER();
pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
if (NULL == pAdapter)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: Adapter is NULL",__func__);
return -EINVAL;
}
pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
ret = wlan_hdd_validate_context(pHddCtx);
if (0 != ret)
{
return ret;
}
pStats = &(pAdapter->hdd_stats.summary_stat);
aStats = &(pAdapter->hdd_stats.ClassA_stat);
dStats = &(pAdapter->hdd_stats.ClassD_stat);
if (eConnectionState_Associated != (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) {
wrqu->txpower.value = 0;
}
else {
status = sme_GetStatistics( pHddCtx->hHal, 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,
(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[0], pAdapter );
if (eHAL_STATUS_SUCCESS != status)
{
hddLog(VOS_TRACE_LEVEL_ERROR,
"%s: Unable to retrieve SME statistics",
__func__);
return -EINVAL;
}
pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
if (NULL == pWextState)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: pWextState is NULL",__func__);
return -EINVAL;
}
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__);
/*Remove the SME statistics list by passing NULL in callback argument*/
status = sme_GetStatistics( pHddCtx->hHal, 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,
NULL, 0, FALSE,
(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[0], pAdapter );
return -EINVAL;
}
FILL_TLV(p, (tANI_U8)WLAN_STATS_RETRY_CNT,
(tANI_U8) sizeof (pStats->retry_cnt),
(char*) &(pStats->retry_cnt[0]),
tlen);
FILL_TLV(p, (tANI_U8)WLAN_STATS_MUL_RETRY_CNT,
(tANI_U8) sizeof (pStats->multiple_retry_cnt),
(char*) &(pStats->multiple_retry_cnt[0]),
tlen);
FILL_TLV(p, (tANI_U8)WLAN_STATS_TX_FRM_CNT,
(tANI_U8) sizeof (pStats->tx_frm_cnt),
(char*) &(pStats->tx_frm_cnt[0]),
tlen);
FILL_TLV(p, (tANI_U8)WLAN_STATS_RX_FRM_CNT,
(tANI_U8) sizeof (pStats->rx_frm_cnt),
(char*) &(pStats->rx_frm_cnt),
tlen);
FILL_TLV(p, (tANI_U8)WLAN_STATS_FRM_DUP_CNT,
(tANI_U8) sizeof (pStats->frm_dup_cnt),
(char*) &(pStats->frm_dup_cnt),
tlen);
FILL_TLV(p, (tANI_U8)WLAN_STATS_FAIL_CNT,
(tANI_U8) sizeof (pStats->fail_cnt),
(char*) &(pStats->fail_cnt[0]),
tlen);
FILL_TLV(p, (tANI_U8)WLAN_STATS_RTS_FAIL_CNT,
(tANI_U8) sizeof (pStats->rts_fail_cnt),
(char*) &(pStats->rts_fail_cnt),
tlen);
FILL_TLV(p, (tANI_U8)WLAN_STATS_ACK_FAIL_CNT,
(tANI_U8) sizeof (pStats->ack_fail_cnt),
(char*) &(pStats->ack_fail_cnt),
tlen);
FILL_TLV(p, (tANI_U8)WLAN_STATS_RTS_SUC_CNT,
(tANI_U8) sizeof (pStats->rts_succ_cnt),
(char*) &(pStats->rts_succ_cnt),
tlen);
FILL_TLV(p, (tANI_U8)WLAN_STATS_RX_DISCARD_CNT,
(tANI_U8) sizeof (pStats->rx_discard_cnt),
(char*) &(pStats->rx_discard_cnt),
tlen);
FILL_TLV(p, (tANI_U8)WLAN_STATS_RX_ERROR_CNT,
(tANI_U8) sizeof (pStats->rx_error_cnt),
(char*) &(pStats->rx_error_cnt),
tlen);
FILL_TLV(p, (tANI_U8)WLAN_STATS_TX_BYTE_CNT,
(tANI_U8) sizeof (dStats->tx_uc_byte_cnt[0]),
(char*) &(dStats->tx_uc_byte_cnt[0]),
tlen);
FILL_TLV(p, (tANI_U8)WLAN_STATS_RX_BYTE_CNT,
(tANI_U8) sizeof (dStats->rx_byte_cnt),
(char*) &(dStats->rx_byte_cnt),
tlen);
FILL_TLV(p, (tANI_U8)WLAN_STATS_RX_RATE,
(tANI_U8) sizeof (dStats->rx_rate),
(char*) &(dStats->rx_rate),
tlen);
/* Transmit rate, in units of 500 kbit/sec */
FILL_TLV(p, (tANI_U8)WLAN_STATS_TX_RATE,
(tANI_U8) sizeof (aStats->tx_rate),
(char*) &(aStats->tx_rate),
tlen);
FILL_TLV(p, (tANI_U8)WLAN_STATS_RX_UC_BYTE_CNT,
(tANI_U8) sizeof (dStats->rx_uc_byte_cnt[0]),
(char*) &(dStats->rx_uc_byte_cnt[0]),
tlen);
FILL_TLV(p, (tANI_U8)WLAN_STATS_RX_MC_BYTE_CNT,
(tANI_U8) sizeof (dStats->rx_mc_byte_cnt),
(char*) &(dStats->rx_mc_byte_cnt),
tlen);
FILL_TLV(p, (tANI_U8)WLAN_STATS_RX_BC_BYTE_CNT,
(tANI_U8) sizeof (dStats->rx_bc_byte_cnt),
(char*) &(dStats->rx_bc_byte_cnt),
tlen);
FILL_TLV(p, (tANI_U8)WLAN_STATS_TX_UC_BYTE_CNT,
(tANI_U8) sizeof (dStats->tx_uc_byte_cnt[0]),
(char*) &(dStats->tx_uc_byte_cnt[0]),
tlen);
FILL_TLV(p, (tANI_U8)WLAN_STATS_TX_MC_BYTE_CNT,
(tANI_U8) sizeof (dStats->tx_mc_byte_cnt),
(char*) &(dStats->tx_mc_byte_cnt),
tlen);
FILL_TLV(p, (tANI_U8)WLAN_STATS_TX_BC_BYTE_CNT,
(tANI_U8) sizeof (dStats->tx_bc_byte_cnt),
(char*) &(dStats->tx_bc_byte_cnt),
tlen);
wrqu->data.length = tlen;
}
EXIT();
return 0;
}
static int iw_get_statistics(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
int ret;
vos_ssr_protect(__func__);
ret = __iw_get_statistics(dev, info, wrqu, extra);
vos_ssr_unprotect(__func__);
return ret;
}
#ifdef FEATURE_WLAN_SCAN_PNO
VOS_STATUS iw_set_rssi_filter(struct net_device *dev, struct iw_request_info *info,
union iwreq_data *wrqu, char *extra, int nOffset)
{
hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
v_U8_t rssiThreshold = 0;
v_U8_t nRead;
nRead = sscanf(extra + nOffset,"%hhu",
&rssiThreshold);
if ( 1 != nRead )
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
"Incorrect format");
return VOS_STATUS_E_FAILURE;
}
sme_SetRSSIFilter(WLAN_HDD_GET_HAL_CTX(pAdapter), rssiThreshold);
return VOS_STATUS_SUCCESS;
}
#endif /*FEATURE_WLAN_SCAN_PNO*/
//Common function to SetBand
int hdd_setBand(struct net_device *dev, u8 ui_band)
{
hdd_adapter_t *pAdapter;
tHalHandle hHal;
hdd_context_t *pHddCtx;
hdd_scaninfo_t *pScanInfo = NULL;
eCsrBand band;
int wait_result;
eCsrBand currBand = eCSR_BAND_MAX;
eCsrBand connectedBand;
tpAniSirGlobal pMac;
int retval = SEND_CHANNEL_CHANGE_EVENT;
ENTER();
pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
if (NULL == pAdapter)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: Adapter is NULL",__func__);
return -EINVAL;
}
pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
retval = wlan_hdd_validate_context(pHddCtx);
if (0 != retval)
{
return retval;
}
hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
if (NULL == hHal)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: Hal Context is NULL",__func__);
return -EINVAL;
}
pMac = PMAC_STRUCT(hHal);
switch(ui_band)
{
case WLAN_HDD_UI_BAND_AUTO:
band = eCSR_BAND_ALL;
break;
case WLAN_HDD_UI_BAND_5_GHZ:
band = eCSR_BAND_5G;
break;
case WLAN_HDD_UI_BAND_2_4_GHZ:
band = eCSR_BAND_24;
break;
default:
band = eCSR_BAND_MAX;
}
connectedBand =
hdd_connGetConnectedBand(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter));
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: change band to %u",
__func__, band);
if (band == eCSR_BAND_MAX)
{
/* Received change band request with invalid band value */
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: Invalid band value %u", __func__, ui_band);
return -EINVAL;
}
if ( (band == eCSR_BAND_24 && pHddCtx->cfg_ini->nBandCapability==2) ||
(band == eCSR_BAND_5G && pHddCtx->cfg_ini->nBandCapability==1) )
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: band value %u violate INI settings %u", __func__,
band, pHddCtx->cfg_ini->nBandCapability);
return -EIO;
}
if (band == eCSR_BAND_ALL)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, FL("Auto Band "
"received. Setting band same as ini value %d"),
pHddCtx->cfg_ini->nBandCapability);
band = pHddCtx->cfg_ini->nBandCapability;
}
if (eHAL_STATUS_SUCCESS != sme_GetFreqBand(hHal, &currBand))
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
"%s: Failed to get current band config",
__func__);
return -EIO;
}
if (currBand != band)
{
if ( band == eCSR_BAND_5G )
{
/* Return failure if current country code is world regulatory domain*/
if( (pMac->scan.countryCodeCurrent[0] == '0' &&
pMac->scan.countryCodeCurrent[1] == '0') )
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: failed to set the band value to %u as country code is 00",
__func__, band);
return -EAGAIN;
}
}
/* Change band request received.
* Abort pending scan requests, flush the existing scan results,
* and change the band capability
*/
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
"%s: Current band value = %u, new setting %u ",
__func__, currBand, band);
/* We need to change the band and flush the scan results here itself
* as we may get timeout for disconnection in which we will return
* with out doing any of these
*/
if (eHAL_STATUS_SUCCESS != sme_SetFreqBand(hHal, (eCsrBand)band))
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
"%s: failed to set the band value to %u ",
__func__, band);
return -EINVAL;
}
if(currBand == eCSR_BAND_24 || currBand == eCSR_BAND_5G)
{
tANI_U8 curr_country[WNI_CFG_COUNTRY_CODE_LEN];
curr_country[0]=pMac->scan.countryCodeCurrent[0];
curr_country[1]=pMac->scan.countryCodeCurrent[1];
INIT_COMPLETION(pHddCtx->linux_reg_req);
/* As currunt band is already set to 2.4Ghz/5Ghz we dont have all channel
* information available in NV so to get the channel information from kernel
* we need to send regulatory hint for the currunt country
* And to set the same country again we need to set the dummy country
* first and then the actual country.
*/
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0))
if(curr_country[0] == '0' && curr_country[1] == '0')
regulatory_hint_user("IN", NL80211_USER_REG_HINT_USER);
else
regulatory_hint_user("00", NL80211_USER_REG_HINT_USER);
#else
if(curr_country[0] == '0' && curr_country[1] == '0')
regulatory_hint_user("IN");
else
regulatory_hint_user("00");
#endif
wait_result = wait_for_completion_interruptible_timeout(
&pHddCtx->linux_reg_req,
msecs_to_jiffies(LINUX_REG_WAIT_TIME));
/* if the country information does not exist with the kernel,
then the driver callback would not be called */
if (wait_result >= 0)
{
VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO,
"runtime country code is found in kernel db");
}
else
{
VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_WARN,
"runtime country code is not found"
" in kernel db");
}
pMac->roam.configParam.fEnforceCountryCode = eANI_BOOLEAN_TRUE;
/*
* Update 11dcountry and current country here as the hint
* with 00 results in 11d and current country with 00
*/
vos_mem_copy(pMac->scan.countryCode11d, curr_country,
WNI_CFG_COUNTRY_CODE_LEN);
vos_mem_copy(pMac->scan.countryCodeCurrent, curr_country,
WNI_CFG_COUNTRY_CODE_LEN);
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0))
regulatory_hint_user(curr_country, NL80211_USER_REG_HINT_USER);
#else
regulatory_hint_user(curr_country);
#endif
wait_result = wait_for_completion_interruptible_timeout(
&pHddCtx->linux_reg_req,
msecs_to_jiffies(LINUX_REG_WAIT_TIME));
/* if the country information does not exist with the kernel,
then the driver callback would not be called */
if (wait_result >= 0)
{
VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO,
"runtime country code is found in kernel db");
}
else
{
VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_WARN,
"runtime country code is not found"
" in kernel db");
}
retval = DO_NOT_SEND_CHANNEL_CHANGE_EVENT;
}
else
{
#ifdef CONFIG_ENABLE_LINUX_REG
vos_update_nv_table_from_wiphy_band((void *)pHddCtx,
(void *)pHddCtx->wiphy, (eCsrBand)band);
#else
wlan_hdd_cfg80211_update_band( pHddCtx->wiphy, (eCsrBand)band );
#endif
}
pScanInfo = &pHddCtx->scan_info;
if ((pScanInfo != NULL) && pHddCtx->scan_info.mScanPending)
{
hdd_abort_mac_scan(pHddCtx, pScanInfo->sessionId,
eCSR_SCAN_ABORT_DUE_TO_BAND_CHANGE);
}
sme_FilterScanResults(hHal, pAdapter->sessionId);
if (band != eCSR_BAND_ALL &&
hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)) &&
(connectedBand != band))
{
eHalStatus status = eHAL_STATUS_SUCCESS;
long lrc;
/* STA already connected on current band, So issue disconnect first,
* then change the band*/
hddLog(VOS_TRACE_LEVEL_INFO,
"%s STA connected in band %u, Changing band to %u, Issuing Disconnect."
, __func__, csrGetCurrentBand(hHal), band);
INIT_COMPLETION(pAdapter->disconnect_comp_var);
status = sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
pAdapter->sessionId, eCSR_DISCONNECT_REASON_UNSPECIFIED);
if ( eHAL_STATUS_SUCCESS != status)
{
hddLog(VOS_TRACE_LEVEL_ERROR,
"%s csrRoamDisconnect failure, returned %d",
__func__, (int)status );
return -EINVAL;
}
lrc = wait_for_completion_interruptible_timeout(
&pAdapter->disconnect_comp_var,
msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
if (lrc <= 0) {
hddLog(VOS_TRACE_LEVEL_ERROR,"%s: %s while waiting for csrRoamDisconnect ",
__func__, (0 == lrc) ? "Timeout" : "Interrupt");
return (0 == lrc) ? -ETIMEDOUT : -EINTR;
}
}
}
EXIT();
if (TRUE == pHddCtx->isSetBandByNL)
return 0;
else
return retval;
}
int hdd_setBand_helper(struct net_device *dev, const char *command)
{
u8 band;
/*convert the band value from ascii to integer*/
band = command[WLAN_HDD_UI_SET_BAND_VALUE_OFFSET] - '0';
return hdd_setBand(dev, band);
}
static int __iw_set_band_config(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
int *value = (int *)extra;
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: ", __func__);
if (!capable(CAP_NET_ADMIN))
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
FL("permission check failed"));
return -EPERM;
}
return hdd_setBand(dev, value[0]);
}
static int iw_set_band_config(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
int ret;
vos_ssr_protect(__func__);
ret = __iw_set_band_config(dev, info, wrqu, extra);
vos_ssr_unprotect(__func__);
return ret;
}
static int __iw_set_power_params_priv(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
int ret;
char *ptr;
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
"Set power params Private");
if (!capable(CAP_NET_ADMIN))
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
FL("permission check failed"));
return -EPERM;
}
/* ODD number is used for set, copy data using copy_from_user */
ptr = mem_alloc_copy_from_user_helper(wrqu->data.pointer,
wrqu->data.length);
if (NULL == ptr)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"mem_alloc_copy_from_user_helper fail");
return -ENOMEM;
}
ret = iw_set_power_params(dev, info, wrqu, ptr, 0);
kfree(ptr);
return ret;
}
static int iw_set_power_params_priv(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
int ret;
vos_ssr_protect(__func__);
ret = __iw_set_power_params_priv(dev, info, wrqu, extra);
vos_ssr_unprotect(__func__);
return ret;
}
/*string based input*/
VOS_STATUS iw_set_power_params(struct net_device *dev, struct iw_request_info *info,
union iwreq_data *wrqu, char *extra, int nOffset)
{
hdd_adapter_t *pAdapter;
hdd_context_t *pHddCtx;
tSirSetPowerParamsReq powerRequest;
char *ptr;
v_U8_t ucType;
v_U32_t uTotalSize, uValue;
int ret = 0;
ENTER();
pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
if (NULL == pAdapter)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: Adapter is NULL",__func__);
return -EINVAL;
}
pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
ret = wlan_hdd_validate_context(pHddCtx);
if (0 != ret)
{
return ret;
}
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
"Power Params data len %d data %s",
wrqu->data.length,
extra);
if (wrqu->data.length <= nOffset )
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, "set power param input is not correct");
return VOS_STATUS_E_FAILURE;
}
uTotalSize = wrqu->data.length - nOffset;
/*-----------------------------------------------------------------------
Input is string based and expected to be like this:
<param_type> <param_value> <param_type> <param_value> ...
e.g:
1 2 2 3 3 0 4 1 5 1
e.g. setting just a few:
1 2 4 1
parameter types:
-----------------------------
1 - Ignore DTIM
2 - Listen Interval
3 - Broadcast Multicas Filter
4 - Beacon Early Termination
5 - Beacon Early Termination Interval
-----------------------------------------------------------------------*/
powerRequest.uIgnoreDTIM = SIR_NOCHANGE_POWER_VALUE;
powerRequest.uListenInterval = SIR_NOCHANGE_POWER_VALUE;
powerRequest.uBcastMcastFilter = SIR_NOCHANGE_POWER_VALUE;
powerRequest.uEnableBET = SIR_NOCHANGE_POWER_VALUE;
powerRequest.uBETInterval = SIR_NOCHANGE_POWER_VALUE;
ptr = extra + nOffset;
while ( uTotalSize )
{
if (1 != sscanf(ptr,"%hhu %n", &(ucType), &nOffset))
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"Invalid input parameter type %s",ptr);
return VOS_STATUS_E_FAILURE;
}
uTotalSize -= nOffset;
if (!uTotalSize)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"Invalid input parameter type : %d with no value at offset %d",
ucType, nOffset);
return VOS_STATUS_E_FAILURE;
}
ptr += nOffset;
if (1 != sscanf(ptr,"%u %n", &(uValue), &nOffset))
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"Invalid input parameter value %s",ptr);
return VOS_STATUS_E_FAILURE;
}
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
"Power request parameter %d value %d offset %d",
ucType, uValue, nOffset);
switch (ucType)
{
case eSIR_IGNORE_DTIM:
powerRequest.uIgnoreDTIM = uValue;
break;
case eSIR_LISTEN_INTERVAL:
powerRequest.uListenInterval = uValue;
break;
case eSIR_MCAST_BCAST_FILTER:
powerRequest.uBcastMcastFilter = uValue;
break;
case eSIR_ENABLE_BET:
powerRequest.uEnableBET = uValue;
break;
case eSIR_BET_INTERVAL:
powerRequest.uBETInterval = uValue;
break;
default:
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"Invalid input parameter type : %d with value: %d at offset %d",
ucType, uValue, nOffset);
return VOS_STATUS_E_FAILURE;
}
uTotalSize -= nOffset;
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
"Power request parameter %d Total size",
uTotalSize);
ptr += nOffset;
/* This is added for dynamic Tele LI enable (0xF1) /disable (0xF0)*/
if(!(uTotalSize - nOffset) &&
(powerRequest.uListenInterval != SIR_NOCHANGE_POWER_VALUE))
{
uTotalSize = 0;
}
}/*Go for as long as we have a valid string*/
/* put the device into full power*/
wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_ACTIVE);
/* Apply the power save params*/
sme_SetPowerParams( WLAN_HDD_GET_HAL_CTX(pAdapter), &powerRequest, FALSE);
/* put the device back to power save*/
wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_AUTO);
EXIT();
return VOS_STATUS_SUCCESS;
}/*iw_set_power_params*/
// tdlsoffchan
#ifdef FEATURE_WLAN_TDLS
int iw_set_tdlsoffchannel(hdd_context_t *pHddCtx, int offchannel)
{
if (offchannel < 0 || offchannel > 165)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: Invalid tdls off channel %u",
__func__, offchannel);
return -1;
}
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: change tdls off channel from %d to %d",
__func__, tdlsOffCh, offchannel);
tdlsOffCh = offchannel;
return 0;
}
int iw_set_tdlssecoffchanneloffset(hdd_context_t *pHddCtx, int offchanoffset)
{
if (offchanoffset == 0)
{
tdlsOffChBwOffset = 1;
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: change tdls secondary off channel offset to %u",
__func__, tdlsOffChBwOffset);
return 0;
}
if ( offchanoffset == 40 )
{
tdlsOffChBwOffset = 2;
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: change tdls secondary off channel offset to %u",
__func__, tdlsOffChBwOffset);
return 0;
}
if (offchanoffset == -40)
{
tdlsOffChBwOffset = 3;
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: change tdls secondary off channel offset to %u",
__func__, tdlsOffChBwOffset);
return 0;
}
if ((offchanoffset == 80) &&
(TRUE == sme_IsFeatureSupportedByFW(DOT11AC)) &&
(TRUE == sme_IsFeatureSupportedByDriver(DOT11AC)))
{
tdlsOffChBwOffset = 4;
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
"%s: change tdls secondary off channel offset to %u",
__func__, tdlsOffChBwOffset);
return 0;
}
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: Invalid tdls secondary off channel offset %d",
__func__, offchanoffset);
return -1;
}
int iw_set_tdlsoffchannelmode(hdd_adapter_t *pAdapter, int offchanmode)
{
hddTdlsPeer_t *connPeer = NULL;
hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
tSirMacAddr peerMac;
if (offchanmode < 0 || offchanmode > 4)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: Invalid tdls off channel mode %d",
__func__, offchanmode);
return -1;
}
if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: tdls off channel mode req in not associated state %d",
__func__, offchanmode);
return -1;
}
if (eTDLS_SUPPORT_ENABLED == pHddCtx->tdls_mode ||
eTDLS_SUPPORT_EXPLICIT_TRIGGER_ONLY == pHddCtx->tdls_mode)
{
/* Send TDLS Channel Switch Request to connected peer */
mutex_lock(&pHddCtx->tdls_lock);
connPeer = wlan_hdd_tdls_get_connected_peer(pAdapter);
if (NULL == connPeer) {
mutex_unlock(&pHddCtx->tdls_lock);
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
"%s: No TDLS Connected Peer", __func__);
return -1;
}
vos_mem_copy(peerMac, connPeer->peerMac, sizeof(tSirMacAddr));
mutex_unlock(&pHddCtx->tdls_lock);
}
else
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
"%s: TDLS Connection not supported", __func__);
return -1;
}
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
("%s: TDLS Channel Switch in swmode=%d"),
__func__, offchanmode);
switch (offchanmode)
{
case 1:/*Enable*/
case 2:/*Disable*/
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
"%s: change tdls off channel mode %d tdls_off_channel %d offchanoffset %d ",
__func__, offchanmode, tdlsOffCh, tdlsOffChBwOffset);
if (TRUE == pHddCtx->cfg_ini->fEnableTDLSOffChannel)
{
sme_SendTdlsChanSwitchReq(WLAN_HDD_GET_HAL_CTX(pAdapter),
pAdapter->sessionId, peerMac,
tdlsOffCh, tdlsOffChBwOffset,
offchanmode);
}
else
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: TDLS Off Channel not supported", __func__);
return -1;
}
break;
}
case 3:
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
"%s: change tdls off channel mode %d REJREQ 3 tdls_off_channel %d offchanoffset %d ",
__func__, offchanmode, tdlsOffCh, tdlsOffChBwOffset);
break;
}
case 4:
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
"%s: change tdls off channel mode %d UNSOLRESP 4 tdls_off_channel %d offchanoffset %d ",
__func__, offchanmode, tdlsOffCh, tdlsOffChBwOffset);
break;
}
default:
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: change tdls off channel mode %d Not SET 0 tdls_off_channel %d offchanoffset %d ",
__func__, offchanmode, tdlsOffCh, tdlsOffChBwOffset);
break;
}
}
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: change tdls off channel mode to %u",
__func__, offchanmode);
return 0;
}
#endif
// Define the Wireless Extensions to the Linux Network Device structure
// A number of these routines are NULL (meaning they are not implemented.)
static const iw_handler we_handler[] =
{
(iw_handler) iw_set_commit, /* SIOCSIWCOMMIT */
(iw_handler) iw_get_name, /* SIOCGIWNAME */
(iw_handler) NULL, /* SIOCSIWNWID */
(iw_handler) NULL, /* SIOCGIWNWID */
(iw_handler) iw_set_freq, /* SIOCSIWFREQ */
(iw_handler) iw_get_freq, /* SIOCGIWFREQ */
(iw_handler) NULL, /* SIOCSIWMODE */
(iw_handler) NULL, /* SIOCGIWMODE */
(iw_handler) NULL, /* SIOCSIWSENS */
(iw_handler) NULL, /* SIOCGIWSENS */
(iw_handler) NULL, /* SIOCSIWRANGE */
(iw_handler) iw_get_range, /* SIOCGIWRANGE */
(iw_handler) iw_set_priv, /* SIOCSIWPRIV */
(iw_handler) NULL, /* SIOCGIWPRIV */
(iw_handler) NULL, /* SIOCSIWSTATS */
(iw_handler) NULL, /* SIOCGIWSTATS */
iw_handler_set_spy, /* SIOCSIWSPY */
iw_handler_get_spy, /* SIOCGIWSPY */
iw_handler_set_thrspy, /* SIOCSIWTHRSPY */
iw_handler_get_thrspy, /* SIOCGIWTHRSPY */
(iw_handler) iw_set_ap_address, /* SIOCSIWAP */
(iw_handler) iw_get_ap_address, /* SIOCGIWAP */
(iw_handler) iw_set_mlme, /* SIOCSIWMLME */
(iw_handler) NULL, /* SIOCGIWAPLIST */
(iw_handler) iw_set_scan, /* SIOCSIWSCAN */
(iw_handler) iw_get_scan, /* SIOCGIWSCAN */
(iw_handler) iw_set_essid, /* SIOCSIWESSID */
(iw_handler) iw_get_essid, /* SIOCGIWESSID */
(iw_handler) iw_set_nick, /* SIOCSIWNICKN */
(iw_handler) iw_get_nick, /* SIOCGIWNICKN */
(iw_handler) NULL, /* -- hole -- */
(iw_handler) NULL, /* -- hole -- */
(iw_handler) iw_set_bitrate, /* SIOCSIWRATE */
(iw_handler) iw_get_bitrate, /* SIOCGIWRATE */
(iw_handler) iw_set_rts_threshold,/* SIOCSIWRTS */
(iw_handler) iw_get_rts_threshold,/* SIOCGIWRTS */
(iw_handler) iw_set_frag_threshold, /* SIOCSIWFRAG */
(iw_handler) iw_get_frag_threshold, /* SIOCGIWFRAG */
(iw_handler) iw_set_tx_power, /* SIOCSIWTXPOW */
(iw_handler) iw_get_tx_power, /* SIOCGIWTXPOW */
(iw_handler) iw_set_retry, /* SIOCSIWRETRY */
(iw_handler) iw_get_retry, /* SIOCGIWRETRY */
(iw_handler) iw_set_encode, /* SIOCSIWENCODE */
(iw_handler) iw_get_encode, /* SIOCGIWENCODE */
(iw_handler) iw_set_power_mode, /* SIOCSIWPOWER */
(iw_handler) iw_get_power_mode, /* SIOCGIWPOWER */
(iw_handler) NULL, /* -- hole -- */
(iw_handler) NULL, /* -- hole -- */
(iw_handler) iw_set_genie, /* SIOCSIWGENIE */
(iw_handler) iw_get_genie, /* SIOCGIWGENIE */
(iw_handler) iw_set_auth, /* SIOCSIWAUTH */
(iw_handler) iw_get_auth, /* SIOCGIWAUTH */
(iw_handler) iw_set_encodeext, /* SIOCSIWENCODEEXT */
(iw_handler) iw_get_encodeext, /* SIOCGIWENCODEEXT */
(iw_handler) NULL, /* SIOCSIWPMKSA */
};
static const iw_handler we_private[] = {
[WLAN_PRIV_SET_INT_GET_NONE - SIOCIWFIRSTPRIV] = iw_setint_getnone, //set priv ioctl
[WLAN_PRIV_SET_NONE_GET_INT - SIOCIWFIRSTPRIV] = iw_setnone_getint, //get priv ioctl
[WLAN_PRIV_SET_CHAR_GET_NONE - SIOCIWFIRSTPRIV] = iw_setchar_getnone, //get priv ioctl
[WLAN_PRIV_SET_THREE_INT_GET_NONE - SIOCIWFIRSTPRIV] = iw_set_three_ints_getnone,
[WLAN_PRIV_GET_CHAR_SET_NONE - SIOCIWFIRSTPRIV] = iw_get_char_setnone,
[WLAN_PRIV_SET_NONE_GET_NONE - SIOCIWFIRSTPRIV] = iw_setnone_getnone, //action priv ioctl
[WLAN_PRIV_SET_VAR_INT_GET_NONE - SIOCIWFIRSTPRIV] = iw_hdd_set_var_ints_getnone,
[WLAN_PRIV_ADD_TSPEC - SIOCIWFIRSTPRIV] = iw_add_tspec,
[WLAN_PRIV_DEL_TSPEC - SIOCIWFIRSTPRIV] = iw_del_tspec,
[WLAN_PRIV_GET_TSPEC - SIOCIWFIRSTPRIV] = iw_get_tspec,
[WLAN_PRIV_SET_NONE_GET_THREE_INT - SIOCIWFIRSTPRIV] =
iw_setnone_get_threeint,
#ifdef FEATURE_OEM_DATA_SUPPORT
[WLAN_PRIV_SET_OEM_DATA_REQ - SIOCIWFIRSTPRIV] = iw_set_oem_data_req, //oem data req Specifc
[WLAN_PRIV_GET_OEM_DATA_RSP - SIOCIWFIRSTPRIV] = iw_get_oem_data_rsp, //oem data req Specifc
#endif
#ifdef WLAN_FEATURE_VOWIFI_11R
[WLAN_PRIV_SET_FTIES - SIOCIWFIRSTPRIV] = iw_set_fties,
#endif
[WLAN_PRIV_SET_HOST_OFFLOAD - SIOCIWFIRSTPRIV] = iw_set_host_offload,
[WLAN_GET_WLAN_STATISTICS - SIOCIWFIRSTPRIV] = iw_get_statistics,
[WLAN_SET_KEEPALIVE_PARAMS - SIOCIWFIRSTPRIV] = iw_set_keepalive_params
#ifdef WLAN_FEATURE_PACKET_FILTERING
,
[WLAN_SET_PACKET_FILTER_PARAMS - SIOCIWFIRSTPRIV] = iw_set_packet_filter_params
#endif
,
[WLAN_SET_BAND_CONFIG - SIOCIWFIRSTPRIV] = iw_set_band_config,
[WLAN_PRIV_SET_MCBC_FILTER - SIOCIWFIRSTPRIV] = iw_set_dynamic_mcbc_filter,
[WLAN_PRIV_CLEAR_MCBC_FILTER - SIOCIWFIRSTPRIV] = iw_clear_dynamic_mcbc_filter,
[WLAN_SET_POWER_PARAMS - SIOCIWFIRSTPRIV] = iw_set_power_params_priv,
[WLAN_GET_LINK_SPEED - SIOCIWFIRSTPRIV] = iw_get_linkspeed_priv,
};
static const iw_handler we_mon_private[] = {
[WLAN_PRIV_SET_INT_GET_NONE - SIOCIWFIRSTPRIV] =
iw_mon_setint_getnone,
};
static const struct iw_priv_args we_mon_private_args[] = {
{WE_SET_MONITOR_STATE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
0, "monitor"},
/* handlers for main ioctl */
{WLAN_PRIV_SET_INT_GET_NONE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
0, "" },
};
/*Maximum command length can be only 15 */
static const struct iw_priv_args we_private_args[] = {
{ WE_SET_MONITOR_STATE,
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
0, "monitor" },
/* handlers for main ioctl */
{ WLAN_PRIV_SET_INT_GET_NONE,
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
0,
"" },
/* handlers for sub-ioctl */
{ WE_SET_11D_STATE,
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
0,
"set11Dstate" },
{ WE_WOWL,
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
0,
"wowl" },
{ WE_SET_POWER,
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
0,
"setPower" },
{ WE_SET_MAX_ASSOC,
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
0,
"setMaxAssoc" },
{ WE_SET_SAP_AUTO_CHANNEL_SELECTION,
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
0,
"setAutoChannel" },
{ WE_SET_DATA_INACTIVITY_TO,
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
0,
"inactivityTO" },
{ WE_SET_MAX_TX_POWER,
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
0,
"setMaxTxPower" },
{ WE_SET_MAX_TX_POWER_2_4,
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
0,
"setTxMaxPower2G" },
{ WE_SET_MAX_TX_POWER_5_0,
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
0,
"setTxMaxPower5G" },
/* SAP has TxMax whereas STA has MaxTx, adding TxMax for STA
* as well to keep same syntax as in SAP. Now onwards, STA
* will support both */
{ WE_SET_MAX_TX_POWER,
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
0,
"setTxMaxPower" },
/* set Higher DTIM Transition (DTIM1 to DTIM3)
* 1 = enable and 0 = disable */
{
WE_SET_HIGHER_DTIM_TRANSITION,
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
0,
"setHDtimTransn" },
{ WE_SET_TM_LEVEL,
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
0,
"setTmLevel" },
{ WE_ENABLE_STRICT_FCC_REG,
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
0,
"setStrictFCCreg" },
{ WE_SET_DEBUG_LOG,
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
0, "setDbgLvl" },
#ifdef FEATURE_WLAN_TDLS
{
WE_SET_TDLS_OFF_CHAN,
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
0,
"tdlsoffchan" },
{
WE_SET_TDLS_SEC_OFF_CHAN_OFFSET,
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
0,
"tdlsecchnoffst" },
{
WE_SET_TDLS_OFF_CHAN_MODE,
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
0,
"tdlsoffchnmode" },
#endif
{ WE_SET_SCAN_BAND_PREFERENCE,
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
0, "set_scan_pref" },
{
WE_GET_FRAME_LOG,
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
0,
"getFrameLogs" },
{ WE_SET_MIRACAST_VENDOR_CONFIG,
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
0, "setMiracstConf" },
#ifdef FEATURE_WLAN_TDLS
{
WE_SET_TDLS_2040_BSS_COEXISTENCE,
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
0,
"tdls_2040bsscox" },
#endif
{ WE_SET_RTS_CTS_HTVHT,
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
0, "setRtsCtsHtVht" },
{ WE_SET_PKT_STATS_ENABLE_DISABLE,
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
0, "setPktStats" },
{ WE_SET_PROXIMITY_ENABLE,
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
0, "setProximity" },
#ifdef WLAN_FEATURE_TSF
{ WE_CAP_TSF,
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
0, "cap_tsf" },
#endif
{ WE_SET_MODULATED_DTIM,
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
0, "setModDTIM" },
{
WLAN_SET_DYNNAMIC_AGGREGATION,
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
0, "setAggregation" },
/* handlers for main ioctl */
{ WLAN_PRIV_SET_NONE_GET_INT,
0,
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
"" },
/* handlers for sub-ioctl */
{ WE_GET_11D_STATE,
0,
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
"get11Dstate" },
{ WE_IBSS_STATUS,
0,
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
"getAdhocStatus" },
{ WE_PMC_STATE,
0,
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
"pmcState" },
{ WE_GET_WLAN_DBG,
0,
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
"getwlandbg" },
{ WE_GET_MAX_ASSOC,
0,
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
"getMaxAssoc" },
{ WE_GET_WDI_DBG,
0,
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
"getwdidbg" },
{ WE_GET_SAP_AUTO_CHANNEL_SELECTION,
0,
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
"getAutoChannel" },
{ WE_GET_CONCURRENCY_MODE,
0,
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
"getconcurrency" },
{ WE_GET_SCAN_BAND_PREFERENCE,
0,
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
"get_scan_pref"},
{ WE_GET_ANTENA_DIVERSITY_SELECTION,
0,
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
"getCurAnt"},
/* handlers for main ioctl */
{ WLAN_PRIV_SET_CHAR_GET_NONE,
IW_PRIV_TYPE_CHAR| 512,
0,
"" },
/* handlers for sub-ioctl */
{ WE_WOWL_ADD_PTRN,
IW_PRIV_TYPE_CHAR| 512,
0,
"wowlAddPtrn" },
{ WE_WOWL_DEL_PTRN,
IW_PRIV_TYPE_CHAR| 512,
0,
"wowlDelPtrn" },
#if defined WLAN_FEATURE_VOWIFI
/* handlers for sub-ioctl */
{ WE_NEIGHBOR_REPORT_REQUEST,
IW_PRIV_TYPE_CHAR | 512,
0,
"neighbor" },
#endif
{ WE_SET_AP_WPS_IE,
IW_PRIV_TYPE_CHAR| 512,
0,
"set_ap_wps_ie" },
{ WE_SET_CONFIG,
IW_PRIV_TYPE_CHAR| 512,
0,
"setConfig" },
{ WE_SET_ENCRYPT_MSG,
IW_PRIV_TYPE_CHAR| 512,
0,
"encryptMsg" },
/* handlers for main ioctl */
{ WLAN_PRIV_SET_THREE_INT_GET_NONE,
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3,
0,
"" },
/* handlers for sub-ioctl */
{ WE_SET_WLAN_DBG,
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3,
0,
"setwlandbg" },
{ WE_SET_WDI_DBG,
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3,
0,
"setwdidbg" },
{ WE_SET_SAP_CHANNELS,
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3,
0,
"setsapchannels" },
/* handlers for main ioctl */
{ WLAN_PRIV_GET_CHAR_SET_NONE,
0,
IW_PRIV_TYPE_CHAR| WE_MAX_STR_LEN,
"" },
/* handlers for sub-ioctl */
{ WE_WLAN_VERSION,
0,
IW_PRIV_TYPE_CHAR| WE_MAX_STR_LEN,
"version" },
{ WE_GET_STATS,
0,
IW_PRIV_TYPE_CHAR| WE_MAX_STR_LEN,
"getStats" },
{ WE_GET_STATES,
0,
IW_PRIV_TYPE_CHAR| WE_MAX_STR_LEN,
"getHostStates" },
{ WE_GET_CFG,
0,
IW_PRIV_TYPE_CHAR| WE_MAX_STR_LEN,
"getConfig" },
#ifdef WLAN_FEATURE_11AC
{ WE_GET_RSSI,
0,
IW_PRIV_TYPE_CHAR| WE_MAX_STR_LEN,
"getRSSI" },
#endif
#if defined WLAN_FEATURE_VOWIFI_11R || defined FEATURE_WLAN_ESE || defined(FEATURE_WLAN_LFR)
{ WE_GET_ROAM_RSSI,
0,
IW_PRIV_TYPE_CHAR| WE_MAX_STR_LEN,
"getRoamRSSI" },
#endif
{ WE_GET_WMM_STATUS,
0,
IW_PRIV_TYPE_CHAR| WE_MAX_STR_LEN,
"getWmmStatus" },
{
WE_GET_CHANNEL_LIST,
0,
IW_PRIV_TYPE_CHAR| WE_MAX_STR_LEN,
"getChannelList" },
#ifdef FEATURE_WLAN_TDLS
{
WE_GET_TDLS_PEERS,
0,
IW_PRIV_TYPE_CHAR| WE_MAX_STR_LEN,
"getTdlsPeers" },
#endif
#ifdef WLAN_FEATURE_11W
{
WE_GET_11W_INFO,
0,
IW_PRIV_TYPE_CHAR| WE_MAX_STR_LEN,
"getPMFInfo" },
#endif
#ifdef WLAN_FEATURE_RMC
{
WE_GET_IBSS_STA_INFO,
0,
IW_PRIV_TYPE_CHAR| WE_MAX_STR_LEN,
"getIbssSTAs" },
#endif
{ WE_GET_SNR,
0,
IW_PRIV_TYPE_CHAR| WE_MAX_STR_LEN,
"getSNR" },
#ifdef FEATURE_OEM_DATA_SUPPORT
{
WE_GET_OEM_DATA_CAP,
0,
IW_PRIV_TYPE_CHAR| WE_MAX_STR_LEN,
"getOemDataCap" },
#endif /* FEATURE_OEM_DATA_SUPPORT */
/* handlers for main ioctl */
{ WLAN_PRIV_SET_NONE_GET_NONE,
0,
0,
"" },
/* handlers for sub-ioctl */
{ WE_CLEAR_STATS,
0,
0,
"clearStats" },
{ WE_INIT_AP,
0,
0,
"initAP" },
#ifdef WLAN_FEATURE_RMC
{
WE_IBSS_GET_PEER_INFO_ALL,
0,
0,
"ibssPeerInfoAll" },
#endif
{ WE_STOP_AP,
0,
0,
"exitAP" },
#ifdef WLAN_BTAMP_FEATURE
{ WE_ENABLE_AMP,
0,
0,
"enableAMP" },
{ WE_DISABLE_AMP,
0,
0,
"disableAMP" },
#endif /* WLAN_BTAMP_FEATURE */
{ WE_ENABLE_DXE_STALL_DETECT,
0,
0,
"dxeStallDetect" },
{ WE_DISPLAY_DXE_SNAP_SHOT,
0,
0,
"dxeSnapshot" },
{ WE_DISPLAY_DATAPATH_SNAP_SHOT,
0,
0,
"dataSnapshot"},
{
WE_SET_REASSOC_TRIGGER,
0,
0,
"reassoc" },
{
WE_STOP_OBSS_SCAN,
0,
0,
"stopOBSSScan" },
{
WE_DUMP_ROAM_TIMER_LOG,
0,
0,
"dumpRoamDelay" },
{
WE_RESET_ROAM_TIMER_LOG,
0,
0,
"resetRoamDelay" },
{
WE_GET_FW_LOGS,
0,
0,
"getFwLogs" },
{
WE_GET_FW_MEMDUMP,
0,
0,
"getFwMemDump" },
/* handlers for main ioctl */
{ WLAN_PRIV_SET_VAR_INT_GET_NONE,
IW_PRIV_TYPE_INT | MAX_VAR_ARGS,
0,
"" },
/* handlers for sub-ioctl */
{ WE_LOG_DUMP_CMD,
IW_PRIV_TYPE_INT | MAX_VAR_ARGS,
0,
"dump" },
#ifdef WLAN_FEATURE_RMC
{ WE_IBSS_GET_PEER_INFO,
IW_PRIV_TYPE_INT | MAX_VAR_ARGS,
0,
"ibssPeerInfo" },
#endif
/* handlers for sub-ioctl */
{ WE_MTRACE_SELECTIVE_MODULE_LOG_ENABLE_CMD,
IW_PRIV_TYPE_INT | MAX_VAR_ARGS,
0,
"setdumplog" },
{ WE_MTRACE_DUMP_CMD,
IW_PRIV_TYPE_INT | MAX_VAR_ARGS,
0,
"dumplog" },
/* handlers for sub ioctl */
{
WE_MCC_CONFIG_CREDENTIAL,
IW_PRIV_TYPE_INT | MAX_VAR_ARGS,
0,
"setMccCrdnl" },
/* handlers for sub ioctl */
{
WE_MCC_CONFIG_PARAMS,
IW_PRIV_TYPE_INT | MAX_VAR_ARGS,
0,
"setMccConfig" },
#ifdef FEATURE_WLAN_TDLS
/* handlers for sub ioctl */
{
WE_TDLS_CONFIG_PARAMS,
IW_PRIV_TYPE_INT | MAX_VAR_ARGS,
0,
"setTdlsConfig" },
#endif
{
WE_CONFIGURE_MONITOR_MODE,
IW_PRIV_TYPE_INT | MAX_VAR_ARGS,
0,
"MonitorModeConf" },
{
WE_SET_MONITOR_MODE_FILTER,
IW_PRIV_TYPE_INT | MAX_VAR_ARGS,
0,
"MonitorFilter" },
/* handlers for main ioctl */
{ WLAN_PRIV_ADD_TSPEC,
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | HDD_WLAN_WMM_PARAM_COUNT,
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
"addTspec" },
/* handlers for main ioctl */
{ WLAN_PRIV_DEL_TSPEC,
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
"delTspec" },
/* handlers for main ioctl */
{ WLAN_PRIV_GET_TSPEC,
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
"getTspec" },
/* handlers for main ioctl */
{ WLAN_PRIV_SET_NONE_GET_THREE_INT,
0,
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3,
"" },
#ifdef WLAN_FEATURE_TSF
{ WE_GET_TSF,
0,
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3,
"get_tsf" },
#endif
#ifdef FEATURE_OEM_DATA_SUPPORT
/* handlers for main ioctl - OEM DATA */
{
WLAN_PRIV_SET_OEM_DATA_REQ,
IW_PRIV_TYPE_BYTE | sizeof(struct iw_oem_data_req) | IW_PRIV_SIZE_FIXED,
0,
"set_oem_data_req" },
/* handlers for main ioctl - OEM DATA */
{
WLAN_PRIV_GET_OEM_DATA_RSP,
0,
IW_PRIV_TYPE_BYTE | MAX_OEM_DATA_RSP_LEN,
"get_oem_data_rsp" },
#endif
/* handlers for main ioctl - host offload */
{
WLAN_PRIV_SET_HOST_OFFLOAD,
IW_PRIV_TYPE_BYTE | sizeof(tHostOffloadRequest),
0,
"setHostOffload" },
{
WLAN_GET_WLAN_STATISTICS,
0,
IW_PRIV_TYPE_BYTE | WE_MAX_STR_LEN,
"getWlanStats" },
{
WLAN_SET_KEEPALIVE_PARAMS,
IW_PRIV_TYPE_BYTE | sizeof(tKeepAliveRequest) |
IW_PRIV_SIZE_FIXED,
0,
"setKeepAlive" },
#ifdef WLAN_FEATURE_PACKET_FILTERING
{
WLAN_SET_PACKET_FILTER_PARAMS,
IW_PRIV_TYPE_BYTE | sizeof(tPacketFilterCfg),
0,
"setPktFilter" },
#endif
#ifdef FEATURE_WLAN_SCAN_PNO
{
WLAN_SET_PNO,
IW_PRIV_TYPE_CHAR| WE_MAX_STR_LEN,
0,
"setpno" },
#endif
{
WLAN_SET_BAND_CONFIG,
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
0,
"SETBAND" },
/* handlers for dynamic MC BC ioctl */
{
WLAN_PRIV_SET_MCBC_FILTER,
IW_PRIV_TYPE_BYTE | sizeof(tRcvFltMcAddrList),
0,
"setMCBCFilter" },
{
WLAN_PRIV_CLEAR_MCBC_FILTER,
0,
0,
"clearMCBCFilter" },
{
WLAN_SET_POWER_PARAMS,
IW_PRIV_TYPE_CHAR| WE_MAX_STR_LEN,
0,
"setpowerparams" },
{
WLAN_GET_LINK_SPEED,
IW_PRIV_TYPE_CHAR | 18,
IW_PRIV_TYPE_CHAR | 5, "getLinkSpeed" },
{
WLAN_PRIV_SET_FTIES,
IW_PRIV_TYPE_CHAR | MAX_FTIE_SIZE,
0, "set_ft_ies"},
};
const struct iw_handler_def we_handler_def = {
.num_standard = sizeof(we_handler) / sizeof(we_handler[0]),
.num_private = sizeof(we_private) / sizeof(we_private[0]),
.num_private_args = sizeof(we_private_args) / sizeof(we_private_args[0]),
.standard = (iw_handler *)we_handler,
.private = (iw_handler *)we_private,
.private_args = we_private_args,
.get_wireless_stats = get_wireless_stats,
};
const struct iw_handler_def we_mon_handler_def = {
.num_standard = 0,
.num_private = sizeof(we_mon_private) / sizeof(we_mon_private[0]),
.num_private_args =
sizeof(we_mon_private_args) / sizeof(we_mon_private_args[0]),
.standard = NULL,
.private = (iw_handler *)we_mon_private,
.private_args = we_mon_private_args,
.get_wireless_stats = NULL,
};
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)
{
v_U32_t cmd = 288; //Command to RIVA
hdd_context_t *pHddCtx = NULL;
tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
/*
*configMccParam : specify the bit which needs to be modified
*allowed to update based on wlan_qcom_cfg.ini
* configuration
* Bit 0 : SCHEDULE_TIME_SLICE MIN : 5 MAX : 20
* Bit 1 : MAX_NULL_SEND_TIME MIN : 1 MAX : 10
* Bit 2 : TX_EARLY_STOP_TIME MIN : 1 MAX : 10
* Bit 3 : RX_DRAIN_TIME MIN : 1 MAX : 10
* Bit 4 : CHANNEL_SWITCH_TIME MIN : 1 MAX : 20
* Bit 5 : MIN_CHANNEL_TIME MIN : 5 MAX : 20
* Bit 6 : PARK_BEFORE_TBTT MIN : 1 MAX : 5
* Bit 7 : MIN_AFTER_DTIM MIN : 5 MAX : 15
* Bit 8 : TOO_CLOSE_MARGIN MIN : 1 MAX : 3
* Bit 9 : Reserved
*/
switch (arg1)
{
//Update MCC SCHEDULE_TIME_SLICE parameter
case MCC_SCHEDULE_TIME_SLICE_CFG_PARAM :
if( pHddCtx->cfg_ini->configMccParam & 0x0001)
{
if((arg2 >= 5) && (arg2 <= 20))
{
logPrintf(hHal, cmd, staId, arg1, arg2, arg3);
}
else
{
hddLog(LOGE, "%s : Enter a valid MCC configuration value",__FUNCTION__);
return 0;
}
}
break;
//Update MCC MAX_NULL_SEND_TIME parameter
case MCC_MAX_NULL_SEND_TIME_CFG_PARAM :
if( pHddCtx->cfg_ini->configMccParam & 0x0002)
{
if((arg2 >= 1) && (arg2 <= 10))
{
logPrintf(hHal, cmd, staId, arg1, arg2, arg3);
}
else
{
hddLog(LOGE, "%s : Enter a valid MCC configuration value",__FUNCTION__);
return 0;
}
}
break;
//Update MCC TX_EARLY_STOP_TIME parameter
case MCC_TX_EARLY_STOP_TIME_CFG_PARAM :
if( pHddCtx->cfg_ini->configMccParam & 0x0004)
{
if((arg2 >= 1) && (arg2 <= 10))
{
logPrintf(hHal, cmd, staId, arg1, arg2, arg3);
}
else
{
hddLog(LOGE, "%s : Enter a valid MCC configuration value",__FUNCTION__);
return 0;
}
}
break;
//Update MCC RX_DRAIN_TIME parameter
case MCC_RX_DRAIN_TIME_CFG_PARAM :
if( pHddCtx->cfg_ini->configMccParam & 0x0008)
{
if((arg2 >= 1) && (arg2 <= 10))
{
logPrintf(hHal, cmd, staId, arg1, arg2, arg3);
}
else
{
hddLog(LOGE, "%s : Enter a valid MCC configuration value",__FUNCTION__);
return 0;
}
}
break;
//Update MCC CHANNEL_SWITCH_TIME parameter
case MCC_CHANNEL_SWITCH_TIME_CFG_PARAM :
if( pHddCtx->cfg_ini->configMccParam & 0x0010)
{
if((arg2 >= 1) && (arg2 <= 20))
{
logPrintf(hHal, cmd, staId, arg1, arg2, arg3);
}
else
{
hddLog(LOGE, "%s : Enter a valid MCC configuration value",__FUNCTION__);
return 0;
}
}
break;
//Update MCC MIN_CHANNEL_TIME parameter
case MCC_MIN_CHANNEL_TIME_CFG_PARAM :
if( pHddCtx->cfg_ini->configMccParam & 0x0020)
{
if((arg2 >= 5) && (arg2 <= 20))
{
logPrintf(hHal, cmd, staId, arg1, arg2, arg3);
}
else
{
hddLog(LOGE, "%s : Enter a valid MCC configuration value",__FUNCTION__);
return 0;
}
}
break;
//Update MCC PARK_BEFORE_TBTT parameter
case MCC_PARK_BEFORE_TBTT_CFG_PARAM :
if( pHddCtx->cfg_ini->configMccParam & 0x0040)
{
if((arg2 >= 1) && (arg2 <= 5))
{
logPrintf(hHal, cmd, staId, arg1, arg2, arg3);
}
else
{
hddLog(LOGE, "%s : Enter a valid MCC configuration value",__FUNCTION__);
return 0;
}
}
break;
//Update MCC MIN_AFTER_DTIM parameter
case MCC_MIN_AFTER_DTIM_CFG_PARAM :
if( pHddCtx->cfg_ini->configMccParam & 0x0080)
{
if((arg2 >= 5) && (arg2 <= 15))
{
logPrintf(hHal, cmd, staId, arg1, arg2, arg3);
}
else
{
hddLog(LOGE, "%s : Enter a valid MCC configuration value",__FUNCTION__);
return 0;
}
}
break;
//Update MCC TOO_CLOSE_MARGIN parameter
case MCC_TOO_CLOSE_MARGIN_CFG_PARAM :
if( pHddCtx->cfg_ini->configMccParam & 0x0100)
{
if((arg2 >= 1) && (arg2 <= 3))
{
logPrintf(hHal, cmd, staId, arg1, arg2, arg3);
}
else
{
hddLog(LOGE, "%s : Enter a valid MCC configuration value",__FUNCTION__);
return 0;
}
}
break;
default :
hddLog(LOGE, "%s : Uknown / Not allowed to configure parameter : %d",
__FUNCTION__,arg1);
break;
}
return 0;
}
int hdd_set_wext(hdd_adapter_t *pAdapter)
{
hdd_wext_state_t *pwextBuf;
hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
pwextBuf = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
// Now configure the roaming profile links. To SSID and bssid.
pwextBuf->roamProfile.SSIDs.numOfSSIDs = 0;
pwextBuf->roamProfile.SSIDs.SSIDList = &pHddStaCtx->conn_info.SSID;
pwextBuf->roamProfile.BSSIDs.numOfBSSIDs = 0;
pwextBuf->roamProfile.BSSIDs.bssid = &pHddStaCtx->conn_info.bssId;
/*Set the numOfChannels to zero to scan all the channels*/
pwextBuf->roamProfile.ChannelInfo.numOfChannels = 0;
pwextBuf->roamProfile.ChannelInfo.ChannelList = NULL;
/* Default is no encryption */
pwextBuf->roamProfile.EncryptionType.numEntries = 1;
pwextBuf->roamProfile.EncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_NONE;
pwextBuf->roamProfile.mcEncryptionType.numEntries = 1;
pwextBuf->roamProfile.mcEncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_NONE;
pwextBuf->roamProfile.BSSType = eCSR_BSS_TYPE_INFRASTRUCTURE;
/* Default is no authentication */
pwextBuf->roamProfile.AuthType.numEntries = 1;
pwextBuf->roamProfile.AuthType.authType[0] = eCSR_AUTH_TYPE_OPEN_SYSTEM;
pwextBuf->roamProfile.phyMode = eCSR_DOT11_MODE_TAURUS;
pwextBuf->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
/*Set the default scan mode*/
pHddCtx->scan_info.scan_mode = eSIR_ACTIVE_SCAN;
hdd_clearRoamProfileIe(pAdapter);
return VOS_STATUS_SUCCESS;
}
int hdd_register_wext(struct net_device *dev)
{
hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
hdd_wext_state_t *pwextBuf = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
VOS_STATUS status;
ENTER();
if (pAdapter->device_mode == WLAN_HDD_MONITOR &&
hdd_get_conparam() != VOS_MONITOR_MODE) {
// Register as a wireless device
dev->wireless_handlers = (struct iw_handler_def *)&we_mon_handler_def;
return 0;
}
// Zero the memory. This zeros the profile structure.
memset(pwextBuf, 0,sizeof(hdd_wext_state_t));
init_completion(&(WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter))->completion_var);
status = hdd_set_wext(pAdapter);
if(!VOS_IS_STATUS_SUCCESS(status)) {
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, ("ERROR: hdd_set_wext failed!!"));
return eHAL_STATUS_FAILURE;
}
if (!VOS_IS_STATUS_SUCCESS(vos_event_init(&pwextBuf->vosevent)))
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, ("ERROR: HDD vos event init failed!!"));
return eHAL_STATUS_FAILURE;
}
if (!VOS_IS_STATUS_SUCCESS(vos_event_init(&pwextBuf->scanevent)))
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, ("ERROR: HDD scan event init failed!!"));
return eHAL_STATUS_FAILURE;
}
// Register as a wireless device
dev->wireless_handlers = (struct iw_handler_def *)&we_handler_def;
EXIT();
return 0;
}
int hdd_UnregisterWext(struct net_device *dev)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"In %s %pK", __func__, dev);
if (dev != NULL)
{
rtnl_lock();
dev->wireless_handlers = NULL;
rtnl_unlock();
}
return 0;
}