diff options
Diffstat (limited to 'drivers/staging/vt6655/IEEE11h.c')
| -rw-r--r-- | drivers/staging/vt6655/IEEE11h.c | 316 |
1 files changed, 316 insertions, 0 deletions
diff --git a/drivers/staging/vt6655/IEEE11h.c b/drivers/staging/vt6655/IEEE11h.c new file mode 100644 index 00000000000..6cfad1c0402 --- /dev/null +++ b/drivers/staging/vt6655/IEEE11h.c @@ -0,0 +1,316 @@ +/* + * 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; +} + +/*--------------------- 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 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; +} |
