linux/drivers/staging/vt6655/IEEE11h.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 1996, 2005 VIA Networking Technologies, Inc.
   3 * All rights reserved.
   4 *
   5 * This program is free software; you can redistribute it and/or modify
   6 * it under the terms of the GNU General Public License as published by
   7 * the Free Software Foundation; either version 2 of the License, or
   8 * (at your option) any later version.
   9 *
  10 * This program is distributed in the hope that it will be useful,
  11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13 * GNU General Public License for more details.
  14 *
  15 * You should have received a copy of the GNU General Public License along
  16 * with this program; if not, write to the Free Software Foundation, Inc.,
  17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  18 *
  19 *
  20 * File: IEEE11h.c
  21 *
  22 * Purpose:
  23 *
  24 * Functions:
  25 *
  26 * Revision History:
  27 *
  28 * Author: Yiching Chen
  29 *
  30 * Date: Mar. 31, 2005
  31 *
  32 */
  33
  34#include "ttype.h"
  35#include "tmacro.h"
  36#include "tether.h"
  37#include "IEEE11h.h"
  38#include "device.h"
  39#include "wmgr.h"
  40#include "rxtx.h"
  41#include "channel.h"
  42
  43/*---------------------  Static Definitions -------------------------*/
  44static int          msglevel                = MSG_LEVEL_INFO;
  45
  46#pragma pack(1)
  47
  48typedef struct _WLAN_FRAME_ACTION {
  49        WLAN_80211HDR_A3    Header;
  50        unsigned char byCategory;
  51        unsigned char byAction;
  52        unsigned char abyVars[1];
  53} WLAN_FRAME_ACTION, *PWLAN_FRAME_ACTION;
  54
  55typedef struct _WLAN_FRAME_MSRREQ {
  56        WLAN_80211HDR_A3    Header;
  57        unsigned char byCategory;
  58        unsigned char byAction;
  59        unsigned char byDialogToken;
  60        WLAN_IE_MEASURE_REQ sMSRReqEIDs[1];
  61} WLAN_FRAME_MSRREQ, *PWLAN_FRAME_MSRREQ;
  62
  63typedef struct _WLAN_FRAME_MSRREP {
  64        WLAN_80211HDR_A3    Header;
  65        unsigned char byCategory;
  66        unsigned char byAction;
  67        unsigned char byDialogToken;
  68        WLAN_IE_MEASURE_REP sMSRRepEIDs[1];
  69} WLAN_FRAME_MSRREP, *PWLAN_FRAME_MSRREP;
  70
  71typedef struct _WLAN_FRAME_TPCREQ {
  72        WLAN_80211HDR_A3    Header;
  73        unsigned char byCategory;
  74        unsigned char byAction;
  75        unsigned char byDialogToken;
  76        WLAN_IE_TPC_REQ     sTPCReqEIDs;
  77} WLAN_FRAME_TPCREQ, *PWLAN_FRAME_TPCREQ;
  78
  79typedef struct _WLAN_FRAME_TPCREP {
  80        WLAN_80211HDR_A3    Header;
  81        unsigned char byCategory;
  82        unsigned char byAction;
  83        unsigned char byDialogToken;
  84        WLAN_IE_TPC_REP     sTPCRepEIDs;
  85} WLAN_FRAME_TPCREP, *PWLAN_FRAME_TPCREP;
  86
  87#pragma pack()
  88
  89/* action field reference ieee 802.11h Table 20e */
  90#define ACTION_MSRREQ       0
  91#define ACTION_MSRREP       1
  92#define ACTION_TPCREQ       2
  93#define ACTION_TPCREP       3
  94#define ACTION_CHSW         4
  95
  96/*---------------------  Static Classes  ----------------------------*/
  97
  98/*---------------------  Static Variables  --------------------------*/
  99
 100/*---------------------  Static Functions  --------------------------*/
 101static bool s_bRxMSRReq(PSMgmtObject pMgmt, PWLAN_FRAME_MSRREQ pMSRReq,
 102                        unsigned int uLength)
 103{
 104        size_t    uNumOfEIDs = 0;
 105        bool bResult = true;
 106
 107        if (uLength <= WLAN_A3FR_MAXLEN)
 108                memcpy(pMgmt->abyCurrentMSRReq, pMSRReq, uLength);
 109        uNumOfEIDs = ((uLength - offsetof(WLAN_FRAME_MSRREQ,
 110                                          sMSRReqEIDs))/
 111                      (sizeof(WLAN_IE_MEASURE_REQ)));
 112        pMgmt->pCurrMeasureEIDRep = &(((PWLAN_FRAME_MSRREP)
 113                                       (pMgmt->abyCurrentMSRRep))->sMSRRepEIDs[0]);
 114        pMgmt->uLengthOfRepEIDs = 0;
 115        bResult = CARDbStartMeasure(pMgmt->pAdapter,
 116                                    ((PWLAN_FRAME_MSRREQ)
 117                                     (pMgmt->abyCurrentMSRReq))->sMSRReqEIDs,
 118                                    uNumOfEIDs
 119);
 120        return bResult;
 121}
 122
 123static bool s_bRxTPCReq(PSMgmtObject pMgmt,
 124                        PWLAN_FRAME_TPCREQ pTPCReq,
 125                        unsigned char byRate,
 126                        unsigned char byRSSI)
 127{
 128        PWLAN_FRAME_TPCREP  pFrame;
 129        PSTxMgmtPacket      pTxPacket = NULL;
 130
 131        pTxPacket = (PSTxMgmtPacket)pMgmt->pbyMgmtPacketPool;
 132        memset(pTxPacket, 0, sizeof(STxMgmtPacket) + WLAN_A3FR_MAXLEN);
 133        pTxPacket->p80211Header = (PUWLAN_80211HDR)((unsigned char *)pTxPacket +
 134                                                    sizeof(STxMgmtPacket));
 135
 136        pFrame = (PWLAN_FRAME_TPCREP)((unsigned char *)pTxPacket +
 137                                      sizeof(STxMgmtPacket));
 138
 139        pFrame->Header.wFrameCtl = (WLAN_SET_FC_FTYPE(WLAN_FTYPE_MGMT) |
 140                                    WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_ACTION)
 141);
 142
 143        memcpy(pFrame->Header.abyAddr1,
 144               pTPCReq->Header.abyAddr2,
 145               WLAN_ADDR_LEN);
 146        memcpy(pFrame->Header.abyAddr2,
 147               CARDpGetCurrentAddress(pMgmt->pAdapter),
 148               WLAN_ADDR_LEN);
 149        memcpy(pFrame->Header.abyAddr3,
 150               pMgmt->abyCurrBSSID,
 151               WLAN_BSSID_LEN);
 152
 153        pFrame->byCategory = 0;
 154        pFrame->byAction = 3;
 155        pFrame->byDialogToken = ((PWLAN_FRAME_MSRREQ)
 156                                 (pMgmt->abyCurrentMSRReq))->byDialogToken;
 157
 158        pFrame->sTPCRepEIDs.byElementID = WLAN_EID_TPC_REP;
 159        pFrame->sTPCRepEIDs.len = 2;
 160        pFrame->sTPCRepEIDs.byTxPower = CARDbyGetTransmitPower(pMgmt->pAdapter);
 161        switch (byRate) {
 162        case RATE_54M:
 163                pFrame->sTPCRepEIDs.byLinkMargin = 65 - byRSSI;
 164                break;
 165        case RATE_48M:
 166                pFrame->sTPCRepEIDs.byLinkMargin = 66 - byRSSI;
 167                break;
 168        case RATE_36M:
 169                pFrame->sTPCRepEIDs.byLinkMargin = 70 - byRSSI;
 170                break;
 171        case RATE_24M:
 172                pFrame->sTPCRepEIDs.byLinkMargin = 74 - byRSSI;
 173                break;
 174        case RATE_18M:
 175                pFrame->sTPCRepEIDs.byLinkMargin = 77 - byRSSI;
 176                break;
 177        case RATE_12M:
 178                pFrame->sTPCRepEIDs.byLinkMargin = 79 - byRSSI;
 179                break;
 180        case RATE_9M:
 181                pFrame->sTPCRepEIDs.byLinkMargin = 81 - byRSSI;
 182                break;
 183        case RATE_6M:
 184        default:
 185                pFrame->sTPCRepEIDs.byLinkMargin = 82 - byRSSI;
 186                break;
 187        }
 188
 189        pTxPacket->cbMPDULen = sizeof(WLAN_FRAME_TPCREP);
 190        pTxPacket->cbPayloadLen = sizeof(WLAN_FRAME_TPCREP) -
 191                WLAN_HDR_ADDR3_LEN;
 192        if (csMgmt_xmit(pMgmt->pAdapter, pTxPacket) != CMD_STATUS_PENDING)
 193                return false;
 194        return true;
 195/*    return CARDbSendPacket(pMgmt->pAdapter, pFrame, PKT_TYPE_802_11_MNG,
 196      sizeof(WLAN_FRAME_TPCREP)); */
 197}
 198
 199/*---------------------  Export Variables  --------------------------*/
 200
 201/*---------------------  Export Functions  --------------------------*/
 202
 203/*+
 204 *
 205 * Description:
 206 *      Handles action management frames.
 207 *
 208 * Parameters:
 209 *  In:
 210 *      pMgmt           - Management Object structure
 211 *      pRxPacket       - Received packet
 212 *  Out:
 213 *      none
 214 *
 215 * Return Value: None.
 216 *
 217 -*/
 218bool
 219IEEE11hbMgrRxAction(void *pMgmtHandle, void *pRxPacket)
 220{
 221        PSMgmtObject            pMgmt = (PSMgmtObject) pMgmtHandle;
 222        PWLAN_FRAME_ACTION      pAction = NULL;
 223        unsigned int uLength = 0;
 224        PWLAN_IE_CH_SW          pChannelSwitch = NULL;
 225
 226        /* decode the frame */
 227        uLength = ((PSRxMgmtPacket)pRxPacket)->cbMPDULen;
 228        if (uLength > WLAN_A3FR_MAXLEN)
 229                return false;
 230
 231        pAction = (PWLAN_FRAME_ACTION)
 232                (((PSRxMgmtPacket)pRxPacket)->p80211Header);
 233
 234        if (pAction->byCategory == 0) {
 235                switch (pAction->byAction) {
 236                case ACTION_MSRREQ:
 237                        return s_bRxMSRReq(pMgmt,
 238                                           (PWLAN_FRAME_MSRREQ)
 239                                           pAction,
 240                                           uLength);
 241                        break;
 242                case ACTION_MSRREP:
 243                        break;
 244                case ACTION_TPCREQ:
 245                        return s_bRxTPCReq(pMgmt,
 246                                           (PWLAN_FRAME_TPCREQ) pAction,
 247                                           ((PSRxMgmtPacket)pRxPacket)->byRxRate,
 248                                           (unsigned char)
 249                                           ((PSRxMgmtPacket)pRxPacket)->uRSSI);
 250                        break;
 251                case ACTION_TPCREP:
 252                        break;
 253                case ACTION_CHSW:
 254                        pChannelSwitch = (PWLAN_IE_CH_SW) (pAction->abyVars);
 255                        if ((pChannelSwitch->byElementID == WLAN_EID_CH_SWITCH)
 256                            && (pChannelSwitch->len == 3)) {
 257                                /* valid element id */
 258                                CARDbChannelSwitch(pMgmt->pAdapter,
 259                                                   pChannelSwitch->byMode,
 260                                                   get_channel_mapping(pMgmt->pAdapter,
 261                                                                       pChannelSwitch->byChannel,
 262                                                                       pMgmt->eCurrentPHYMode),
 263                                                   pChannelSwitch->byCount);
 264                        }
 265                        break;
 266                default:
 267                        DBG_PRT(MSG_LEVEL_DEBUG,
 268                                KERN_INFO "Unknown Action = %d\n",
 269                                pAction->byAction);
 270                        break;
 271                }
 272        } else {
 273                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Unknown Category = %d\n",
 274                        pAction->byCategory);
 275                pAction->byCategory |= 0x80;
 276
 277                /*return CARDbSendPacket(pMgmt->pAdapter, pAction, PKT_TYPE_802_11_MNG,
 278                  uLength);*/
 279                return true;
 280        }
 281        return true;
 282}
 283
 284bool IEEE11hbMSRRepTx(void *pMgmtHandle)
 285{
 286        PSMgmtObject            pMgmt = (PSMgmtObject) pMgmtHandle;
 287        PWLAN_FRAME_MSRREP      pMSRRep = (PWLAN_FRAME_MSRREP)
 288                (pMgmt->abyCurrentMSRRep + sizeof(STxMgmtPacket));
 289        size_t                    uLength = 0;
 290        PSTxMgmtPacket          pTxPacket = NULL;
 291
 292        pTxPacket = (PSTxMgmtPacket)pMgmt->abyCurrentMSRRep;
 293        memset(pTxPacket, 0, sizeof(STxMgmtPacket) + WLAN_A3FR_MAXLEN);
 294        pTxPacket->p80211Header = (PUWLAN_80211HDR)((unsigned char *)pTxPacket +
 295                                                    sizeof(STxMgmtPacket));
 296
 297        pMSRRep->Header.wFrameCtl = (WLAN_SET_FC_FTYPE(WLAN_FTYPE_MGMT) |
 298                                     WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_ACTION)
 299);
 300
 301        memcpy(pMSRRep->Header.abyAddr1, ((PWLAN_FRAME_MSRREQ)
 302                                          (pMgmt->abyCurrentMSRReq))->Header.abyAddr2, WLAN_ADDR_LEN);
 303        memcpy(pMSRRep->Header.abyAddr2,
 304               CARDpGetCurrentAddress(pMgmt->pAdapter), WLAN_ADDR_LEN);
 305        memcpy(pMSRRep->Header.abyAddr3, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN);
 306
 307        pMSRRep->byCategory = 0;
 308        pMSRRep->byAction = 1;
 309        pMSRRep->byDialogToken = ((PWLAN_FRAME_MSRREQ)
 310                                  (pMgmt->abyCurrentMSRReq))->byDialogToken;
 311
 312        uLength = pMgmt->uLengthOfRepEIDs + offsetof(WLAN_FRAME_MSRREP,
 313                                                     sMSRRepEIDs);
 314
 315        pTxPacket->cbMPDULen = uLength;
 316        pTxPacket->cbPayloadLen = uLength - WLAN_HDR_ADDR3_LEN;
 317        if (csMgmt_xmit(pMgmt->pAdapter, pTxPacket) != CMD_STATUS_PENDING)
 318                return false;
 319        return true;
 320/*    return CARDbSendPacket(pMgmt->pAdapter, pMSRRep, PKT_TYPE_802_11_MNG,
 321      uLength); */
 322}
 323