blob: e07ebd578d449e17ed5b79e6f9c7722239e4ea6b [file] [log] [blame]
/*
* Copyright (c) 1996, 2005 VIA Networking Technologies, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*
* File: IEEE11h.c
*
* Purpose:
*
* Functions:
*
* Revision History:
*
* Author: Yiching Chen
*
* Date: Mar. 31, 2005
*
*/
#include "ttype.h"
#include "tmacro.h"
#include "tether.h"
#include "IEEE11h.h"
#include "device.h"
#include "wmgr.h"
#include "rxtx.h"
#include "channel.h"
/*--------------------- Static Definitions -------------------------*/
static int msglevel =MSG_LEVEL_INFO;
#pragma pack(1)
typedef struct _WLAN_FRAME_ACTION {
WLAN_80211HDR_A3 Header;
unsigned char byCategory;
unsigned char byAction;
unsigned char abyVars[1];
} WLAN_FRAME_ACTION, *PWLAN_FRAME_ACTION;
typedef struct _WLAN_FRAME_MSRREQ {
WLAN_80211HDR_A3 Header;
unsigned char byCategory;
unsigned char byAction;
unsigned char byDialogToken;
WLAN_IE_MEASURE_REQ sMSRReqEIDs[1];
} WLAN_FRAME_MSRREQ, *PWLAN_FRAME_MSRREQ;
typedef struct _WLAN_FRAME_MSRREP {
WLAN_80211HDR_A3 Header;
unsigned char byCategory;
unsigned char byAction;
unsigned char byDialogToken;
WLAN_IE_MEASURE_REP sMSRRepEIDs[1];
} WLAN_FRAME_MSRREP, *PWLAN_FRAME_MSRREP;
typedef struct _WLAN_FRAME_TPCREQ {
WLAN_80211HDR_A3 Header;
unsigned char byCategory;
unsigned char byAction;
unsigned char byDialogToken;
WLAN_IE_TPC_REQ sTPCReqEIDs;
} WLAN_FRAME_TPCREQ, *PWLAN_FRAME_TPCREQ;
typedef struct _WLAN_FRAME_TPCREP {
WLAN_80211HDR_A3 Header;
unsigned char byCategory;
unsigned char byAction;
unsigned char byDialogToken;
WLAN_IE_TPC_REP sTPCRepEIDs;
} WLAN_FRAME_TPCREP, *PWLAN_FRAME_TPCREP;
#pragma pack()
// action field reference ieee 802.11h Table 20e
#define ACTION_MSRREQ 0
#define ACTION_MSRREP 1
#define ACTION_TPCREQ 2
#define ACTION_TPCREP 3
#define ACTION_CHSW 4
/*--------------------- Static Classes ----------------------------*/
/*--------------------- Static Variables --------------------------*/
/*--------------------- Static Functions --------------------------*/
static bool s_bRxMSRReq(PSMgmtObject pMgmt, PWLAN_FRAME_MSRREQ pMSRReq,
unsigned int uLength)
{
size_t uNumOfEIDs = 0;
bool bResult = true;
if (uLength <= WLAN_A3FR_MAXLEN) {
memcpy(pMgmt->abyCurrentMSRReq, pMSRReq, uLength);
}
uNumOfEIDs = ((uLength - offsetof(WLAN_FRAME_MSRREQ, sMSRReqEIDs))/ (sizeof(WLAN_IE_MEASURE_REQ)));
pMgmt->pCurrMeasureEIDRep = &(((PWLAN_FRAME_MSRREP) (pMgmt->abyCurrentMSRRep))->sMSRRepEIDs[0]);
pMgmt->uLengthOfRepEIDs = 0;
bResult = CARDbStartMeasure(pMgmt->pAdapter,
((PWLAN_FRAME_MSRREQ) (pMgmt->abyCurrentMSRReq))->sMSRReqEIDs,
uNumOfEIDs
);
return (bResult);
}
static bool s_bRxTPCReq(PSMgmtObject pMgmt, PWLAN_FRAME_TPCREQ pTPCReq, unsigned char byRate, unsigned char byRSSI)
{
PWLAN_FRAME_TPCREP pFrame;
PSTxMgmtPacket pTxPacket = NULL;
pTxPacket = (PSTxMgmtPacket)pMgmt->pbyMgmtPacketPool;
memset(pTxPacket, 0, sizeof(STxMgmtPacket) + WLAN_A3FR_MAXLEN);
pTxPacket->p80211Header = (PUWLAN_80211HDR)((unsigned char *)pTxPacket + sizeof(STxMgmtPacket));
pFrame = (PWLAN_FRAME_TPCREP)((unsigned char *)pTxPacket + sizeof(STxMgmtPacket));
pFrame->Header.wFrameCtl = ( WLAN_SET_FC_FTYPE(WLAN_FTYPE_MGMT) |
WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_ACTION)
);
memcpy( pFrame->Header.abyAddr1, pTPCReq->Header.abyAddr2, WLAN_ADDR_LEN);
memcpy( pFrame->Header.abyAddr2, CARDpGetCurrentAddress(pMgmt->pAdapter), WLAN_ADDR_LEN);
memcpy( pFrame->Header.abyAddr3, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN);
pFrame->byCategory = 0;
pFrame->byAction = 3;
pFrame->byDialogToken = ((PWLAN_FRAME_MSRREQ) (pMgmt->abyCurrentMSRReq))->byDialogToken;
pFrame->sTPCRepEIDs.byElementID = WLAN_EID_TPC_REP;
pFrame->sTPCRepEIDs.len = 2;
pFrame->sTPCRepEIDs.byTxPower = CARDbyGetTransmitPower(pMgmt->pAdapter);
switch (byRate) {
case RATE_54M:
pFrame->sTPCRepEIDs.byLinkMargin = 65 - byRSSI;
break;
case RATE_48M:
pFrame->sTPCRepEIDs.byLinkMargin = 66 - byRSSI;
break;
case RATE_36M:
pFrame->sTPCRepEIDs.byLinkMargin = 70 - byRSSI;
break;
case RATE_24M:
pFrame->sTPCRepEIDs.byLinkMargin = 74 - byRSSI;
break;
case RATE_18M:
pFrame->sTPCRepEIDs.byLinkMargin = 77 - byRSSI;
break;
case RATE_12M:
pFrame->sTPCRepEIDs.byLinkMargin = 79 - byRSSI;
break;
case RATE_9M:
pFrame->sTPCRepEIDs.byLinkMargin = 81 - byRSSI;
break;
case RATE_6M:
default:
pFrame->sTPCRepEIDs.byLinkMargin = 82 - byRSSI;
break;
}
pTxPacket->cbMPDULen = sizeof(WLAN_FRAME_TPCREP);
pTxPacket->cbPayloadLen = sizeof(WLAN_FRAME_TPCREP) - WLAN_HDR_ADDR3_LEN;
if (csMgmt_xmit(pMgmt->pAdapter, pTxPacket) != CMD_STATUS_PENDING)
return (false);
return (true);
// return (CARDbSendPacket(pMgmt->pAdapter, pFrame, PKT_TYPE_802_11_MNG, sizeof(WLAN_FRAME_TPCREP)));
}
/*--------------------- Export Variables --------------------------*/
/*--------------------- Export Functions --------------------------*/
/*+
*
* Description:
* Handles action management frames.
*
* Parameters:
* In:
* pMgmt - Management Object structure
* pRxPacket - Received packet
* Out:
* none
*
* Return Value: None.
*
-*/
bool
IEEE11hbMgrRxAction (
void *pMgmtHandle,
void *pRxPacket
)
{
PSMgmtObject pMgmt = (PSMgmtObject) pMgmtHandle;
PWLAN_FRAME_ACTION pAction = NULL;
unsigned int uLength = 0;
PWLAN_IE_CH_SW pChannelSwitch = NULL;
// decode the frame
uLength = ((PSRxMgmtPacket)pRxPacket)->cbMPDULen;
if (uLength > WLAN_A3FR_MAXLEN) {
return (false);
}
pAction = (PWLAN_FRAME_ACTION) (((PSRxMgmtPacket)pRxPacket)->p80211Header);
if (pAction->byCategory == 0) {
switch (pAction->byAction) {
case ACTION_MSRREQ:
return (s_bRxMSRReq(pMgmt, (PWLAN_FRAME_MSRREQ) pAction, uLength));
break;
case ACTION_MSRREP:
break;
case ACTION_TPCREQ:
return (s_bRxTPCReq(pMgmt,
(PWLAN_FRAME_TPCREQ) pAction,
((PSRxMgmtPacket)pRxPacket)->byRxRate,
(unsigned char) ((PSRxMgmtPacket)pRxPacket)->uRSSI));
break;
case ACTION_TPCREP:
break;
case ACTION_CHSW:
pChannelSwitch = (PWLAN_IE_CH_SW) (pAction->abyVars);
if ((pChannelSwitch->byElementID == WLAN_EID_CH_SWITCH) &&
(pChannelSwitch->len == 3)) {
// valid element id
CARDbChannelSwitch( pMgmt->pAdapter,
pChannelSwitch->byMode,
get_channel_mapping(pMgmt->pAdapter, pChannelSwitch->byChannel, pMgmt->eCurrentPHYMode),
pChannelSwitch->byCount
);
}
break;
default:
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Unknown Action = %d\n", pAction->byAction);
break;
}
} else {
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Unknown Category = %d\n", pAction->byCategory);
pAction->byCategory |= 0x80;
//return (CARDbSendPacket(pMgmt->pAdapter, pAction, PKT_TYPE_802_11_MNG, uLength));
return (true);
}
return (true);
}
bool IEEE11hbMSRRepTx (
void *pMgmtHandle
)
{
PSMgmtObject pMgmt = (PSMgmtObject) pMgmtHandle;
PWLAN_FRAME_MSRREP pMSRRep = (PWLAN_FRAME_MSRREP) (pMgmt->abyCurrentMSRRep + sizeof(STxMgmtPacket));
size_t uLength = 0;
PSTxMgmtPacket pTxPacket = NULL;
pTxPacket = (PSTxMgmtPacket)pMgmt->abyCurrentMSRRep;
memset(pTxPacket, 0, sizeof(STxMgmtPacket) + WLAN_A3FR_MAXLEN);
pTxPacket->p80211Header = (PUWLAN_80211HDR)((unsigned char *)pTxPacket + sizeof(STxMgmtPacket));
pMSRRep->Header.wFrameCtl = ( WLAN_SET_FC_FTYPE(WLAN_FTYPE_MGMT) |
WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_ACTION)
);
memcpy( pMSRRep->Header.abyAddr1, ((PWLAN_FRAME_MSRREQ) (pMgmt->abyCurrentMSRReq))->Header.abyAddr2, WLAN_ADDR_LEN);
memcpy( pMSRRep->Header.abyAddr2, CARDpGetCurrentAddress(pMgmt->pAdapter), WLAN_ADDR_LEN);
memcpy( pMSRRep->Header.abyAddr3, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN);
pMSRRep->byCategory = 0;
pMSRRep->byAction = 1;
pMSRRep->byDialogToken = ((PWLAN_FRAME_MSRREQ) (pMgmt->abyCurrentMSRReq))->byDialogToken;
uLength = pMgmt->uLengthOfRepEIDs + offsetof(WLAN_FRAME_MSRREP, sMSRRepEIDs);
pTxPacket->cbMPDULen = uLength;
pTxPacket->cbPayloadLen = uLength - WLAN_HDR_ADDR3_LEN;
if (csMgmt_xmit(pMgmt->pAdapter, pTxPacket) != CMD_STATUS_PENDING)
return (false);
return (true);
// return (CARDbSendPacket(pMgmt->pAdapter, pMSRRep, PKT_TYPE_802_11_MNG, uLength));
}