linux/drivers/staging/rt3090/sta/dls.c
<<
>>
Prefs
   1/*
   2 *************************************************************************
   3 * Ralink Tech Inc.
   4 * 5F., No.36, Taiyuan St., Jhubei City,
   5 * Hsinchu County 302,
   6 * Taiwan, R.O.C.
   7 *
   8 * (c) Copyright 2002-2007, Ralink Technology, Inc.
   9 *
  10 * This program is free software; you can redistribute it and/or modify  *
  11 * it under the terms of the GNU General Public License as published by  *
  12 * the Free Software Foundation; either version 2 of the License, or     *
  13 * (at your option) any later version.                                   *
  14 *                                                                       *
  15 * This program is distributed in the hope that it will be useful,       *
  16 * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
  17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
  18 * GNU General Public License for more details.                          *
  19 *                                                                       *
  20 * You should have received a copy of the GNU General Public License     *
  21 * along with this program; if not, write to the                         *
  22 * Free Software Foundation, Inc.,                                       *
  23 * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
  24 *                                                                       *
  25 *************************************************************************
  26
  27    Module Name:
  28    dls.c
  29
  30    Abstract:
  31    Handle WMM-DLS state machine
  32
  33    Revision History:
  34    Who         When          What
  35    --------    ----------    ----------------------------------------------
  36    Rory Chen   02-14-2006
  37        Arvin Tai       06-03-2008        Modified for RT28xx
  38 */
  39
  40#include "../rt_config.h"
  41
  42
  43/*
  44    ==========================================================================
  45    Description:
  46        dls state machine init, including state transition and timer init
  47    Parameters:
  48        Sm - pointer to the dls state machine
  49    Note:
  50        The state machine looks like this
  51
  52                            DLS_IDLE
  53    MT2_MLME_DLS_REQUEST   MlmeDlsReqAction
  54    MT2_PEER_DLS_REQUEST   PeerDlsReqAction
  55    MT2_PEER_DLS_RESPONSE  PeerDlsRspAction
  56    MT2_MLME_DLS_TEARDOWN  MlmeTearDownAction
  57    MT2_PEER_DLS_TEARDOWN  PeerTearDownAction
  58
  59        IRQL = PASSIVE_LEVEL
  60
  61    ==========================================================================
  62 */
  63void DlsStateMachineInit(
  64    IN PRTMP_ADAPTER pAd,
  65    IN STATE_MACHINE *Sm,
  66    OUT STATE_MACHINE_FUNC Trans[])
  67{
  68        UCHAR   i;
  69
  70    StateMachineInit(Sm, (STATE_MACHINE_FUNC*)Trans, MAX_DLS_STATE, MAX_DLS_MSG, (STATE_MACHINE_FUNC)Drop, DLS_IDLE, DLS_MACHINE_BASE);
  71
  72    // the first column
  73    StateMachineSetAction(Sm, DLS_IDLE, MT2_MLME_DLS_REQ, (STATE_MACHINE_FUNC)MlmeDlsReqAction);
  74    StateMachineSetAction(Sm, DLS_IDLE, MT2_PEER_DLS_REQ, (STATE_MACHINE_FUNC)PeerDlsReqAction);
  75    StateMachineSetAction(Sm, DLS_IDLE, MT2_PEER_DLS_RSP, (STATE_MACHINE_FUNC)PeerDlsRspAction);
  76    StateMachineSetAction(Sm, DLS_IDLE, MT2_MLME_DLS_TEAR_DOWN, (STATE_MACHINE_FUNC)MlmeDlsTearDownAction);
  77    StateMachineSetAction(Sm, DLS_IDLE, MT2_PEER_DLS_TEAR_DOWN, (STATE_MACHINE_FUNC)PeerDlsTearDownAction);
  78
  79        for (i=0; i<MAX_NUM_OF_DLS_ENTRY; i++)
  80        {
  81                pAd->StaCfg.DLSEntry[i].pAd = pAd;
  82                RTMPInitTimer(pAd, &pAd->StaCfg.DLSEntry[i].Timer, GET_TIMER_FUNCTION(DlsTimeoutAction), pAd, FALSE);
  83        }
  84}
  85
  86/*
  87    ==========================================================================
  88    Description:
  89
  90        IRQL = DISPATCH_LEVEL
  91
  92    ==========================================================================
  93 */
  94VOID MlmeDlsReqAction(
  95    IN PRTMP_ADAPTER pAd,
  96    IN MLME_QUEUE_ELEM *Elem)
  97{
  98        PUCHAR                  pOutBuffer = NULL;
  99        NDIS_STATUS             NStatus;
 100        ULONG                   FrameLen = 0;
 101        HEADER_802_11   DlsReqHdr;
 102        PRT_802_11_DLS  pDLS = NULL;
 103        UCHAR                   Category = CATEGORY_DLS;
 104        UCHAR                   Action = ACTION_DLS_REQUEST;
 105        ULONG                   tmp;
 106        USHORT                  reason;
 107        ULONG                   Timeout;
 108        BOOLEAN                 TimerCancelled;
 109
 110        if(!MlmeDlsReqSanity(pAd, Elem->Msg, Elem->MsgLen, &pDLS, &reason))
 111                return;
 112
 113        DBGPRINT(RT_DEBUG_TRACE,("DLS - MlmeDlsReqAction() \n"));
 114
 115        NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);  //Get an unused nonpaged memory
 116        if (NStatus != NDIS_STATUS_SUCCESS)
 117        {
 118                DBGPRINT(RT_DEBUG_ERROR,("DLS - MlmeDlsReqAction() allocate memory failed \n"));
 119                return;
 120        }
 121
 122        ActHeaderInit(pAd, &DlsReqHdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAd->CommonCfg.Bssid);
 123
 124        // Build basic frame first
 125        MakeOutgoingFrame(pOutBuffer,                           &FrameLen,
 126                                        sizeof(HEADER_802_11),          &DlsReqHdr,
 127                                        1,                                                      &Category,
 128                                        1,                                                      &Action,
 129                                        6,                                                      &pDLS->MacAddr,
 130                                        6,                                                      pAd->CurrentAddress,
 131                                        2,                                                      &pAd->StaActive.CapabilityInfo,
 132                                        2,                                                      &pDLS->TimeOut,
 133                                        1,                                                      &SupRateIe,
 134                                        1,                                                      &pAd->MlmeAux.SupRateLen,
 135                                        pAd->MlmeAux.SupRateLen,        pAd->MlmeAux.SupRate,
 136                                        END_OF_ARGS);
 137
 138        if (pAd->MlmeAux.ExtRateLen != 0)
 139        {
 140                MakeOutgoingFrame(pOutBuffer + FrameLen,        &tmp,
 141                                                  1,                                            &ExtRateIe,
 142                                                  1,                                            &pAd->MlmeAux.ExtRateLen,
 143                                                  pAd->MlmeAux.ExtRateLen,      pAd->MlmeAux.ExtRate,
 144                                                  END_OF_ARGS);
 145                FrameLen += tmp;
 146        }
 147
 148#ifdef DOT11_N_SUPPORT
 149        if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED))
 150        {
 151                UCHAR HtLen;
 152
 153#ifdef RT_BIG_ENDIAN
 154                HT_CAPABILITY_IE HtCapabilityTmp;
 155#endif
 156
 157                // add HT Capability IE
 158                HtLen = sizeof(HT_CAPABILITY_IE);
 159#ifndef RT_BIG_ENDIAN
 160                MakeOutgoingFrame(pOutBuffer + FrameLen,        &tmp,
 161                                                        1,                                              &HtCapIe,
 162                                                        1,                                              &HtLen,
 163                                                        HtLen,                                  &pAd->CommonCfg.HtCapability,
 164                                                        END_OF_ARGS);
 165#else
 166                NdisMoveMemory(&HtCapabilityTmp, &pAd->CommonCfg.HtCapability, HtLen);
 167                                                        *(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo));
 168                                                        *(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo));
 169
 170                MakeOutgoingFrame(pOutBuffer + FrameLen,        &tmp,
 171                                                        1,                                              &HtCapIe,
 172                                                        1,                                              &HtLen,
 173                                                        HtLen,                                  &HtCapabilityTmp,
 174                                                        END_OF_ARGS);
 175#endif
 176                FrameLen = FrameLen + tmp;
 177        }
 178#endif // DOT11_N_SUPPORT //
 179
 180        RTMPCancelTimer(&pDLS->Timer, &TimerCancelled);
 181        Timeout = DLS_TIMEOUT;
 182        RTMPSetTimer(&pDLS->Timer, Timeout);
 183
 184        MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
 185        MlmeFreeMemory(pAd, pOutBuffer);
 186}
 187
 188/*
 189    ==========================================================================
 190    Description:
 191
 192        IRQL = DISPATCH_LEVEL
 193
 194    ==========================================================================
 195 */
 196VOID PeerDlsReqAction(
 197    IN PRTMP_ADAPTER pAd,
 198    IN MLME_QUEUE_ELEM *Elem)
 199{
 200        PUCHAR                  pOutBuffer = NULL;
 201        NDIS_STATUS             NStatus;
 202        ULONG                   FrameLen = 0;
 203        USHORT                  StatusCode = MLME_SUCCESS;
 204        HEADER_802_11   DlsRspHdr;
 205        UCHAR                   Category = CATEGORY_DLS;
 206        UCHAR                   Action = ACTION_DLS_RESPONSE;
 207        ULONG                   tmp;
 208        USHORT                  CapabilityInfo;
 209        UCHAR                   DA[MAC_ADDR_LEN], SA[MAC_ADDR_LEN];
 210        USHORT                  DLSTimeOut;
 211        SHORT                   i;
 212        ULONG                   Timeout;
 213        BOOLEAN                 TimerCancelled;
 214        PRT_802_11_DLS  pDLS = NULL;
 215        UCHAR                   MaxSupportedRateIn500Kbps = 0;
 216    UCHAR                       SupportedRatesLen;
 217    UCHAR                       SupportedRates[MAX_LEN_OF_SUPPORTED_RATES];
 218        UCHAR                   HtCapabilityLen;
 219        HT_CAPABILITY_IE        HtCapability;
 220
 221        if (!PeerDlsReqSanity(pAd, Elem->Msg, Elem->MsgLen, DA, SA, &CapabilityInfo, &DLSTimeOut,
 222                                                        &SupportedRatesLen, &SupportedRates[0], &HtCapabilityLen, &HtCapability))
 223                return;
 224
 225    // supported rates array may not be sorted. sort it and find the maximum rate
 226    for (i = 0; i < SupportedRatesLen; i++)
 227    {
 228        if (MaxSupportedRateIn500Kbps < (SupportedRates[i] & 0x7f))
 229            MaxSupportedRateIn500Kbps = SupportedRates[i] & 0x7f;
 230    }
 231
 232        DBGPRINT(RT_DEBUG_TRACE,("DLS - PeerDlsReqAction() from %02x:%02x:%02x:%02x:%02x:%02x\n", SA[0], SA[1], SA[2], SA[3], SA[4], SA[5]));
 233
 234        NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);  //Get an unused nonpaged memory
 235        if (NStatus != NDIS_STATUS_SUCCESS)
 236        {
 237                DBGPRINT(RT_DEBUG_ERROR,("DLS - PeerDlsReqAction() allocate memory failed \n"));
 238                return;
 239        }
 240
 241        if (!INFRA_ON(pAd))
 242        {
 243                StatusCode = MLME_REQUEST_DECLINED;
 244        }
 245        else if (!pAd->CommonCfg.bWmmCapable)
 246        {
 247                StatusCode = MLME_DEST_STA_IS_NOT_A_QSTA;
 248        }
 249        else if (!pAd->CommonCfg.bDLSCapable)
 250        {
 251                StatusCode = MLME_REQUEST_DECLINED;
 252        }
 253        else
 254        {
 255                // find table to update parameters
 256                for (i = (MAX_NUM_OF_DLS_ENTRY-1); i >= 0; i--)
 257                {
 258                        if (pAd->StaCfg.DLSEntry[i].Valid && MAC_ADDR_EQUAL(SA, pAd->StaCfg.DLSEntry[i].MacAddr))
 259                        {
 260                                if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
 261                                        pAd->StaCfg.DLSEntry[i].Status = DLS_WAIT_KEY;
 262                                else
 263                                {
 264                                        RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled);
 265                                        pAd->StaCfg.DLSEntry[i].Status = DLS_FINISH;
 266                                }
 267
 268                                pAd->StaCfg.DLSEntry[i].Sequence = 0;
 269                                pAd->StaCfg.DLSEntry[i].TimeOut = DLSTimeOut;
 270                                pAd->StaCfg.DLSEntry[i].CountDownTimer = DLSTimeOut;
 271                                if (HtCapabilityLen != 0)
 272                                        pAd->StaCfg.DLSEntry[i].bHTCap = TRUE;
 273                                else
 274                                        pAd->StaCfg.DLSEntry[i].bHTCap = FALSE;
 275                                pDLS = &pAd->StaCfg.DLSEntry[i];
 276                                break;
 277                        }
 278                }
 279
 280                // can not find in table, create a new one
 281                if (i < 0)
 282                {
 283                        DBGPRINT(RT_DEBUG_TRACE,("DLS - PeerDlsReqAction() can not find same entry \n"));
 284                        for (i=(MAX_NUM_OF_DLS_ENTRY - 1); i >= MAX_NUM_OF_INIT_DLS_ENTRY; i--)
 285                        {
 286                                if (!pAd->StaCfg.DLSEntry[i].Valid)
 287                                {
 288                                        MAC_TABLE_ENTRY *pEntry;
 289                                        UCHAR MaxSupportedRate = RATE_11;
 290
 291                                        if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
 292                                        {
 293                                                pAd->StaCfg.DLSEntry[i].Status = DLS_WAIT_KEY;
 294                                        }
 295                                        else
 296                                        {
 297                                                RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled);
 298                                                pAd->StaCfg.DLSEntry[i].Status = DLS_FINISH;
 299                                        }
 300
 301                                        pAd->StaCfg.DLSEntry[i].Sequence = 0;
 302                                        pAd->StaCfg.DLSEntry[i].Valid = TRUE;
 303                                        pAd->StaCfg.DLSEntry[i].TimeOut = DLSTimeOut;
 304                                        pAd->StaCfg.DLSEntry[i].CountDownTimer = DLSTimeOut;
 305                                        NdisMoveMemory(pAd->StaCfg.DLSEntry[i].MacAddr, SA, MAC_ADDR_LEN);
 306                                        if (HtCapabilityLen != 0)
 307                                                pAd->StaCfg.DLSEntry[i].bHTCap = TRUE;
 308                                        else
 309                                                pAd->StaCfg.DLSEntry[i].bHTCap = FALSE;
 310                                        pDLS = &pAd->StaCfg.DLSEntry[i];
 311                                        pEntry = MacTableInsertDlsEntry(pAd, SA, i);
 312
 313                                        switch (MaxSupportedRateIn500Kbps)
 314                                        {
 315                                                case 108: MaxSupportedRate = RATE_54;   break;
 316                                                case 96:  MaxSupportedRate = RATE_48;   break;
 317                                                case 72:  MaxSupportedRate = RATE_36;   break;
 318                                                case 48:  MaxSupportedRate = RATE_24;   break;
 319                                                case 36:  MaxSupportedRate = RATE_18;   break;
 320                                                case 24:  MaxSupportedRate = RATE_12;   break;
 321                                                case 18:  MaxSupportedRate = RATE_9;    break;
 322                                                case 12:  MaxSupportedRate = RATE_6;    break;
 323                                                case 22:  MaxSupportedRate = RATE_11;   break;
 324                                                case 11:  MaxSupportedRate = RATE_5_5;  break;
 325                                                case 4:   MaxSupportedRate = RATE_2;    break;
 326                                                case 2:   MaxSupportedRate = RATE_1;    break;
 327                                                default:  MaxSupportedRate = RATE_11;   break;
 328                                        }
 329
 330                                        pEntry->MaxSupportedRate = min(pAd->CommonCfg.MaxTxRate, MaxSupportedRate);
 331
 332                                        if (pEntry->MaxSupportedRate < RATE_FIRST_OFDM_RATE)
 333                                        {
 334                                                pEntry->MaxHTPhyMode.field.MODE = MODE_CCK;
 335                                                pEntry->MaxHTPhyMode.field.MCS = pEntry->MaxSupportedRate;
 336                                                pEntry->MinHTPhyMode.field.MODE = MODE_CCK;
 337                                                pEntry->MinHTPhyMode.field.MCS = pEntry->MaxSupportedRate;
 338                                                pEntry->HTPhyMode.field.MODE = MODE_CCK;
 339                                                pEntry->HTPhyMode.field.MCS = pEntry->MaxSupportedRate;
 340                                        }
 341                                        else
 342                                        {
 343                                                pEntry->MaxHTPhyMode.field.MODE = MODE_OFDM;
 344                                                pEntry->MaxHTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate];
 345                                                pEntry->MinHTPhyMode.field.MODE = MODE_OFDM;
 346                                                pEntry->MinHTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate];
 347                                                pEntry->HTPhyMode.field.MODE = MODE_OFDM;
 348                                                pEntry->HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate];
 349                                        }
 350
 351                                        pEntry->MaxHTPhyMode.field.BW = BW_20;
 352                                        pEntry->MinHTPhyMode.field.BW = BW_20;
 353
 354#ifdef DOT11_N_SUPPORT
 355                                        pEntry->HTCapability.MCSSet[0] = 0;
 356                                        pEntry->HTCapability.MCSSet[1] = 0;
 357
 358                                        // If this Entry supports 802.11n, upgrade to HT rate.
 359                                        if ((HtCapabilityLen != 0) && (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED))
 360                                        {
 361                                                UCHAR   j, bitmask; //k,bitmask;
 362                                                CHAR    ii;
 363
 364                                                DBGPRINT(RT_DEBUG_TRACE, ("DLS - PeerDlsReqAction() Receive Peer HT Capable STA from %02x:%02x:%02x:%02x:%02x:%02x\n",
 365                                                                        SA[0], SA[1], SA[2], SA[3], SA[4], SA[5]));
 366
 367                                                if ((HtCapability.HtCapInfo.GF) && (pAd->CommonCfg.DesiredHtPhy.GF))
 368                                                {
 369                                                        pEntry->MaxHTPhyMode.field.MODE = MODE_HTGREENFIELD;
 370                                                }
 371                                                else
 372                                                {
 373                                                        pEntry->MaxHTPhyMode.field.MODE = MODE_HTMIX;
 374                                                        pAd->MacTab.fAnyStationNonGF = TRUE;
 375                                                        pAd->CommonCfg.AddHTInfo.AddHtInfo2.NonGfPresent = 1;
 376                                                }
 377
 378                                                if ((HtCapability.HtCapInfo.ChannelWidth) && (pAd->CommonCfg.DesiredHtPhy.ChannelWidth))
 379                                                {
 380                                                        pEntry->MaxHTPhyMode.field.BW= BW_40;
 381                                                        pEntry->MaxHTPhyMode.field.ShortGI = ((pAd->CommonCfg.DesiredHtPhy.ShortGIfor40)&(HtCapability.HtCapInfo.ShortGIfor40));
 382                                                }
 383                                                else
 384                                                {
 385                                                        pEntry->MaxHTPhyMode.field.BW = BW_20;
 386                                                        pEntry->MaxHTPhyMode.field.ShortGI = ((pAd->CommonCfg.DesiredHtPhy.ShortGIfor20)&(HtCapability.HtCapInfo.ShortGIfor20));
 387                                                        pAd->MacTab.fAnyStation20Only = TRUE;
 388                                                }
 389
 390                                                // find max fixed rate
 391                                                for (ii=15; ii>=0; ii--)
 392                                                {
 393                                                        j = ii/8;
 394                                                        bitmask = (1<<(ii-(j*8)));
 395                                                        if ( (pAd->StaCfg.DesiredHtPhyInfo.MCSSet[j]&bitmask) && (HtCapability.MCSSet[j]&bitmask))
 396                                                        {
 397                                                                pEntry->MaxHTPhyMode.field.MCS = ii;
 398                                                                break;
 399                                                        }
 400                                                        if (ii==0)
 401                                                                break;
 402                                                }
 403
 404
 405                                                if (pAd->StaCfg.DesiredTransmitSetting.field.MCS != MCS_AUTO)
 406                                                {
 407
 408                                                        DBGPRINT(RT_DEBUG_OFF, ("@@@ pAd->CommonCfg.RegTransmitSetting.field.MCS = %d\n",
 409                                                                                pAd->StaCfg.DesiredTransmitSetting.field.MCS));
 410                                                        if (pAd->StaCfg.DesiredTransmitSetting.field.MCS == 32)
 411                                                        {
 412                                                                // Fix MCS as HT Duplicated Mode
 413                                                                pEntry->MaxHTPhyMode.field.BW = 1;
 414                                                                pEntry->MaxHTPhyMode.field.MODE = MODE_HTMIX;
 415                                                                pEntry->MaxHTPhyMode.field.STBC = 0;
 416                                                                pEntry->MaxHTPhyMode.field.ShortGI = 0;
 417                                                                pEntry->MaxHTPhyMode.field.MCS = 32;
 418                                                        }
 419                                                        else if (pEntry->MaxHTPhyMode.field.MCS > pAd->StaCfg.HTPhyMode.field.MCS)
 420                                                        {
 421                                                                // STA supports fixed MCS
 422                                                                pEntry->MaxHTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
 423                                                        }
 424                                                }
 425
 426                                                pEntry->MaxHTPhyMode.field.STBC = (HtCapability.HtCapInfo.RxSTBC & (pAd->CommonCfg.DesiredHtPhy.TxSTBC));
 427                                                pEntry->MpduDensity = HtCapability.HtCapParm.MpduDensity;
 428                                                pEntry->MaxRAmpduFactor = HtCapability.HtCapParm.MaxRAmpduFactor;
 429                                                pEntry->MmpsMode = (UCHAR)HtCapability.HtCapInfo.MimoPs;
 430                                                pEntry->AMsduSize = (UCHAR)HtCapability.HtCapInfo.AMsduSize;
 431                                                pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word;
 432
 433                                                if (HtCapability.HtCapInfo.ShortGIfor20)
 434                                                        CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE);
 435                                                if (HtCapability.HtCapInfo.ShortGIfor40)
 436                                                        CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE);
 437                                                if (HtCapability.HtCapInfo.TxSTBC)
 438                                                        CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_TxSTBC_CAPABLE);
 439                                                if (HtCapability.HtCapInfo.RxSTBC)
 440                                                        CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RxSTBC_CAPABLE);
 441                                                if (HtCapability.ExtHtCapInfo.PlusHTC)
 442                                                        CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_HTC_CAPABLE);
 443                                                if (pAd->CommonCfg.bRdg && HtCapability.ExtHtCapInfo.RDGSupport)
 444                                                        CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RDG_CAPABLE);
 445                                                if (HtCapability.ExtHtCapInfo.MCSFeedback == 0x03)
 446                                                        CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_MCSFEEDBACK_CAPABLE);
 447
 448                                                NdisMoveMemory(&pEntry->HTCapability, &HtCapability, sizeof(HT_CAPABILITY_IE));
 449                                        }
 450#endif // DOT11_N_SUPPORT //
 451
 452                                        pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word;
 453                                        pEntry->CurrTxRate = pEntry->MaxSupportedRate;
 454                                        CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE);
 455
 456                                        if (pAd->StaCfg.bAutoTxRateSwitch == TRUE)
 457                                        {
 458                                                PUCHAR pTable;
 459                                                UCHAR TableSize = 0;
 460
 461                                                MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &pEntry->CurrTxRateIndex);
 462                                                pEntry->bAutoTxRateSwitch = TRUE;
 463                                        }
 464                                        else
 465                                        {
 466                                                pEntry->HTPhyMode.field.MODE    = pAd->StaCfg.HTPhyMode.field.MODE;
 467                                                pEntry->HTPhyMode.field.MCS     = pAd->StaCfg.HTPhyMode.field.MCS;
 468                                                pEntry->bAutoTxRateSwitch = FALSE;
 469
 470                                                RTMPUpdateLegacyTxSetting((UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode, pEntry);
 471                                        }
 472                                        pEntry->RateLen = SupportedRatesLen;
 473
 474                                        break;
 475                                }
 476                        }
 477                }
 478                StatusCode = MLME_SUCCESS;
 479
 480                // can not find in table, create a new one
 481                if (i < 0)
 482                {
 483                        StatusCode = MLME_QOS_UNSPECIFY;
 484                        DBGPRINT(RT_DEBUG_ERROR,("DLS - PeerDlsReqAction() DLSEntry table full(only can support %d DLS session) \n", MAX_NUM_OF_DLS_ENTRY - MAX_NUM_OF_INIT_DLS_ENTRY));
 485                }
 486                else
 487                {
 488                        DBGPRINT(RT_DEBUG_TRACE,("DLS - PeerDlsReqAction() use entry(%d) %02x:%02x:%02x:%02x:%02x:%02x\n",
 489                                i, SA[0], SA[1], SA[2], SA[3], SA[4], SA[5]));
 490                }
 491        }
 492
 493        ActHeaderInit(pAd, &DlsRspHdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAd->CommonCfg.Bssid);
 494
 495        // Build basic frame first
 496        if (StatusCode == MLME_SUCCESS)
 497        {
 498                MakeOutgoingFrame(pOutBuffer,                           &FrameLen,
 499                                                sizeof(HEADER_802_11),          &DlsRspHdr,
 500                                                1,                                                      &Category,
 501                                                1,                                                      &Action,
 502                                                2,                                                      &StatusCode,
 503                                                6,                                                      SA,
 504                                                6,                                                      pAd->CurrentAddress,
 505                                                2,                                                      &pAd->StaActive.CapabilityInfo,
 506                                                1,                                                      &SupRateIe,
 507                                                1,                                                      &pAd->MlmeAux.SupRateLen,
 508                                                pAd->MlmeAux.SupRateLen,        pAd->MlmeAux.SupRate,
 509                                                END_OF_ARGS);
 510
 511                if (pAd->MlmeAux.ExtRateLen != 0)
 512                {
 513                        MakeOutgoingFrame(pOutBuffer + FrameLen,        &tmp,
 514                                                          1,                                            &ExtRateIe,
 515                                                          1,                                            &pAd->MlmeAux.ExtRateLen,
 516                                                          pAd->MlmeAux.ExtRateLen,      pAd->MlmeAux.ExtRate,
 517                                                          END_OF_ARGS);
 518                        FrameLen += tmp;
 519                }
 520
 521#ifdef DOT11_N_SUPPORT
 522                if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED))
 523                {
 524                        UCHAR HtLen;
 525
 526#ifdef RT_BIG_ENDIAN
 527                        HT_CAPABILITY_IE HtCapabilityTmp;
 528#endif
 529
 530                        // add HT Capability IE
 531                        HtLen = sizeof(HT_CAPABILITY_IE);
 532#ifndef RT_BIG_ENDIAN
 533                        MakeOutgoingFrame(pOutBuffer + FrameLen,        &tmp,
 534                                                                1,                                              &HtCapIe,
 535                                                                1,                                              &HtLen,
 536                                                                HtLen,                                  &pAd->CommonCfg.HtCapability,
 537                                                                END_OF_ARGS);
 538#else
 539                        NdisMoveMemory(&HtCapabilityTmp, &pAd->CommonCfg.HtCapability, HtLen);
 540                                                                *(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo));
 541                                                                *(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo));
 542
 543                        MakeOutgoingFrame(pOutBuffer + FrameLen,        &tmp,
 544                                                                1,                                              &HtCapIe,
 545                                                                1,                                              &HtLen,
 546                                                                HtLen,                                  &HtCapabilityTmp,
 547                                                                END_OF_ARGS);
 548#endif
 549                        FrameLen = FrameLen + tmp;
 550                }
 551#endif // DOT11_N_SUPPORT //
 552
 553                if (pDLS && (pDLS->Status != DLS_FINISH))
 554                {
 555                        RTMPCancelTimer(&pDLS->Timer, &TimerCancelled);
 556                        Timeout = DLS_TIMEOUT;
 557                        RTMPSetTimer(&pDLS->Timer, Timeout);
 558                }
 559        }
 560        else
 561        {
 562                MakeOutgoingFrame(pOutBuffer,                           &FrameLen,
 563                                                sizeof(HEADER_802_11),          &DlsRspHdr,
 564                                                1,                                                      &Category,
 565                                                1,                                                      &Action,
 566                                                2,                                                      &StatusCode,
 567                                                6,                                                      SA,
 568                                                6,                                                      pAd->CurrentAddress,
 569                                                END_OF_ARGS);
 570        }
 571
 572        MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
 573        MlmeFreeMemory(pAd, pOutBuffer);
 574}
 575
 576/*
 577    ==========================================================================
 578    Description:
 579
 580        IRQL = DISPATCH_LEVEL
 581
 582    ==========================================================================
 583 */
 584VOID PeerDlsRspAction(
 585    IN PRTMP_ADAPTER pAd,
 586    IN MLME_QUEUE_ELEM *Elem)
 587{
 588        USHORT          CapabilityInfo;
 589        UCHAR           DA[MAC_ADDR_LEN], SA[MAC_ADDR_LEN];
 590        USHORT          StatusCode;
 591        SHORT           i;
 592        BOOLEAN         TimerCancelled;
 593        UCHAR           MaxSupportedRateIn500Kbps = 0;
 594    UCHAR               SupportedRatesLen;
 595    UCHAR               SupportedRates[MAX_LEN_OF_SUPPORTED_RATES];
 596        UCHAR           HtCapabilityLen;
 597        HT_CAPABILITY_IE        HtCapability;
 598
 599        if (!pAd->CommonCfg.bDLSCapable)
 600                return;
 601
 602        if (!INFRA_ON(pAd))
 603                return;
 604
 605        if (!PeerDlsRspSanity(pAd, Elem->Msg, Elem->MsgLen, DA, SA, &CapabilityInfo, &StatusCode,
 606                                                        &SupportedRatesLen, &SupportedRates[0], &HtCapabilityLen, &HtCapability))
 607                return;
 608
 609    // supported rates array may not be sorted. sort it and find the maximum rate
 610    for (i=0; i<SupportedRatesLen; i++)
 611    {
 612        if (MaxSupportedRateIn500Kbps < (SupportedRates[i] & 0x7f))
 613            MaxSupportedRateIn500Kbps = SupportedRates[i] & 0x7f;
 614    }
 615
 616        DBGPRINT(RT_DEBUG_TRACE,("DLS - PeerDlsRspAction() from %02x:%02x:%02x:%02x:%02x:%02x with StatusCode=%d, CapabilityInfo=0x%x\n",
 617                SA[0], SA[1], SA[2], SA[3], SA[4], SA[5], StatusCode, CapabilityInfo));
 618
 619        for (i = 0; i < MAX_NUM_OF_INIT_DLS_ENTRY; i++)
 620        {
 621                if (pAd->StaCfg.DLSEntry[i].Valid && MAC_ADDR_EQUAL(SA, pAd->StaCfg.DLSEntry[i].MacAddr))
 622                {
 623                        if (StatusCode == MLME_SUCCESS)
 624                        {
 625                                MAC_TABLE_ENTRY *pEntry;
 626                                UCHAR MaxSupportedRate = RATE_11;
 627
 628                                pEntry = MacTableInsertDlsEntry(pAd, SA, i);
 629
 630                                switch (MaxSupportedRateIn500Kbps)
 631                                {
 632                                        case 108: MaxSupportedRate = RATE_54;   break;
 633                                        case 96:  MaxSupportedRate = RATE_48;   break;
 634                                        case 72:  MaxSupportedRate = RATE_36;   break;
 635                                        case 48:  MaxSupportedRate = RATE_24;   break;
 636                                        case 36:  MaxSupportedRate = RATE_18;   break;
 637                                        case 24:  MaxSupportedRate = RATE_12;   break;
 638                                        case 18:  MaxSupportedRate = RATE_9;    break;
 639                                        case 12:  MaxSupportedRate = RATE_6;    break;
 640                                        case 22:  MaxSupportedRate = RATE_11;   break;
 641                                        case 11:  MaxSupportedRate = RATE_5_5;  break;
 642                                        case 4:   MaxSupportedRate = RATE_2;    break;
 643                                        case 2:   MaxSupportedRate = RATE_1;    break;
 644                                        default:  MaxSupportedRate = RATE_11;   break;
 645                                }
 646
 647                                pEntry->MaxSupportedRate = min(pAd->CommonCfg.MaxTxRate, MaxSupportedRate);
 648
 649                                if (pEntry->MaxSupportedRate < RATE_FIRST_OFDM_RATE)
 650                                {
 651                                        pEntry->MaxHTPhyMode.field.MODE = MODE_CCK;
 652                                        pEntry->MaxHTPhyMode.field.MCS = pEntry->MaxSupportedRate;
 653                                        pEntry->MinHTPhyMode.field.MODE = MODE_CCK;
 654                                        pEntry->MinHTPhyMode.field.MCS = pEntry->MaxSupportedRate;
 655                                        pEntry->HTPhyMode.field.MODE = MODE_CCK;
 656                                        pEntry->HTPhyMode.field.MCS = pEntry->MaxSupportedRate;
 657                                }
 658                                else
 659                                {
 660                                        pEntry->MaxHTPhyMode.field.MODE = MODE_OFDM;
 661                                        pEntry->MaxHTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate];
 662                                        pEntry->MinHTPhyMode.field.MODE = MODE_OFDM;
 663                                        pEntry->MinHTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate];
 664                                        pEntry->HTPhyMode.field.MODE = MODE_OFDM;
 665                                        pEntry->HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate];
 666                                }
 667
 668                                pEntry->MaxHTPhyMode.field.BW = BW_20;
 669                                pEntry->MinHTPhyMode.field.BW = BW_20;
 670
 671#ifdef DOT11_N_SUPPORT
 672                                pEntry->HTCapability.MCSSet[0] = 0;
 673                                pEntry->HTCapability.MCSSet[1] = 0;
 674
 675                                // If this Entry supports 802.11n, upgrade to HT rate.
 676                                if ((HtCapabilityLen != 0) && (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED))
 677                                {
 678                                        UCHAR   j, bitmask; //k,bitmask;
 679                                        CHAR    ii;
 680
 681                                        DBGPRINT(RT_DEBUG_OFF, ("DLS - PeerDlsRspAction Receive Peer HT Capable STA from %02x:%02x:%02x:%02x:%02x:%02x\n",
 682                                                                SA[0], SA[1], SA[2], SA[3], SA[4], SA[5]));
 683
 684                                        if ((HtCapability.HtCapInfo.GF) && (pAd->CommonCfg.DesiredHtPhy.GF))
 685                                        {
 686                                                pEntry->MaxHTPhyMode.field.MODE = MODE_HTGREENFIELD;
 687                                        }
 688                                        else
 689                                        {
 690                                                pEntry->MaxHTPhyMode.field.MODE = MODE_HTMIX;
 691                                                pAd->MacTab.fAnyStationNonGF = TRUE;
 692                                                pAd->CommonCfg.AddHTInfo.AddHtInfo2.NonGfPresent = 1;
 693                                        }
 694
 695                                        if ((HtCapability.HtCapInfo.ChannelWidth) && (pAd->CommonCfg.DesiredHtPhy.ChannelWidth))
 696                                        {
 697                                                pEntry->MaxHTPhyMode.field.BW= BW_40;
 698                                                pEntry->MaxHTPhyMode.field.ShortGI = ((pAd->CommonCfg.DesiredHtPhy.ShortGIfor40)&(HtCapability.HtCapInfo.ShortGIfor40));
 699                                        }
 700                                        else
 701                                        {
 702                                                pEntry->MaxHTPhyMode.field.BW = BW_20;
 703                                                pEntry->MaxHTPhyMode.field.ShortGI = ((pAd->CommonCfg.DesiredHtPhy.ShortGIfor20)&(HtCapability.HtCapInfo.ShortGIfor20));
 704                                                pAd->MacTab.fAnyStation20Only = TRUE;
 705                                        }
 706
 707                                        // find max fixed rate
 708                                        for (ii=15; ii>=0; ii--)
 709                                        {
 710                                                j = ii/8;
 711                                                bitmask = (1<<(ii-(j*8)));
 712                                                if ( (pAd->StaCfg.DesiredHtPhyInfo.MCSSet[j]&bitmask) && (HtCapability.MCSSet[j]&bitmask))
 713                                                {
 714                                                        pEntry->MaxHTPhyMode.field.MCS = ii;
 715                                                        break;
 716                                                }
 717                                                if (ii==0)
 718                                                        break;
 719                                        }
 720
 721                                        if (pAd->StaCfg.DesiredTransmitSetting.field.MCS != MCS_AUTO)
 722                                        {
 723                                                if (pAd->StaCfg.DesiredTransmitSetting.field.MCS == 32)
 724                                                {
 725                                                        // Fix MCS as HT Duplicated Mode
 726                                                        pEntry->MaxHTPhyMode.field.BW = 1;
 727                                                        pEntry->MaxHTPhyMode.field.MODE = MODE_HTMIX;
 728                                                        pEntry->MaxHTPhyMode.field.STBC = 0;
 729                                                        pEntry->MaxHTPhyMode.field.ShortGI = 0;
 730                                                        pEntry->MaxHTPhyMode.field.MCS = 32;
 731                                                }
 732                                                else if (pEntry->MaxHTPhyMode.field.MCS > pAd->StaCfg.HTPhyMode.field.MCS)
 733                                                {
 734                                                        // STA supports fixed MCS
 735                                                        pEntry->MaxHTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
 736                                                }
 737                                        }
 738
 739                                        pEntry->MaxHTPhyMode.field.STBC = (HtCapability.HtCapInfo.RxSTBC & (pAd->CommonCfg.DesiredHtPhy.TxSTBC));
 740                                        pEntry->MpduDensity = HtCapability.HtCapParm.MpduDensity;
 741                                        pEntry->MaxRAmpduFactor = HtCapability.HtCapParm.MaxRAmpduFactor;
 742                                        pEntry->MmpsMode = (UCHAR)HtCapability.HtCapInfo.MimoPs;
 743                                        pEntry->AMsduSize = (UCHAR)HtCapability.HtCapInfo.AMsduSize;
 744                                        pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word;
 745
 746                                        if (HtCapability.HtCapInfo.ShortGIfor20)
 747                                                CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE);
 748                                        if (HtCapability.HtCapInfo.ShortGIfor40)
 749                                                CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE);
 750                                        if (HtCapability.HtCapInfo.TxSTBC)
 751                                                CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_TxSTBC_CAPABLE);
 752                                        if (HtCapability.HtCapInfo.RxSTBC)
 753                                                CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RxSTBC_CAPABLE);
 754                                        if (HtCapability.ExtHtCapInfo.PlusHTC)
 755                                                CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_HTC_CAPABLE);
 756                                        if (pAd->CommonCfg.bRdg && HtCapability.ExtHtCapInfo.RDGSupport)
 757                                                CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RDG_CAPABLE);
 758                                        if (HtCapability.ExtHtCapInfo.MCSFeedback == 0x03)
 759                                                CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_MCSFEEDBACK_CAPABLE);
 760
 761                                        NdisMoveMemory(&pEntry->HTCapability, &HtCapability, sizeof(HT_CAPABILITY_IE));
 762                                }
 763#endif // DOT11_N_SUPPORT //
 764                                pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word;
 765                                pEntry->CurrTxRate = pEntry->MaxSupportedRate;
 766                                CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE);
 767
 768                                if (pAd->StaCfg.bAutoTxRateSwitch == TRUE)
 769                                {
 770                                        PUCHAR pTable;
 771                                        UCHAR TableSize = 0;
 772
 773                                        MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &pEntry->CurrTxRateIndex);
 774                                        pEntry->bAutoTxRateSwitch = TRUE;
 775                                }
 776                                else
 777                                {
 778                                        pEntry->HTPhyMode.field.MODE    = pAd->StaCfg.HTPhyMode.field.MODE;
 779                                        pEntry->HTPhyMode.field.MCS     = pAd->StaCfg.HTPhyMode.field.MCS;
 780                                        pEntry->bAutoTxRateSwitch = FALSE;
 781
 782                                        RTMPUpdateLegacyTxSetting((UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode, pEntry);
 783                                }
 784                                pEntry->RateLen = SupportedRatesLen;
 785
 786                                if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
 787                                {
 788                                        // If support WPA or WPA2, start STAKey hand shake,
 789                                        // If failed hand shake, just tear down peer DLS
 790                                        if (RTMPSendSTAKeyRequest(pAd, pAd->StaCfg.DLSEntry[i].MacAddr) != NDIS_STATUS_SUCCESS)
 791                                        {
 792                                                MLME_DLS_REQ_STRUCT     MlmeDlsReq;
 793                                                USHORT                          reason = REASON_QOS_CIPHER_NOT_SUPPORT;
 794
 795                                                DlsParmFill(pAd, &MlmeDlsReq, &pAd->StaCfg.DLSEntry[i], reason);
 796                                                MlmeEnqueue(pAd, DLS_STATE_MACHINE, MT2_MLME_DLS_TEAR_DOWN, sizeof(MLME_DLS_REQ_STRUCT), &MlmeDlsReq);
 797                                                pAd->StaCfg.DLSEntry[i].Status = DLS_NONE;
 798                                                pAd->StaCfg.DLSEntry[i].Valid   = FALSE;
 799                                                DBGPRINT(RT_DEBUG_ERROR,("DLS - PeerDlsRspAction failed when call RTMPSendSTAKeyRequest \n"));
 800                                        }
 801                                        else
 802                                        {
 803                                                pAd->StaCfg.DLSEntry[i].Status = DLS_WAIT_KEY;
 804                                                DBGPRINT(RT_DEBUG_TRACE,("DLS - waiting for STAKey handshake procedure\n"));
 805                                        }
 806                                }
 807                                else
 808                                {
 809                                        RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled);
 810                                        pAd->StaCfg.DLSEntry[i].Status = DLS_FINISH;
 811                                        DBGPRINT(RT_DEBUG_TRACE,("DLS - PeerDlsRspAction() from %02x:%02x:%02x:%02x:%02x:%02x Succeed with WEP or no security\n", SA[0], SA[1], SA[2], SA[3], SA[4], SA[5]));
 812                                }
 813
 814                                //initialize seq no for DLS frames.
 815                                pAd->StaCfg.DLSEntry[i].Sequence = 0;
 816                                if (HtCapabilityLen != 0)
 817                                        pAd->StaCfg.DLSEntry[i].bHTCap = TRUE;
 818                                else
 819                                        pAd->StaCfg.DLSEntry[i].bHTCap = FALSE;
 820                        }
 821                        else
 822                        {
 823                                // DLS setup procedure failed.
 824                                pAd->StaCfg.DLSEntry[i].Status = DLS_NONE;
 825                                pAd->StaCfg.DLSEntry[i].Valid   = FALSE;
 826                                RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled);
 827                                DBGPRINT(RT_DEBUG_ERROR,("DLS - PeerDlsRspAction failed with StatusCode=%d \n", StatusCode));
 828                        }
 829                }
 830        }
 831
 832        if (i >= MAX_NUM_OF_INIT_DLS_ENTRY)
 833        {
 834                DBGPRINT(RT_DEBUG_TRACE,("DLS - PeerDlsRspAction() update timeout value \n"));
 835                for (i=(MAX_NUM_OF_DLS_ENTRY-1); i>=MAX_NUM_OF_INIT_DLS_ENTRY; i--)
 836                {
 837                        if (pAd->StaCfg.DLSEntry[i].Valid && MAC_ADDR_EQUAL(SA, pAd->StaCfg.DLSEntry[i].MacAddr))
 838                        {
 839                                if (StatusCode == MLME_SUCCESS)
 840                                {
 841                                        MAC_TABLE_ENTRY *pEntry;
 842                                        UCHAR MaxSupportedRate = RATE_11;
 843
 844                                        pEntry = MacTableInsertDlsEntry(pAd, SA, i);
 845
 846                                        switch (MaxSupportedRateIn500Kbps)
 847                                        {
 848                                                case 108: MaxSupportedRate = RATE_54;   break;
 849                                                case 96:  MaxSupportedRate = RATE_48;   break;
 850                                                case 72:  MaxSupportedRate = RATE_36;   break;
 851                                                case 48:  MaxSupportedRate = RATE_24;   break;
 852                                                case 36:  MaxSupportedRate = RATE_18;   break;
 853                                                case 24:  MaxSupportedRate = RATE_12;   break;
 854                                                case 18:  MaxSupportedRate = RATE_9;    break;
 855                                                case 12:  MaxSupportedRate = RATE_6;    break;
 856                                                case 22:  MaxSupportedRate = RATE_11;   break;
 857                                                case 11:  MaxSupportedRate = RATE_5_5;  break;
 858                                                case 4:   MaxSupportedRate = RATE_2;    break;
 859                                                case 2:   MaxSupportedRate = RATE_1;    break;
 860                                                default:  MaxSupportedRate = RATE_11;   break;
 861                                        }
 862
 863                                        pEntry->MaxSupportedRate = min(pAd->CommonCfg.MaxTxRate, MaxSupportedRate);
 864
 865                                        if (pEntry->MaxSupportedRate < RATE_FIRST_OFDM_RATE)
 866                                        {
 867                                                pEntry->MaxHTPhyMode.field.MODE = MODE_CCK;
 868                                                pEntry->MaxHTPhyMode.field.MCS = pEntry->MaxSupportedRate;
 869                                                pEntry->MinHTPhyMode.field.MODE = MODE_CCK;
 870                                                pEntry->MinHTPhyMode.field.MCS = pEntry->MaxSupportedRate;
 871                                                pEntry->HTPhyMode.field.MODE = MODE_CCK;
 872                                                pEntry->HTPhyMode.field.MCS = pEntry->MaxSupportedRate;
 873                                        }
 874                                        else
 875                                        {
 876                                                pEntry->MaxHTPhyMode.field.MODE = MODE_OFDM;
 877                                                pEntry->MaxHTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate];
 878                                                pEntry->MinHTPhyMode.field.MODE = MODE_OFDM;
 879                                                pEntry->MinHTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate];
 880                                                pEntry->HTPhyMode.field.MODE = MODE_OFDM;
 881                                                pEntry->HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate];
 882                                        }
 883
 884                                        pEntry->MaxHTPhyMode.field.BW = BW_20;
 885                                        pEntry->MinHTPhyMode.field.BW = BW_20;
 886
 887#ifdef DOT11_N_SUPPORT
 888                                        pEntry->HTCapability.MCSSet[0] = 0;
 889                                        pEntry->HTCapability.MCSSet[1] = 0;
 890
 891                                        // If this Entry supports 802.11n, upgrade to HT rate.
 892                                        if ((HtCapabilityLen != 0) && (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED))
 893                                        {
 894                                                UCHAR   j, bitmask; //k,bitmask;
 895                                                CHAR    ii;
 896
 897                                                DBGPRINT(RT_DEBUG_TRACE, ("DLS - PeerDlsRspAction Receive Peer HT Capable STA from %02x:%02x:%02x:%02x:%02x:%02x\n",
 898                                                                        SA[0], SA[1], SA[2], SA[3], SA[4], SA[5]));
 899
 900                                                if ((HtCapability.HtCapInfo.GF) && (pAd->CommonCfg.DesiredHtPhy.GF))
 901                                                {
 902                                                        pEntry->MaxHTPhyMode.field.MODE = MODE_HTGREENFIELD;
 903                                                }
 904                                                else
 905                                                {
 906                                                        pEntry->MaxHTPhyMode.field.MODE = MODE_HTMIX;
 907                                                        pAd->MacTab.fAnyStationNonGF = TRUE;
 908                                                        pAd->CommonCfg.AddHTInfo.AddHtInfo2.NonGfPresent = 1;
 909                                                }
 910
 911                                                if ((HtCapability.HtCapInfo.ChannelWidth) && (pAd->CommonCfg.DesiredHtPhy.ChannelWidth))
 912                                                {
 913                                                        pEntry->MaxHTPhyMode.field.BW= BW_40;
 914                                                        pEntry->MaxHTPhyMode.field.ShortGI = ((pAd->CommonCfg.DesiredHtPhy.ShortGIfor40)&(HtCapability.HtCapInfo.ShortGIfor40));
 915                                                }
 916                                                else
 917                                                {
 918                                                        pEntry->MaxHTPhyMode.field.BW = BW_20;
 919                                                        pEntry->MaxHTPhyMode.field.ShortGI = ((pAd->CommonCfg.DesiredHtPhy.ShortGIfor20)&(HtCapability.HtCapInfo.ShortGIfor20));
 920                                                        pAd->MacTab.fAnyStation20Only = TRUE;
 921                                                }
 922
 923                                                // find max fixed rate
 924                                                for (ii=15; ii>=0; ii--)
 925                                                {
 926                                                        j = ii/8;
 927                                                        bitmask = (1<<(ii-(j*8)));
 928                                                        if ( (pAd->StaCfg.DesiredHtPhyInfo.MCSSet[j]&bitmask) && (HtCapability.MCSSet[j]&bitmask))
 929                                                        {
 930                                                                pEntry->MaxHTPhyMode.field.MCS = ii;
 931                                                                break;
 932                                                        }
 933                                                        if (ii==0)
 934                                                                break;
 935                                                }
 936
 937                                                if (pAd->StaCfg.DesiredTransmitSetting.field.MCS != MCS_AUTO)
 938                                                {
 939                                                        DBGPRINT(RT_DEBUG_OFF, ("@@@ pAd->CommonCfg.RegTransmitSetting.field.MCS = %d\n",
 940                                                                                                        pAd->StaCfg.DesiredTransmitSetting.field.MCS));
 941                                                        if (pAd->StaCfg.DesiredTransmitSetting.field.MCS == 32)
 942                                                        {
 943                                                                // Fix MCS as HT Duplicated Mode
 944                                                                pEntry->MaxHTPhyMode.field.BW = 1;
 945                                                                pEntry->MaxHTPhyMode.field.MODE = MODE_HTMIX;
 946                                                                pEntry->MaxHTPhyMode.field.STBC = 0;
 947                                                                pEntry->MaxHTPhyMode.field.ShortGI = 0;
 948                                                                pEntry->MaxHTPhyMode.field.MCS = 32;
 949                                                        }
 950                                                        else if (pEntry->MaxHTPhyMode.field.MCS > pAd->StaCfg.HTPhyMode.field.MCS)
 951                                                        {
 952                                                                // STA supports fixed MCS
 953                                                                pEntry->MaxHTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
 954                                                        }
 955                                                }
 956
 957                                                pEntry->MaxHTPhyMode.field.STBC = (HtCapability.HtCapInfo.RxSTBC & (pAd->CommonCfg.DesiredHtPhy.TxSTBC));
 958                                                pEntry->MpduDensity = HtCapability.HtCapParm.MpduDensity;
 959                                                pEntry->MaxRAmpduFactor = HtCapability.HtCapParm.MaxRAmpduFactor;
 960                                                pEntry->MmpsMode = (UCHAR)HtCapability.HtCapInfo.MimoPs;
 961                                                pEntry->AMsduSize = (UCHAR)HtCapability.HtCapInfo.AMsduSize;
 962                                                pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word;
 963
 964                                                if (HtCapability.HtCapInfo.ShortGIfor20)
 965                                                        CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE);
 966                                                if (HtCapability.HtCapInfo.ShortGIfor40)
 967                                                        CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE);
 968                                                if (HtCapability.HtCapInfo.TxSTBC)
 969                                                        CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_TxSTBC_CAPABLE);
 970                                                if (HtCapability.HtCapInfo.RxSTBC)
 971                                                        CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RxSTBC_CAPABLE);
 972                                                if (HtCapability.ExtHtCapInfo.PlusHTC)
 973                                                        CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_HTC_CAPABLE);
 974                                                if (pAd->CommonCfg.bRdg && HtCapability.ExtHtCapInfo.RDGSupport)
 975                                                        CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RDG_CAPABLE);
 976                                                if (HtCapability.ExtHtCapInfo.MCSFeedback == 0x03)
 977                                                        CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_MCSFEEDBACK_CAPABLE);
 978
 979                                                NdisMoveMemory(&pEntry->HTCapability, &HtCapability, sizeof(HT_CAPABILITY_IE));
 980                                        }
 981#endif // DOT11_N_SUPPORT //
 982
 983                                        pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word;
 984                                        pEntry->CurrTxRate = pEntry->MaxSupportedRate;
 985                                        CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE);
 986
 987                                        if (pAd->StaCfg.bAutoTxRateSwitch == TRUE)
 988                                        {
 989                                                PUCHAR pTable;
 990                                                UCHAR TableSize = 0;
 991
 992                                                MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &pEntry->CurrTxRateIndex);
 993                                                pEntry->bAutoTxRateSwitch = TRUE;
 994                                        }
 995                                        else
 996                                        {
 997                                                pEntry->HTPhyMode.field.MODE    = pAd->StaCfg.HTPhyMode.field.MODE;
 998                                                pEntry->HTPhyMode.field.MCS     = pAd->StaCfg.HTPhyMode.field.MCS;
 999                                                pEntry->bAutoTxRateSwitch = FALSE;
1000
1001                                                RTMPUpdateLegacyTxSetting((UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode, pEntry);
1002                                        }
1003                                        pEntry->RateLen = SupportedRatesLen;
1004
1005                                        if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
1006                                        {
1007                                                // If support WPA or WPA2, start STAKey hand shake,
1008                                                // If failed hand shake, just tear down peer DLS
1009                                                if (RTMPSendSTAKeyRequest(pAd, pAd->StaCfg.DLSEntry[i].MacAddr) != NDIS_STATUS_SUCCESS)
1010                                                {
1011                                                        MLME_DLS_REQ_STRUCT     MlmeDlsReq;
1012                                                        USHORT                          reason = REASON_QOS_CIPHER_NOT_SUPPORT;
1013
1014                                                        DlsParmFill(pAd, &MlmeDlsReq, &pAd->StaCfg.DLSEntry[i], reason);
1015                                                        MlmeEnqueue(pAd, DLS_STATE_MACHINE, MT2_MLME_DLS_TEAR_DOWN, sizeof(MLME_DLS_REQ_STRUCT), &MlmeDlsReq);
1016                                                        pAd->StaCfg.DLSEntry[i].Status = DLS_NONE;
1017                                                        pAd->StaCfg.DLSEntry[i].Valid   = FALSE;
1018                                                        DBGPRINT(RT_DEBUG_ERROR,("DLS - PeerDlsRspAction failed when call RTMPSendSTAKeyRequest \n"));
1019                                                }
1020                                                else
1021                                                {
1022                                                        pAd->StaCfg.DLSEntry[i].Status = DLS_WAIT_KEY;
1023                                                        DBGPRINT(RT_DEBUG_TRACE,("DLS - waiting for STAKey handshake procedure\n"));
1024                                                }
1025                                        }
1026                                        else
1027                                        {
1028                                                RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled);
1029                                                pAd->StaCfg.DLSEntry[i].Status = DLS_FINISH;
1030                                                DBGPRINT(RT_DEBUG_TRACE,("DLS - PeerDlsRspAction() from %02x:%02x:%02x:%02x:%02x:%02x Succeed with WEP or no security\n", SA[0], SA[1], SA[2], SA[3], SA[4], SA[5]));
1031                                        }
1032                                        pAd->StaCfg.DLSEntry[i].Sequence = 0;
1033                                        if (HtCapabilityLen != 0)
1034                                                pAd->StaCfg.DLSEntry[i].bHTCap = TRUE;
1035                                        else
1036                                                pAd->StaCfg.DLSEntry[i].bHTCap = FALSE;
1037                                }
1038                                else
1039                                {
1040                                        // DLS setup procedure failed.
1041                                        pAd->StaCfg.DLSEntry[i].Status = DLS_NONE;
1042                                        pAd->StaCfg.DLSEntry[i].Valid   = FALSE;
1043                                        RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled);
1044                                        DBGPRINT(RT_DEBUG_ERROR,("DLS - PeerDlsRspAction failed with StatusCode=%d \n", StatusCode));
1045                                }
1046                        }
1047                }
1048        }
1049}
1050
1051/*
1052    ==========================================================================
1053    Description:
1054
1055        IRQL = DISPATCH_LEVEL
1056
1057    ==========================================================================
1058 */
1059VOID MlmeDlsTearDownAction(
1060    IN PRTMP_ADAPTER pAd,
1061    IN MLME_QUEUE_ELEM *Elem)
1062{
1063        PUCHAR                  pOutBuffer = NULL;
1064        NDIS_STATUS             NStatus;
1065        ULONG                   FrameLen = 0;
1066        UCHAR                   Category = CATEGORY_DLS;
1067        UCHAR                   Action = ACTION_DLS_TEARDOWN;
1068        USHORT                  ReasonCode = REASON_QOS_UNSPECIFY;
1069        HEADER_802_11   DlsTearDownHdr;
1070        PRT_802_11_DLS  pDLS;
1071        BOOLEAN                 TimerCancelled;
1072        UCHAR                   i;
1073
1074        if(!MlmeDlsReqSanity(pAd, Elem->Msg, Elem->MsgLen, &pDLS, &ReasonCode))
1075                return;
1076
1077        DBGPRINT(RT_DEBUG_TRACE,("DLS - MlmeDlsTearDownAction() with ReasonCode=%d \n", ReasonCode));
1078
1079        NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);  //Get an unused nonpaged memory
1080        if (NStatus != NDIS_STATUS_SUCCESS)
1081        {
1082                DBGPRINT(RT_DEBUG_ERROR,("DLS - MlmeDlsTearDownAction() allocate memory failed \n"));
1083                return;
1084        }
1085
1086        ActHeaderInit(pAd, &DlsTearDownHdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAd->CommonCfg.Bssid);
1087
1088        // Build basic frame first
1089        MakeOutgoingFrame(pOutBuffer,                           &FrameLen,
1090                                        sizeof(HEADER_802_11),          &DlsTearDownHdr,
1091                                        1,                                                      &Category,
1092                                        1,                                                      &Action,
1093                                        6,                                                      &pDLS->MacAddr,
1094                                        6,                                                      pAd->CurrentAddress,
1095                                        2,                                                      &ReasonCode,
1096                                        END_OF_ARGS);
1097
1098        MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
1099        MlmeFreeMemory(pAd, pOutBuffer);
1100        RTMPCancelTimer(&pDLS->Timer, &TimerCancelled);
1101
1102        // Remove key in local dls table entry
1103        for (i = 0; i < MAX_NUM_OF_INIT_DLS_ENTRY; i++)
1104        {
1105                if (MAC_ADDR_EQUAL(pDLS->MacAddr, pAd->StaCfg.DLSEntry[i].MacAddr))
1106                {
1107                        MacTableDeleteDlsEntry(pAd, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID, pAd->StaCfg.DLSEntry[i].MacAddr);
1108                }
1109        }
1110
1111        // clear peer dls table entry
1112        for (i = MAX_NUM_OF_INIT_DLS_ENTRY; i < MAX_NUM_OF_DLS_ENTRY; i++)
1113        {
1114                if (MAC_ADDR_EQUAL(pDLS->MacAddr, pAd->StaCfg.DLSEntry[i].MacAddr))
1115                {
1116                        pAd->StaCfg.DLSEntry[i].Status  = DLS_NONE;
1117                        pAd->StaCfg.DLSEntry[i].Valid   = FALSE;
1118                        RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled);
1119                        MacTableDeleteDlsEntry(pAd, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID, pAd->StaCfg.DLSEntry[i].MacAddr);
1120                }
1121        }
1122}
1123
1124/*
1125    ==========================================================================
1126    Description:
1127
1128        IRQL = DISPATCH_LEVEL
1129
1130    ==========================================================================
1131 */
1132VOID PeerDlsTearDownAction(
1133    IN PRTMP_ADAPTER pAd,
1134    IN MLME_QUEUE_ELEM *Elem)
1135{
1136        UCHAR                   DA[MAC_ADDR_LEN], SA[MAC_ADDR_LEN];
1137        USHORT                  ReasonCode;
1138        UINT                    i;
1139        BOOLEAN                 TimerCancelled;
1140
1141        if (!pAd->CommonCfg.bDLSCapable)
1142                return;
1143
1144        if (!INFRA_ON(pAd))
1145                return;
1146
1147        if (!PeerDlsTearDownSanity(pAd, Elem->Msg, Elem->MsgLen, DA, SA, &ReasonCode))
1148                return;
1149
1150        DBGPRINT(RT_DEBUG_TRACE,("DLS - PeerDlsTearDownAction() from %02x:%02x:%02x:%02x:%02x:%02x with ReasonCode=%d\n", SA[0], SA[1], SA[2], SA[3], SA[4], SA[5], ReasonCode));
1151
1152        // clear local dls table entry
1153        for (i=0; i<MAX_NUM_OF_INIT_DLS_ENTRY; i++)
1154        {
1155                if (pAd->StaCfg.DLSEntry[i].Valid && MAC_ADDR_EQUAL(SA, pAd->StaCfg.DLSEntry[i].MacAddr))
1156                {
1157                        pAd->StaCfg.DLSEntry[i].Status  = DLS_NONE;
1158                        pAd->StaCfg.DLSEntry[i].Valid   = FALSE;
1159                        RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled);
1160                        //AsicDelWcidTab(pAd, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID);
1161                        //AsicRemovePairwiseKeyEntry(pAd, BSS0, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID);
1162                        MacTableDeleteDlsEntry(pAd, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID, pAd->StaCfg.DLSEntry[i].MacAddr);
1163                }
1164        }
1165
1166        // clear peer dls table entry
1167        for (i=MAX_NUM_OF_INIT_DLS_ENTRY; i<MAX_NUM_OF_DLS_ENTRY; i++)
1168        {
1169                if (pAd->StaCfg.DLSEntry[i].Valid && MAC_ADDR_EQUAL(SA, pAd->StaCfg.DLSEntry[i].MacAddr))
1170                {
1171                        pAd->StaCfg.DLSEntry[i].Status  = DLS_NONE;
1172                        pAd->StaCfg.DLSEntry[i].Valid   = FALSE;
1173                        RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled);
1174                        //AsicDelWcidTab(pAd, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID);
1175                        //AsicRemovePairwiseKeyEntry(pAd, BSS0, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID);
1176                        MacTableDeleteDlsEntry(pAd, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID, pAd->StaCfg.DLSEntry[i].MacAddr);
1177                }
1178        }
1179}
1180
1181/*
1182    ==========================================================================
1183    Description:
1184
1185        IRQL = DISPATCH_LEVEL
1186
1187    ==========================================================================
1188 */
1189VOID RTMPCheckDLSTimeOut(
1190        IN PRTMP_ADAPTER        pAd)
1191{
1192        ULONG                           i;
1193        MLME_DLS_REQ_STRUCT     MlmeDlsReq;
1194        USHORT                          reason = REASON_QOS_UNSPECIFY;
1195
1196        if (! pAd->CommonCfg.bDLSCapable)
1197                return;
1198
1199        if (! INFRA_ON(pAd))
1200                return;
1201
1202        // If timeout value is equaled to zero, it means always not be timeout.
1203
1204        // update local dls table entry
1205        for (i=0; i<MAX_NUM_OF_INIT_DLS_ENTRY; i++)
1206        {
1207                if ((pAd->StaCfg.DLSEntry[i].Valid) && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH)
1208                        && (pAd->StaCfg.DLSEntry[i].TimeOut != 0))
1209                {
1210                        pAd->StaCfg.DLSEntry[i].CountDownTimer --;
1211
1212                        if (pAd->StaCfg.DLSEntry[i].CountDownTimer == 0)
1213                        {
1214                                reason = REASON_QOS_REQUEST_TIMEOUT;
1215                                pAd->StaCfg.DLSEntry[i].Valid   = FALSE;
1216                                pAd->StaCfg.DLSEntry[i].Status  = DLS_NONE;
1217                                DlsParmFill(pAd, &MlmeDlsReq, &pAd->StaCfg.DLSEntry[i], reason);
1218                                MlmeEnqueue(pAd, DLS_STATE_MACHINE, MT2_MLME_DLS_TEAR_DOWN, sizeof(MLME_DLS_REQ_STRUCT), &MlmeDlsReq);
1219                        }
1220                }
1221        }
1222
1223        // update peer dls table entry
1224        for (i=MAX_NUM_OF_INIT_DLS_ENTRY; i<MAX_NUM_OF_DLS_ENTRY; i++)
1225        {
1226                if ((pAd->StaCfg.DLSEntry[i].Valid) && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH)
1227                        && (pAd->StaCfg.DLSEntry[i].TimeOut != 0))
1228                {
1229                        pAd->StaCfg.DLSEntry[i].CountDownTimer --;
1230
1231                        if (pAd->StaCfg.DLSEntry[i].CountDownTimer == 0)
1232                        {
1233                                reason = REASON_QOS_REQUEST_TIMEOUT;
1234                                pAd->StaCfg.DLSEntry[i].Valid   = FALSE;
1235                                pAd->StaCfg.DLSEntry[i].Status  = DLS_NONE;
1236                                DlsParmFill(pAd, &MlmeDlsReq, &pAd->StaCfg.DLSEntry[i], reason);
1237                                MlmeEnqueue(pAd, DLS_STATE_MACHINE, MT2_MLME_DLS_TEAR_DOWN, sizeof(MLME_DLS_REQ_STRUCT), &MlmeDlsReq);
1238                        }
1239                }
1240        }
1241}
1242
1243/*
1244    ==========================================================================
1245    Description:
1246
1247        IRQL = DISPATCH_LEVEL
1248
1249    ==========================================================================
1250 */
1251BOOLEAN RTMPRcvFrameDLSCheck(
1252        IN PRTMP_ADAPTER        pAd,
1253        IN PHEADER_802_11       pHeader,
1254        IN ULONG                        Len,
1255        IN PRT28XX_RXD_STRUC    pRxD)
1256{
1257        ULONG                   i;
1258        BOOLEAN                 bFindEntry = FALSE;
1259        BOOLEAN                 bSTAKeyFrame = FALSE;
1260        PEAPOL_PACKET   pEap;
1261        PUCHAR                  pProto, pAddr = NULL;
1262        PUCHAR                  pSTAKey = NULL;
1263        UCHAR                   ZeroReplay[LEN_KEY_DESC_REPLAY];
1264        UCHAR                   Mic[16], OldMic[16];
1265        UCHAR                   digest[80];
1266        UCHAR                   DlsPTK[80];
1267        UCHAR                   temp[64];
1268        BOOLEAN                 TimerCancelled;
1269        CIPHER_KEY              PairwiseKey;
1270
1271
1272        if (! pAd->CommonCfg.bDLSCapable)
1273                return bSTAKeyFrame;
1274
1275        if (! INFRA_ON(pAd))
1276                return bSTAKeyFrame;
1277
1278        if (Len < LENGTH_802_11 + 6 + 2) /* LENGTH_802_11 + LLC + EAPOL protocol type */
1279                return bSTAKeyFrame;
1280
1281        pProto  = (PUCHAR)pHeader + LENGTH_802_11;
1282
1283        if ((pHeader->FC.SubType & 0x08))
1284                pProto  += 2;   /* QOS Control field */
1285
1286     /* Skip 4-bytes for HTC */
1287     if (pHeader->FC.Order && (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED)))
1288     {
1289          pProto += 4;
1290     }
1291
1292        /* L2PAD bit on will pad 2 bytes at LLC */
1293        if (pRxD->L2PAD)
1294        {
1295                pProto += 2;
1296        }
1297
1298        pProto  += 6;   /* 0xAA 0xAA 0xAA 0x00 0x00 0x00 */
1299
1300        if ((!(pHeader->FC.SubType & 0x08)) && (!RTMPEqualMemory(EAPOL, pProto, 2)))
1301                return bSTAKeyFrame;
1302
1303        pAddr   = pHeader->Addr2;
1304
1305        if (RTMPEqualMemory(EAPOL, pProto, 2) && (pAd->StaCfg.AuthMode >=  Ndis802_11AuthModeWPA))
1306        {
1307                pEap = (PEAPOL_PACKET) (pProto + 2);
1308
1309                DBGPRINT(RT_DEBUG_TRACE,("DLS - Sniff Len=%ld, DataLen=%d, KeyMic=%d, Install=%d, KeyAck=%d, Secure=%d, EKD_DL=%d, Error=%d, Request=%d\n", Len,
1310                                                                                     (LENGTH_802_11 + 6 + 2 + 2 + sizeof(EAPOL_PACKET) - MAX_LEN_OF_RSNIE + 16),
1311                                                                                     pEap->KeyDesc.KeyInfo.KeyMic,
1312                                                                                     pEap->KeyDesc.KeyInfo.Install,
1313                                                                                     pEap->KeyDesc.KeyInfo.KeyAck,
1314                                                                                     pEap->KeyDesc.KeyInfo.Secure,
1315                                                                                     pEap->KeyDesc.KeyInfo.EKD_DL,
1316                                                                                     pEap->KeyDesc.KeyInfo.Error,
1317                                                                                     pEap->KeyDesc.KeyInfo.Request));
1318
1319                if ((Len >= (LENGTH_802_11 + 6 + 2 + 2 + sizeof(EAPOL_PACKET) - MAX_LEN_OF_RSNIE + 16)) && pEap->KeyDesc.KeyInfo.KeyMic
1320                        && pEap->KeyDesc.KeyInfo.Install && pEap->KeyDesc.KeyInfo.KeyAck && pEap->KeyDesc.KeyInfo.Secure
1321                        && pEap->KeyDesc.KeyInfo.EKD_DL && !pEap->KeyDesc.KeyInfo.Error && !pEap->KeyDesc.KeyInfo.Request)
1322                {
1323                        // First validate replay counter, only accept message with larger replay counter
1324                        // Let equal pass, some AP start with all zero replay counter
1325                        NdisZeroMemory(ZeroReplay, LEN_KEY_DESC_REPLAY);
1326                        if ((RTMPCompareMemory(pEap->KeyDesc.ReplayCounter, pAd->StaCfg.ReplayCounter, LEN_KEY_DESC_REPLAY) != 1) &&
1327                                (RTMPCompareMemory(pEap->KeyDesc.ReplayCounter, ZeroReplay, LEN_KEY_DESC_REPLAY) != 0))
1328                                return bSTAKeyFrame;
1329
1330                        //RTMPMoveMemory(pAd->StaCfg.ReplayCounter, pEap->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY);
1331                        RTMPMoveMemory(pAd->StaCfg.DlsReplayCounter, pEap->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY);
1332                        DBGPRINT(RT_DEBUG_TRACE,("DLS - Sniff replay counter (%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x) Len=%ld, KeyDataLen=%d\n",
1333                                pAd->StaCfg.ReplayCounter[0], pAd->StaCfg.ReplayCounter[1], pAd->StaCfg.ReplayCounter[2],
1334                                pAd->StaCfg.ReplayCounter[3], pAd->StaCfg.ReplayCounter[4],     pAd->StaCfg.ReplayCounter[5],
1335                                pAd->StaCfg.ReplayCounter[6], pAd->StaCfg.ReplayCounter[7], Len, pEap->KeyDesc.KeyData[1]));
1336
1337                        // put these code segment to get the replay counter
1338                        if (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED)
1339                                return bSTAKeyFrame;
1340
1341                        // Check MIC value
1342                        // Save the MIC and replace with zero
1343                        // use proprietary PTK
1344                        NdisZeroMemory(temp, 64);
1345                        NdisMoveMemory(temp, "IEEE802.11 WIRELESS ACCESS POINT", 32);
1346                        WpaDerivePTK(pAd, temp, temp, pAd->CommonCfg.Bssid, temp, pAd->CurrentAddress, DlsPTK, LEN_PTK);
1347
1348                        NdisMoveMemory(OldMic, pEap->KeyDesc.KeyMic, LEN_KEY_DESC_MIC);
1349                        NdisZeroMemory(pEap->KeyDesc.KeyMic, LEN_KEY_DESC_MIC);
1350                        if (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled)
1351                        {
1352                                // AES
1353                                HMAC_SHA1(DlsPTK, LEN_EAP_MICK, (PUCHAR) pEap, pEap->Body_Len[1] + 4, digest, SHA1_DIGEST_SIZE);
1354                                NdisMoveMemory(Mic,     digest, LEN_KEY_DESC_MIC);
1355                        }
1356                        else
1357                        {
1358                                HMAC_MD5(DlsPTK, LEN_EAP_MICK, (PUCHAR) pEap, pEap->Body_Len[1] + 4, Mic, MD5_DIGEST_SIZE);
1359                        }
1360
1361                        if (!NdisEqualMemory(OldMic, Mic, LEN_KEY_DESC_MIC))
1362                        {
1363                                DBGPRINT(RT_DEBUG_ERROR, ("MIC Different in Msg1 of STAKey handshake! \n"));
1364                                return bSTAKeyFrame;
1365                        }
1366                        else
1367                                DBGPRINT(RT_DEBUG_TRACE, ("MIC VALID in Msg1 of STAKey handshake! \n"));
1368                        if ((pEap->KeyDesc.KeyData[0] == 0xDD) && (pEap->KeyDesc.KeyData[2] == 0x00) && (pEap->KeyDesc.KeyData[3] == 0x0C)
1369                                && (pEap->KeyDesc.KeyData[4] == 0x43) && (pEap->KeyDesc.KeyData[5] == 0x02))
1370                        {
1371                                pAddr                   = pEap->KeyDesc.KeyData + 8;            // Tpe(1), Len(1), OUI(3), DataType(1), Reserved(2)
1372                                pSTAKey                 = pEap->KeyDesc.KeyData + 14;   // Tpe(1), Len(1), OUI(3), DataType(1), Reserved(2), STAKey_Mac_Addr(6)
1373
1374                                DBGPRINT(RT_DEBUG_TRACE,("DLS - Receive STAKey Message-1 from %02x:%02x:%02x:%02x:%02x:%02x Len=%ld, KeyDataLen=%d\n",
1375                                        pAddr[0], pAddr[1], pAddr[2], pAddr[3], pAddr[4], pAddr[5], Len, pEap->KeyDesc.KeyData[1]));
1376
1377                                bSTAKeyFrame = TRUE;
1378                        }
1379
1380                }
1381                else if (Len >= (LENGTH_802_11 + 6 + 2 + 2 + sizeof(EAPOL_PACKET) - MAX_LEN_OF_RSNIE))
1382                {
1383                        RTMPMoveMemory(pAd->StaCfg.DlsReplayCounter, pEap->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY);
1384                        DBGPRINT(RT_DEBUG_TRACE,("DLS - Sniff replay counter 2(%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x) Len=%ld, KeyDataLen=%d\n",
1385                                pAd->StaCfg.ReplayCounter[0], pAd->StaCfg.ReplayCounter[1], pAd->StaCfg.ReplayCounter[2],
1386                                pAd->StaCfg.ReplayCounter[3], pAd->StaCfg.ReplayCounter[4],     pAd->StaCfg.ReplayCounter[5],
1387                                pAd->StaCfg.ReplayCounter[6], pAd->StaCfg.ReplayCounter[7], Len, pEap->KeyDesc.KeyData[1]));
1388                }
1389        }
1390
1391        // If timeout value is equaled to zero, it means always not be timeout.
1392        // update local dls table entry
1393        for (i= 0; i < MAX_NUM_OF_INIT_DLS_ENTRY; i++)
1394        {
1395                if (pAd->StaCfg.DLSEntry[i].Valid && MAC_ADDR_EQUAL(pAddr, pAd->StaCfg.DLSEntry[i].MacAddr))
1396                {
1397                        if (bSTAKeyFrame)
1398                        {
1399                                PMAC_TABLE_ENTRY pEntry;
1400
1401                                // STAKey frame, add pairwise key table
1402                                pAd->StaCfg.DLSEntry[i].Status = DLS_FINISH;
1403                                RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled);
1404
1405                                PairwiseKey.KeyLen = LEN_TKIP_EK;
1406                                NdisMoveMemory(PairwiseKey.Key, &pSTAKey[0], LEN_TKIP_EK);
1407                                NdisMoveMemory(PairwiseKey.TxMic, &pSTAKey[16], LEN_TKIP_RXMICK);
1408                                NdisMoveMemory(PairwiseKey.RxMic, &pSTAKey[24], LEN_TKIP_TXMICK);
1409
1410                                //PairwiseKey.CipherAlg = pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg;
1411                                if (pAd->StaCfg.PairCipher == Ndis802_11Encryption2Enabled)
1412                                        PairwiseKey.CipherAlg = CIPHER_TKIP;
1413                                else if (pAd->StaCfg.PairCipher == Ndis802_11Encryption3Enabled)
1414                                        PairwiseKey.CipherAlg = CIPHER_AES;
1415
1416                                pEntry = DlsEntryTableLookup(pAd, pAd->StaCfg.DLSEntry[i].MacAddr, TRUE);
1417                                //AsicAddKeyEntry(pAd, (USHORT)(i + 2), BSS0, 0, &PairwiseKey, TRUE, TRUE);     // reserve 0 for multicast, 1 for unicast
1418                                //AsicUpdateRxWCIDTable(pAd, (USHORT)(i + 2), pAddr);
1419                                // Add Pair-wise key to Asic
1420#ifdef RTMP_MAC_PCI
1421                                AsicAddPairwiseKeyEntry(pAd,
1422                                                                                pAd->StaCfg.DLSEntry[i].MacAddr,
1423                                                                                (UCHAR)pAd->StaCfg.DLSEntry[i].MacTabMatchWCID,
1424                                                                                &PairwiseKey);
1425
1426                                RTMPAddWcidAttributeEntry(pAd,
1427                                                                                  BSS0,
1428                                                                                  0,
1429                                                                                  PairwiseKey.CipherAlg,
1430                                                                                  pEntry);
1431
1432#endif // RTMP_MAC_PCI //
1433                                NdisMoveMemory(&pEntry->PairwiseKey, &PairwiseKey, sizeof(CIPHER_KEY));
1434                                DBGPRINT(RT_DEBUG_TRACE,("DLS - Receive STAKey Message-1 (Peer STA MAC Address STAKey) \n"));
1435
1436                                RTMPSendSTAKeyHandShake(pAd, pAd->StaCfg.DLSEntry[i].MacAddr);
1437
1438                                DBGPRINT(RT_DEBUG_TRACE,("DLS - Finish STAKey handshake procedure (Initiator side)\n"));
1439                        }
1440                        else
1441                        {
1442                                // Data frame, update timeout value
1443                                if (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH)
1444                                {
1445                                        pAd->StaCfg.DLSEntry[i].CountDownTimer = pAd->StaCfg.DLSEntry[i].TimeOut;
1446                                        //AsicUpdateRxWCIDTable(pAd, (USHORT)(i + 2), pAddr);
1447                                }
1448                        }
1449
1450                        bFindEntry = TRUE;
1451                }
1452        }
1453
1454        // update peer dls table entry
1455        for (i=MAX_NUM_OF_INIT_DLS_ENTRY; i<MAX_NUM_OF_DLS_ENTRY; i++)
1456        {
1457                if (pAd->StaCfg.DLSEntry[i].Valid && MAC_ADDR_EQUAL(pAddr, pAd->StaCfg.DLSEntry[i].MacAddr))
1458                {
1459                        if (bSTAKeyFrame)
1460                        {
1461                                PMAC_TABLE_ENTRY pEntry = NULL;
1462
1463                                // STAKey frame, add pairwise key table, and send STAkey Msg-2
1464                                pAd->StaCfg.DLSEntry[i].Status = DLS_FINISH;
1465                                RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled);
1466
1467                                PairwiseKey.KeyLen = LEN_TKIP_EK;
1468                                NdisMoveMemory(PairwiseKey.Key, &pSTAKey[0], LEN_TKIP_EK);
1469                                NdisMoveMemory(PairwiseKey.TxMic, &pSTAKey[16], LEN_TKIP_RXMICK);
1470                                NdisMoveMemory(PairwiseKey.RxMic, &pSTAKey[24], LEN_TKIP_TXMICK);
1471
1472                                //PairwiseKey.CipherAlg = pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg;
1473                                if (pAd->StaCfg.PairCipher == Ndis802_11Encryption2Enabled)
1474                                        PairwiseKey.CipherAlg = CIPHER_TKIP;
1475                                else if (pAd->StaCfg.PairCipher == Ndis802_11Encryption3Enabled)
1476                                        PairwiseKey.CipherAlg = CIPHER_AES;
1477
1478                                pEntry = DlsEntryTableLookup(pAd, pAd->StaCfg.DLSEntry[i].MacAddr, TRUE);
1479                                //AsicAddKeyEntry(pAd, (USHORT)(i + 2), BSS0, 0, &PairwiseKey, TRUE, TRUE);     // reserve 0 for multicast, 1 for unicast
1480                                //AsicUpdateRxWCIDTable(pAd, (USHORT)(i + 2), pAddr);
1481                                // Add Pair-wise key to Asic
1482#ifdef RTMP_MAC_PCI
1483                AsicAddPairwiseKeyEntry(pAd,
1484                                                                                pAd->StaCfg.DLSEntry[i].MacAddr,
1485                                                                                (UCHAR)pAd->StaCfg.DLSEntry[i].MacTabMatchWCID,
1486                                                                                &PairwiseKey);
1487
1488                                RTMPAddWcidAttributeEntry(pAd,
1489                                                                                  BSS0,
1490                                                                                  0,
1491                                                                                  PairwiseKey.CipherAlg,
1492                                                                                  pEntry);
1493#endif // RTMP_MAC_PCI //
1494                                NdisMoveMemory(&pEntry->PairwiseKey, &PairwiseKey, sizeof(CIPHER_KEY));
1495                                DBGPRINT(RT_DEBUG_TRACE,("DLS - Receive STAKey Message-1 (Initiator STA MAC Address STAKey)\n"));
1496
1497                                // If support WPA or WPA2, start STAKey hand shake,
1498                                // If failed hand shake, just tear down peer DLS
1499                                if (RTMPSendSTAKeyHandShake(pAd, pAddr) != NDIS_STATUS_SUCCESS)
1500                                {
1501                                        MLME_DLS_REQ_STRUCT     MlmeDlsReq;
1502                                        USHORT                          reason = REASON_QOS_CIPHER_NOT_SUPPORT;
1503
1504                                        pAd->StaCfg.DLSEntry[i].Valid   = FALSE;
1505                                        pAd->StaCfg.DLSEntry[i].Status  = DLS_NONE;
1506                                        DlsParmFill(pAd, &MlmeDlsReq, &pAd->StaCfg.DLSEntry[i], reason);
1507                                        MlmeEnqueue(pAd, DLS_STATE_MACHINE, MT2_MLME_DLS_TEAR_DOWN, sizeof(MLME_DLS_REQ_STRUCT), &MlmeDlsReq);
1508                                }
1509                                else
1510                                {
1511                                        DBGPRINT(RT_DEBUG_TRACE,("DLS - Finish STAKey handshake procedure (Peer side)\n"));
1512                                }
1513                        }
1514                        else
1515                        {
1516                                // Data frame, update timeout value
1517                                if (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH)
1518                                {
1519                                        pAd->StaCfg.DLSEntry[i].CountDownTimer = pAd->StaCfg.DLSEntry[i].TimeOut;
1520                                }
1521                        }
1522
1523                        bFindEntry = TRUE;
1524                }
1525        }
1526
1527
1528        return bSTAKeyFrame;
1529}
1530
1531/*
1532        ========================================================================
1533
1534        Routine Description:
1535                Check if the frame can be sent through DLS direct link interface
1536
1537        Arguments:
1538                pAd             Pointer to adapter
1539
1540        Return Value:
1541                DLS entry index
1542
1543        Note:
1544
1545        ========================================================================
1546*/
1547INT     RTMPCheckDLSFrame(
1548        IN      PRTMP_ADAPTER   pAd,
1549        IN  PUCHAR          pDA)
1550{
1551        INT rval = -1;
1552        INT     i;
1553
1554        if (!pAd->CommonCfg.bDLSCapable)
1555                return rval;
1556
1557        if (!INFRA_ON(pAd))
1558                return rval;
1559
1560        do{
1561                // check local dls table entry
1562                for (i=0; i<MAX_NUM_OF_INIT_DLS_ENTRY; i++)
1563                {
1564                        if (pAd->StaCfg.DLSEntry[i].Valid && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH) &&
1565                                MAC_ADDR_EQUAL(pDA, pAd->StaCfg.DLSEntry[i].MacAddr))
1566                        {
1567                                rval = i;
1568                                break;
1569                        }
1570                }
1571
1572                // check peer dls table entry
1573                for (i=MAX_NUM_OF_INIT_DLS_ENTRY; i<MAX_NUM_OF_DLS_ENTRY; i++)
1574                {
1575                        if (pAd->StaCfg.DLSEntry[i].Valid && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH) &&
1576                                MAC_ADDR_EQUAL(pDA, pAd->StaCfg.DLSEntry[i].MacAddr))
1577                        {
1578                                rval = i;
1579                                break;
1580                        }
1581                }
1582        } while (FALSE);
1583
1584        return rval;
1585}
1586
1587/*
1588    ==========================================================================
1589    Description:
1590
1591        IRQL = DISPATCH_LEVEL
1592
1593    ==========================================================================
1594 */
1595VOID RTMPSendDLSTearDownFrame(
1596        IN      PRTMP_ADAPTER   pAd,
1597        IN  PUCHAR          pDA)
1598{
1599        PUCHAR                  pOutBuffer = NULL;
1600        NDIS_STATUS             NStatus;
1601        HEADER_802_11   DlsTearDownHdr;
1602        ULONG                   FrameLen = 0;
1603        USHORT                  Reason = REASON_QOS_QSTA_LEAVING_QBSS;
1604        UCHAR                   Category = CATEGORY_DLS;
1605        UCHAR                   Action = ACTION_DLS_TEARDOWN;
1606        UCHAR                   i = 0;
1607
1608        if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
1609                RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS))
1610                return;
1611
1612        DBGPRINT(RT_DEBUG_TRACE, ("Send DLS TearDown Frame \n"));
1613
1614        NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);  //Get an unused nonpaged memory
1615        if (NStatus != NDIS_STATUS_SUCCESS)
1616        {
1617                DBGPRINT(RT_DEBUG_ERROR,("ASSOC - RTMPSendDLSTearDownFrame() allocate memory failed \n"));
1618                return;
1619        }
1620
1621        ActHeaderInit(pAd, &DlsTearDownHdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAd->CommonCfg.Bssid);
1622        MakeOutgoingFrame(pOutBuffer,                           &FrameLen,
1623                                        sizeof(HEADER_802_11),          &DlsTearDownHdr,
1624                                        1,                                                      &Category,
1625                                        1,                                                      &Action,
1626                                        6,                                                      pDA,
1627                                        6,                                                      pAd->CurrentAddress,
1628                                        2,                                                      &Reason,
1629                                        END_OF_ARGS);
1630
1631        MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
1632        MlmeFreeMemory(pAd, pOutBuffer);
1633
1634        // Remove key in local dls table entry
1635        for (i = 0; i < MAX_NUM_OF_INIT_DLS_ENTRY; i++)
1636        {
1637                if (pAd->StaCfg.DLSEntry[i].Valid && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH)
1638                        && MAC_ADDR_EQUAL(pDA, pAd->StaCfg.DLSEntry[i].MacAddr))
1639                {
1640                        MacTableDeleteDlsEntry(pAd, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID, pAd->StaCfg.DLSEntry[i].MacAddr);
1641                }
1642        }
1643
1644        // Remove key in peer dls table entry
1645        for (i=MAX_NUM_OF_INIT_DLS_ENTRY; i<MAX_NUM_OF_DLS_ENTRY; i++)
1646        {
1647                if (pAd->StaCfg.DLSEntry[i].Valid && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH)
1648                        && MAC_ADDR_EQUAL(pDA, pAd->StaCfg.DLSEntry[i].MacAddr))
1649                {
1650                        MacTableDeleteDlsEntry(pAd, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID, pAd->StaCfg.DLSEntry[i].MacAddr);
1651                }
1652        }
1653
1654        DBGPRINT(RT_DEBUG_TRACE, ("Send DLS TearDown Frame and remove key in (i=%d) \n", i));
1655}
1656
1657/*
1658    ==========================================================================
1659    Description:
1660
1661        IRQL = DISPATCH_LEVEL
1662
1663    ==========================================================================
1664 */
1665NDIS_STATUS RTMPSendSTAKeyRequest(
1666        IN      PRTMP_ADAPTER   pAd,
1667        IN      PUCHAR                  pDA)
1668{
1669        UCHAR                           Header802_3[14];
1670        NDIS_STATUS                     NStatus;
1671        ULONG                           FrameLen = 0;
1672        EAPOL_PACKET            Packet;
1673        UCHAR                           Mic[16];
1674        UCHAR                           digest[80];
1675        PUCHAR                          pOutBuffer = NULL;
1676        PNDIS_PACKET            pNdisPacket;
1677        UCHAR                           temp[64];
1678        UCHAR                           DlsPTK[80];
1679
1680        DBGPRINT(RT_DEBUG_TRACE,("DLS - RTMPSendSTAKeyRequest() to %02x:%02x:%02x:%02x:%02x:%02x\n", pDA[0], pDA[1], pDA[2], pDA[3], pDA[4], pDA[5]));
1681
1682        pAd->Sequence ++;
1683        MAKE_802_3_HEADER(Header802_3, pAd->CommonCfg.Bssid, pAd->CurrentAddress, EAPOL);
1684
1685        // Zero message body
1686        NdisZeroMemory(&Packet, sizeof(Packet));
1687        Packet.ProVer = EAPOL_VER;
1688        Packet.ProType    = EAPOLKey;
1689        Packet.Body_Len[1]  = sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE + 6 + MAC_ADDR_LEN;             // data field contain KDE andPeer MAC address
1690
1691        // STAKey Message is as EAPOL-Key(1,1,0,0,G/0,0,0, MIC, 0,Peer MAC KDE)
1692        if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
1693    {
1694        Packet.KeyDesc.Type = WPA1_KEY_DESC;
1695    }
1696    else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
1697    {
1698        Packet.KeyDesc.Type = WPA2_KEY_DESC;
1699    }
1700
1701        // Key descriptor version
1702        Packet.KeyDesc.KeyInfo.KeyDescVer =
1703                (((pAd->StaCfg.PairCipher == Ndis802_11Encryption3Enabled) || (pAd->StaCfg.GroupCipher == Ndis802_11Encryption3Enabled)) ? (DESC_TYPE_AES) : (DESC_TYPE_TKIP));
1704
1705        Packet.KeyDesc.KeyInfo.KeyMic   = 1;
1706        Packet.KeyDesc.KeyInfo.Secure   = 1;
1707        Packet.KeyDesc.KeyInfo.Request  = 1;
1708
1709        Packet.KeyDesc.KeyDataLen[1]    = 12;
1710
1711        // use our own OUI to distinguish proprietary with standard.
1712        Packet.KeyDesc.KeyData[0]               = 0xDD;
1713        Packet.KeyDesc.KeyData[1]               = 0x0A;
1714        Packet.KeyDesc.KeyData[2]               = 0x00;
1715        Packet.KeyDesc.KeyData[3]               = 0x0C;
1716        Packet.KeyDesc.KeyData[4]               = 0x43;
1717        Packet.KeyDesc.KeyData[5]               = 0x03;
1718        NdisMoveMemory(&Packet.KeyDesc.KeyData[6], pDA, MAC_ADDR_LEN);
1719
1720        NdisMoveMemory(Packet.KeyDesc.ReplayCounter, pAd->StaCfg.DlsReplayCounter, LEN_KEY_DESC_REPLAY);
1721
1722        // Allocate buffer for transmitting message
1723        NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);
1724        if (NStatus     != NDIS_STATUS_SUCCESS)
1725                return NStatus;
1726
1727        // Prepare EAPOL frame for MIC calculation
1728        // Be careful, only EAPOL frame is counted for MIC calculation
1729        MakeOutgoingFrame(pOutBuffer,           &FrameLen,
1730                              Packet.Body_Len[1] + 4,    &Packet,
1731                              END_OF_ARGS);
1732
1733        // use proprietary PTK
1734        NdisZeroMemory(temp, 64);
1735        NdisMoveMemory(temp, "IEEE802.11 WIRELESS ACCESS POINT", 32);
1736        WpaDerivePTK(pAd, temp, temp, pAd->CommonCfg.Bssid, temp, pAd->CurrentAddress, DlsPTK, LEN_PTK);
1737
1738        // calculate MIC
1739        if (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled)
1740        {
1741                // AES
1742                NdisZeroMemory(digest,  sizeof(digest));
1743                HMAC_SHA1(DlsPTK, LEN_EAP_MICK, pOutBuffer, FrameLen, digest, SHA1_DIGEST_SIZE);
1744                NdisMoveMemory(Packet.KeyDesc.KeyMic, digest, LEN_KEY_DESC_MIC);
1745        }
1746        else
1747        {
1748                NdisZeroMemory(Mic,     sizeof(Mic));
1749                HMAC_MD5(DlsPTK, LEN_EAP_MICK, pOutBuffer, FrameLen, Mic, MD5_DIGEST_SIZE);
1750                NdisMoveMemory(Packet.KeyDesc.KeyMic, Mic, LEN_KEY_DESC_MIC);
1751        }
1752
1753        MakeOutgoingFrame(pOutBuffer,           &FrameLen,
1754                          sizeof(Header802_3),  Header802_3,
1755                              Packet.Body_Len[1] + 4,   &Packet,
1756                              END_OF_ARGS);
1757
1758        NStatus = RTMPAllocateNdisPacket(pAd, &pNdisPacket, NULL, 0, pOutBuffer, FrameLen);
1759        if (NStatus == NDIS_STATUS_SUCCESS)
1760        {
1761                RTMP_SET_PACKET_WCID(pNdisPacket, BSSID_WCID);
1762                STASendPacket(pAd, pNdisPacket);
1763                RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
1764        }
1765
1766        MlmeFreeMemory(pAd, pOutBuffer);
1767
1768        DBGPRINT(RT_DEBUG_TRACE, ("RTMPSendSTAKeyRequest- Send STAKey request (NStatus=%x, FrameLen=%ld)\n", NStatus, FrameLen));
1769
1770        return NStatus;
1771}
1772
1773/*
1774    ==========================================================================
1775    Description:
1776
1777        IRQL = DISPATCH_LEVEL
1778
1779    ==========================================================================
1780 */
1781NDIS_STATUS RTMPSendSTAKeyHandShake(
1782        IN      PRTMP_ADAPTER   pAd,
1783        IN      PUCHAR                  pDA)
1784{
1785        UCHAR                           Header802_3[14];
1786        NDIS_STATUS                     NStatus;
1787        ULONG                           FrameLen = 0;
1788        EAPOL_PACKET            Packet;
1789        UCHAR                           Mic[16];
1790        UCHAR                           digest[80];
1791        PUCHAR                          pOutBuffer = NULL;
1792        PNDIS_PACKET            pNdisPacket;
1793        UCHAR                           temp[64];
1794        UCHAR                           DlsPTK[80];                     // Due to dirver can not get PTK, use proprietary PTK
1795
1796        DBGPRINT(RT_DEBUG_TRACE,("DLS - RTMPSendSTAKeyHandShake() to %02x:%02x:%02x:%02x:%02x:%02x\n", pDA[0], pDA[1], pDA[2], pDA[3], pDA[4], pDA[5]));
1797
1798        pAd->Sequence ++;
1799        MAKE_802_3_HEADER(Header802_3, pAd->CommonCfg.Bssid, pAd->CurrentAddress, EAPOL);
1800
1801        // Zero message body
1802        NdisZeroMemory(&Packet, sizeof(Packet));
1803        Packet.ProVer = EAPOL_VER;
1804        Packet.ProType    = EAPOLKey;
1805        Packet.Body_Len[1]  = sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE + 6 + MAC_ADDR_LEN;             // data field contain KDE and Peer MAC address
1806
1807        // STAKey Message is as EAPOL-Key(1,1,0,0,G/0,0,0, MIC, 0,Peer MAC KDE)
1808        if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
1809    {
1810        Packet.KeyDesc.Type = WPA1_KEY_DESC;
1811    }
1812    else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
1813    {
1814        Packet.KeyDesc.Type = WPA2_KEY_DESC;
1815    }
1816
1817        // Key descriptor version
1818        Packet.KeyDesc.KeyInfo.KeyDescVer =
1819                (((pAd->StaCfg.PairCipher == Ndis802_11Encryption3Enabled) || (pAd->StaCfg.GroupCipher == Ndis802_11Encryption3Enabled)) ? (DESC_TYPE_AES) : (DESC_TYPE_TKIP));
1820
1821        Packet.KeyDesc.KeyInfo.KeyMic   = 1;
1822        Packet.KeyDesc.KeyInfo.Secure   = 1;
1823
1824        Packet.KeyDesc.KeyDataLen[1]    = 12;
1825
1826        // use our own OUI to distinguish proprietary with standard.
1827        Packet.KeyDesc.KeyData[0]               = 0xDD;
1828        Packet.KeyDesc.KeyData[1]               = 0x0A;
1829        Packet.KeyDesc.KeyData[2]               = 0x00;
1830        Packet.KeyDesc.KeyData[3]               = 0x0C;
1831        Packet.KeyDesc.KeyData[4]               = 0x43;
1832        Packet.KeyDesc.KeyData[5]               = 0x03;
1833        NdisMoveMemory(&Packet.KeyDesc.KeyData[6], pDA, MAC_ADDR_LEN);
1834
1835        NdisMoveMemory(Packet.KeyDesc.ReplayCounter, pAd->StaCfg.DlsReplayCounter, LEN_KEY_DESC_REPLAY);
1836
1837        // Allocate buffer for transmitting message
1838        NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);
1839        if (NStatus     != NDIS_STATUS_SUCCESS)
1840                return NStatus;
1841
1842        // Prepare EAPOL frame for MIC calculation
1843        // Be careful, only EAPOL frame is counted for MIC calculation
1844        MakeOutgoingFrame(pOutBuffer,           &FrameLen,
1845                              Packet.Body_Len[1] + 4,    &Packet,
1846                              END_OF_ARGS);
1847
1848        // use proprietary PTK
1849        NdisZeroMemory(temp, 64);
1850        NdisMoveMemory(temp, "IEEE802.11 WIRELESS ACCESS POINT", 32);
1851        WpaDerivePTK(pAd, temp, temp, pAd->CommonCfg.Bssid, temp, pAd->CurrentAddress, DlsPTK, LEN_PTK);
1852
1853        // calculate MIC
1854        if (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled)
1855        {
1856                // AES
1857                NdisZeroMemory(digest,  sizeof(digest));
1858                HMAC_SHA1(DlsPTK, LEN_EAP_MICK, pOutBuffer, FrameLen, digest, SHA1_DIGEST_SIZE);
1859                NdisMoveMemory(Packet.KeyDesc.KeyMic, digest, LEN_KEY_DESC_MIC);
1860        }
1861        else
1862        {
1863                NdisZeroMemory(Mic,     sizeof(Mic));
1864                HMAC_MD5(DlsPTK, LEN_EAP_MICK, pOutBuffer, FrameLen, Mic, MD5_DIGEST_SIZE);
1865                NdisMoveMemory(Packet.KeyDesc.KeyMic, Mic, LEN_KEY_DESC_MIC);
1866        }
1867
1868        MakeOutgoingFrame(pOutBuffer,           &FrameLen,
1869                          sizeof(Header802_3),  Header802_3,
1870                              Packet.Body_Len[1] + 4,   &Packet,
1871                              END_OF_ARGS);
1872
1873        NStatus = RTMPAllocateNdisPacket(pAd, &pNdisPacket, NULL, 0, pOutBuffer, FrameLen);
1874        if (NStatus == NDIS_STATUS_SUCCESS)
1875        {
1876                RTMP_SET_PACKET_WCID(pNdisPacket, BSSID_WCID);
1877                STASendPacket(pAd, pNdisPacket);
1878                RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
1879        }
1880
1881        MlmeFreeMemory(pAd, pOutBuffer);
1882
1883        DBGPRINT(RT_DEBUG_TRACE, ("RTMPSendSTAKeyHandShake- Send STAKey Message-2 (NStatus=%x, FrameLen=%ld)\n", NStatus, FrameLen));
1884
1885        return NStatus;
1886}
1887
1888VOID DlsTimeoutAction(
1889        IN PVOID SystemSpecific1,
1890        IN PVOID FunctionContext,
1891        IN PVOID SystemSpecific2,
1892        IN PVOID SystemSpecific3)
1893{
1894        MLME_DLS_REQ_STRUCT             MlmeDlsReq;
1895        USHORT                                  reason;
1896        PRT_802_11_DLS                  pDLS = (PRT_802_11_DLS)FunctionContext;
1897        PRTMP_ADAPTER                   pAd = pDLS->pAd;
1898
1899        DBGPRINT(RT_DEBUG_TRACE, ("DlsTimeout - Tear down DLS links (%02x:%02x:%02x:%02x:%02x:%02x)\n",
1900                pDLS->MacAddr[0], pDLS->MacAddr[1], pDLS->MacAddr[2], pDLS->MacAddr[3], pDLS->MacAddr[4], pDLS->MacAddr[5]));
1901
1902        if ((pDLS) && (pDLS->Valid))
1903        {
1904                reason                  = REASON_QOS_REQUEST_TIMEOUT;
1905                pDLS->Valid             = FALSE;
1906                pDLS->Status    = DLS_NONE;
1907                DlsParmFill(pAd, &MlmeDlsReq, pDLS, reason);
1908                MlmeEnqueue(pAd, DLS_STATE_MACHINE, MT2_MLME_DLS_TEAR_DOWN, sizeof(MLME_DLS_REQ_STRUCT), &MlmeDlsReq);
1909                RTMP_MLME_HANDLER(pAd);
1910        }
1911}
1912
1913/*
1914================================================================
1915Description : because DLS and CLI share the same WCID table in ASIC.
1916Mesh entry also insert to pAd->MacTab.content[].  Such is marked as ValidAsDls = TRUE.
1917Also fills the pairwise key.
1918Because front MAX_AID_BA entries have direct mapping to BAEntry, which is only used as CLI. So we insert Dls
1919from index MAX_AID_BA.
1920================================================================
1921*/
1922MAC_TABLE_ENTRY *MacTableInsertDlsEntry(
1923        IN  PRTMP_ADAPTER   pAd,
1924        IN  PUCHAR      pAddr,
1925        IN  UINT        DlsEntryIdx)
1926{
1927        PMAC_TABLE_ENTRY pEntry = NULL;
1928
1929        DBGPRINT(RT_DEBUG_TRACE, ("====> MacTableInsertDlsEntry\n"));
1930        // if FULL, return
1931        if (pAd->MacTab.Size >= MAX_LEN_OF_MAC_TABLE)
1932                return NULL;
1933
1934        do
1935        {
1936                if((pEntry = DlsEntryTableLookup(pAd, pAddr, TRUE)) != NULL)
1937                        break;
1938
1939                // allocate one MAC entry
1940                pEntry = MacTableInsertEntry(pAd, pAddr, DlsEntryIdx + MIN_NET_DEVICE_FOR_DLS, TRUE);
1941                if (pEntry)
1942                {
1943                        pAd->StaCfg.DLSEntry[DlsEntryIdx].MacTabMatchWCID = pEntry->Aid;
1944                        pEntry->MatchDlsEntryIdx = DlsEntryIdx;
1945                        pEntry->AuthMode = pAd->StaCfg.AuthMode;
1946                        pEntry->WepStatus = pAd->StaCfg.WepStatus;
1947                        pEntry->PortSecured = WPA_802_1X_PORT_SECURED;
1948
1949                        DBGPRINT(RT_DEBUG_TRACE, ("MacTableInsertDlsEntry - allocate entry #%d, Total= %d\n",pEntry->Aid, pAd->MacTab.Size));
1950
1951                        // If legacy WEP is used, set pair-wise cipherAlg into WCID attribute table for this entry
1952                        if ((pEntry->ValidAsDls) && (pAd->StaCfg.WepStatus == Ndis802_11WEPEnabled))
1953                        {
1954                                UCHAR KeyIdx = 0;
1955                                UCHAR CipherAlg = 0;
1956
1957                                KeyIdx  = pAd->StaCfg.DefaultKeyId;
1958
1959                                CipherAlg       = pAd->SharedKey[BSS0][KeyIdx].CipherAlg;
1960
1961                                RTMPAddWcidAttributeEntry(pAd,
1962                                                                                        BSS0,
1963                                                                                        pAd->StaCfg.DefaultKeyId,
1964                                                                                        pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg,
1965                                                                                        pEntry);
1966                        }
1967
1968                        break;
1969                }
1970        } while(FALSE);
1971
1972        DBGPRINT(RT_DEBUG_TRACE, ("<==== MacTableInsertDlsEntry\n"));
1973
1974        return pEntry;
1975}
1976
1977
1978/*
1979        ==========================================================================
1980        Description:
1981                Delete all Mesh Entry in pAd->MacTab
1982        ==========================================================================
1983 */
1984BOOLEAN MacTableDeleteDlsEntry(
1985        IN PRTMP_ADAPTER pAd,
1986        IN USHORT wcid,
1987        IN PUCHAR pAddr)
1988{
1989        DBGPRINT(RT_DEBUG_TRACE, ("====> MacTableDeleteDlsEntry\n"));
1990
1991        if (!VALID_WCID(wcid))
1992                return FALSE;
1993
1994        MacTableDeleteEntry(pAd, wcid, pAddr);
1995
1996        DBGPRINT(RT_DEBUG_TRACE, ("<==== MacTableDeleteDlsEntry\n"));
1997
1998        return TRUE;
1999}
2000
2001MAC_TABLE_ENTRY *DlsEntryTableLookup(
2002        IN PRTMP_ADAPTER pAd,
2003        IN PUCHAR       pAddr,
2004        IN BOOLEAN      bResetIdelCount)
2005{
2006        ULONG HashIdx;
2007        MAC_TABLE_ENTRY *pEntry = NULL;
2008
2009        RTMP_SEM_LOCK(&pAd->MacTabLock);
2010        HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
2011        pEntry = pAd->MacTab.Hash[HashIdx];
2012
2013        while (pEntry)
2014        {
2015                if ((pEntry->ValidAsDls == TRUE)
2016                        && MAC_ADDR_EQUAL(pEntry->Addr, pAddr))
2017                {
2018                        if(bResetIdelCount)
2019                                pEntry->NoDataIdleCount = 0;
2020                        break;
2021                }
2022                else
2023                        pEntry = pEntry->pNext;
2024        }
2025
2026        RTMP_SEM_UNLOCK(&pAd->MacTabLock);
2027        return pEntry;
2028}
2029
2030MAC_TABLE_ENTRY *DlsEntryTableLookupByWcid(
2031        IN PRTMP_ADAPTER pAd,
2032        IN UCHAR        wcid,
2033        IN PUCHAR       pAddr,
2034        IN BOOLEAN      bResetIdelCount)
2035{
2036        ULONG DLsIndex;
2037        PMAC_TABLE_ENTRY pCurEntry = NULL;
2038        PMAC_TABLE_ENTRY pEntry = NULL;
2039
2040        if (!VALID_WCID(wcid))
2041                return NULL;
2042
2043        RTMP_SEM_LOCK(&pAd->MacTabLock);
2044
2045        do
2046        {
2047                pCurEntry = &pAd->MacTab.Content[wcid];
2048
2049                DLsIndex = 0xff;
2050                if ((pCurEntry) && (pCurEntry->ValidAsDls== TRUE))
2051                {
2052                        DLsIndex = pCurEntry->MatchDlsEntryIdx;
2053                }
2054
2055                if (DLsIndex == 0xff)
2056                        break;
2057
2058                if (MAC_ADDR_EQUAL(pCurEntry->Addr, pAddr))
2059                {
2060                        if(bResetIdelCount)
2061                                pCurEntry->NoDataIdleCount = 0;
2062                        pEntry = pCurEntry;
2063                        break;
2064                }
2065        } while(FALSE);
2066
2067        RTMP_SEM_UNLOCK(&pAd->MacTabLock);
2068
2069        return pEntry;
2070}
2071
2072INT Set_DlsEntryInfo_Display_Proc(
2073        IN PRTMP_ADAPTER pAd,
2074        IN PUCHAR arg)
2075{
2076        INT i;
2077
2078        DBGPRINT(RT_DEBUG_OFF, ("\n%-19s%-8s\n", "MAC", "TIMEOUT\n"));
2079        for (i=0; i<MAX_NUM_OF_DLS_ENTRY; i++)
2080        {
2081                if ((pAd->StaCfg.DLSEntry[i].Valid) && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH))
2082                {
2083                        PMAC_TABLE_ENTRY pEntry = &pAd->MacTab.Content[pAd->StaCfg.DLSEntry[i].MacTabMatchWCID];
2084
2085                        DBGPRINT(RT_DEBUG_OFF, ("%02x:%02x:%02x:%02x:%02x:%02x  ",
2086                                pAd->StaCfg.DLSEntry[i].MacAddr[0], pAd->StaCfg.DLSEntry[i].MacAddr[1], pAd->StaCfg.DLSEntry[i].MacAddr[2],
2087                                pAd->StaCfg.DLSEntry[i].MacAddr[3], pAd->StaCfg.DLSEntry[i].MacAddr[4], pAd->StaCfg.DLSEntry[i].MacAddr[5]));
2088                        DBGPRINT(RT_DEBUG_OFF, ("%-8d\n", pAd->StaCfg.DLSEntry[i].TimeOut));
2089
2090                        DBGPRINT(RT_DEBUG_OFF, ("\n"));
2091                        DBGPRINT(RT_DEBUG_OFF, ("\n%-19s%-4s%-4s%-4s%-4s%-7s%-7s%-7s","MAC", "AID", "BSS", "PSM", "WMM", "RSSI0", "RSSI1", "RSSI2"));
2092#ifdef DOT11_N_SUPPORT
2093                        DBGPRINT(RT_DEBUG_OFF, ("%-8s%-10s%-6s%-6s%-6s%-6s", "MIMOPS", "PhMd", "BW", "MCS", "SGI", "STBC"));
2094#endif // DOT11_N_SUPPORT //
2095                        DBGPRINT(RT_DEBUG_OFF, ("\n%02X:%02X:%02X:%02X:%02X:%02X  ",
2096                                pEntry->Addr[0], pEntry->Addr[1], pEntry->Addr[2],
2097                                pEntry->Addr[3], pEntry->Addr[4], pEntry->Addr[5]));
2098                        DBGPRINT(RT_DEBUG_OFF, ("%-4d", (int)pEntry->Aid));
2099                        DBGPRINT(RT_DEBUG_OFF, ("%-4d", (int)pEntry->apidx));
2100                        DBGPRINT(RT_DEBUG_OFF, ("%-4d", (int)pEntry->PsMode));
2101                        DBGPRINT(RT_DEBUG_OFF, ("%-4d", (int)CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE)));
2102                        DBGPRINT(RT_DEBUG_OFF, ("%-7d", pEntry->RssiSample.AvgRssi0));
2103                        DBGPRINT(RT_DEBUG_OFF, ("%-7d", pEntry->RssiSample.AvgRssi1));
2104                        DBGPRINT(RT_DEBUG_OFF, ("%-7d", pEntry->RssiSample.AvgRssi2));
2105#ifdef DOT11_N_SUPPORT
2106                        DBGPRINT(RT_DEBUG_OFF, ("%-8d", (int)pEntry->MmpsMode));
2107                        DBGPRINT(RT_DEBUG_OFF, ("%-10s", GetPhyMode(pEntry->HTPhyMode.field.MODE)));
2108                        DBGPRINT(RT_DEBUG_OFF, ("%-6s", GetBW(pEntry->HTPhyMode.field.BW)));
2109                        DBGPRINT(RT_DEBUG_OFF, ("%-6d", pEntry->HTPhyMode.field.MCS));
2110                        DBGPRINT(RT_DEBUG_OFF, ("%-6d", pEntry->HTPhyMode.field.ShortGI));
2111                        DBGPRINT(RT_DEBUG_OFF, ("%-6d", pEntry->HTPhyMode.field.STBC));
2112#endif // DOT11_N_SUPPORT //
2113                        DBGPRINT(RT_DEBUG_OFF, ("%-10d, %d, %d%%\n", pEntry->DebugFIFOCount, pEntry->DebugTxCount,
2114                                                (pEntry->DebugTxCount) ? ((pEntry->DebugTxCount-pEntry->DebugFIFOCount)*100/pEntry->DebugTxCount) : 0));
2115                        DBGPRINT(RT_DEBUG_OFF, ("\n"));
2116
2117                }
2118        }
2119
2120        return TRUE;
2121}
2122
2123INT     Set_DlsAddEntry_Proc(
2124        IN      PRTMP_ADAPTER   pAd,
2125        IN      PSTRING                 arg)
2126{
2127    UCHAR       mac[MAC_ADDR_LEN];
2128        USHORT  Timeout;
2129        PSTRING token;
2130        STRING sepValue[] = ":", DASH = '-';
2131        INT i;
2132    RT_802_11_DLS       Dls;
2133
2134    if(strlen(arg) < 19)  //Mac address acceptable format 01:02:03:04:05:06 length 17 plus the "-" and timeout value in decimal format.
2135                return FALSE;
2136
2137        token = strchr(arg, DASH);
2138        if ((token != NULL) && (strlen(token)>1))
2139        {
2140                Timeout = (USHORT) simple_strtol((token+1), 0, 10);
2141
2142                *token = '\0';
2143                for (i = 0, token = rstrtok(arg, &sepValue[0]); token; token = rstrtok(NULL, &sepValue[0]), i++)
2144                {
2145                        if((strlen(token) != 2) || (!isxdigit(*token)) || (!isxdigit(*(token+1))))
2146                                return FALSE;
2147                        AtoH(token, (&mac[i]), 1);
2148                }
2149                if(i != 6)
2150                        return FALSE;
2151
2152            DBGPRINT(RT_DEBUG_OFF, ("\n%02x:%02x:%02x:%02x:%02x:%02x-%d", mac[0], mac[1],
2153                   mac[2], mac[3], mac[4], mac[5], (int)Timeout));
2154
2155                NdisZeroMemory(&Dls, sizeof(RT_802_11_DLS));
2156                Dls.TimeOut = Timeout;
2157                COPY_MAC_ADDR(Dls.MacAddr, mac);
2158                Dls.Valid = 1;
2159
2160                MlmeEnqueue(pAd,
2161                                        MLME_CNTL_STATE_MACHINE,
2162                                        RT_OID_802_11_SET_DLS_PARAM,
2163                                        sizeof(RT_802_11_DLS),
2164                                        &Dls);
2165
2166                return TRUE;
2167        }
2168
2169        return FALSE;
2170
2171}
2172
2173INT     Set_DlsTearDownEntry_Proc(
2174        IN      PRTMP_ADAPTER   pAd,
2175        IN      PSTRING                 arg)
2176{
2177        UCHAR                   macAddr[MAC_ADDR_LEN];
2178        PSTRING                 value;
2179        INT                             i;
2180        RT_802_11_DLS   Dls;
2181
2182        if(strlen(arg) != 17)  //Mac address acceptable format 01:02:03:04:05:06 length 17
2183                return FALSE;
2184
2185        for (i=0, value = rstrtok(arg,":"); value; value = rstrtok(NULL,":"))
2186        {
2187                if((strlen(value) != 2) || (!isxdigit(*value)) || (!isxdigit(*(value+1))) )
2188                        return FALSE;  //Invalid
2189
2190                AtoH(value, &macAddr[i++], 2);
2191        }
2192
2193        DBGPRINT(RT_DEBUG_OFF, ("\n%02x:%02x:%02x:%02x:%02x:%02x", macAddr[0], macAddr[1],
2194                   macAddr[2], macAddr[3], macAddr[4], macAddr[5]));
2195
2196        NdisZeroMemory(&Dls, sizeof(RT_802_11_DLS));
2197        COPY_MAC_ADDR(Dls.MacAddr, macAddr);
2198        Dls.Valid = 0;
2199
2200        MlmeEnqueue(pAd,
2201                                MLME_CNTL_STATE_MACHINE,
2202                                RT_OID_802_11_SET_DLS_PARAM,
2203                                sizeof(RT_802_11_DLS),
2204                                &Dls);
2205
2206        return TRUE;
2207}
2208