blob: 30fadcd205cdf09208368cab3f2268d2bab071b5 [file] [log] [blame]
/*
* Copyright (c) 2012-2015 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 csr_tdls_process.c
Implementation for the TDLS interface to PE.
========================================================================== */
#ifdef FEATURE_WLAN_TDLS
#include "ani_global.h" /* for tpAniSirGlobal */
#include "cds_mq.h"
#include "csr_inside_api.h"
#include "sme_inside.h"
#include "sms_debug.h"
#include "csr_support.h"
#include "host_diag_core_log.h"
#include "host_diag_core_event.h"
#include "csr_internal.h"
/*
* common routine to remove TDLS cmd from SME command list..
* commands are removed after getting reponse from PE.
*/
CDF_STATUS csr_tdls_remove_sme_cmd(tpAniSirGlobal pMac, eSmeCommandType cmdType)
{
CDF_STATUS status = CDF_STATUS_E_FAILURE;
tListElem *pEntry;
tSmeCmd *pCommand;
pEntry = csr_ll_peek_head(&pMac->sme.smeCmdActiveList, LL_ACCESS_LOCK);
if (pEntry) {
pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link);
if (cmdType == pCommand->command) {
if (csr_ll_remove_entry(&pMac->sme.smeCmdActiveList,
pEntry, LL_ACCESS_LOCK)) {
cdf_mem_zero(&pCommand->u.tdlsCmd,
sizeof(tTdlsCmd));
csr_release_command(pMac, pCommand);
sme_process_pending_queue(pMac);
status = CDF_STATUS_SUCCESS;
}
}
}
return status;
}
/**
* csr_tdls_send_mgmt_req() - to send a TDLS frame to PE through SME
* @hHal: HAL context
* @sessionId: SME session id
* @tdlsSendMgmt: tdls mgmt pointer
*
* TDLS request API, called from HDD to send a TDLS frame in SME/CSR and
* send message to PE to trigger TDLS discovery procedure.
*/
CDF_STATUS csr_tdls_send_mgmt_req(tHalHandle hHal, uint8_t sessionId,
tCsrTdlsSendMgmt *tdlsSendMgmt)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
tSmeCmd *tdlsSendMgmtCmd;
tTdlsSendMgmtCmdInfo *tdlsSendMgmtCmdInfo;
CDF_STATUS status = CDF_STATUS_E_FAILURE;
/* If connected and in Infra. Only then allow this */
if (!CSR_IS_SESSION_VALID(pMac, sessionId) ||
!csr_is_conn_state_connected_infra(pMac, sessionId) ||
(NULL == tdlsSendMgmt))
return status;
tdlsSendMgmtCmd = csr_get_command_buffer(pMac);
if (!tdlsSendMgmtCmd)
return status;
tdlsSendMgmtCmdInfo = &tdlsSendMgmtCmd->u.tdlsCmd.u.tdlsSendMgmtCmdInfo;
tdlsSendMgmtCmd->sessionId = sessionId;
tdlsSendMgmtCmdInfo->frameType = tdlsSendMgmt->frameType;
tdlsSendMgmtCmdInfo->dialog = tdlsSendMgmt->dialog;
tdlsSendMgmtCmdInfo->statusCode = tdlsSendMgmt->statusCode;
tdlsSendMgmtCmdInfo->responder = tdlsSendMgmt->responder;
tdlsSendMgmtCmdInfo->peerCapability = tdlsSendMgmt->peerCapability;
cdf_mem_copy(tdlsSendMgmtCmdInfo->peerMac, tdlsSendMgmt->peerMac,
sizeof(tSirMacAddr));
if ((0 != tdlsSendMgmt->len) && (NULL != tdlsSendMgmt->buf)) {
tdlsSendMgmtCmdInfo->buf = cdf_mem_malloc(tdlsSendMgmt->len);
if (NULL == tdlsSendMgmtCmdInfo->buf) {
status = CDF_STATUS_E_NOMEM;
sms_log(pMac, LOGE, FL("Alloc Failed"));
CDF_ASSERT(0);
return status;
}
cdf_mem_copy(tdlsSendMgmtCmdInfo->buf, tdlsSendMgmt->buf,
tdlsSendMgmt->len);
tdlsSendMgmtCmdInfo->len = tdlsSendMgmt->len;
} else {
tdlsSendMgmtCmdInfo->buf = NULL;
tdlsSendMgmtCmdInfo->len = 0;
}
tdlsSendMgmtCmd->command = eSmeCommandTdlsSendMgmt;
tdlsSendMgmtCmd->u.tdlsCmd.size = sizeof(tTdlsSendMgmtCmdInfo);
sme_push_command(pMac, tdlsSendMgmtCmd, false);
status = CDF_STATUS_SUCCESS;
return status;
}
/*
* TDLS request API, called from HDD to add a TDLS peer
*/
CDF_STATUS csr_tdls_change_peer_sta(tHalHandle hHal, uint8_t sessionId,
const tSirMacAddr peerMac,
tCsrStaParams *pstaParams)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
tSmeCmd *tdlsAddStaCmd;
CDF_STATUS status = CDF_STATUS_E_FAILURE;
/* If connected and in Infra. Only then allow this */
if (CSR_IS_SESSION_VALID(pMac, sessionId) &&
csr_is_conn_state_connected_infra(pMac, sessionId) &&
(NULL != peerMac) && (NULL != pstaParams)) {
tdlsAddStaCmd = csr_get_command_buffer(pMac);
if (tdlsAddStaCmd) {
tTdlsAddStaCmdInfo *tdlsAddStaCmdInfo =
&tdlsAddStaCmd->u.tdlsCmd.u.tdlsAddStaCmdInfo;
tdlsAddStaCmdInfo->tdlsAddOper = TDLS_OPER_UPDATE;
tdlsAddStaCmd->sessionId = sessionId;
cdf_mem_copy(tdlsAddStaCmdInfo->peerMac,
peerMac, sizeof(tSirMacAddr));
tdlsAddStaCmdInfo->capability = pstaParams->capability;
tdlsAddStaCmdInfo->uapsdQueues =
pstaParams->uapsd_queues;
tdlsAddStaCmdInfo->maxSp = pstaParams->max_sp;
cdf_mem_copy(tdlsAddStaCmdInfo->extnCapability,
pstaParams->extn_capability,
sizeof(pstaParams->extn_capability));
tdlsAddStaCmdInfo->htcap_present =
pstaParams->htcap_present;
if (pstaParams->htcap_present)
cdf_mem_copy(&tdlsAddStaCmdInfo->HTCap,
&pstaParams->HTCap,
sizeof(pstaParams->HTCap));
else
cdf_mem_set(&tdlsAddStaCmdInfo->HTCap,
sizeof(pstaParams->HTCap), 0);
tdlsAddStaCmdInfo->vhtcap_present =
pstaParams->vhtcap_present;
if (pstaParams->vhtcap_present)
cdf_mem_copy(&tdlsAddStaCmdInfo->VHTCap,
&pstaParams->VHTCap,
sizeof(pstaParams->VHTCap));
else
cdf_mem_set(&tdlsAddStaCmdInfo->VHTCap,
sizeof(pstaParams->VHTCap), 0);
tdlsAddStaCmdInfo->supportedRatesLen =
pstaParams->supported_rates_len;
if (0 != pstaParams->supported_rates_len)
cdf_mem_copy(&tdlsAddStaCmdInfo->supportedRates,
pstaParams->supported_rates,
pstaParams->supported_rates_len);
tdlsAddStaCmd->command = eSmeCommandTdlsAddPeer;
tdlsAddStaCmd->u.tdlsCmd.size =
sizeof(tTdlsAddStaCmdInfo);
sme_push_command(pMac, tdlsAddStaCmd, false);
status = CDF_STATUS_SUCCESS;
}
}
return status;
}
/*
* TDLS request API, called from HDD to Send Link Establishment Parameters
*/
CDF_STATUS csr_tdls_send_link_establish_params(tHalHandle hHal,
uint8_t sessionId,
const tSirMacAddr peerMac,
tCsrTdlsLinkEstablishParams *
tdlsLinkEstablishParams)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
tSmeCmd *tdlsLinkEstablishCmd;
CDF_STATUS status = CDF_STATUS_E_FAILURE;
/* If connected and in Infra. Only then allow this */
if (CSR_IS_SESSION_VALID(pMac, sessionId) &&
csr_is_conn_state_connected_infra(pMac, sessionId) &&
(NULL != peerMac)) {
tdlsLinkEstablishCmd = csr_get_command_buffer(pMac);
if (tdlsLinkEstablishCmd) {
tTdlsLinkEstablishCmdInfo *tdlsLinkEstablishCmdInfo =
&tdlsLinkEstablishCmd->u.tdlsCmd.u.
tdlsLinkEstablishCmdInfo;
tdlsLinkEstablishCmd->sessionId = sessionId;
cdf_mem_copy(tdlsLinkEstablishCmdInfo->peerMac,
peerMac, sizeof(tSirMacAddr));
tdlsLinkEstablishCmdInfo->isBufSta =
tdlsLinkEstablishParams->isBufSta;
tdlsLinkEstablishCmdInfo->isResponder =
tdlsLinkEstablishParams->isResponder;
tdlsLinkEstablishCmdInfo->maxSp =
tdlsLinkEstablishParams->maxSp;
tdlsLinkEstablishCmdInfo->uapsdQueues =
tdlsLinkEstablishParams->uapsdQueues;
tdlsLinkEstablishCmdInfo->isOffChannelSupported =
tdlsLinkEstablishParams->isOffChannelSupported;
cdf_mem_copy(tdlsLinkEstablishCmdInfo->
supportedChannels,
tdlsLinkEstablishParams->supportedChannels,
tdlsLinkEstablishParams->
supportedChannelsLen);
tdlsLinkEstablishCmdInfo->supportedChannelsLen =
tdlsLinkEstablishParams->supportedChannelsLen;
cdf_mem_copy(tdlsLinkEstablishCmdInfo->
supportedOperClasses,
tdlsLinkEstablishParams->
supportedOperClasses,
tdlsLinkEstablishParams->
supportedOperClassesLen);
tdlsLinkEstablishCmdInfo->supportedOperClassesLen =
tdlsLinkEstablishParams->supportedOperClassesLen;
tdlsLinkEstablishCmdInfo->isResponder =
tdlsLinkEstablishParams->isResponder;
tdlsLinkEstablishCmdInfo->maxSp =
tdlsLinkEstablishParams->maxSp;
tdlsLinkEstablishCmdInfo->uapsdQueues =
tdlsLinkEstablishParams->uapsdQueues;
tdlsLinkEstablishCmd->command =
eSmeCommandTdlsLinkEstablish;
tdlsLinkEstablishCmd->u.tdlsCmd.size =
sizeof(tTdlsLinkEstablishCmdInfo);
sme_push_command(pMac, tdlsLinkEstablishCmd, false);
status = CDF_STATUS_SUCCESS;
}
}
return status;
}
/*
* TDLS request API, called from HDD to add a TDLS peer
*/
CDF_STATUS csr_tdls_add_peer_sta(tHalHandle hHal, uint8_t sessionId,
const tSirMacAddr peerMac)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
tSmeCmd *tdlsAddStaCmd;
CDF_STATUS status = CDF_STATUS_E_FAILURE;
/* If connected and in Infra. Only then allow this */
if (CSR_IS_SESSION_VALID(pMac, sessionId) &&
csr_is_conn_state_connected_infra(pMac, sessionId) &&
(NULL != peerMac)) {
tdlsAddStaCmd = csr_get_command_buffer(pMac);
if (tdlsAddStaCmd) {
tTdlsAddStaCmdInfo *tdlsAddStaCmdInfo =
&tdlsAddStaCmd->u.tdlsCmd.u.tdlsAddStaCmdInfo;
tdlsAddStaCmd->sessionId = sessionId;
tdlsAddStaCmdInfo->tdlsAddOper = TDLS_OPER_ADD;
cdf_mem_copy(tdlsAddStaCmdInfo->peerMac,
peerMac, sizeof(tSirMacAddr));
tdlsAddStaCmd->command = eSmeCommandTdlsAddPeer;
tdlsAddStaCmd->u.tdlsCmd.size =
sizeof(tTdlsAddStaCmdInfo);
sme_push_command(pMac, tdlsAddStaCmd, false);
status = CDF_STATUS_SUCCESS;
}
}
return status;
}
/*
* TDLS request API, called from HDD to delete a TDLS peer
*/
CDF_STATUS csr_tdls_del_peer_sta(tHalHandle hHal, uint8_t sessionId,
const tSirMacAddr peerMac)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
tSmeCmd *tdlsDelStaCmd;
CDF_STATUS status = CDF_STATUS_E_FAILURE;
/* If connected and in Infra. Only then allow this */
if (CSR_IS_SESSION_VALID(pMac, sessionId) &&
csr_is_conn_state_connected_infra(pMac, sessionId) &&
(NULL != peerMac)) {
tdlsDelStaCmd = csr_get_command_buffer(pMac);
if (tdlsDelStaCmd) {
tTdlsDelStaCmdInfo *tdlsDelStaCmdInfo =
&tdlsDelStaCmd->u.tdlsCmd.u.tdlsDelStaCmdInfo;
tdlsDelStaCmd->sessionId = sessionId;
cdf_mem_copy(tdlsDelStaCmdInfo->peerMac,
peerMac, sizeof(tSirMacAddr));
tdlsDelStaCmd->command = eSmeCommandTdlsDelPeer;
tdlsDelStaCmd->u.tdlsCmd.size =
sizeof(tTdlsDelStaCmdInfo);
sme_push_command(pMac, tdlsDelStaCmd, false);
status = CDF_STATUS_SUCCESS;
}
}
return status;
}
/*
* TDLS messages sent to PE .
*/
CDF_STATUS tdls_send_message(tpAniSirGlobal pMac, uint16_t msg_type,
void *msg_data, uint32_t msg_size)
{
tSirMbMsg *pMsg = (tSirMbMsg *) msg_data;
pMsg->type = msg_type;
pMsg->msgLen = (uint16_t) (msg_size);
CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO,
("sending msg = %d"), pMsg->type);
/* Send message. */
if (cds_send_mb_message_to_mac(pMsg) != CDF_STATUS_SUCCESS) {
sms_log(pMac, LOGE, FL("Cannot send message"));
return CDF_STATUS_E_FAILURE;
}
return CDF_STATUS_SUCCESS;
}
CDF_STATUS csr_tdls_process_send_mgmt(tpAniSirGlobal pMac, tSmeCmd *cmd)
{
tTdlsSendMgmtCmdInfo *tdlsSendMgmtCmdInfo =
&cmd->u.tdlsCmd.u.tdlsSendMgmtCmdInfo;
tSirTdlsSendMgmtReq *tdlsSendMgmtReq = NULL;
tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, cmd->sessionId);
CDF_STATUS status = CDF_STATUS_E_FAILURE;
if (NULL == pSession) {
sms_log(pMac, LOGE, FL("pSession is NULL"));
return CDF_STATUS_E_FAILURE;
}
if (NULL == pSession->pConnectBssDesc) {
sms_log(pMac, LOGE, FL("BSS Description is not present"));
return CDF_STATUS_E_FAILURE;
}
tdlsSendMgmtReq =
cdf_mem_malloc(sizeof(tSirTdlsSendMgmtReq) +
tdlsSendMgmtCmdInfo->len);
if (NULL == tdlsSendMgmtReq)
status = CDF_STATUS_E_NOMEM;
else
status = CDF_STATUS_SUCCESS;
if (!CDF_IS_STATUS_SUCCESS(status)) {
sms_log(pMac, LOGE, FL("alloc failed"));
CDF_ASSERT(0);
return status;
}
tdlsSendMgmtReq->sessionId = cmd->sessionId;
/* Using dialog as transactionId. This can be used to match response with request */
tdlsSendMgmtReq->transactionId = tdlsSendMgmtCmdInfo->dialog;
tdlsSendMgmtReq->reqType = tdlsSendMgmtCmdInfo->frameType;
tdlsSendMgmtReq->dialog = tdlsSendMgmtCmdInfo->dialog;
tdlsSendMgmtReq->statusCode = tdlsSendMgmtCmdInfo->statusCode;
tdlsSendMgmtReq->responder = tdlsSendMgmtCmdInfo->responder;
tdlsSendMgmtReq->peerCapability = tdlsSendMgmtCmdInfo->peerCapability;
cdf_mem_copy(tdlsSendMgmtReq->bssid,
pSession->pConnectBssDesc->bssId, sizeof(tSirMacAddr));
cdf_mem_copy(tdlsSendMgmtReq->peerMac,
tdlsSendMgmtCmdInfo->peerMac, sizeof(tSirMacAddr));
if (tdlsSendMgmtCmdInfo->len && tdlsSendMgmtCmdInfo->buf) {
cdf_mem_copy(tdlsSendMgmtReq->addIe, tdlsSendMgmtCmdInfo->buf,
tdlsSendMgmtCmdInfo->len);
}
/* Send the request to PE. */
sms_log(pMac, LOG1, "sending TDLS Mgmt Frame req to PE ");
status = tdls_send_message(pMac, eWNI_SME_TDLS_SEND_MGMT_REQ,
(void *)tdlsSendMgmtReq,
sizeof(tSirTdlsSendMgmtReq) +
tdlsSendMgmtCmdInfo->len);
if (!CDF_IS_STATUS_SUCCESS(status)) {
sms_log(pMac, LOGE, FL("Failed to send request to MAC"));
}
if (tdlsSendMgmtCmdInfo->len && tdlsSendMgmtCmdInfo->buf) {
/* Done with the buf. Free it. */
cdf_mem_free(tdlsSendMgmtCmdInfo->buf);
tdlsSendMgmtCmdInfo->buf = NULL;
tdlsSendMgmtCmdInfo->len = 0;
}
return status;
}
CDF_STATUS csr_tdls_process_add_sta(tpAniSirGlobal pMac, tSmeCmd *cmd)
{
tTdlsAddStaCmdInfo *tdlsAddStaCmdInfo =
&cmd->u.tdlsCmd.u.tdlsAddStaCmdInfo;
tSirTdlsAddStaReq *tdlsAddStaReq = NULL;
tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, cmd->sessionId);
CDF_STATUS status = CDF_STATUS_E_FAILURE;
if (NULL == pSession) {
sms_log(pMac, LOGE, FL("pSession is NULL"));
return CDF_STATUS_E_FAILURE;
}
if (NULL == pSession->pConnectBssDesc) {
sms_log(pMac, LOGE, FL("BSS description is not present"));
return CDF_STATUS_E_FAILURE;
}
tdlsAddStaReq = cdf_mem_malloc(sizeof(tSirTdlsAddStaReq));
if (NULL == tdlsAddStaReq)
status = CDF_STATUS_E_NOMEM;
else
status = CDF_STATUS_SUCCESS;
if (!CDF_IS_STATUS_SUCCESS(status)) {
sms_log(pMac, LOGE, FL("alloc failed"));
CDF_ASSERT(0);
return status;
}
tdlsAddStaReq->sessionId = cmd->sessionId;
tdlsAddStaReq->tdlsAddOper = tdlsAddStaCmdInfo->tdlsAddOper;
/* Using dialog as transactionId. This can be used to match response with request */
tdlsAddStaReq->transactionId = 0;
cdf_mem_copy(tdlsAddStaReq->bssid,
pSession->pConnectBssDesc->bssId, sizeof(tSirMacAddr));
cdf_mem_copy(tdlsAddStaReq->peerMac,
tdlsAddStaCmdInfo->peerMac, sizeof(tSirMacAddr));
tdlsAddStaReq->capability = tdlsAddStaCmdInfo->capability;
tdlsAddStaReq->uapsd_queues = tdlsAddStaCmdInfo->uapsdQueues;
tdlsAddStaReq->max_sp = tdlsAddStaCmdInfo->maxSp;
cdf_mem_copy(tdlsAddStaReq->extn_capability,
tdlsAddStaCmdInfo->extnCapability, SIR_MAC_MAX_EXTN_CAP);
tdlsAddStaReq->htcap_present = tdlsAddStaCmdInfo->htcap_present;
cdf_mem_copy(&tdlsAddStaReq->htCap,
&tdlsAddStaCmdInfo->HTCap,
sizeof(tdlsAddStaCmdInfo->HTCap));
tdlsAddStaReq->vhtcap_present = tdlsAddStaCmdInfo->vhtcap_present;
cdf_mem_copy(&tdlsAddStaReq->vhtCap,
&tdlsAddStaCmdInfo->VHTCap,
sizeof(tdlsAddStaCmdInfo->VHTCap));
tdlsAddStaReq->supported_rates_length =
tdlsAddStaCmdInfo->supportedRatesLen;
cdf_mem_copy(&tdlsAddStaReq->supported_rates,
tdlsAddStaCmdInfo->supportedRates,
tdlsAddStaCmdInfo->supportedRatesLen);
/* Send the request to PE. */
sms_log(pMac, LOGE, "sending TDLS Add Sta req to PE ");
status = tdls_send_message(pMac, eWNI_SME_TDLS_ADD_STA_REQ,
(void *)tdlsAddStaReq,
sizeof(tSirTdlsAddStaReq));
if (!CDF_IS_STATUS_SUCCESS(status)) {
sms_log(pMac, LOGE, FL("Failed to send request to MAC"));
}
return status;
}
CDF_STATUS csr_tdls_process_del_sta(tpAniSirGlobal pMac, tSmeCmd *cmd)
{
tTdlsDelStaCmdInfo *tdlsDelStaCmdInfo =
&cmd->u.tdlsCmd.u.tdlsDelStaCmdInfo;
tSirTdlsDelStaReq *tdlsDelStaReq = NULL;
tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, cmd->sessionId);
CDF_STATUS status = CDF_STATUS_E_FAILURE;
if (NULL == pSession) {
sms_log(pMac, LOGE, FL("pSession is NULL"));
return CDF_STATUS_E_FAILURE;
}
if (NULL == pSession->pConnectBssDesc) {
sms_log(pMac, LOGE, FL("BSS description is not present"));
return CDF_STATUS_E_FAILURE;
}
tdlsDelStaReq = cdf_mem_malloc(sizeof(tSirTdlsDelStaReq));
if (NULL == tdlsDelStaReq)
status = CDF_STATUS_E_NOMEM;
else
status = CDF_STATUS_SUCCESS;
if (!CDF_IS_STATUS_SUCCESS(status)) {
sms_log(pMac, LOGE, FL("alloc failed"));
CDF_ASSERT(0);
return status;
}
tdlsDelStaReq->sessionId = cmd->sessionId;
/* Using dialog as transactionId. This can be used to match response with request */
tdlsDelStaReq->transactionId = 0;
cdf_mem_copy(tdlsDelStaReq->bssid,
pSession->pConnectBssDesc->bssId, sizeof(tSirMacAddr));
cdf_mem_copy(tdlsDelStaReq->peerMac,
tdlsDelStaCmdInfo->peerMac, sizeof(tSirMacAddr));
/* Send the request to PE. */
sms_log(pMac, LOG1,
"sending TDLS Del Sta " MAC_ADDRESS_STR " req to PE",
MAC_ADDR_ARRAY(tdlsDelStaCmdInfo->peerMac));
status = tdls_send_message(pMac, eWNI_SME_TDLS_DEL_STA_REQ,
(void *)tdlsDelStaReq,
sizeof(tSirTdlsDelStaReq));
if (!CDF_IS_STATUS_SUCCESS(status)) {
sms_log(pMac, LOGE, FL("Failed to send request to MAC"));
}
return status;
}
/*
* commands received from CSR
*/
CDF_STATUS csr_tdls_process_cmd(tpAniSirGlobal pMac, tSmeCmd *cmd)
{
eSmeCommandType cmdType = cmd->command;
bool status = true;
switch (cmdType) {
case eSmeCommandTdlsSendMgmt:
{
status = csr_tdls_process_send_mgmt(pMac, cmd);
if (CDF_IS_STATUS_SUCCESS(status)) {
status = false;
}
}
break;
case eSmeCommandTdlsAddPeer:
{
status = csr_tdls_process_add_sta(pMac, cmd);
if (CDF_IS_STATUS_SUCCESS(status)) {
status = false;
}
}
break;
case eSmeCommandTdlsDelPeer:
{
status = csr_tdls_process_del_sta(pMac, cmd);
if (CDF_IS_STATUS_SUCCESS(status)) {
status = false;
}
}
break;
case eSmeCommandTdlsLinkEstablish:
{
status = csr_tdls_process_link_establish(pMac, cmd);
if (CDF_IS_STATUS_SUCCESS(status)) {
status = false;
}
}
break;
default:
{
/* TODO: Add defualt handling */
break;
}
}
return status;
}
CDF_STATUS csr_tdls_process_link_establish(tpAniSirGlobal pMac, tSmeCmd *cmd)
{
tTdlsLinkEstablishCmdInfo *tdlsLinkEstablishCmdInfo =
&cmd->u.tdlsCmd.u.tdlsLinkEstablishCmdInfo;
tSirTdlsLinkEstablishReq *tdlsLinkEstablishReq = NULL;
CDF_STATUS status = CDF_STATUS_E_FAILURE;
tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, cmd->sessionId);
if (NULL == pSession) {
sms_log(pMac, LOGE, FL("pSession is NULL"));
return CDF_STATUS_E_FAILURE;
}
tdlsLinkEstablishReq = cdf_mem_malloc(sizeof(tSirTdlsLinkEstablishReq));
if (tdlsLinkEstablishReq == NULL) {
sms_log(pMac, LOGE, FL("alloc failed"));
CDF_ASSERT(0);
return CDF_STATUS_E_NOMEM;
}
tdlsLinkEstablishReq->sessionId = cmd->sessionId;
/* Using dialog as transactionId. This can be used to match response with request */
tdlsLinkEstablishReq->transactionId = 0;
cdf_mem_copy(tdlsLinkEstablishReq->peerMac,
tdlsLinkEstablishCmdInfo->peerMac, sizeof(tSirMacAddr));
cdf_mem_copy(tdlsLinkEstablishReq->bssid,
pSession->pConnectBssDesc->bssId, sizeof(tSirMacAddr));
cdf_mem_copy(tdlsLinkEstablishReq->supportedChannels,
tdlsLinkEstablishCmdInfo->supportedChannels,
tdlsLinkEstablishCmdInfo->supportedChannelsLen);
tdlsLinkEstablishReq->supportedChannelsLen =
tdlsLinkEstablishCmdInfo->supportedChannelsLen;
cdf_mem_copy(tdlsLinkEstablishReq->supportedOperClasses,
tdlsLinkEstablishCmdInfo->supportedOperClasses,
tdlsLinkEstablishCmdInfo->supportedOperClassesLen);
tdlsLinkEstablishReq->supportedOperClassesLen =
tdlsLinkEstablishCmdInfo->supportedOperClassesLen;
tdlsLinkEstablishReq->isBufSta = tdlsLinkEstablishCmdInfo->isBufSta;
tdlsLinkEstablishReq->isResponder =
tdlsLinkEstablishCmdInfo->isResponder;
tdlsLinkEstablishReq->uapsdQueues =
tdlsLinkEstablishCmdInfo->uapsdQueues;
tdlsLinkEstablishReq->maxSp = tdlsLinkEstablishCmdInfo->maxSp;
/* Send the request to PE. */
sms_log(pMac, LOGE, "sending TDLS Link Establish Request to PE \n");
status = tdls_send_message(pMac, eWNI_SME_TDLS_LINK_ESTABLISH_REQ,
(void *)tdlsLinkEstablishReq,
sizeof(tSirTdlsLinkEstablishReq));
if (!CDF_IS_STATUS_SUCCESS(status)) {
sms_log(pMac, LOGE, FL("Failed to send request to MAC\n"));
}
return status;
}
/*
* TDLS Message processor, will be called after TDLS message recieved from
* PE
*/
CDF_STATUS tdls_msg_processor(tpAniSirGlobal pMac, uint16_t msgType,
void *pMsgBuf)
{
tCsrRoamInfo roamInfo = { 0 };
eCsrRoamResult roamResult;
tSirTdlsAddStaRsp *addStaRsp = (tSirTdlsAddStaRsp *) pMsgBuf;
tSirTdlsDelStaRsp *delStaRsp = (tSirTdlsDelStaRsp *) pMsgBuf;
tpSirTdlsDelStaInd pSirTdlsDelStaInd = (tpSirTdlsDelStaInd) pMsgBuf;
tpSirTdlsDelAllPeerInd pSirTdlsDelAllPeerInd =
(tpSirTdlsDelAllPeerInd) pMsgBuf;
tpSirMgmtTxCompletionInd tdls_tx_comp_ind =
(tpSirMgmtTxCompletionInd) pMsgBuf;
tSirTdlsLinkEstablishReqRsp *linkEstablishReqRsp =
(tSirTdlsLinkEstablishReqRsp *) pMsgBuf;
tSirTdlsEventnotify *tevent = (tSirTdlsEventnotify *) pMsgBuf;
switch (msgType) {
case eWNI_SME_TDLS_SEND_MGMT_RSP:
/* remove pending eSmeCommandTdlsDiscovery command */
csr_tdls_remove_sme_cmd(pMac, eSmeCommandTdlsSendMgmt);
break;
case eWNI_SME_TDLS_ADD_STA_RSP:
cdf_mem_copy(&roamInfo.peerMac, addStaRsp->peerMac,
sizeof(tSirMacAddr));
roamInfo.staId = addStaRsp->staId;
roamInfo.ucastSig = addStaRsp->ucastSig;
roamInfo.bcastSig = addStaRsp->bcastSig;
roamInfo.statusCode = addStaRsp->statusCode;
/*
* register peer with TL, we have to go through HDD as
* this is the only way to register any STA with TL.
*/
if (addStaRsp->tdlsAddOper == TDLS_OPER_ADD)
roamResult = eCSR_ROAM_RESULT_ADD_TDLS_PEER;
else /* addStaRsp->tdlsAddOper must be TDLS_OPER_UPDATE */
roamResult = eCSR_ROAM_RESULT_UPDATE_TDLS_PEER;
csr_roam_call_callback(pMac, addStaRsp->sessionId,
&roamInfo, 0, eCSR_ROAM_TDLS_STATUS_UPDATE,
roamResult);
/* remove pending eSmeCommandTdlsDiscovery command */
csr_tdls_remove_sme_cmd(pMac, eSmeCommandTdlsAddPeer);
break;
case eWNI_SME_TDLS_DEL_STA_RSP:
cdf_mem_copy(&roamInfo.peerMac, delStaRsp->peerMac,
sizeof(tSirMacAddr));
roamInfo.staId = delStaRsp->staId;
roamInfo.statusCode = delStaRsp->statusCode;
/*
* register peer with TL, we have to go through HDD as
* this is the only way to register any STA with TL.
*/
csr_roam_call_callback(pMac, delStaRsp->sessionId,
&roamInfo, 0,
eCSR_ROAM_TDLS_STATUS_UPDATE,
eCSR_ROAM_RESULT_DELETE_TDLS_PEER);
csr_tdls_remove_sme_cmd(pMac, eSmeCommandTdlsDelPeer);
break;
case eWNI_SME_TDLS_DEL_STA_IND:
cdf_mem_copy(&roamInfo.peerMac,
pSirTdlsDelStaInd->peerMac,
sizeof(tSirMacAddr));
roamInfo.staId = pSirTdlsDelStaInd->staId;
roamInfo.reasonCode = pSirTdlsDelStaInd->reasonCode;
/* Sending the TEARDOWN indication to HDD. */
csr_roam_call_callback(pMac,
pSirTdlsDelStaInd->sessionId, &roamInfo,
0, eCSR_ROAM_TDLS_STATUS_UPDATE,
eCSR_ROAM_RESULT_TEARDOWN_TDLS_PEER_IND);
break;
case eWNI_SME_TDLS_DEL_ALL_PEER_IND:
/* Sending the TEARDOWN indication to HDD. */
csr_roam_call_callback(pMac,
pSirTdlsDelAllPeerInd->sessionId,
&roamInfo, 0,
eCSR_ROAM_TDLS_STATUS_UPDATE,
eCSR_ROAM_RESULT_DELETE_ALL_TDLS_PEER_IND);
break;
case eWNI_SME_MGMT_FRM_TX_COMPLETION_IND:
roamInfo.reasonCode =
tdls_tx_comp_ind->txCompleteStatus;
csr_roam_call_callback(pMac,
tdls_tx_comp_ind->sessionId,
&roamInfo, 0,
eCSR_ROAM_RESULT_MGMT_TX_COMPLETE_IND,
0);
break;
case eWNI_SME_TDLS_LINK_ESTABLISH_RSP:
csr_roam_call_callback(pMac,
linkEstablishReqRsp->sessionId,
&roamInfo, 0,
eCSR_ROAM_TDLS_STATUS_UPDATE,
eCSR_ROAM_RESULT_LINK_ESTABLISH_REQ_RSP);
/* remove pending eSmeCommandTdlsLinkEstablish command */
csr_tdls_remove_sme_cmd(pMac, eSmeCommandTdlsLinkEstablish);
break;
case eWNI_SME_TDLS_SHOULD_DISCOVER:
cdf_mem_copy(&roamInfo.peerMac, tevent->peerMac,
sizeof(tSirMacAddr));
roamInfo.reasonCode = tevent->peer_reason;
CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO,
"%s: eWNI_SME_TDLS_SHOULD_DISCOVER for peer mac: "
MAC_ADDRESS_STR " peer_reason: %d",
__func__, MAC_ADDR_ARRAY(tevent->peerMac),
tevent->peer_reason);
csr_roam_call_callback(pMac, tevent->sessionId, &roamInfo,
0, eCSR_ROAM_TDLS_STATUS_UPDATE,
eCSR_ROAM_RESULT_TDLS_SHOULD_DISCOVER);
break;
case eWNI_SME_TDLS_SHOULD_TEARDOWN:
cdf_mem_copy(&roamInfo.peerMac, tevent->peerMac,
sizeof(tSirMacAddr));
roamInfo.reasonCode = tevent->peer_reason;
CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO,
"%s: eWNI_SME_TDLS_SHOULD_TEARDOWN for peer mac: "
MAC_ADDRESS_STR " peer_reason: %d",
__func__, MAC_ADDR_ARRAY(tevent->peerMac),
tevent->peer_reason);
csr_roam_call_callback(pMac, tevent->sessionId, &roamInfo,
0, eCSR_ROAM_TDLS_STATUS_UPDATE,
eCSR_ROAM_RESULT_TDLS_SHOULD_TEARDOWN);
break;
case eWNI_SME_TDLS_PEER_DISCONNECTED:
cdf_mem_copy(&roamInfo.peerMac, tevent->peerMac,
sizeof(tSirMacAddr));
roamInfo.reasonCode = tevent->peer_reason;
CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO,
"%s: eWNI_SME_TDLS_PEER_DISCONNECTED for peer mac: "
MAC_ADDRESS_STR " peer_reason: %d",
__func__, MAC_ADDR_ARRAY(tevent->peerMac),
tevent->peer_reason);
csr_roam_call_callback(pMac, tevent->sessionId, &roamInfo,
0, eCSR_ROAM_TDLS_STATUS_UPDATE,
eCSR_ROAM_RESULT_TDLS_SHOULD_PEER_DISCONNECTED);
break;
default:
break;
}
return CDF_STATUS_SUCCESS;
}
#endif