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 action.c 29 30 Abstract: 31 Handle association related requests either from WSTA or from local MLME 32 33 Revision History: 34 Who When What 35 --------- ---------- ---------------------------------------------- 36 Fonchi Wu 2008 created for 802.11h 37 */ 38 39#include "../rt_config.h" 40#include "action.h" 41 42/* The regulatory information in the USA (US) */ 43struct rt_dot11_regulatory_information USARegulatoryInfo[] = { 44/* "regulatory class" "number of channels" "Max Tx Pwr" "channel list" */ 45 {0, {0, 0, {0} 46 } 47 } 48 , /* Invlid entry */ 49 {1, {4, 16, {36, 40, 44, 48} 50 } 51 } 52 , 53 {2, {4, 23, {52, 56, 60, 64} 54 } 55 } 56 , 57 {3, {4, 29, {149, 153, 157, 161} 58 } 59 } 60 , 61 {4, {11, 23, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140} 62 } 63 } 64 , 65 {5, {5, 30, {149, 153, 157, 161, 165} 66 } 67 } 68 , 69 {6, {10, 14, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10} 70 } 71 } 72 , 73 {7, {10, 27, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10} 74 } 75 } 76 , 77 {8, {5, 17, {11, 13, 15, 17, 19} 78 } 79 } 80 , 81 {9, {5, 30, {11, 13, 15, 17, 19} 82 } 83 } 84 , 85 {10, {2, 20, {21, 25} 86 } 87 } 88 , 89 {11, {2, 33, {21, 25} 90 } 91 } 92 , 93 {12, {11, 30, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11} 94 } 95 } 96}; 97 98#define USA_REGULATORY_INFO_SIZE (sizeof(USARegulatoryInfo) / sizeof(struct rt_dot11_regulatory_information)) 99 100/* The regulatory information in Europe */ 101struct rt_dot11_regulatory_information EuropeRegulatoryInfo[] = { 102/* "regulatory class" "number of channels" "Max Tx Pwr" "channel list" */ 103 {0, {0, 0, {0} 104 } 105 } 106 , /* Invalid entry */ 107 {1, {4, 20, {36, 40, 44, 48} 108 } 109 } 110 , 111 {2, {4, 20, {52, 56, 60, 64} 112 } 113 } 114 , 115 {3, {11, 30, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140} 116 } 117 } 118 , 119 {4, {13, 20, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13} 120 } 121 } 122}; 123 124#define EU_REGULATORY_INFO_SIZE (sizeof(EuropeRegulatoryInfo) / sizeof(struct rt_dot11_regulatory_information)) 125 126/* The regulatory information in Japan */ 127struct rt_dot11_regulatory_information JapanRegulatoryInfo[] = { 128/* "regulatory class" "number of channels" "Max Tx Pwr" "channel list" */ 129 {0, {0, 0, {0} 130 } 131 } 132 , /* Invalid entry */ 133 {1, {4, 22, {34, 38, 42, 46} 134 } 135 } 136 , 137 {2, {3, 24, {8, 12, 16} 138 } 139 } 140 , 141 {3, {3, 24, {8, 12, 16} 142 } 143 } 144 , 145 {4, {3, 24, {8, 12, 16} 146 } 147 } 148 , 149 {5, {3, 24, {8, 12, 16} 150 } 151 } 152 , 153 {6, {3, 22, {8, 12, 16} 154 } 155 } 156 , 157 {7, {4, 24, {184, 188, 192, 196} 158 } 159 } 160 , 161 {8, {4, 24, {184, 188, 192, 196} 162 } 163 } 164 , 165 {9, {4, 24, {184, 188, 192, 196} 166 } 167 } 168 , 169 {10, {4, 24, {184, 188, 192, 196} 170 } 171 } 172 , 173 {11, {4, 22, {184, 188, 192, 196} 174 } 175 } 176 , 177 {12, {4, 24, {7, 8, 9, 11} 178 } 179 } 180 , 181 {13, {4, 24, {7, 8, 9, 11} 182 } 183 } 184 , 185 {14, {4, 24, {7, 8, 9, 11} 186 } 187 } 188 , 189 {15, {4, 24, {7, 8, 9, 11} 190 } 191 } 192 , 193 {16, {6, 24, {183, 184, 185, 187, 188, 189} 194 } 195 } 196 , 197 {17, {6, 24, {183, 184, 185, 187, 188, 189} 198 } 199 } 200 , 201 {18, {6, 24, {183, 184, 185, 187, 188, 189} 202 } 203 } 204 , 205 {19, {6, 24, {183, 184, 185, 187, 188, 189} 206 } 207 } 208 , 209 {20, {6, 17, {183, 184, 185, 187, 188, 189} 210 } 211 } 212 , 213 {21, {6, 24, {6, 7, 8, 9, 10, 11} 214 } 215 } 216 , 217 {22, {6, 24, {6, 7, 8, 9, 10, 11} 218 } 219 } 220 , 221 {23, {6, 24, {6, 7, 8, 9, 10, 11} 222 } 223 } 224 , 225 {24, {6, 24, {6, 7, 8, 9, 10, 11} 226 } 227 } 228 , 229 {25, {8, 24, {182, 183, 184, 185, 186, 187, 188, 189} 230 } 231 } 232 , 233 {26, {8, 24, {182, 183, 184, 185, 186, 187, 188, 189} 234 } 235 } 236 , 237 {27, {8, 24, {182, 183, 184, 185, 186, 187, 188, 189} 238 } 239 } 240 , 241 {28, {8, 24, {182, 183, 184, 185, 186, 187, 188, 189} 242 } 243 } 244 , 245 {29, {8, 17, {182, 183, 184, 185, 186, 187, 188, 189} 246 } 247 } 248 , 249 {30, {13, 23, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13} 250 } 251 } 252 , 253 {31, {1, 23, {14} 254 } 255 } 256 , 257 {32, {4, 22, {52, 56, 60, 64} 258 } 259 } 260}; 261 262#define JP_REGULATORY_INFO_SIZE (sizeof(JapanRegulatoryInfo) / sizeof(struct rt_dot11_regulatory_information)) 263 264char RTMP_GetTxPwr(struct rt_rtmp_adapter *pAd, IN HTTRANSMIT_SETTING HTTxMode) 265{ 266 struct tx_pwr_cfg { 267 u8 Mode; 268 u8 MCS; 269 u16 req; 270 u8 shift; 271 u32 BitMask; 272 }; 273 274 u32 Value; 275 int Idx; 276 u8 PhyMode; 277 char CurTxPwr; 278 u8 TxPwrRef = 0; 279 char DaltaPwr; 280 unsigned long TxPwr[5]; 281 282 struct tx_pwr_cfg TxPwrCfg[] = { 283 {MODE_CCK, 0, 0, 4, 0x000000f0}, 284 {MODE_CCK, 1, 0, 0, 0x0000000f}, 285 {MODE_CCK, 2, 0, 12, 0x0000f000}, 286 {MODE_CCK, 3, 0, 8, 0x00000f00}, 287 288 {MODE_OFDM, 0, 0, 20, 0x00f00000}, 289 {MODE_OFDM, 1, 0, 16, 0x000f0000}, 290 {MODE_OFDM, 2, 0, 28, 0xf0000000}, 291 {MODE_OFDM, 3, 0, 24, 0x0f000000}, 292 {MODE_OFDM, 4, 1, 4, 0x000000f0}, 293 {MODE_OFDM, 5, 1, 0, 0x0000000f}, 294 {MODE_OFDM, 6, 1, 12, 0x0000f000}, 295 {MODE_OFDM, 7, 1, 8, 0x00000f00} 296 , {MODE_HTMIX, 0, 1, 20, 0x00f00000}, 297 {MODE_HTMIX, 1, 1, 16, 0x000f0000}, 298 {MODE_HTMIX, 2, 1, 28, 0xf0000000}, 299 {MODE_HTMIX, 3, 1, 24, 0x0f000000}, 300 {MODE_HTMIX, 4, 2, 4, 0x000000f0}, 301 {MODE_HTMIX, 5, 2, 0, 0x0000000f}, 302 {MODE_HTMIX, 6, 2, 12, 0x0000f000}, 303 {MODE_HTMIX, 7, 2, 8, 0x00000f00}, 304 {MODE_HTMIX, 8, 2, 20, 0x00f00000}, 305 {MODE_HTMIX, 9, 2, 16, 0x000f0000}, 306 {MODE_HTMIX, 10, 2, 28, 0xf0000000}, 307 {MODE_HTMIX, 11, 2, 24, 0x0f000000}, 308 {MODE_HTMIX, 12, 3, 4, 0x000000f0}, 309 {MODE_HTMIX, 13, 3, 0, 0x0000000f}, 310 {MODE_HTMIX, 14, 3, 12, 0x0000f000}, 311 {MODE_HTMIX, 15, 3, 8, 0x00000f00} 312 }; 313#define MAX_TXPWR_TAB_SIZE (sizeof(TxPwrCfg) / sizeof(struct tx_pwr_cfg)) 314 315 CurTxPwr = 19; 316 317 /* check Tx Power setting from UI. */ 318 if (pAd->CommonCfg.TxPowerPercentage > 90) ; 319 else if (pAd->CommonCfg.TxPowerPercentage > 60) /* reduce Pwr for 1 dB. */ 320 CurTxPwr -= 1; 321 else if (pAd->CommonCfg.TxPowerPercentage > 30) /* reduce Pwr for 3 dB. */ 322 CurTxPwr -= 3; 323 else if (pAd->CommonCfg.TxPowerPercentage > 15) /* reduce Pwr for 6 dB. */ 324 CurTxPwr -= 6; 325 else if (pAd->CommonCfg.TxPowerPercentage > 9) /* reduce Pwr for 9 dB. */ 326 CurTxPwr -= 9; 327 else /* reduce Pwr for 12 dB. */ 328 CurTxPwr -= 12; 329 330 if (pAd->CommonCfg.BBPCurrentBW == BW_40) { 331 if (pAd->CommonCfg.CentralChannel > 14) { 332 TxPwr[0] = pAd->Tx40MPwrCfgABand[0]; 333 TxPwr[1] = pAd->Tx40MPwrCfgABand[1]; 334 TxPwr[2] = pAd->Tx40MPwrCfgABand[2]; 335 TxPwr[3] = pAd->Tx40MPwrCfgABand[3]; 336 TxPwr[4] = pAd->Tx40MPwrCfgABand[4]; 337 } else { 338 TxPwr[0] = pAd->Tx40MPwrCfgGBand[0]; 339 TxPwr[1] = pAd->Tx40MPwrCfgGBand[1]; 340 TxPwr[2] = pAd->Tx40MPwrCfgGBand[2]; 341 TxPwr[3] = pAd->Tx40MPwrCfgGBand[3]; 342 TxPwr[4] = pAd->Tx40MPwrCfgGBand[4]; 343 } 344 } else { 345 if (pAd->CommonCfg.Channel > 14) { 346 TxPwr[0] = pAd->Tx20MPwrCfgABand[0]; 347 TxPwr[1] = pAd->Tx20MPwrCfgABand[1]; 348 TxPwr[2] = pAd->Tx20MPwrCfgABand[2]; 349 TxPwr[3] = pAd->Tx20MPwrCfgABand[3]; 350 TxPwr[4] = pAd->Tx20MPwrCfgABand[4]; 351 } else { 352 TxPwr[0] = pAd->Tx20MPwrCfgGBand[0]; 353 TxPwr[1] = pAd->Tx20MPwrCfgGBand[1]; 354 TxPwr[2] = pAd->Tx20MPwrCfgGBand[2]; 355 TxPwr[3] = pAd->Tx20MPwrCfgGBand[3]; 356 TxPwr[4] = pAd->Tx20MPwrCfgGBand[4]; 357 } 358 } 359 360 switch (HTTxMode.field.MODE) { 361 case MODE_CCK: 362 case MODE_OFDM: 363 Value = TxPwr[1]; 364 TxPwrRef = (Value & 0x00000f00) >> 8; 365 366 break; 367 368 case MODE_HTMIX: 369 case MODE_HTGREENFIELD: 370 if (pAd->CommonCfg.TxStream == 1) { 371 Value = TxPwr[2]; 372 TxPwrRef = (Value & 0x00000f00) >> 8; 373 } else if (pAd->CommonCfg.TxStream == 2) { 374 Value = TxPwr[3]; 375 TxPwrRef = (Value & 0x00000f00) >> 8; 376 } 377 break; 378 } 379 380 PhyMode = (HTTxMode.field.MODE == MODE_HTGREENFIELD) 381 ? MODE_HTMIX : HTTxMode.field.MODE; 382 383 for (Idx = 0; Idx < MAX_TXPWR_TAB_SIZE; Idx++) { 384 if ((TxPwrCfg[Idx].Mode == PhyMode) 385 && (TxPwrCfg[Idx].MCS == HTTxMode.field.MCS)) { 386 Value = TxPwr[TxPwrCfg[Idx].req]; 387 DaltaPwr = 388 TxPwrRef - (char)((Value & TxPwrCfg[Idx].BitMask) 389 >> TxPwrCfg[Idx].shift); 390 CurTxPwr -= DaltaPwr; 391 break; 392 } 393 } 394 395 return CurTxPwr; 396} 397 398void MeasureReqTabInit(struct rt_rtmp_adapter *pAd) 399{ 400 NdisAllocateSpinLock(&pAd->CommonCfg.MeasureReqTabLock); 401 402 pAd->CommonCfg.pMeasureReqTab = 403 kmalloc(sizeof(struct rt_measure_req_tab), GFP_ATOMIC); 404 if (pAd->CommonCfg.pMeasureReqTab) 405 NdisZeroMemory(pAd->CommonCfg.pMeasureReqTab, 406 sizeof(struct rt_measure_req_tab)); 407 else 408 DBGPRINT(RT_DEBUG_ERROR, 409 ("%s Fail to alloc memory for pAd->CommonCfg.pMeasureReqTab.\n", 410 __func__)); 411 412 return; 413} 414 415void MeasureReqTabExit(struct rt_rtmp_adapter *pAd) 416{ 417 NdisFreeSpinLock(&pAd->CommonCfg.MeasureReqTabLock); 418 419 if (pAd->CommonCfg.pMeasureReqTab) 420 kfree(pAd->CommonCfg.pMeasureReqTab); 421 pAd->CommonCfg.pMeasureReqTab = NULL; 422 423 return; 424} 425 426struct rt_measure_req_entry *MeasureReqLookUp(struct rt_rtmp_adapter *pAd, u8 DialogToken) 427{ 428 u32 HashIdx; 429 struct rt_measure_req_tab *pTab = pAd->CommonCfg.pMeasureReqTab; 430 struct rt_measure_req_entry *pEntry = NULL; 431 struct rt_measure_req_entry *pPrevEntry = NULL; 432 433 if (pTab == NULL) { 434 DBGPRINT(RT_DEBUG_ERROR, 435 ("%s: pMeasureReqTab doesn't exist.\n", __func__)); 436 return NULL; 437 } 438 439 RTMP_SEM_LOCK(&pAd->CommonCfg.MeasureReqTabLock); 440 441 HashIdx = MQ_DIALOGTOKEN_HASH_INDEX(DialogToken); 442 pEntry = pTab->Hash[HashIdx]; 443 444 while (pEntry) { 445 if (pEntry->DialogToken == DialogToken) 446 break; 447 else { 448 pPrevEntry = pEntry; 449 pEntry = pEntry->pNext; 450 } 451 } 452 453 RTMP_SEM_UNLOCK(&pAd->CommonCfg.MeasureReqTabLock); 454 455 return pEntry; 456} 457 458struct rt_measure_req_entry *MeasureReqInsert(struct rt_rtmp_adapter *pAd, u8 DialogToken) 459{ 460 int i; 461 unsigned long HashIdx; 462 struct rt_measure_req_tab *pTab = pAd->CommonCfg.pMeasureReqTab; 463 struct rt_measure_req_entry *pEntry = NULL, *pCurrEntry; 464 unsigned long Now; 465 466 if (pTab == NULL) { 467 DBGPRINT(RT_DEBUG_ERROR, 468 ("%s: pMeasureReqTab doesn't exist.\n", __func__)); 469 return NULL; 470 } 471 472 pEntry = MeasureReqLookUp(pAd, DialogToken); 473 if (pEntry == NULL) { 474 RTMP_SEM_LOCK(&pAd->CommonCfg.MeasureReqTabLock); 475 for (i = 0; i < MAX_MEASURE_REQ_TAB_SIZE; i++) { 476 NdisGetSystemUpTime(&Now); 477 pEntry = &pTab->Content[i]; 478 479 if ((pEntry->Valid == TRUE) 480 && RTMP_TIME_AFTER((unsigned long)Now, 481 (unsigned long)(pEntry-> 482 lastTime + 483 MQ_REQ_AGE_OUT))) 484 { 485 struct rt_measure_req_entry *pPrevEntry = NULL; 486 unsigned long HashIdx = 487 MQ_DIALOGTOKEN_HASH_INDEX(pEntry-> 488 DialogToken); 489 struct rt_measure_req_entry *pProbeEntry = 490 pTab->Hash[HashIdx]; 491 492 /* update Hash list */ 493 do { 494 if (pProbeEntry == pEntry) { 495 if (pPrevEntry == NULL) { 496 pTab->Hash[HashIdx] = 497 pEntry->pNext; 498 } else { 499 pPrevEntry->pNext = 500 pEntry->pNext; 501 } 502 break; 503 } 504 505 pPrevEntry = pProbeEntry; 506 pProbeEntry = pProbeEntry->pNext; 507 } while (pProbeEntry); 508 509 NdisZeroMemory(pEntry, 510 sizeof(struct rt_measure_req_entry)); 511 pTab->Size--; 512 513 break; 514 } 515 516 if (pEntry->Valid == FALSE) 517 break; 518 } 519 520 if (i < MAX_MEASURE_REQ_TAB_SIZE) { 521 NdisGetSystemUpTime(&Now); 522 pEntry->lastTime = Now; 523 pEntry->Valid = TRUE; 524 pEntry->DialogToken = DialogToken; 525 pTab->Size++; 526 } else { 527 pEntry = NULL; 528 DBGPRINT(RT_DEBUG_ERROR, 529 ("%s: pMeasureReqTab tab full.\n", __func__)); 530 } 531 532 /* add this Neighbor entry into HASH table */ 533 if (pEntry) { 534 HashIdx = MQ_DIALOGTOKEN_HASH_INDEX(DialogToken); 535 if (pTab->Hash[HashIdx] == NULL) { 536 pTab->Hash[HashIdx] = pEntry; 537 } else { 538 pCurrEntry = pTab->Hash[HashIdx]; 539 while (pCurrEntry->pNext != NULL) 540 pCurrEntry = pCurrEntry->pNext; 541 pCurrEntry->pNext = pEntry; 542 } 543 } 544 545 RTMP_SEM_UNLOCK(&pAd->CommonCfg.MeasureReqTabLock); 546 } 547 548 return pEntry; 549} 550 551void MeasureReqDelete(struct rt_rtmp_adapter *pAd, u8 DialogToken) 552{ 553 struct rt_measure_req_tab *pTab = pAd->CommonCfg.pMeasureReqTab; 554 struct rt_measure_req_entry *pEntry = NULL; 555 556 if (pTab == NULL) { 557 DBGPRINT(RT_DEBUG_ERROR, 558 ("%s: pMeasureReqTab doesn't exist.\n", __func__)); 559 return; 560 } 561 /* if empty, return */ 562 if (pTab->Size == 0) { 563 DBGPRINT(RT_DEBUG_ERROR, ("pMeasureReqTab empty.\n")); 564 return; 565 } 566 567 pEntry = MeasureReqLookUp(pAd, DialogToken); 568 if (pEntry != NULL) { 569 struct rt_measure_req_entry *pPrevEntry = NULL; 570 unsigned long HashIdx = MQ_DIALOGTOKEN_HASH_INDEX(pEntry->DialogToken); 571 struct rt_measure_req_entry *pProbeEntry = pTab->Hash[HashIdx]; 572 573 RTMP_SEM_LOCK(&pAd->CommonCfg.MeasureReqTabLock); 574 /* update Hash list */ 575 do { 576 if (pProbeEntry == pEntry) { 577 if (pPrevEntry == NULL) { 578 pTab->Hash[HashIdx] = pEntry->pNext; 579 } else { 580 pPrevEntry->pNext = pEntry->pNext; 581 } 582 break; 583 } 584 585 pPrevEntry = pProbeEntry; 586 pProbeEntry = pProbeEntry->pNext; 587 } while (pProbeEntry); 588 589 NdisZeroMemory(pEntry, sizeof(struct rt_measure_req_entry)); 590 pTab->Size--; 591 592 RTMP_SEM_UNLOCK(&pAd->CommonCfg.MeasureReqTabLock); 593 } 594 595 return; 596} 597 598void TpcReqTabInit(struct rt_rtmp_adapter *pAd) 599{ 600 NdisAllocateSpinLock(&pAd->CommonCfg.TpcReqTabLock); 601 602 pAd->CommonCfg.pTpcReqTab = kmalloc(sizeof(struct rt_tpc_req_tab), GFP_ATOMIC); 603 if (pAd->CommonCfg.pTpcReqTab) 604 NdisZeroMemory(pAd->CommonCfg.pTpcReqTab, sizeof(struct rt_tpc_req_tab)); 605 else 606 DBGPRINT(RT_DEBUG_ERROR, 607 ("%s Fail to alloc memory for pAd->CommonCfg.pTpcReqTab.\n", 608 __func__)); 609 610 return; 611} 612 613void TpcReqTabExit(struct rt_rtmp_adapter *pAd) 614{ 615 NdisFreeSpinLock(&pAd->CommonCfg.TpcReqTabLock); 616 617 if (pAd->CommonCfg.pTpcReqTab) 618 kfree(pAd->CommonCfg.pTpcReqTab); 619 pAd->CommonCfg.pTpcReqTab = NULL; 620 621 return; 622} 623 624static struct rt_tpc_req_entry *TpcReqLookUp(struct rt_rtmp_adapter *pAd, u8 DialogToken) 625{ 626 u32 HashIdx; 627 struct rt_tpc_req_tab *pTab = pAd->CommonCfg.pTpcReqTab; 628 struct rt_tpc_req_entry *pEntry = NULL; 629 struct rt_tpc_req_entry *pPrevEntry = NULL; 630 631 if (pTab == NULL) { 632 DBGPRINT(RT_DEBUG_ERROR, 633 ("%s: pTpcReqTab doesn't exist.\n", __func__)); 634 return NULL; 635 } 636 637 RTMP_SEM_LOCK(&pAd->CommonCfg.TpcReqTabLock); 638 639 HashIdx = TPC_DIALOGTOKEN_HASH_INDEX(DialogToken); 640 pEntry = pTab->Hash[HashIdx]; 641 642 while (pEntry) { 643 if (pEntry->DialogToken == DialogToken) 644 break; 645 else { 646 pPrevEntry = pEntry; 647 pEntry = pEntry->pNext; 648 } 649 } 650 651 RTMP_SEM_UNLOCK(&pAd->CommonCfg.TpcReqTabLock); 652 653 return pEntry; 654} 655 656static struct rt_tpc_req_entry *TpcReqInsert(struct rt_rtmp_adapter *pAd, u8 DialogToken) 657{ 658 int i; 659 unsigned long HashIdx; 660 struct rt_tpc_req_tab *pTab = pAd->CommonCfg.pTpcReqTab; 661 struct rt_tpc_req_entry *pEntry = NULL, *pCurrEntry; 662 unsigned long Now; 663 664 if (pTab == NULL) { 665 DBGPRINT(RT_DEBUG_ERROR, 666 ("%s: pTpcReqTab doesn't exist.\n", __func__)); 667 return NULL; 668 } 669 670 pEntry = TpcReqLookUp(pAd, DialogToken); 671 if (pEntry == NULL) { 672 RTMP_SEM_LOCK(&pAd->CommonCfg.TpcReqTabLock); 673 for (i = 0; i < MAX_TPC_REQ_TAB_SIZE; i++) { 674 NdisGetSystemUpTime(&Now); 675 pEntry = &pTab->Content[i]; 676 677 if ((pEntry->Valid == TRUE) 678 && RTMP_TIME_AFTER((unsigned long)Now, 679 (unsigned long)(pEntry-> 680 lastTime + 681 TPC_REQ_AGE_OUT))) 682 { 683 struct rt_tpc_req_entry *pPrevEntry = NULL; 684 unsigned long HashIdx = 685 TPC_DIALOGTOKEN_HASH_INDEX(pEntry-> 686 DialogToken); 687 struct rt_tpc_req_entry *pProbeEntry = 688 pTab->Hash[HashIdx]; 689 690 /* update Hash list */ 691 do { 692 if (pProbeEntry == pEntry) { 693 if (pPrevEntry == NULL) { 694 pTab->Hash[HashIdx] = 695 pEntry->pNext; 696 } else { 697 pPrevEntry->pNext = 698 pEntry->pNext; 699 } 700 break; 701 } 702 703 pPrevEntry = pProbeEntry; 704 pProbeEntry = pProbeEntry->pNext; 705 } while (pProbeEntry); 706 707 NdisZeroMemory(pEntry, sizeof(struct rt_tpc_req_entry)); 708 pTab->Size--; 709 710 break; 711 } 712 713 if (pEntry->Valid == FALSE) 714 break; 715 } 716 717 if (i < MAX_TPC_REQ_TAB_SIZE) { 718 NdisGetSystemUpTime(&Now); 719 pEntry->lastTime = Now; 720 pEntry->Valid = TRUE; 721 pEntry->DialogToken = DialogToken; 722 pTab->Size++; 723 } else { 724 pEntry = NULL; 725 DBGPRINT(RT_DEBUG_ERROR, 726 ("%s: pTpcReqTab tab full.\n", __func__)); 727 } 728 729 /* add this Neighbor entry into HASH table */ 730 if (pEntry) { 731 HashIdx = TPC_DIALOGTOKEN_HASH_INDEX(DialogToken); 732 if (pTab->Hash[HashIdx] == NULL) { 733 pTab->Hash[HashIdx] = pEntry; 734 } else { 735 pCurrEntry = pTab->Hash[HashIdx]; 736 while (pCurrEntry->pNext != NULL) 737 pCurrEntry = pCurrEntry->pNext; 738 pCurrEntry->pNext = pEntry; 739 } 740 } 741 742 RTMP_SEM_UNLOCK(&pAd->CommonCfg.TpcReqTabLock); 743 } 744 745 return pEntry; 746} 747 748static void TpcReqDelete(struct rt_rtmp_adapter *pAd, u8 DialogToken) 749{ 750 struct rt_tpc_req_tab *pTab = pAd->CommonCfg.pTpcReqTab; 751 struct rt_tpc_req_entry *pEntry = NULL; 752 753 if (pTab == NULL) { 754 DBGPRINT(RT_DEBUG_ERROR, 755 ("%s: pTpcReqTab doesn't exist.\n", __func__)); 756 return; 757 } 758 /* if empty, return */ 759 if (pTab->Size == 0) { 760 DBGPRINT(RT_DEBUG_ERROR, ("pTpcReqTab empty.\n")); 761 return; 762 } 763 764 pEntry = TpcReqLookUp(pAd, DialogToken); 765 if (pEntry != NULL) { 766 struct rt_tpc_req_entry *pPrevEntry = NULL; 767 unsigned long HashIdx = TPC_DIALOGTOKEN_HASH_INDEX(pEntry->DialogToken); 768 struct rt_tpc_req_entry *pProbeEntry = pTab->Hash[HashIdx]; 769 770 RTMP_SEM_LOCK(&pAd->CommonCfg.TpcReqTabLock); 771 /* update Hash list */ 772 do { 773 if (pProbeEntry == pEntry) { 774 if (pPrevEntry == NULL) { 775 pTab->Hash[HashIdx] = pEntry->pNext; 776 } else { 777 pPrevEntry->pNext = pEntry->pNext; 778 } 779 break; 780 } 781 782 pPrevEntry = pProbeEntry; 783 pProbeEntry = pProbeEntry->pNext; 784 } while (pProbeEntry); 785 786 NdisZeroMemory(pEntry, sizeof(struct rt_tpc_req_entry)); 787 pTab->Size--; 788 789 RTMP_SEM_UNLOCK(&pAd->CommonCfg.TpcReqTabLock); 790 } 791 792 return; 793} 794 795/* 796 ========================================================================== 797 Description: 798 Get Current TimeS tamp. 799 800 Parametrs: 801 802 Return : Current Time Stamp. 803 ========================================================================== 804 */ 805static u64 GetCurrentTimeStamp(struct rt_rtmp_adapter *pAd) 806{ 807 /* get current time stamp. */ 808 return 0; 809} 810 811/* 812 ========================================================================== 813 Description: 814 Get Current Transmit Power. 815 816 Parametrs: 817 818 Return : Current Time Stamp. 819 ========================================================================== 820 */ 821static u8 GetCurTxPwr(struct rt_rtmp_adapter *pAd, u8 Wcid) 822{ 823 return 16; /* 16 dBm */ 824} 825 826/* 827 ========================================================================== 828 Description: 829 Get Current Transmit Power. 830 831 Parametrs: 832 833 Return : Current Time Stamp. 834 ========================================================================== 835 */ 836void InsertChannelRepIE(struct rt_rtmp_adapter *pAd, 837 u8 *pFrameBuf, 838 unsigned long *pFrameLen, 839 char *pCountry, u8 RegulatoryClass) 840{ 841 unsigned long TempLen; 842 u8 Len; 843 u8 IEId = IE_AP_CHANNEL_REPORT; 844 u8 *pChListPtr = NULL; 845 846 Len = 1; 847 if (strncmp(pCountry, "US", 2) == 0) { 848 if (RegulatoryClass >= USA_REGULATORY_INFO_SIZE) { 849 DBGPRINT(RT_DEBUG_ERROR, 850 ("%s: USA Unknow Requlatory class (%d)\n", 851 __func__, RegulatoryClass)); 852 return; 853 } 854 855 Len += 856 USARegulatoryInfo[RegulatoryClass].ChannelSet. 857 NumberOfChannels; 858 pChListPtr = 859 USARegulatoryInfo[RegulatoryClass].ChannelSet.ChannelList; 860 } else if (strncmp(pCountry, "JP", 2) == 0) { 861 if (RegulatoryClass >= JP_REGULATORY_INFO_SIZE) { 862 DBGPRINT(RT_DEBUG_ERROR, 863 ("%s: JP Unknow Requlatory class (%d)\n", 864 __func__, RegulatoryClass)); 865 return; 866 } 867 868 Len += 869 JapanRegulatoryInfo[RegulatoryClass].ChannelSet. 870 NumberOfChannels; 871 pChListPtr = 872 JapanRegulatoryInfo[RegulatoryClass].ChannelSet.ChannelList; 873 } else { 874 DBGPRINT(RT_DEBUG_ERROR, ("%s: Unknow Country (%s)\n", 875 __func__, pCountry)); 876 return; 877 } 878 879 MakeOutgoingFrame(pFrameBuf, &TempLen, 880 1, &IEId, 881 1, &Len, 882 1, &RegulatoryClass, 883 Len - 1, pChListPtr, END_OF_ARGS); 884 885 *pFrameLen = *pFrameLen + TempLen; 886 887 return; 888} 889 890/* 891 ========================================================================== 892 Description: 893 Insert Dialog Token into frame. 894 895 Parametrs: 896 1. frame buffer pointer. 897 2. frame length. 898 3. Dialog token. 899 900 Return : None. 901 ========================================================================== 902 */ 903void InsertDialogToken(struct rt_rtmp_adapter *pAd, 904 u8 *pFrameBuf, 905 unsigned long *pFrameLen, u8 DialogToken) 906{ 907 unsigned long TempLen; 908 MakeOutgoingFrame(pFrameBuf, &TempLen, 1, &DialogToken, END_OF_ARGS); 909 910 *pFrameLen = *pFrameLen + TempLen; 911 912 return; 913} 914 915/* 916 ========================================================================== 917 Description: 918 Insert TPC Request IE into frame. 919 920 Parametrs: 921 1. frame buffer pointer. 922 2. frame length. 923 924 Return : None. 925 ========================================================================== 926 */ 927static void InsertTpcReqIE(struct rt_rtmp_adapter *pAd, 928 u8 *pFrameBuf, unsigned long *pFrameLen) 929{ 930 unsigned long TempLen; 931 unsigned long Len = 0; 932 u8 ElementID = IE_TPC_REQUEST; 933 934 MakeOutgoingFrame(pFrameBuf, &TempLen, 935 1, &ElementID, 1, &Len, END_OF_ARGS); 936 937 *pFrameLen = *pFrameLen + TempLen; 938 939 return; 940} 941 942/* 943 ========================================================================== 944 Description: 945 Insert TPC Report IE into frame. 946 947 Parametrs: 948 1. frame buffer pointer. 949 2. frame length. 950 3. Transmit Power. 951 4. Link Margin. 952 953 Return : None. 954 ========================================================================== 955 */ 956void InsertTpcReportIE(struct rt_rtmp_adapter *pAd, 957 u8 *pFrameBuf, 958 unsigned long *pFrameLen, 959 u8 TxPwr, u8 LinkMargin) 960{ 961 unsigned long TempLen; 962 unsigned long Len = sizeof(struct rt_tpc_report_info); 963 u8 ElementID = IE_TPC_REPORT; 964 struct rt_tpc_report_info TpcReportIE; 965 966 TpcReportIE.TxPwr = TxPwr; 967 TpcReportIE.LinkMargin = LinkMargin; 968 969 MakeOutgoingFrame(pFrameBuf, &TempLen, 970 1, &ElementID, 971 1, &Len, Len, &TpcReportIE, END_OF_ARGS); 972 973 *pFrameLen = *pFrameLen + TempLen; 974 975 return; 976} 977 978/* 979 ========================================================================== 980 Description: 981 Insert Channel Switch Announcement IE into frame. 982 983 Parametrs: 984 1. frame buffer pointer. 985 2. frame length. 986 3. channel switch announcement mode. 987 4. new selected channel. 988 5. channel switch announcement count. 989 990 Return : None. 991 ========================================================================== 992 */ 993static void InsertChSwAnnIE(struct rt_rtmp_adapter *pAd, 994 u8 *pFrameBuf, 995 unsigned long *pFrameLen, 996 u8 ChSwMode, 997 u8 NewChannel, u8 ChSwCnt) 998{ 999 unsigned long TempLen; 1000 unsigned long Len = sizeof(struct rt_ch_sw_ann_info); 1001 u8 ElementID = IE_CHANNEL_SWITCH_ANNOUNCEMENT; 1002 struct rt_ch_sw_ann_info ChSwAnnIE; 1003 1004 ChSwAnnIE.ChSwMode = ChSwMode; 1005 ChSwAnnIE.Channel = NewChannel; 1006 ChSwAnnIE.ChSwCnt = ChSwCnt; 1007 1008 MakeOutgoingFrame(pFrameBuf, &TempLen, 1009 1, &ElementID, 1, &Len, Len, &ChSwAnnIE, END_OF_ARGS); 1010 1011 *pFrameLen = *pFrameLen + TempLen; 1012 1013 return; 1014} 1015 1016/* 1017 ========================================================================== 1018 Description: 1019 Insert Measure Request IE into frame. 1020 1021 Parametrs: 1022 1. frame buffer pointer. 1023 2. frame length. 1024 3. Measure Token. 1025 4. Measure Request Mode. 1026 5. Measure Request Type. 1027 6. Measure Channel. 1028 7. Measure Start time. 1029 8. Measure Duration. 1030 1031 Return : None. 1032 ========================================================================== 1033 */ 1034static void InsertMeasureReqIE(struct rt_rtmp_adapter *pAd, 1035 u8 *pFrameBuf, 1036 unsigned long *pFrameLen, 1037 u8 Len, struct rt_measure_req_info * pMeasureReqIE) 1038{ 1039 unsigned long TempLen; 1040 u8 ElementID = IE_MEASUREMENT_REQUEST; 1041 1042 MakeOutgoingFrame(pFrameBuf, &TempLen, 1043 1, &ElementID, 1044 1, &Len, 1045 sizeof(struct rt_measure_req_info), pMeasureReqIE, END_OF_ARGS); 1046 1047 *pFrameLen = *pFrameLen + TempLen; 1048 1049 return; 1050} 1051 1052/* 1053 ========================================================================== 1054 Description: 1055 Insert Measure Report IE into frame. 1056 1057 Parametrs: 1058 1. frame buffer pointer. 1059 2. frame length. 1060 3. Measure Token. 1061 4. Measure Request Mode. 1062 5. Measure Request Type. 1063 6. Length of Report Infomation 1064 7. Pointer of Report Infomation Buffer. 1065 1066 Return : None. 1067 ========================================================================== 1068 */ 1069static void InsertMeasureReportIE(struct rt_rtmp_adapter *pAd, 1070 u8 *pFrameBuf, 1071 unsigned long *pFrameLen, 1072 struct rt_measure_report_info * pMeasureReportIE, 1073 u8 ReportLnfoLen, u8 *pReportInfo) 1074{ 1075 unsigned long TempLen; 1076 unsigned long Len; 1077 u8 ElementID = IE_MEASUREMENT_REPORT; 1078 1079 Len = sizeof(struct rt_measure_report_info) + ReportLnfoLen; 1080 1081 MakeOutgoingFrame(pFrameBuf, &TempLen, 1082 1, &ElementID, 1083 1, &Len, Len, pMeasureReportIE, END_OF_ARGS); 1084 1085 *pFrameLen = *pFrameLen + TempLen; 1086 1087 if ((ReportLnfoLen > 0) && (pReportInfo != NULL)) { 1088 MakeOutgoingFrame(pFrameBuf + *pFrameLen, &TempLen, 1089 ReportLnfoLen, pReportInfo, END_OF_ARGS); 1090 1091 *pFrameLen = *pFrameLen + TempLen; 1092 } 1093 return; 1094} 1095 1096/* 1097 ========================================================================== 1098 Description: 1099 Prepare Measurement request action frame and enqueue it into 1100 management queue waiting for transmition. 1101 1102 Parametrs: 1103 1. the destination mac address of the frame. 1104 1105 Return : None. 1106 ========================================================================== 1107 */ 1108void MakeMeasurementReqFrame(struct rt_rtmp_adapter *pAd, 1109 u8 *pOutBuffer, 1110 unsigned long *pFrameLen, 1111 u8 TotalLen, 1112 u8 Category, 1113 u8 Action, 1114 u8 MeasureToken, 1115 u8 MeasureReqMode, 1116 u8 MeasureReqType, u8 NumOfRepetitions) 1117{ 1118 unsigned long TempLen; 1119 struct rt_measure_req_info MeasureReqIE; 1120 1121 InsertActField(pAd, (pOutBuffer + *pFrameLen), pFrameLen, Category, 1122 Action); 1123 1124 /* fill Dialog Token */ 1125 InsertDialogToken(pAd, (pOutBuffer + *pFrameLen), pFrameLen, 1126 MeasureToken); 1127 1128 /* fill Number of repetitions. */ 1129 if (Category == CATEGORY_RM) { 1130 MakeOutgoingFrame((pOutBuffer + *pFrameLen), &TempLen, 1131 2, &NumOfRepetitions, END_OF_ARGS); 1132 1133 *pFrameLen += TempLen; 1134 } 1135 /* prepare Measurement IE. */ 1136 NdisZeroMemory(&MeasureReqIE, sizeof(struct rt_measure_req_info)); 1137 MeasureReqIE.Token = MeasureToken; 1138 MeasureReqIE.ReqMode.word = MeasureReqMode; 1139 MeasureReqIE.ReqType = MeasureReqType; 1140 InsertMeasureReqIE(pAd, (pOutBuffer + *pFrameLen), pFrameLen, 1141 TotalLen, &MeasureReqIE); 1142 1143 return; 1144} 1145 1146/* 1147 ========================================================================== 1148 Description: 1149 Prepare Measurement report action frame and enqueue it into 1150 management queue waiting for transmition. 1151 1152 Parametrs: 1153 1. the destination mac address of the frame. 1154 1155 Return : None. 1156 ========================================================================== 1157 */ 1158void EnqueueMeasurementRep(struct rt_rtmp_adapter *pAd, 1159 u8 *pDA, 1160 u8 DialogToken, 1161 u8 MeasureToken, 1162 u8 MeasureReqMode, 1163 u8 MeasureReqType, 1164 u8 ReportInfoLen, u8 *pReportInfo) 1165{ 1166 u8 *pOutBuffer = NULL; 1167 int NStatus; 1168 unsigned long FrameLen; 1169 struct rt_header_802_11 ActHdr; 1170 struct rt_measure_report_info MeasureRepIE; 1171 1172 /* build action frame header. */ 1173 MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA, 1174 pAd->CurrentAddress); 1175 1176 NStatus = MlmeAllocateMemory(pAd, (void *)& pOutBuffer); /*Get an unused nonpaged memory */ 1177 if (NStatus != NDIS_STATUS_SUCCESS) { 1178 DBGPRINT(RT_DEBUG_TRACE, 1179 ("%s() allocate memory failed \n", __func__)); 1180 return; 1181 } 1182 NdisMoveMemory(pOutBuffer, (char *)& ActHdr, sizeof(struct rt_header_802_11)); 1183 FrameLen = sizeof(struct rt_header_802_11); 1184 1185 InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, 1186 CATEGORY_SPECTRUM, SPEC_MRP); 1187 1188 /* fill Dialog Token */ 1189 InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, DialogToken); 1190 1191 /* prepare Measurement IE. */ 1192 NdisZeroMemory(&MeasureRepIE, sizeof(struct rt_measure_report_info)); 1193 MeasureRepIE.Token = MeasureToken; 1194 MeasureRepIE.ReportMode = MeasureReqMode; 1195 MeasureRepIE.ReportType = MeasureReqType; 1196 InsertMeasureReportIE(pAd, (pOutBuffer + FrameLen), &FrameLen, 1197 &MeasureRepIE, ReportInfoLen, pReportInfo); 1198 1199 MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); 1200 MlmeFreeMemory(pAd, pOutBuffer); 1201 1202 return; 1203} 1204 1205/* 1206 ========================================================================== 1207 Description: 1208 Prepare TPC Request action frame and enqueue it into 1209 management queue waiting for transmition. 1210 1211 Parametrs: 1212 1. the destination mac address of the frame. 1213 1214 Return : None. 1215 ========================================================================== 1216 */ 1217void EnqueueTPCReq(struct rt_rtmp_adapter *pAd, u8 *pDA, u8 DialogToken) 1218{ 1219 u8 *pOutBuffer = NULL; 1220 int NStatus; 1221 unsigned long FrameLen; 1222 1223 struct rt_header_802_11 ActHdr; 1224 1225 /* build action frame header. */ 1226 MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA, 1227 pAd->CurrentAddress); 1228 1229 NStatus = MlmeAllocateMemory(pAd, (void *)& pOutBuffer); /*Get an unused nonpaged memory */ 1230 if (NStatus != NDIS_STATUS_SUCCESS) { 1231 DBGPRINT(RT_DEBUG_TRACE, 1232 ("%s() allocate memory failed \n", __func__)); 1233 return; 1234 } 1235 NdisMoveMemory(pOutBuffer, (char *)& ActHdr, sizeof(struct rt_header_802_11)); 1236 FrameLen = sizeof(struct rt_header_802_11); 1237 1238 InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, 1239 CATEGORY_SPECTRUM, SPEC_TPCRQ); 1240 1241 /* fill Dialog Token */ 1242 InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, DialogToken); 1243 1244 /* Insert TPC Request IE. */ 1245 InsertTpcReqIE(pAd, (pOutBuffer + FrameLen), &FrameLen); 1246 1247 MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); 1248 MlmeFreeMemory(pAd, pOutBuffer); 1249 1250 return; 1251} 1252 1253/* 1254 ========================================================================== 1255 Description: 1256 Prepare TPC Report action frame and enqueue it into 1257 management queue waiting for transmition. 1258 1259 Parametrs: 1260 1. the destination mac address of the frame. 1261 1262 Return : None. 1263 ========================================================================== 1264 */ 1265void EnqueueTPCRep(struct rt_rtmp_adapter *pAd, 1266 u8 *pDA, 1267 u8 DialogToken, u8 TxPwr, u8 LinkMargin) 1268{ 1269 u8 *pOutBuffer = NULL; 1270 int NStatus; 1271 unsigned long FrameLen; 1272 1273 struct rt_header_802_11 ActHdr; 1274 1275 /* build action frame header. */ 1276 MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA, 1277 pAd->CurrentAddress); 1278 1279 NStatus = MlmeAllocateMemory(pAd, (void *)& pOutBuffer); /*Get an unused nonpaged memory */ 1280 if (NStatus != NDIS_STATUS_SUCCESS) { 1281 DBGPRINT(RT_DEBUG_TRACE, 1282 ("%s() allocate memory failed \n", __func__)); 1283 return; 1284 } 1285 NdisMoveMemory(pOutBuffer, (char *)& ActHdr, sizeof(struct rt_header_802_11)); 1286 FrameLen = sizeof(struct rt_header_802_11); 1287 1288 InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, 1289 CATEGORY_SPECTRUM, SPEC_TPCRP); 1290 1291 /* fill Dialog Token */ 1292 InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, DialogToken); 1293 1294 /* Insert TPC Request IE. */ 1295 InsertTpcReportIE(pAd, (pOutBuffer + FrameLen), &FrameLen, TxPwr, 1296 LinkMargin); 1297 1298 MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); 1299 MlmeFreeMemory(pAd, pOutBuffer); 1300 1301 return; 1302} 1303 1304/* 1305 ========================================================================== 1306 Description: 1307 Prepare Channel Switch Announcement action frame and enqueue it into 1308 management queue waiting for transmition. 1309 1310 Parametrs: 1311 1. the destination mac address of the frame. 1312 2. Channel switch announcement mode. 1313 2. a New selected channel. 1314 1315 Return : None. 1316 ========================================================================== 1317 */ 1318void EnqueueChSwAnn(struct rt_rtmp_adapter *pAd, 1319 u8 *pDA, u8 ChSwMode, u8 NewCh) 1320{ 1321 u8 *pOutBuffer = NULL; 1322 int NStatus; 1323 unsigned long FrameLen; 1324 1325 struct rt_header_802_11 ActHdr; 1326 1327 /* build action frame header. */ 1328 MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA, 1329 pAd->CurrentAddress); 1330 1331 NStatus = MlmeAllocateMemory(pAd, (void *)& pOutBuffer); /*Get an unused nonpaged memory */ 1332 if (NStatus != NDIS_STATUS_SUCCESS) { 1333 DBGPRINT(RT_DEBUG_TRACE, 1334 ("%s() allocate memory failed \n", __func__)); 1335 return; 1336 } 1337 NdisMoveMemory(pOutBuffer, (char *)& ActHdr, sizeof(struct rt_header_802_11)); 1338 FrameLen = sizeof(struct rt_header_802_11); 1339 1340 InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, 1341 CATEGORY_SPECTRUM, SPEC_CHANNEL_SWITCH); 1342 1343 InsertChSwAnnIE(pAd, (pOutBuffer + FrameLen), &FrameLen, ChSwMode, 1344 NewCh, 0); 1345 1346 MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); 1347 MlmeFreeMemory(pAd, pOutBuffer); 1348 1349 return; 1350} 1351 1352static BOOLEAN DfsRequirementCheck(struct rt_rtmp_adapter *pAd, u8 Channel) 1353{ 1354 BOOLEAN Result = FALSE; 1355 int i; 1356 1357 do { 1358 /* check DFS procedure is running. */ 1359 /* make sure DFS procedure won't start twice. */ 1360 if (pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE) { 1361 Result = FALSE; 1362 break; 1363 } 1364 /* check the new channel carried from Channel Switch Announcemnet is valid. */ 1365 for (i = 0; i < pAd->ChannelListNum; i++) { 1366 if ((Channel == pAd->ChannelList[i].Channel) 1367 && (pAd->ChannelList[i].RemainingTimeForUse == 0)) { 1368 /* found radar signal in the channel. the channel can't use at least for 30 minutes. */ 1369 pAd->ChannelList[i].RemainingTimeForUse = 1800; /*30 min = 1800 sec */ 1370 Result = TRUE; 1371 break; 1372 } 1373 } 1374 } while (FALSE); 1375 1376 return Result; 1377} 1378 1379void NotifyChSwAnnToPeerAPs(struct rt_rtmp_adapter *pAd, 1380 u8 *pRA, 1381 u8 *pTA, u8 ChSwMode, u8 Channel) 1382{ 1383} 1384 1385static void StartDFSProcedure(struct rt_rtmp_adapter *pAd, 1386 u8 Channel, u8 ChSwMode) 1387{ 1388 /* start DFS procedure */ 1389 pAd->CommonCfg.Channel = Channel; 1390 1391 N_ChannelCheck(pAd); 1392 1393 pAd->CommonCfg.RadarDetect.RDMode = RD_SWITCHING_MODE; 1394 pAd->CommonCfg.RadarDetect.CSCount = 0; 1395} 1396 1397/* 1398 ========================================================================== 1399 Description: 1400 Channel Switch Announcement action frame sanity check. 1401 1402 Parametrs: 1403 1. MLME message containing the received frame 1404 2. message length. 1405 3. Channel switch announcement infomation buffer. 1406 1407 Return : None. 1408 ========================================================================== 1409 */ 1410 1411/* 1412 Channel Switch Announcement IE. 1413 +----+-----+-----------+------------+-----------+ 1414 | ID | Len |Ch Sw Mode | New Ch Num | Ch Sw Cnt | 1415 +----+-----+-----------+------------+-----------+ 1416 1 1 1 1 1 1417*/ 1418static BOOLEAN PeerChSwAnnSanity(struct rt_rtmp_adapter *pAd, 1419 void * pMsg, 1420 unsigned long MsgLen, 1421 struct rt_ch_sw_ann_info * pChSwAnnInfo) 1422{ 1423 struct rt_frame_802_11 * Fr = (struct rt_frame_802_11 *) pMsg; 1424 u8 *pFramePtr = Fr->Octet; 1425 BOOLEAN result = FALSE; 1426 struct rt_eid * eid_ptr; 1427 1428 /* skip 802.11 header. */ 1429 MsgLen -= sizeof(struct rt_header_802_11); 1430 1431 /* skip category and action code. */ 1432 pFramePtr += 2; 1433 MsgLen -= 2; 1434 1435 if (pChSwAnnInfo == NULL) 1436 return result; 1437 1438 eid_ptr = (struct rt_eid *) pFramePtr; 1439 while (((u8 *) eid_ptr + eid_ptr->Len + 1) < 1440 ((u8 *)pFramePtr + MsgLen)) { 1441 switch (eid_ptr->Eid) { 1442 case IE_CHANNEL_SWITCH_ANNOUNCEMENT: 1443 NdisMoveMemory(&pChSwAnnInfo->ChSwMode, eid_ptr->Octet, 1444 1); 1445 NdisMoveMemory(&pChSwAnnInfo->Channel, 1446 eid_ptr->Octet + 1, 1); 1447 NdisMoveMemory(&pChSwAnnInfo->ChSwCnt, 1448 eid_ptr->Octet + 2, 1); 1449 1450 result = TRUE; 1451 break; 1452 1453 default: 1454 break; 1455 } 1456 eid_ptr = (struct rt_eid *) ((u8 *) eid_ptr + 2 + eid_ptr->Len); 1457 } 1458 1459 return result; 1460} 1461 1462/* 1463 ========================================================================== 1464 Description: 1465 Measurement request action frame sanity check. 1466 1467 Parametrs: 1468 1. MLME message containing the received frame 1469 2. message length. 1470 3. Measurement request infomation buffer. 1471 1472 Return : None. 1473 ========================================================================== 1474 */ 1475static BOOLEAN PeerMeasureReqSanity(struct rt_rtmp_adapter *pAd, 1476 void * pMsg, 1477 unsigned long MsgLen, 1478 u8 *pDialogToken, 1479 struct rt_measure_req_info * pMeasureReqInfo, 1480 struct rt_measure_req * pMeasureReq) 1481{ 1482 struct rt_frame_802_11 * Fr = (struct rt_frame_802_11 *) pMsg; 1483 u8 *pFramePtr = Fr->Octet; 1484 BOOLEAN result = FALSE; 1485 struct rt_eid * eid_ptr; 1486 u8 *ptr; 1487 u64 MeasureStartTime; 1488 u16 MeasureDuration; 1489 1490 /* skip 802.11 header. */ 1491 MsgLen -= sizeof(struct rt_header_802_11); 1492 1493 /* skip category and action code. */ 1494 pFramePtr += 2; 1495 MsgLen -= 2; 1496 1497 if (pMeasureReqInfo == NULL) 1498 return result; 1499 1500 NdisMoveMemory(pDialogToken, pFramePtr, 1); 1501 pFramePtr += 1; 1502 MsgLen -= 1; 1503 1504 eid_ptr = (struct rt_eid *) pFramePtr; 1505 while (((u8 *) eid_ptr + eid_ptr->Len + 1) < 1506 ((u8 *)pFramePtr + MsgLen)) { 1507 switch (eid_ptr->Eid) { 1508 case IE_MEASUREMENT_REQUEST: 1509 NdisMoveMemory(&pMeasureReqInfo->Token, eid_ptr->Octet, 1510 1); 1511 NdisMoveMemory(&pMeasureReqInfo->ReqMode.word, 1512 eid_ptr->Octet + 1, 1); 1513 NdisMoveMemory(&pMeasureReqInfo->ReqType, 1514 eid_ptr->Octet + 2, 1); 1515 ptr = (u8 *)(eid_ptr->Octet + 3); 1516 NdisMoveMemory(&pMeasureReq->ChNum, ptr, 1); 1517 NdisMoveMemory(&MeasureStartTime, ptr + 1, 8); 1518 pMeasureReq->MeasureStartTime = 1519 SWAP64(MeasureStartTime); 1520 NdisMoveMemory(&MeasureDuration, ptr + 9, 2); 1521 pMeasureReq->MeasureDuration = SWAP16(MeasureDuration); 1522 1523 result = TRUE; 1524 break; 1525 1526 default: 1527 break; 1528 } 1529 eid_ptr = (struct rt_eid *) ((u8 *) eid_ptr + 2 + eid_ptr->Len); 1530 } 1531 1532 return result; 1533} 1534 1535/* 1536 ========================================================================== 1537 Description: 1538 Measurement report action frame sanity check. 1539 1540 Parametrs: 1541 1. MLME message containing the received frame 1542 2. message length. 1543 3. Measurement report infomation buffer. 1544 4. basic report infomation buffer. 1545 1546 Return : None. 1547 ========================================================================== 1548 */ 1549 1550/* 1551 Measurement Report IE. 1552 +----+-----+-------+-------------+--------------+----------------+ 1553 | ID | Len | Token | Report Mode | Measure Type | Measure Report | 1554 +----+-----+-------+-------------+--------------+----------------+ 1555 1 1 1 1 1 variable 1556 1557 Basic Report. 1558 +--------+------------+----------+-----+ 1559 | Ch Num | Start Time | Duration | Map | 1560 +--------+------------+----------+-----+ 1561 1 8 2 1 1562 1563 Map Field Bit Format. 1564 +-----+---------------+---------------------+-------+------------+----------+ 1565 | Bss | OFDM Preamble | Unidentified signal | Radar | Unmeasured | Reserved | 1566 +-----+---------------+---------------------+-------+------------+----------+ 1567 0 1 2 3 4 5-7 1568*/ 1569static BOOLEAN PeerMeasureReportSanity(struct rt_rtmp_adapter *pAd, 1570 void * pMsg, 1571 unsigned long MsgLen, 1572 u8 *pDialogToken, 1573 struct rt_measure_report_info * 1574 pMeasureReportInfo, 1575 u8 *pReportBuf) 1576{ 1577 struct rt_frame_802_11 * Fr = (struct rt_frame_802_11 *) pMsg; 1578 u8 *pFramePtr = Fr->Octet; 1579 BOOLEAN result = FALSE; 1580 struct rt_eid * eid_ptr; 1581 u8 *ptr; 1582 1583 /* skip 802.11 header. */ 1584 MsgLen -= sizeof(struct rt_header_802_11); 1585 1586 /* skip category and action code. */ 1587 pFramePtr += 2; 1588 MsgLen -= 2; 1589 1590 if (pMeasureReportInfo == NULL) 1591 return result; 1592 1593 NdisMoveMemory(pDialogToken, pFramePtr, 1); 1594 pFramePtr += 1; 1595 MsgLen -= 1; 1596 1597 eid_ptr = (struct rt_eid *) pFramePtr; 1598 while (((u8 *) eid_ptr + eid_ptr->Len + 1) < 1599 ((u8 *)pFramePtr + MsgLen)) { 1600 switch (eid_ptr->Eid) { 1601 case IE_MEASUREMENT_REPORT: 1602 NdisMoveMemory(&pMeasureReportInfo->Token, 1603 eid_ptr->Octet, 1); 1604 NdisMoveMemory(&pMeasureReportInfo->ReportMode, 1605 eid_ptr->Octet + 1, 1); 1606 NdisMoveMemory(&pMeasureReportInfo->ReportType, 1607 eid_ptr->Octet + 2, 1); 1608 if (pMeasureReportInfo->ReportType == RM_BASIC) { 1609 struct rt_measure_basic_report * pReport = 1610 (struct rt_measure_basic_report *) pReportBuf; 1611 ptr = (u8 *)(eid_ptr->Octet + 3); 1612 NdisMoveMemory(&pReport->ChNum, ptr, 1); 1613 NdisMoveMemory(&pReport->MeasureStartTime, 1614 ptr + 1, 8); 1615 NdisMoveMemory(&pReport->MeasureDuration, 1616 ptr + 9, 2); 1617 NdisMoveMemory(&pReport->Map, ptr + 11, 1); 1618 1619 } else if (pMeasureReportInfo->ReportType == RM_CCA) { 1620 struct rt_measure_cca_report * pReport = 1621 (struct rt_measure_cca_report *) pReportBuf; 1622 ptr = (u8 *)(eid_ptr->Octet + 3); 1623 NdisMoveMemory(&pReport->ChNum, ptr, 1); 1624 NdisMoveMemory(&pReport->MeasureStartTime, 1625 ptr + 1, 8); 1626 NdisMoveMemory(&pReport->MeasureDuration, 1627 ptr + 9, 2); 1628 NdisMoveMemory(&pReport->CCA_Busy_Fraction, 1629 ptr + 11, 1); 1630 1631 } else if (pMeasureReportInfo->ReportType == 1632 RM_RPI_HISTOGRAM) { 1633 struct rt_measure_rpi_report * pReport = 1634 (struct rt_measure_rpi_report *) pReportBuf; 1635 ptr = (u8 *)(eid_ptr->Octet + 3); 1636 NdisMoveMemory(&pReport->ChNum, ptr, 1); 1637 NdisMoveMemory(&pReport->MeasureStartTime, 1638 ptr + 1, 8); 1639 NdisMoveMemory(&pReport->MeasureDuration, 1640 ptr + 9, 2); 1641 NdisMoveMemory(&pReport->RPI_Density, ptr + 11, 1642 8); 1643 } 1644 result = TRUE; 1645 break; 1646 1647 default: 1648 break; 1649 } 1650 eid_ptr = (struct rt_eid *) ((u8 *) eid_ptr + 2 + eid_ptr->Len); 1651 } 1652 1653 return result; 1654} 1655 1656/* 1657 ========================================================================== 1658 Description: 1659 TPC Request action frame sanity check. 1660 1661 Parametrs: 1662 1. MLME message containing the received frame 1663 2. message length. 1664 3. Dialog Token. 1665 1666 Return : None. 1667 ========================================================================== 1668 */ 1669static BOOLEAN PeerTpcReqSanity(struct rt_rtmp_adapter *pAd, 1670 void * pMsg, 1671 unsigned long MsgLen, u8 *pDialogToken) 1672{ 1673 struct rt_frame_802_11 * Fr = (struct rt_frame_802_11 *) pMsg; 1674 u8 *pFramePtr = Fr->Octet; 1675 BOOLEAN result = FALSE; 1676 struct rt_eid * eid_ptr; 1677 1678 MsgLen -= sizeof(struct rt_header_802_11); 1679 1680 /* skip category and action code. */ 1681 pFramePtr += 2; 1682 MsgLen -= 2; 1683 1684 if (pDialogToken == NULL) 1685 return result; 1686 1687 NdisMoveMemory(pDialogToken, pFramePtr, 1); 1688 pFramePtr += 1; 1689 MsgLen -= 1; 1690 1691 eid_ptr = (struct rt_eid *) pFramePtr; 1692 while (((u8 *) eid_ptr + eid_ptr->Len + 1) < 1693 ((u8 *)pFramePtr + MsgLen)) { 1694 switch (eid_ptr->Eid) { 1695 case IE_TPC_REQUEST: 1696 result = TRUE; 1697 break; 1698 1699 default: 1700 break; 1701 } 1702 eid_ptr = (struct rt_eid *) ((u8 *) eid_ptr + 2 + eid_ptr->Len); 1703 } 1704 1705 return result; 1706} 1707 1708/* 1709 ========================================================================== 1710 Description: 1711 TPC Report action frame sanity check. 1712 1713 Parametrs: 1714 1. MLME message containing the received frame 1715 2. message length. 1716 3. Dialog Token. 1717 4. TPC Report IE. 1718 1719 Return : None. 1720 ========================================================================== 1721 */ 1722static BOOLEAN PeerTpcRepSanity(struct rt_rtmp_adapter *pAd, 1723 void * pMsg, 1724 unsigned long MsgLen, 1725 u8 *pDialogToken, 1726 struct rt_tpc_report_info * pTpcRepInfo) 1727{ 1728 struct rt_frame_802_11 * Fr = (struct rt_frame_802_11 *) pMsg; 1729 u8 *pFramePtr = Fr->Octet; 1730 BOOLEAN result = FALSE; 1731 struct rt_eid * eid_ptr; 1732 1733 MsgLen -= sizeof(struct rt_header_802_11); 1734 1735 /* skip category and action code. */ 1736 pFramePtr += 2; 1737 MsgLen -= 2; 1738 1739 if (pDialogToken == NULL) 1740 return result; 1741 1742 NdisMoveMemory(pDialogToken, pFramePtr, 1); 1743 pFramePtr += 1; 1744 MsgLen -= 1; 1745 1746 eid_ptr = (struct rt_eid *) pFramePtr; 1747 while (((u8 *) eid_ptr + eid_ptr->Len + 1) < 1748 ((u8 *)pFramePtr + MsgLen)) { 1749 switch (eid_ptr->Eid) { 1750 case IE_TPC_REPORT: 1751 NdisMoveMemory(&pTpcRepInfo->TxPwr, eid_ptr->Octet, 1); 1752 NdisMoveMemory(&pTpcRepInfo->LinkMargin, 1753 eid_ptr->Octet + 1, 1); 1754 result = TRUE; 1755 break; 1756 1757 default: 1758 break; 1759 } 1760 eid_ptr = (struct rt_eid *) ((u8 *) eid_ptr + 2 + eid_ptr->Len); 1761 } 1762 1763 return result; 1764} 1765 1766/* 1767 ========================================================================== 1768 Description: 1769 Channel Switch Announcement action frame handler. 1770 1771 Parametrs: 1772 Elme - MLME message containing the received frame 1773 1774 Return : None. 1775 ========================================================================== 1776 */ 1777static void PeerChSwAnnAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) 1778{ 1779 struct rt_ch_sw_ann_info ChSwAnnInfo; 1780 struct rt_frame_802_11 * pFr = (struct rt_frame_802_11 *) Elem->Msg; 1781 u8 index = 0, Channel = 0, NewChannel = 0; 1782 unsigned long Bssidx = 0; 1783 1784 NdisZeroMemory(&ChSwAnnInfo, sizeof(struct rt_ch_sw_ann_info)); 1785 if (!PeerChSwAnnSanity(pAd, Elem->Msg, Elem->MsgLen, &ChSwAnnInfo)) { 1786 DBGPRINT(RT_DEBUG_TRACE, 1787 ("Invalid Channel Switch Action Frame.\n")); 1788 return; 1789 } 1790 1791 if (pAd->OpMode == OPMODE_STA) { 1792 Bssidx = 1793 BssTableSearch(&pAd->ScanTab, pFr->Hdr.Addr3, 1794 pAd->CommonCfg.Channel); 1795 if (Bssidx == BSS_NOT_FOUND) { 1796 DBGPRINT(RT_DEBUG_TRACE, 1797 ("PeerChSwAnnAction - Bssidx is not found\n")); 1798 return; 1799 } 1800 1801 DBGPRINT(RT_DEBUG_TRACE, 1802 ("\n****Bssidx is %d, Channel = %d\n", index, 1803 pAd->ScanTab.BssEntry[Bssidx].Channel)); 1804 hex_dump("SSID", pAd->ScanTab.BssEntry[Bssidx].Bssid, 6); 1805 1806 Channel = pAd->CommonCfg.Channel; 1807 NewChannel = ChSwAnnInfo.Channel; 1808 1809 if ((pAd->CommonCfg.bIEEE80211H == 1) && (NewChannel != 0) 1810 && (Channel != NewChannel)) { 1811 /* Switching to channel 1 can prevent from rescanning the current channel immediately (by auto reconnection). */ 1812 /* In addition, clear the MLME queue and the scan table to discard the RX packets and previous scanning results. */ 1813 AsicSwitchChannel(pAd, 1, FALSE); 1814 AsicLockChannel(pAd, 1); 1815 LinkDown(pAd, FALSE); 1816 MlmeQueueInit(&pAd->Mlme.Queue); 1817 BssTableInit(&pAd->ScanTab); 1818 RTMPusecDelay(1000000); /* use delay to prevent STA do reassoc */ 1819 1820 /* channel sanity check */ 1821 for (index = 0; index < pAd->ChannelListNum; index++) { 1822 if (pAd->ChannelList[index].Channel == 1823 NewChannel) { 1824 pAd->ScanTab.BssEntry[Bssidx].Channel = 1825 NewChannel; 1826 pAd->CommonCfg.Channel = NewChannel; 1827 AsicSwitchChannel(pAd, 1828 pAd->CommonCfg. 1829 Channel, FALSE); 1830 AsicLockChannel(pAd, 1831 pAd->CommonCfg.Channel); 1832 DBGPRINT(RT_DEBUG_TRACE, 1833 ("&&&&&&&&&&&&&&&&PeerChSwAnnAction - STA receive channel switch announcement IE (New Channel =%d)\n", 1834 NewChannel)); 1835 break; 1836 } 1837 } 1838 1839 if (index >= pAd->ChannelListNum) { 1840 DBGPRINT_ERR(("&&&&&&&&&&&&&&&&&&&&&&&&&&PeerChSwAnnAction(can not find New Channel=%d in ChannelList[%d]\n", pAd->CommonCfg.Channel, pAd->ChannelListNum)); 1841 } 1842 } 1843 } 1844 1845 return; 1846} 1847 1848/* 1849 ========================================================================== 1850 Description: 1851 Measurement Request action frame handler. 1852 1853 Parametrs: 1854 Elme - MLME message containing the received frame 1855 1856 Return : None. 1857 ========================================================================== 1858 */ 1859static void PeerMeasureReqAction(struct rt_rtmp_adapter *pAd, 1860 struct rt_mlme_queue_elem *Elem) 1861{ 1862 struct rt_frame_802_11 * pFr = (struct rt_frame_802_11 *) Elem->Msg; 1863 u8 DialogToken; 1864 struct rt_measure_req_info MeasureReqInfo; 1865 struct rt_measure_req MeasureReq; 1866 MEASURE_REPORT_MODE ReportMode; 1867 1868 if (PeerMeasureReqSanity 1869 (pAd, Elem->Msg, Elem->MsgLen, &DialogToken, &MeasureReqInfo, 1870 &MeasureReq)) { 1871 ReportMode.word = 0; 1872 ReportMode.field.Incapable = 1; 1873 EnqueueMeasurementRep(pAd, pFr->Hdr.Addr2, DialogToken, 1874 MeasureReqInfo.Token, ReportMode.word, 1875 MeasureReqInfo.ReqType, 0, NULL); 1876 } 1877 1878 return; 1879} 1880 1881/* 1882 ========================================================================== 1883 Description: 1884 Measurement Report action frame handler. 1885 1886 Parametrs: 1887 Elme - MLME message containing the received frame 1888 1889 Return : None. 1890 ========================================================================== 1891 */ 1892static void PeerMeasureReportAction(struct rt_rtmp_adapter *pAd, 1893 struct rt_mlme_queue_elem *Elem) 1894{ 1895 struct rt_measure_report_info MeasureReportInfo; 1896 struct rt_frame_802_11 * pFr = (struct rt_frame_802_11 *) Elem->Msg; 1897 u8 DialogToken; 1898 u8 *pMeasureReportInfo; 1899 1900/* if (pAd->CommonCfg.bIEEE80211H != TRUE) */ 1901/* return; */ 1902 1903 pMeasureReportInfo = kmalloc(sizeof(struct rt_measure_rpi_report), GFP_ATOMIC); 1904 if (pMeasureReportInfo == NULL) { 1905 DBGPRINT(RT_DEBUG_ERROR, 1906 ("%s unable to alloc memory for measure report buffer (size=%zu).\n", 1907 __func__, sizeof(struct rt_measure_rpi_report))); 1908 return; 1909 } 1910 1911 NdisZeroMemory(&MeasureReportInfo, sizeof(struct rt_measure_report_info)); 1912 NdisZeroMemory(pMeasureReportInfo, sizeof(struct rt_measure_rpi_report)); 1913 if (PeerMeasureReportSanity 1914 (pAd, Elem->Msg, Elem->MsgLen, &DialogToken, &MeasureReportInfo, 1915 pMeasureReportInfo)) { 1916 do { 1917 struct rt_measure_req_entry *pEntry = NULL; 1918 1919 /* Not a autonomous measure report. */ 1920 /* check the dialog token field. drop it if the dialog token doesn't match. */ 1921 if ((DialogToken != 0) 1922 && ((pEntry = MeasureReqLookUp(pAd, DialogToken)) == 1923 NULL)) 1924 break; 1925 1926 if (pEntry != NULL) 1927 MeasureReqDelete(pAd, pEntry->DialogToken); 1928 1929 if (MeasureReportInfo.ReportType == RM_BASIC) { 1930 struct rt_measure_basic_report * pBasicReport = 1931 (struct rt_measure_basic_report *) pMeasureReportInfo; 1932 if ((pBasicReport->Map.field.Radar) 1933 && 1934 (DfsRequirementCheck 1935 (pAd, pBasicReport->ChNum) == TRUE)) { 1936 NotifyChSwAnnToPeerAPs(pAd, 1937 pFr->Hdr.Addr1, 1938 pFr->Hdr.Addr2, 1939 1, 1940 pBasicReport-> 1941 ChNum); 1942 StartDFSProcedure(pAd, 1943 pBasicReport->ChNum, 1944 1); 1945 } 1946 } 1947 } while (FALSE); 1948 } else 1949 DBGPRINT(RT_DEBUG_TRACE, 1950 ("Invalid Measurement Report Frame.\n")); 1951 1952 kfree(pMeasureReportInfo); 1953 1954 return; 1955} 1956 1957/* 1958 ========================================================================== 1959 Description: 1960 TPC Request action frame handler. 1961 1962 Parametrs: 1963 Elme - MLME message containing the received frame 1964 1965 Return : None. 1966 ========================================================================== 1967 */ 1968static void PeerTpcReqAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) 1969{ 1970 struct rt_frame_802_11 * pFr = (struct rt_frame_802_11 *) Elem->Msg; 1971 u8 *pFramePtr = pFr->Octet; 1972 u8 DialogToken; 1973 u8 TxPwr = GetCurTxPwr(pAd, Elem->Wcid); 1974 u8 LinkMargin = 0; 1975 char RealRssi; 1976 1977 /* link margin: Ratio of the received signal power to the minimum desired by the station (STA). The */ 1978 /* STA may incorporate rate information and channel conditions, including interference, into its computation */ 1979 /* of link margin. */ 1980 1981 RealRssi = RTMPMaxRssi(pAd, ConvertToRssi(pAd, Elem->Rssi0, RSSI_0), 1982 ConvertToRssi(pAd, Elem->Rssi1, RSSI_1), 1983 ConvertToRssi(pAd, Elem->Rssi2, RSSI_2)); 1984 1985 /* skip Category and action code. */ 1986 pFramePtr += 2; 1987 1988 /* Dialog token. */ 1989 NdisMoveMemory(&DialogToken, pFramePtr, 1); 1990 1991 LinkMargin = (RealRssi / MIN_RCV_PWR); 1992 if (PeerTpcReqSanity(pAd, Elem->Msg, Elem->MsgLen, &DialogToken)) 1993 EnqueueTPCRep(pAd, pFr->Hdr.Addr2, DialogToken, TxPwr, 1994 LinkMargin); 1995 1996 return; 1997} 1998 1999/* 2000 ========================================================================== 2001 Description: 2002 TPC Report action frame handler. 2003 2004 Parametrs: 2005 Elme - MLME message containing the received frame 2006 2007 Return : None. 2008 ========================================================================== 2009 */ 2010static void PeerTpcRepAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) 2011{ 2012 u8 DialogToken; 2013 struct rt_tpc_report_info TpcRepInfo; 2014 struct rt_tpc_req_entry *pEntry = NULL; 2015 2016 NdisZeroMemory(&TpcRepInfo, sizeof(struct rt_tpc_report_info)); 2017 if (PeerTpcRepSanity 2018 (pAd, Elem->Msg, Elem->MsgLen, &DialogToken, &TpcRepInfo)) { 2019 pEntry = TpcReqLookUp(pAd, DialogToken); 2020 if (pEntry != NULL) { 2021 TpcReqDelete(pAd, pEntry->DialogToken); 2022 DBGPRINT(RT_DEBUG_TRACE, 2023 ("%s: DialogToken=%x, TxPwr=%d, LinkMargin=%d\n", 2024 __func__, DialogToken, TpcRepInfo.TxPwr, 2025 TpcRepInfo.LinkMargin)); 2026 } 2027 } 2028 2029 return; 2030} 2031 2032/* 2033 ========================================================================== 2034 Description: 2035 Spectrun action frames Handler such as channel switch annoucement, 2036 measurement report, measurement request actions frames. 2037 2038 Parametrs: 2039 Elme - MLME message containing the received frame 2040 2041 Return : None. 2042 ========================================================================== 2043 */ 2044void PeerSpectrumAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) 2045{ 2046 2047 u8 Action = Elem->Msg[LENGTH_802_11 + 1]; 2048 2049 if (pAd->CommonCfg.bIEEE80211H != TRUE) 2050 return; 2051 2052 switch (Action) { 2053 case SPEC_MRQ: 2054 /* current rt2860 unable do such measure specified in Measurement Request. */ 2055 /* reject all measurement request. */ 2056 PeerMeasureReqAction(pAd, Elem); 2057 break; 2058 2059 case SPEC_MRP: 2060 PeerMeasureReportAction(pAd, Elem); 2061 break; 2062 2063 case SPEC_TPCRQ: 2064 PeerTpcReqAction(pAd, Elem); 2065 break; 2066 2067 case SPEC_TPCRP: 2068 PeerTpcRepAction(pAd, Elem); 2069 break; 2070 2071 case SPEC_CHANNEL_SWITCH: 2072 2073 PeerChSwAnnAction(pAd, Elem); 2074 break; 2075 } 2076 2077 return; 2078} 2079 2080/* 2081 ========================================================================== 2082 Description: 2083 2084 Parametrs: 2085 2086 Return : None. 2087 ========================================================================== 2088 */ 2089int Set_MeasureReq_Proc(struct rt_rtmp_adapter *pAd, char *arg) 2090{ 2091 u32 Aid = 1; 2092 u32 ArgIdx; 2093 char *thisChar; 2094 2095 MEASURE_REQ_MODE MeasureReqMode; 2096 u8 MeasureReqToken = RandomByte(pAd); 2097 u8 MeasureReqType = RM_BASIC; 2098 u8 MeasureCh = 1; 2099 u64 MeasureStartTime = GetCurrentTimeStamp(pAd); 2100 struct rt_measure_req MeasureReq; 2101 u8 TotalLen; 2102 2103 struct rt_header_802_11 ActHdr; 2104 u8 *pOutBuffer = NULL; 2105 int NStatus; 2106 unsigned long FrameLen; 2107 2108 NStatus = MlmeAllocateMemory(pAd, (void *)& pOutBuffer); /*Get an unused nonpaged memory */ 2109 if (NStatus != NDIS_STATUS_SUCCESS) { 2110 DBGPRINT(RT_DEBUG_TRACE, 2111 ("%s() allocate memory failed \n", __func__)); 2112 goto END_OF_MEASURE_REQ; 2113 } 2114 2115 ArgIdx = 1; 2116 while ((thisChar = strsep((char **)&arg, "-")) != NULL) { 2117 switch (ArgIdx) { 2118 case 1: /* Aid. */ 2119 Aid = (u8)simple_strtol(thisChar, 0, 16); 2120 break; 2121 2122 case 2: /* Measurement Request Type. */ 2123 MeasureReqType = simple_strtol(thisChar, 0, 16); 2124 if (MeasureReqType > 3) { 2125 DBGPRINT(RT_DEBUG_ERROR, 2126 ("%s: unknow MeasureReqType(%d)\n", 2127 __func__, MeasureReqType)); 2128 goto END_OF_MEASURE_REQ; 2129 } 2130 break; 2131 2132 case 3: /* Measurement channel. */ 2133 MeasureCh = (u8)simple_strtol(thisChar, 0, 16); 2134 break; 2135 } 2136 ArgIdx++; 2137 } 2138 2139 DBGPRINT(RT_DEBUG_TRACE, 2140 ("%s::Aid = %d, MeasureReqType=%d MeasureCh=%d\n", __func__, 2141 Aid, MeasureReqType, MeasureCh)); 2142 if (!VALID_WCID(Aid)) { 2143 DBGPRINT(RT_DEBUG_ERROR, 2144 ("%s: unknow sta of Aid(%d)\n", __func__, Aid)); 2145 goto END_OF_MEASURE_REQ; 2146 } 2147 2148 MeasureReqMode.word = 0; 2149 MeasureReqMode.field.Enable = 1; 2150 2151 MeasureReqInsert(pAd, MeasureReqToken); 2152 2153 /* build action frame header. */ 2154 MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, 2155 pAd->MacTab.Content[Aid].Addr, pAd->CurrentAddress); 2156 2157 NdisMoveMemory(pOutBuffer, (char *)& ActHdr, sizeof(struct rt_header_802_11)); 2158 FrameLen = sizeof(struct rt_header_802_11); 2159 2160 TotalLen = sizeof(struct rt_measure_req_info) + sizeof(struct rt_measure_req); 2161 2162 MakeMeasurementReqFrame(pAd, pOutBuffer, &FrameLen, 2163 sizeof(struct rt_measure_req_info), CATEGORY_RM, RM_BASIC, 2164 MeasureReqToken, MeasureReqMode.word, 2165 MeasureReqType, 0); 2166 2167 MeasureReq.ChNum = MeasureCh; 2168 MeasureReq.MeasureStartTime = cpu2le64(MeasureStartTime); 2169 MeasureReq.MeasureDuration = cpu2le16(2000); 2170 2171 { 2172 unsigned long TempLen; 2173 MakeOutgoingFrame(pOutBuffer + FrameLen, &TempLen, 2174 sizeof(struct rt_measure_req), &MeasureReq, 2175 END_OF_ARGS); 2176 FrameLen += TempLen; 2177 } 2178 2179 MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, (u32)FrameLen); 2180 2181END_OF_MEASURE_REQ: 2182 MlmeFreeMemory(pAd, pOutBuffer); 2183 2184 return TRUE; 2185} 2186 2187int Set_TpcReq_Proc(struct rt_rtmp_adapter *pAd, char *arg) 2188{ 2189 u32 Aid; 2190 2191 u8 TpcReqToken = RandomByte(pAd); 2192 2193 Aid = (u32)simple_strtol(arg, 0, 16); 2194 2195 DBGPRINT(RT_DEBUG_TRACE, ("%s::Aid = %d\n", __func__, Aid)); 2196 if (!VALID_WCID(Aid)) { 2197 DBGPRINT(RT_DEBUG_ERROR, 2198 ("%s: unknow sta of Aid(%d)\n", __func__, Aid)); 2199 return TRUE; 2200 } 2201 2202 TpcReqInsert(pAd, TpcReqToken); 2203 2204 EnqueueTPCReq(pAd, pAd->MacTab.Content[Aid].Addr, TpcReqToken); 2205 2206 return TRUE; 2207} 2208