MOXA linux-2.6.x / linux-2.6.9-uc0 from sdlinux-moxaart.tgz
[linux-2.6.9-moxart.git] / drivers / net / wireless / rtlink.org / sync.c
blob5a1c20f1300e971b4e04d5933534ceaf5ddc7fc2
1 /****************************************************************************
2 * Ralink Tech Inc.
3 * 4F, No. 2 Technology 5th Rd.
4 * Science-based Industrial Park
5 * Hsin-chu, Taiwan, R.O.C.
6 * (c) Copyright 2002, Ralink Technology, Inc.
8 * All rights reserved. Ralink's source code is an unpublished work and the
9 * use of a copyright notice does not imply otherwise. This source code
10 * contains confidential trade secret material of Ralink Tech. Any attemp
11 * or participation in deciphering, decoding, reverse engineering or in any
12 * way altering the source code is stricitly prohibited, unless the prior
13 * written consent of Ralink Technology, Inc. is obtained.
14 ****************************************************************************/
16 #include "rt_config.h"
18 // 2.4 Ghz channel plan
19 UCHAR Ra24Ghz_FCC[] = {1,2,3,4,5,6,7,8,9,10,11};
20 UCHAR Ra24Ghz_IC[] = {1,2,3,4,5,6,7,8,9,10,11};
21 UCHAR Ra24Ghz_ESTI[]= {1,2,3,4,5,6,7,8,9,10,11,12,13};
22 UCHAR Ra24Ghz_SPAIN[] = {10,11};
23 UCHAR Ra24Ghz_FRANCE[] = {10,11,12,13};
24 UCHAR Ra24Ghz_MKK[] = {14};
25 UCHAR Ra24Ghz_MKK1[] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14};
26 UCHAR Ra24Ghz_ISRAEL[] = {3,4,5,6,7,8,9};
28 // 5 Ghz channel plan
29 UCHAR Ra5Ghz_UNII[] = {36,40,44,48,52,56,60,64, 149,153,157,161};
30 UCHAR Ra5Ghz_MMAC[] = {34,38,42,46};
31 UCHAR Ra5Ghz_HyperLAN2[] = {36,40,44,48,52,56,60,64, 100,104,108,112,116,120,124,128,132,136,140};
33 extern UCHAR CipherSuiteWpaNoneTkip[];
34 extern UCHAR CipherSuiteWpaNoneTkipLen;
36 extern UCHAR CipherSuiteWpaNoneAes[];
37 extern UCHAR CipherSuiteWpaNoneAesLen;
40 ==========================================================================
41 Description:
42 The sync state machine,
43 Parameters:
44 Sm - pointer to the state machine
45 Note:
46 the state machine looks like the following
48 Column 1-2
49 SYNC_IDLE JOIN_WAIT_BEACON
50 MT2_MLME_SCAN_REQ mlme_scan_req_action invalid_state_when_scan
51 MT2_MLME_JOIN_REQ mlme_join_req_action invalid_state_when_join
52 MT2_MLME_START_REQ mlme_start_req_action invalid_state_when_start
53 MT2_PEER_BEACON peer_beacon peer_beacon_at_join_wait_beacon_action
54 MT2_PEER_PROBE_RSP peer_beacon drop
55 MT2_PEER_ATIM drop drop
56 MT2_SCAN_TIMEOUT Drop Drop
57 MT2_BEACON_TIMEOUT Drop beacon_timeout_at_join_wait_beacon_action
58 MT2_ATIM_TIMEOUT Drop Drop
59 MT2_PEER_PROBE_REQ ???? drop
61 column 3
62 SCAN_LISTEN
63 MT2_MLME_SCAN_REQ invalid_state_when_scan
64 MT2_MLME_JOIN_REQ invalid_state_when_join
65 MT2_MLME_START_REQ invalid_state_when_start
66 MT2_PEER_BEACON peer_beacon_at_scan_action
67 MT2_PEER_PROBE_RSP peer_probe_rsp_at_scan_action
68 MT2_PEER_ATIM drop
69 MT2_SCAN_TIMEOUT scan_timeout_action
70 MT2_BEACON_TIMEOUT Drop
71 MT2_ATIM_TIMEOUT Drop
72 MT2_PEER_PROBE_REQ drop
73 ==========================================================================
75 VOID SyncStateMachineInit(
76 IN PRTMP_ADAPTER pAd,
77 IN STATE_MACHINE *Sm,
78 OUT STATE_MACHINE_FUNC Trans[])
80 StateMachineInit(Sm, (STATE_MACHINE_FUNC*)Trans, MAX_SYNC_STATE, MAX_SYNC_MSG, (STATE_MACHINE_FUNC)Drop, SYNC_IDLE, SYNC_MACHINE_BASE);
82 // column 1
83 StateMachineSetAction(Sm, SYNC_IDLE, MT2_MLME_SCAN_REQ, (STATE_MACHINE_FUNC)MlmeScanReqAction);
84 StateMachineSetAction(Sm, SYNC_IDLE, MT2_MLME_JOIN_REQ, (STATE_MACHINE_FUNC)MlmeJoinReqAction);
85 StateMachineSetAction(Sm, SYNC_IDLE, MT2_MLME_START_REQ, (STATE_MACHINE_FUNC)MlmeStartReqAction);
86 StateMachineSetAction(Sm, SYNC_IDLE, MT2_PEER_BEACON, (STATE_MACHINE_FUNC)PeerBeacon);
87 // StateMachineSetAction(Sm, SYNC_IDLE, MT2_PEER_PROBE_RSP, (STATE_MACHINE_FUNC)PeerBeacon);
88 StateMachineSetAction(Sm, SYNC_IDLE, MT2_PEER_PROBE_REQ, (STATE_MACHINE_FUNC)PeerProbeReqAction);
90 //column 2
91 StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_MLME_SCAN_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenScan);
92 StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_MLME_JOIN_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenJoin);
93 StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_MLME_START_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenStart);
94 StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_PEER_BEACON, (STATE_MACHINE_FUNC)PeerBeaconAtJoinAction);
95 StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_BEACON_TIMEOUT, (STATE_MACHINE_FUNC)BeaconTimeoutAtJoinAction);
97 // column 3
98 StateMachineSetAction(Sm, SCAN_LISTEN, MT2_MLME_SCAN_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenScan);
99 StateMachineSetAction(Sm, SCAN_LISTEN, MT2_MLME_JOIN_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenJoin);
100 StateMachineSetAction(Sm, SCAN_LISTEN, MT2_MLME_START_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenStart);
101 StateMachineSetAction(Sm, SCAN_LISTEN, MT2_PEER_BEACON, (STATE_MACHINE_FUNC)PeerBeaconAtScanAction);
102 StateMachineSetAction(Sm, SCAN_LISTEN, MT2_PEER_PROBE_RSP, (STATE_MACHINE_FUNC)PeerBeaconAtScanAction);
103 StateMachineSetAction(Sm, SCAN_LISTEN, MT2_SCAN_TIMEOUT, (STATE_MACHINE_FUNC)ScanTimeoutAction);
105 // timer init
106 RTMPInitTimer(pAd, &pAd->Mlme.SyncAux.BeaconTimer, BeaconTimeout);
107 RTMPInitTimer(pAd, &pAd->Mlme.SyncAux.ScanTimer, ScanTimeout);
111 ==========================================================================
112 Description:
113 Becaon timeout handler, executed in timer thread
114 ==========================================================================
116 VOID BeaconTimeout(
117 IN unsigned long data)
119 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)data;
121 DBGPRINT(RT_DEBUG_TRACE,"SYNC - BeaconTimeout\n");
122 MlmeEnqueue(&pAd->Mlme.Queue, SYNC_STATE_MACHINE, MT2_BEACON_TIMEOUT, 0, NULL);
123 MlmeHandler(pAd);
127 ==========================================================================
128 Description:
129 ATIM timeout handler, executed in timer thread
130 ==========================================================================
132 VOID AtimTimeout(
133 IN unsigned long data)
135 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)data;
137 DBGPRINT(RT_DEBUG_TRACE,"SYNC - AtimTimeout \n");
138 MlmeEnqueue(&pAd->Mlme.Queue, SYNC_STATE_MACHINE, MT2_ATIM_TIMEOUT, 0, NULL);
139 MlmeHandler(pAd);
143 ==========================================================================
144 Description:
145 Scan timeout handler, executed in timer thread
146 ==========================================================================
148 VOID ScanTimeout(
149 IN unsigned long data)
151 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)data;
153 //DBGPRINT(RT_DEBUG_INFO,"SYNC - Scan Timeout \n");
154 MlmeEnqueue(&pAd->Mlme.Queue, SYNC_STATE_MACHINE, MT2_SCAN_TIMEOUT, 0, NULL);
155 MlmeHandler(pAd);
159 ==========================================================================
160 Description:
161 MLME SCAN req state machine procedure
162 ==========================================================================
164 VOID MlmeScanReqAction(
165 IN PRTMP_ADAPTER pAd,
166 IN MLME_QUEUE_ELEM *Elem)
168 UCHAR Ssid[MAX_LEN_OF_SSID], SsidLen, ScanType, BssType;
169 ULONG Now;
171 // Suspend MSDU transmission here
172 RTMPSuspendMsduTransmission(pAd);
174 // first check the parameter sanity
175 if (MlmeScanReqSanity(pAd,
176 Elem->Msg,
177 Elem->MsgLen,
178 &BssType,
179 Ssid,
180 &SsidLen,
181 &ScanType))
183 Now = jiffies;
184 pAd->PortCfg.LastScanTime = Now;
185 // reset all the timers
186 RTMPCancelTimer(&pAd->Mlme.SyncAux.BeaconTimer);
187 RTMPCancelTimer(&pAd->Mlme.SyncAux.ScanTimer);
189 // record desired BSS parameters
190 pAd->Mlme.SyncAux.BssType = BssType;
191 pAd->Mlme.SyncAux.ScanType = ScanType;
192 pAd->Mlme.SyncAux.SsidLen = SsidLen;
193 NdisMoveMemory(pAd->Mlme.SyncAux.Ssid, Ssid, SsidLen);
195 // start from the first channel
196 pAd->Mlme.SyncAux.Channel = FirstChannel(pAd);
197 ScanNextChannel(pAd);
199 else
201 DBGPRINT(RT_DEBUG_ERROR, "SYNC - MlmeScanReqAction() sanity check fail. BUG!!!\n");
202 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
203 MlmeCntlConfirm(pAd, MT2_SCAN_CONF, MLME_INVALID_FORMAT);
208 ==========================================================================
209 Description:
210 MLME JOIN req state machine procedure
211 ==========================================================================
213 VOID MlmeJoinReqAction(
214 IN PRTMP_ADAPTER pAd,
215 IN MLME_QUEUE_ELEM *Elem)
217 BSS_ENTRY *pBss;
218 MLME_JOIN_REQ_STRUCT *Info = (MLME_JOIN_REQ_STRUCT *)(Elem->Msg);
220 DBGPRINT(RT_DEBUG_TRACE, "SYNC - MlmeJoinReqAction(BSS #%d)\n", Info->BssIdx);
222 // reset all the timers
223 RTMPCancelTimer(&pAd->Mlme.SyncAux.ScanTimer);
224 RTMPCancelTimer(&pAd->Mlme.SyncAux.BeaconTimer);
226 pBss = &pAd->Mlme.CntlAux.SsidBssTab.BssEntry[Info->BssIdx];
228 // record the desired SSID & BSSID we're waiting for
229 COPY_MAC_ADDR(&pAd->Mlme.SyncAux.Bssid, &pBss->Bssid);
230 NdisMoveMemory(pAd->Mlme.SyncAux.Ssid, pBss->Ssid, pBss->SsidLen);
231 pAd->Mlme.SyncAux.SsidLen = pBss->SsidLen;
233 // switch channel and waiting for beacon timer
234 AsicSwitchChannel(pAd, pBss->Channel);
235 AsicLockChannel(pAd, pBss->Channel);
236 DBGPRINT(RT_DEBUG_TRACE, "SYNC - Switch to channel %d, SSID %s \n", pBss->Channel, pAd->Mlme.SyncAux.Ssid);
237 DBGPRINT(RT_DEBUG_TRACE, "SYNC - Wait BEACON from %02x:%02x:%02x:%02x:%02x:%02x ...\n",
238 pAd->Mlme.SyncAux.Bssid.Octet[0], pAd->Mlme.SyncAux.Bssid.Octet[1],
239 pAd->Mlme.SyncAux.Bssid.Octet[2], pAd->Mlme.SyncAux.Bssid.Octet[3],
240 pAd->Mlme.SyncAux.Bssid.Octet[4], pAd->Mlme.SyncAux.Bssid.Octet[5]);
241 RTMPSetTimer(pAd, &pAd->Mlme.SyncAux.BeaconTimer, JOIN_TIMEOUT);
243 pAd->Mlme.SyncMachine.CurrState = JOIN_WAIT_BEACON;
247 ==========================================================================
248 Description:
249 MLME START Request state machine procedure, starting an IBSS
250 ==========================================================================
252 VOID MlmeStartReqAction(
253 IN PRTMP_ADAPTER pAd,
254 IN MLME_QUEUE_ELEM *Elem)
256 UCHAR Ssid[MAX_LEN_OF_SSID], SsidLen;
258 // New for WPA security suites
259 UCHAR VarIE[MAX_VIE_LEN]; // Total VIE length = MAX_VIE_LEN - -5
260 NDIS_802_11_VARIABLE_IEs *pVIE = NULL;
261 LARGE_INTEGER TimeStamp;
262 BOOLEAN Privacy;
263 #ifdef SINGLE_ADHOC_LINKUP
264 ULONG Bssidx;
265 BOOLEAN CfExist = FALSE;
266 CF_PARM CfParm;
267 #endif
269 // Init Variable IE structure
270 pVIE = (PNDIS_802_11_VARIABLE_IEs) VarIE;
271 pVIE->Length = 0;
272 TimeStamp.u.LowPart = 0;
273 TimeStamp.u.HighPart = 0;
275 if (MlmeStartReqSanity(pAd, Elem->Msg, Elem->MsgLen, Ssid, &SsidLen))
277 // reset all the timers
278 RTMPCancelTimer(&pAd->Mlme.SyncAux.ScanTimer);
279 RTMPCancelTimer(&pAd->Mlme.SyncAux.BeaconTimer);
281 // PortCfg.PrivacyInvoked should have been set via OID_802_11_WEP_STATUS.
282 // pAd->PortCfg.PrivacyInvoked = FALSE;
284 NdisMoveMemory(pAd->PortCfg.Ssid, Ssid, SsidLen);
285 pAd->PortCfg.SsidLen = SsidLen;
286 pAd->PortCfg.BssType = BSS_INDEP;
287 Privacy = (pAd->PortCfg.WepStatus == Ndis802_11Encryption1Enabled) ||
288 (pAd->PortCfg.WepStatus == Ndis802_11Encryption2Enabled) ||
289 (pAd->PortCfg.WepStatus == Ndis802_11Encryption3Enabled);
290 pAd->PortCfg.CapabilityInfo = CAP_GENERATE(0,1,0,0,Privacy, (pAd->PortCfg.WindowsTxPreamble == Rt802_11PreambleShort));
291 pAd->PortCfg.BeaconPeriod = pAd->PortCfg.IbssConfig.BeaconPeriod;
292 pAd->PortCfg.AtimWin = pAd->PortCfg.IbssConfig.AtimWin;
293 pAd->PortCfg.Channel = pAd->PortCfg.IbssConfig.Channel;
294 if ((pAd->PortCfg.PhyMode == PHY_11ABG_MIXED) && (pAd->PortCfg.Channel > 14))
296 // no 1,2,5.5,11 Mbps when in 5Ghz band
297 pAd->PortCfg.SupportedRatesLen = pAd->PortCfg.IbssConfig.SupportedRatesLen - 4;
298 NdisZeroMemory(pAd->PortCfg.SupportedRates, MAX_LEN_OF_SUPPORTED_RATES);
299 NdisMoveMemory(pAd->PortCfg.SupportedRates, &pAd->PortCfg.IbssConfig.SupportedRates[4], MAX_LEN_OF_SUPPORTED_RATES - 4);
301 else
303 pAd->PortCfg.SupportedRatesLen = pAd->PortCfg.IbssConfig.SupportedRatesLen;
304 NdisMoveMemory(pAd->PortCfg.SupportedRates, pAd->PortCfg.IbssConfig.SupportedRates, MAX_LEN_OF_SUPPORTED_RATES);
306 // pAd->PortCfg.Pss = PWR_ACTIVE;
308 // generate a radom number as BSSID
309 MacAddrRandomBssid(pAd, &pAd->PortCfg.Bssid);
310 AsicSetBssid(pAd, &pAd->PortCfg.Bssid);
311 AsicSwitchChannel(pAd, pAd->PortCfg.Channel);
312 AsicLockChannel(pAd, pAd->PortCfg.Channel);
314 DBGPRINT(RT_DEBUG_TRACE, "SYNC - MlmeStartReqAction(ch= %d,supported rate len= %d)\n",
315 pAd->PortCfg.Channel, pAd->PortCfg.SupportedRatesLen);
317 #ifdef SINGLE_ADHOC_LINKUP
318 // Add itself as the entry within BSS table
319 Bssidx = BssTableSearch(&pAd->PortCfg.BssTab, &pAd->PortCfg.Bssid);
320 if (Bssidx == BSS_NOT_FOUND)
322 Bssidx = BssTableSetEntry(pAd, &pAd->PortCfg.BssTab, &pAd->PortCfg.Bssid,
323 Ssid, SsidLen, pAd->PortCfg.BssType, pAd->PortCfg.BeaconPeriod,
324 CfExist, &CfParm, pAd->PortCfg.AtimWin, pAd->PortCfg.CapabilityInfo,
325 pAd->PortCfg.SupportedRates, pAd->PortCfg.SupportedRatesLen, TRUE,
326 pAd->PortCfg.Channel, Elem->Rssi, TimeStamp, pVIE);
328 #endif
330 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
331 MlmeCntlConfirm(pAd, MT2_START_CONF, (USHORT)MLME_SUCCESS);
333 else
335 DBGPRINT(RT_DEBUG_ERROR, "SYNC - MlmeStartReqAction() sanity check fail. BUG!!!\n");
336 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
337 MlmeCntlConfirm(pAd, MT2_START_CONF, MLME_INVALID_FORMAT);
342 ==========================================================================
343 Description:
344 peer sends beacon back when scanning
345 ==========================================================================
347 VOID PeerBeaconAtScanAction(
348 IN PRTMP_ADAPTER pAd,
349 IN MLME_QUEUE_ELEM *Elem)
351 MACADDR Bssid, Addr2;
352 UCHAR Ssid[MAX_LEN_OF_SSID], BssType, Channel, Rates[MAX_LEN_OF_SUPPORTED_RATES], RatesLen,
353 SsidLen, DtimCount, DtimPeriod, BcastFlag, MessageToMe, Legacy;
354 CF_PARM CfParm;
355 USHORT BeaconPeriod, AtimWin, CapabilityInfo;
356 MACFRAME *Fr;
357 LARGE_INTEGER TimeStamp;
358 BOOLEAN CfExist = FALSE;
359 BOOLEAN ExtendedRateIeExist;
360 UCHAR Erp;
361 UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES], ExtRate[MAX_LEN_OF_SUPPORTED_RATES];
362 UCHAR SupRateLen, ExtRateLen;
364 // New for WPA security suites
365 UCHAR VarIE[MAX_VIE_LEN]; // Total VIE length = MAX_VIE_LEN - -5
366 NDIS_802_11_VARIABLE_IEs *pVIE = NULL;
368 // NdisFillMemory(Ssid, MAX_LEN_OF_SSID, 0x00);
369 Fr = (MACFRAME *) Elem->Msg;
370 // Init Variable IE structure
371 pVIE = (PNDIS_802_11_VARIABLE_IEs) VarIE;
372 pVIE->Length = 0;
373 if (PeerBeaconAndProbeRspSanity(pAd,
374 Elem->Msg,
375 Elem->MsgLen,
376 &Addr2,
377 &Bssid, Ssid,
378 &SsidLen,
379 &BssType,
380 &BeaconPeriod,
381 &Channel,
382 &TimeStamp,
383 &CfExist,
384 &CfParm,
385 &AtimWin,
386 &CapabilityInfo,
387 Rates,
388 &RatesLen,
389 &ExtendedRateIeExist,
390 &Erp,
391 &DtimCount,
392 &DtimPeriod,
393 &BcastFlag,
394 &MessageToMe,
395 &Legacy,
396 SupRate,
397 &SupRateLen,
398 ExtRate,
399 &ExtRateLen,
400 pVIE))
402 ULONG Idx;
403 UCHAR Rssi = 0;
405 // This correct im-proper RSSI indication during SITE SURVEY issue.
406 // Always report bigger RSSI during SCANNING when receiving multiple BEACONs from the same AP.
407 // This case happens because BEACONs come from adjacent channels, so RSSI become weaker as we
408 // switch to more far away channels.
409 Idx = BssTableSearch(&pAd->PortCfg.BssTab, &Bssid);
410 if (Idx != BSS_NOT_FOUND)
411 Rssi = pAd->PortCfg.BssTab.BssEntry[Idx].Rssi;
412 if (Elem->Rssi > Rssi)
413 Rssi = Elem->Rssi;
415 DBGPRINT(RT_DEBUG_INFO, "SYNC - PeerBeaconAtScanAction (Subtype=%d, SsidLen=%d, Ssid=%s)\n", Fr->Hdr.SubType, SsidLen,Ssid);
417 // Mask out unnecessary capability information
418 CapabilityInfo &= SUPPORTED_CAPABILITY_INFO;
420 BssTableSetEntry(pAd, &pAd->PortCfg.BssTab, &Bssid, Ssid, SsidLen, BssType,
421 BeaconPeriod, CfExist, &CfParm, AtimWin, CapabilityInfo, Rates,
422 RatesLen, ExtendedRateIeExist, Channel, Rssi, TimeStamp, pVIE);
424 // sanity check fail, ignored
428 ==========================================================================
429 Description:
430 When waiting joining the (I)BSS, beacon received from external
431 ==========================================================================
433 VOID PeerBeaconAtJoinAction(
434 IN PRTMP_ADAPTER pAd,
435 IN MLME_QUEUE_ELEM *Elem)
437 MACADDR Bssid, Addr2;
438 UCHAR Ssid[MAX_LEN_OF_SSID], SsidLen, BssType, Channel, RatesLen, MessageToMe,
439 Rates[MAX_LEN_OF_SUPPORTED_RATES], DtimCount, DtimPeriod, BcastFlag, Legacy;
440 LARGE_INTEGER TimeStamp;
441 USHORT BeaconPeriod, AtimWin, CapabilityInfo;
442 CF_PARM Cf;
443 BOOLEAN CfExist = FALSE, ExtendedRateIeExist;
444 UCHAR Erp;
445 UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES], ExtRate[MAX_LEN_OF_SUPPORTED_RATES];
446 UCHAR SupRateLen, ExtRateLen;
448 // New for WPA security suites
449 UCHAR VarIE[MAX_VIE_LEN]; // Total VIE length = MAX_VIE_LEN - -5
450 NDIS_802_11_VARIABLE_IEs *pVIE = NULL;
452 DBGPRINT(RT_DEBUG_TRACE, "Enter PeerBeaconAtJoinAction. l=%d\n", Elem->MsgLen);
454 // Init Variable IE structure
455 pVIE = (PNDIS_802_11_VARIABLE_IEs) VarIE;
456 pVIE->Length = 0;
457 if (PeerBeaconAndProbeRspSanity(pAd,
458 Elem->Msg,
459 Elem->MsgLen,
460 &Addr2,
461 &Bssid,
462 Ssid,
463 &SsidLen,
464 &BssType,
465 &BeaconPeriod,
466 &Channel,
467 &TimeStamp,
468 &CfExist,
469 &Cf,
470 &AtimWin,
471 &CapabilityInfo,
472 Rates,
473 &RatesLen,
474 &ExtendedRateIeExist,
475 &Erp,
476 &DtimCount,
477 &DtimPeriod,
478 &BcastFlag,
479 &MessageToMe,
480 &Legacy,
481 SupRate,
482 &SupRateLen,
483 ExtRate,
484 &ExtRateLen,
485 pVIE))
487 // Disqualify 11b only adhoc when we are in 11g only adhoc mode
488 if ((BssType == BSS_INDEP) && (pAd->PortCfg.AdhocMode == 2) && (RatesLen < 12))
489 return;
491 if (MAC_ADDR_EQUAL(&pAd->Mlme.SyncAux.Bssid, &Bssid))
493 DBGPRINT(RT_DEBUG_TRACE, "SYNC - receive desired BEACON at JoinWaitBeacon...\n");
494 RTMPCancelTimer(&pAd->Mlme.SyncAux.BeaconTimer);
496 // Update RSSI to prevent No signal display when cards first initialized
497 pAd->PortCfg.LastRssi = Elem->Rssi;
498 pAd->PortCfg.AvgRssi = Elem->Rssi;
500 if (pAd->Mlme.CntlAux.SsidLen > 0)
502 NdisMoveMemory(pAd->PortCfg.Ssid, pAd->Mlme.CntlAux.Ssid, pAd->Mlme.CntlAux.SsidLen);
503 pAd->PortCfg.SsidLen = pAd->Mlme.CntlAux.SsidLen;
505 else
507 NdisMoveMemory(pAd->PortCfg.Ssid, Ssid, SsidLen);
508 pAd->PortCfg.SsidLen = SsidLen;
511 COPY_MAC_ADDR(&pAd->PortCfg.Bssid, &Bssid);
512 AsicSetBssid(pAd, &pAd->PortCfg.Bssid);
514 pAd->PortCfg.BssType = BssType;
515 pAd->PortCfg.BeaconPeriod = BeaconPeriod;
516 pAd->PortCfg.Channel = Channel;
518 // filter out non-supported rates
520 int i;
521 pAd->PortCfg.SupportedRatesLen = 0;
522 for (i=0;i<RatesLen;i++)
524 UCHAR Rate = Rates[i] & 0x7f;
525 if ((pAd->PortCfg.PhyMode == PHY_11B) &&
526 (Rate == 2 || Rate == 4 || Rate == 11 || Rate == 22))
528 ///DBGPRINT(RT_DEBUG_TRACE, ("SYNC - Supported Rate[%d] = 0x%02x\n",pAd->PortCfg.SupportedRatesLen, Rates[i]));
529 pAd->PortCfg.SupportedRates[pAd->PortCfg.SupportedRatesLen] = Rates[i];
530 pAd->PortCfg.SupportedRatesLen ++;
532 else if ((Rate == 2 || Rate == 4 || Rate == 11 || Rate == 22) ||
533 (Rate == 12 || Rate == 18 || Rate == 24 || Rate == 36) ||
534 (Rate == 48 || Rate == 72 || Rate == 96 || Rate == 108))
536 // DBGPRINT(RT_DEBUG_TRACE, ("SYNC - Supported Rate[%d] = 0x%02x\n",pAd->PortCfg.SupportedRatesLen, Rates[i]));
537 pAd->PortCfg.SupportedRates[pAd->PortCfg.SupportedRatesLen] = Rates[i];
538 pAd->PortCfg.SupportedRatesLen ++;
543 // Copy AP's supported rate to portcfg for creating assoication request
544 // Also filter out not supported rate
545 // Supported rate
547 int i;
548 pAd->PortCfg.SupRateLen = 0;
549 for (i = 0; i < SupRateLen; i++)
551 UCHAR Rate = SupRate[i] & 0x7f;
552 if ((pAd->PortCfg.PhyMode == PHY_11B) &&
553 (Rate == 2 || Rate == 4 || Rate == 11 || Rate == 22))
555 pAd->PortCfg.SupRate[pAd->PortCfg.SupRateLen] = SupRate[i];
556 pAd->PortCfg.SupRateLen ++;
558 else if ((Rate == 2 || Rate == 4 || Rate == 11 || Rate == 22) ||
559 (Rate == 12 || Rate == 18 || Rate == 24 || Rate == 36) ||
560 (Rate == 48 || Rate == 72 || Rate == 96 || Rate == 108))
562 pAd->PortCfg.SupRate[pAd->PortCfg.SupRateLen] = SupRate[i];
563 pAd->PortCfg.SupRateLen ++;
568 // Copy AP's supported rate to portcfg for creating assoication request
569 // Also filter out not supported rate
570 // Extended rate
571 if (ExtendedRateIeExist == TRUE)
573 int i;
574 pAd->PortCfg.ExtRateLen = 0;
575 for (i = 0; i < ExtRateLen; i++)
577 UCHAR Rate = ExtRate[i] & 0x7f;
578 if ((pAd->PortCfg.PhyMode == PHY_11B) &&
579 (Rate == 2 || Rate == 4 || Rate == 11 || Rate == 22))
581 pAd->PortCfg.ExtRate[pAd->PortCfg.ExtRateLen] = ExtRate[i];
582 pAd->PortCfg.ExtRateLen ++;
584 else if ((Rate == 2 || Rate == 4 || Rate == 11 || Rate == 22) ||
585 (Rate == 12 || Rate == 18 || Rate == 24 || Rate == 36) ||
586 (Rate == 48 || Rate == 72 || Rate == 96 || Rate == 108))
588 pAd->PortCfg.ExtRate[pAd->PortCfg.ExtRateLen] = ExtRate[i];
589 pAd->PortCfg.ExtRateLen ++;
593 else
595 pAd->PortCfg.ExtRateLen = 0;
598 DBGPRINT(RT_DEBUG_TRACE, "SYNC - AP's SupportedRatesLen=%d, set STA's SupportedRateLen=%d\n",
599 RatesLen, pAd->PortCfg.SupportedRatesLen);
601 // Mask out unnecessary capability information
602 CapabilityInfo &= SUPPORTED_CAPABILITY_INFO;
604 // Check for 802.11g information, if 802.11 b/g mixed mode.
605 // We can't support its short preamble for now.
606 pAd->PortCfg.CapabilityInfo = CapabilityInfo;
608 if ((BssType == BSS_INDEP) && (CAP_IS_IBSS_ON(CapabilityInfo)))
610 pAd->PortCfg.AtimWin = AtimWin;
612 else if (BssType == BSS_INFRA)
614 pAd->PortCfg.CfpPeriod = Cf.CfpPeriod;
615 pAd->PortCfg.CfpMaxDuration = Cf.CfpMaxDuration;
616 pAd->PortCfg.CfpDurRemain = Cf.CfpDurRemaining;
617 pAd->PortCfg.CfpCount = Cf.CfpCount;
618 pAd->PortCfg.CfpPeriod = Cf.CfpPeriod;
620 AsicEnableBssSync(pAd);
623 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
624 MlmeCntlConfirm(pAd, MT2_JOIN_CONF, MLME_SUCCESS);
626 // not to me BEACON, ignored
628 // sanity check fail, ignore this frame
632 ==========================================================================
633 Description:
634 receive BEACON from peer
635 ==========================================================================
637 VOID PeerBeacon(
638 IN PRTMP_ADAPTER pAd,
639 IN MLME_QUEUE_ELEM *Elem)
641 MACADDR Bssid, Addr2;
642 CHAR Ssid[MAX_LEN_OF_SSID];
643 CF_PARM CfParm;
644 UCHAR SsidLen, MessageToMe=0, BssType, Channel, Rates[MAX_LEN_OF_SUPPORTED_RATES];
645 UCHAR RatesLen, DtimCount=0, DtimPeriod=0, BcastFlag=0, Legacy;
646 USHORT CapabilityInfo, AtimWin, BeaconPeriod;
647 LARGE_INTEGER TimeStamp;
648 BOOLEAN CfExist = FALSE;
649 USHORT TbttNumToNextWakeUp;
650 BOOLEAN ExtendedRateIeExist;
651 UCHAR Erp;
652 UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES], ExtRate[MAX_LEN_OF_SUPPORTED_RATES];
653 UCHAR SupRateLen, ExtRateLen;
655 // New for WPA security suites
656 UCHAR VarIE[MAX_VIE_LEN]; // Total VIE length = MAX_VIE_LEN - -5
657 NDIS_802_11_VARIABLE_IEs *pVIE = NULL;
659 if (!INFRA_ON(pAd) && !ADHOC_ON(pAd))
660 return;
662 // Init Variable IE structure
663 pVIE = (PNDIS_802_11_VARIABLE_IEs) VarIE;
664 pVIE->Length = 0;
665 if (PeerBeaconAndProbeRspSanity(pAd,
666 Elem->Msg,
667 Elem->MsgLen,
668 &Addr2,
669 &Bssid,
670 Ssid,
671 &SsidLen,
672 &BssType,
673 &BeaconPeriod,
674 &Channel,
675 &TimeStamp,
676 &CfExist,
677 &CfParm,
678 &AtimWin,
679 &CapabilityInfo,
680 Rates,
681 &RatesLen,
682 &ExtendedRateIeExist,
683 &Erp,
684 &DtimCount,
685 &DtimPeriod,
686 &BcastFlag,
687 &MessageToMe,
688 &Legacy,
689 SupRate,
690 &SupRateLen,
691 ExtRate,
692 &ExtRateLen,
693 pVIE))
695 BOOLEAN is_my_bssid, is_my_ssid;
696 ULONG Bssidx, Now;
697 BSS_ENTRY *pBss;
699 is_my_bssid = (MAC_ADDR_EQUAL(&Bssid, &pAd->PortCfg.Bssid) ? TRUE : FALSE);
700 is_my_ssid = (((pAd->PortCfg.SsidLen == SsidLen) && RTMPEqualMemory(Ssid, pAd->PortCfg.Ssid, (ULONG) SsidLen)) ? TRUE : FALSE);
701 // Mask out unnecessary capability information
702 CapabilityInfo &= SUPPORTED_CAPABILITY_INFO;
704 // ignore BEACON not for my SSID
705 if ((! is_my_ssid) && (! is_my_bssid))
706 return;
709 // Housekeeping "SsidBssTab" table for later-on ROAMing usage.
711 Bssidx = BssTableSearch(&pAd->Mlme.CntlAux.SsidBssTab, &Bssid);
712 if (Bssidx == BSS_NOT_FOUND)
714 // Return immediately when in transition process when changing association
715 // Found this bug when doing WHQL ad-hoc test case
716 if (pAd->PortCfg.SsidLen != pAd->Mlme.CntlAux.SsidLen)
717 return;
718 if (!RTMPEqualMemory(pAd->PortCfg.Ssid, pAd->Mlme.CntlAux.Ssid, pAd->PortCfg.SsidLen))
719 return;
721 // discover new AP of this network, create BSS entry
722 Bssidx = BssTableSetEntry(pAd, &pAd->Mlme.CntlAux.SsidBssTab, &Bssid, Ssid, SsidLen,
723 BssType, BeaconPeriod, CfExist, &CfParm, AtimWin, CapabilityInfo,
724 Rates, RatesLen, ExtendedRateIeExist, Channel, Elem->Rssi, TimeStamp, pVIE);
726 if (Bssidx == BSS_NOT_FOUND) // return if BSS table full
727 return;
729 DBGPRINT(RT_DEBUG_TRACE, "SYNC - New AP added to SsidBssTab[%d], RSSI=%d, MAC=%02x:%02x:%02x:%02x:%02x:%02x\n",
730 Bssidx, Elem->Rssi, Bssid.Octet[0], Bssid.Octet[1], Bssid.Octet[2],
731 Bssid.Octet[3], Bssid.Octet[4], Bssid.Octet[5]);
734 // if the ssid matched & bssid unmatched, we should select the bssid with large value.
735 // This might happened when two STA start at the same time
736 if (is_my_ssid && (! is_my_bssid) && ADHOC_ON(pAd))
738 INT i;
739 // Add to safe guard adhoc wep status mismatch
740 if (pAd->PortCfg.WepStatus != pAd->Mlme.CntlAux.SsidBssTab.BssEntry[Bssidx].WepStatus)
741 return;
743 // link down the one with smaller BSSID value.
744 for (i = 0; i < 6; i++)
746 if (Bssid.Octet[i] > pAd->PortCfg.Bssid.Octet[i])
748 AsicDisableSync(pAd);
749 NdisMoveMemory(&pAd->PortCfg.Bssid, &Bssid, 6);
750 AsicSetBssid(pAd, &pAd->PortCfg.Bssid);
751 MakeIbssBeacon(pAd);
752 AsicEnableIbssSync(pAd);
753 break;
758 DBGPRINT(RT_DEBUG_INFO, "SYNC - PeerBeacon from %02x:%02x:%02x:%02x:%02x:%02x - Dtim=%d/%d, Rssi=%02x\n",
759 Bssid.Octet[0], Bssid.Octet[1], Bssid.Octet[2],
760 Bssid.Octet[3], Bssid.Octet[4], Bssid.Octet[5],
761 DtimCount, DtimPeriod, Elem->Rssi);
763 Now = jiffies;
764 pBss = &pAd->Mlme.CntlAux.SsidBssTab.BssEntry[Bssidx];
765 pBss->Rssi = Elem->Rssi; // lastest RSSI
766 pBss->LastBeaconRxTime = Now; // last RX timestamp
769 // BEACON from my BSSID - either IBSS or INFRA network
771 if (is_my_bssid)
773 // 2002/12/06 - patch Abocom AP bug, which forgets to set "Privacy" bit in
774 // AssocRsp even though this bit is ON in Beacon. So we update according
775 // to following Beacon frame.
776 // pAd->PortCfg.PrivacyInvoked = CAP_IS_PRIVACY_ON(CapabilityInfo);
778 pAd->PortCfg.LastBeaconRxTime = Now;
779 #if 1
780 // at least one 11b peer joined. downgrade the MaxTxRate to 11Mbps
781 // after last 11b peer left for several seconds, we'll auto switch back to 11G rate
782 // in MlmePeriodicExec()
783 if (ADHOC_ON(pAd) && (RatesLen <= 4))
785 // this timestamp is for MlmePeriodicExec() to check if all 11B peers have left
786 pAd->PortCfg.Last11bBeaconRxTime = Now;
788 if (pAd->PortCfg.MaxTxRate > RATE_11)
790 DBGPRINT(RT_DEBUG_TRACE, "SYNC - 11b peer joined. down-grade to 11b TX rates \n");
791 NdisMoveMemory(pAd->PortCfg.SupportedRates, Rates, MAX_LEN_OF_SUPPORTED_RATES);
792 pAd->PortCfg.SupportedRatesLen = RatesLen;
793 MlmeUpdateTxRates(pAd, FALSE);
794 MakeIbssBeacon(pAd); // supported rates changed
797 #endif
798 // check if RSSI reaches threshold
799 pAd->PortCfg.LastRssi = (pAd->PortCfg.LastRssi + Elem->Rssi) / 2;
800 pAd->PortCfg.AvgRssi = (pAd->PortCfg.AvgRssi * 7 + Elem->Rssi) >> 3;
801 if ((pAd->PortCfg.RssiTriggerMode == RSSI_TRIGGERED_UPON_BELOW_THRESHOLD) &&
802 (pAd->PortCfg.LastRssi < pAd->PortCfg.RssiTrigger))
804 // NDIS_802_11_RSSI Dbm = pAd->PortCfg.LastRssi - RSSI_TO_DBM_OFFSET;
805 // DBGPRINT(RT_DEBUG_TRACE, "SYNC - NdisMIndicateStatus *** RSSI %d dBm, less than threshold %d dBm\n",
806 // Dbm, pAd->PortCfg.RssiTrigger - RSSI_TO_DBM_OFFSET);
808 else if ((pAd->PortCfg.RssiTriggerMode == RSSI_TRIGGERED_UPON_EXCCEED_THRESHOLD) &&
809 (pAd->PortCfg.LastRssi > pAd->PortCfg.RssiTrigger))
811 // NDIS_802_11_RSSI Dbm = pAd->PortCfg.LastRssi - RSSI_TO_DBM_OFFSET;
812 // DBGPRINT(RT_DEBUG_TRACE, "SYNC - NdisMIndicateStatus *** RSSI %d dBm, greater than threshold %d dBm\n",
813 // Dbm, pAd->PortCfg.RssiTrigger - RSSI_TO_DBM_OFFSET);
816 if (INFRA_ON(pAd)) // && (pAd->PortCfg.PhyMode == PHY_11BG_MIXED))
818 BOOLEAN bUseShortSlot, bUseBGProtection;
820 // decide to use/change to -
821 // 1. long slot (20 us) or short slot (9 us) time
822 // 2. turn on/off RTS/CTS and/or CTS-to-self protection
823 // 3. short preamble
824 bUseShortSlot = (pAd->PortCfg.UseShortSlotTime == TRUE) && CAP_IS_SHORT_SLOT_TIME(CapabilityInfo);
825 if (bUseShortSlot != pAd->PortCfg.ShortSlotInUsed)
826 AsicSetSlotTime(pAd, bUseShortSlot);
828 bUseBGProtection = (pAd->PortCfg.UseBGProtection == 1) || // always use
829 ((pAd->PortCfg.UseBGProtection == 0) && ERP_IS_USE_PROTECTION(Erp));
830 if (bUseBGProtection != pAd->PortCfg.BGProtectionInUsed)
832 pAd->PortCfg.BGProtectionInUsed = bUseBGProtection;
833 DBGPRINT(RT_DEBUG_TRACE, "SYNC - AP changed B/G protection to %d\n", bUseBGProtection);
836 if ((pAd->PortCfg.TxPreambleInUsed == Rt802_11PreambleShort) && ERP_IS_USE_BARKER_PREAMBLE(Erp))
838 MlmeSetTxPreamble(pAd, Rt802_11PreambleLong);
839 DBGPRINT(RT_DEBUG_TRACE, "SYNC - AP forced to use LONG preamble\n");
843 // only INFRASTRUCTURE mode support power-saving feature
844 if (INFRA_ON(pAd) && (pAd->PortCfg.Psm == PWR_SAVE))
846 // 1. AP has backlogged unicast-to-me frame, stay AWAKE, send PSPOLL
847 // 2. AP has backlogged broadcast/multicast frame and we want those frames, stay AWAKE
848 // 3. we have outgoing frames in TxRing or PrioRing, better stay AWAKE
849 // 4. Psm change to PWR_SAVE, but AP not been informed yet, we better stay AWAKE
850 // 5. otherwise, put PHY back to sleep to save battery.
851 if (MessageToMe)
853 DBGPRINT(RT_DEBUG_TRACE, "SYNC - AP backlog unicast-to-me, stay AWAKE, send PSPOLL\n");
854 EnqueuePsPoll(pAd);
856 else if (BcastFlag && (DtimCount == 0) && pAd->PortCfg.RecvDtim)
858 DBGPRINT(RT_DEBUG_TRACE, "SYNC - AP backlog broadcast/multicast, stay AWAKE\n");
860 else if ((RTMPFreeDescriptorRequest(pAd, TX_RING, TX_RING_SIZE) != NDIS_STATUS_SUCCESS) ||
861 (RTMPFreeDescriptorRequest(pAd, PRIO_RING, PRIO_RING_SIZE) != NDIS_STATUS_SUCCESS))
863 DBGPRINT(RT_DEBUG_TRACE, "SYNC - outgoing frame in TxRing/PrioRing, stay AWAKE\n");
865 else
867 USHORT NextDtim = DtimCount;
869 if (NextDtim == 0)
870 NextDtim = DtimPeriod;
872 TbttNumToNextWakeUp = pAd->PortCfg.DefaultListenCount;
873 if (pAd->PortCfg.RecvDtim && (TbttNumToNextWakeUp > NextDtim))
874 TbttNumToNextWakeUp = NextDtim;
876 DBGPRINT(RT_DEBUG_TRACE, "SYNC - PHY sleeps for %d Tbcn, Dtim=%d/%d\n", TbttNumToNextWakeUp, DtimCount, DtimPeriod);
877 AsicSleepThenAutoWakeup(pAd, TbttNumToNextWakeUp);
881 #ifndef SINGLE_ADHOC_LINKUP
882 // At least another peer in this IBSS, declare MediaState as CONNECTED
883 if (ADHOC_ON(pAd) && (pAd->MediaState == NdisMediaStateDisconnected))
885 pAd->MediaState = NdisMediaStateConnected;
887 // 2003/03/12 - john
888 // Make sure this entry in "PortCfg.BssTab" table, thus complies to Microsoft's policy that
889 // "site survey" result should always include the current connected network.
891 Bssidx = BssTableSearch(&pAd->PortCfg.BssTab, &Bssid);
892 if (Bssidx == BSS_NOT_FOUND)
894 Bssidx = BssTableSetEntry(pAd, &pAd->PortCfg.BssTab, &Bssid, Ssid, SsidLen,
895 BssType, BeaconPeriod, CfExist, &CfParm, AtimWin, CapabilityInfo,
896 Rates, RatesLen, ExtendedRateIeExist, Channel, Elem->Rssi, TimeStamp, pVIE);
899 #endif
901 // not my BSSID, ignore it
903 // sanity check fail, ignore this frame
907 ==========================================================================
908 Description:
909 Receive PROBE REQ from remote peer when operating in IBSS mode
910 ==========================================================================
912 VOID PeerProbeReqAction(
913 IN PRTMP_ADAPTER pAd,
914 IN MLME_QUEUE_ELEM *Elem)
916 MACADDR Addr2;
917 CHAR Ssid[MAX_LEN_OF_SSID];
918 UCHAR SsidLen;
919 MACHDR ProbeRspHdr;
920 NDIS_STATUS NStatus;
921 UCHAR *OutBuffer = NULL;
922 ULONG FrameLen = 0;
923 LARGE_INTEGER FakeTimestamp;
924 UCHAR SsidIe = IE_SSID, DsIe = IE_DS_PARM, IbssIe = IE_IBSS_PARM, SuppIe = IE_SUPP_RATES,
925 DsLen = 1, IbssLen = 2;
926 UCHAR SupportedRatesLen;
927 UCHAR SupportedRates[MAX_LEN_OF_SUPPORTED_RATES];
928 UCHAR ExtRateIe = IE_EXT_SUPP_RATES, ExtRatesLen;
929 UCHAR ErpIe[3] = {IE_ERP, 1, 0};
931 if (! ADHOC_ON(pAd))
932 return;
934 if (PeerProbeReqSanity(pAd, Elem->Msg, Elem->MsgLen, &Addr2, Ssid, &SsidLen)) //, Rates, &RatesLen))
936 if ((SsidLen == 0) || RTMPEqualMemory(Ssid, pAd->PortCfg.Ssid, (ULONG) SsidLen))
938 CSR15_STRUC Csr15;
940 // we should respond a ProbeRsp only when we're the last BEACON transmitter
941 // in this ADHOC network.
942 RTMP_IO_READ32(pAd, CSR15, &Csr15.word);
943 if (Csr15.field.BeaconSent == 0)
945 DBGPRINT(RT_DEBUG_INFO, "SYNC - NOT last BEACON sender, no PROBE_RSP to %02x:%02x:%02x:%02x:%02x:%02x...\n",
946 Addr2.Octet[0],Addr2.Octet[1],Addr2.Octet[2],Addr2.Octet[3],Addr2.Octet[4],Addr2.Octet[5] );
947 return;
950 // 2003-12-10 802.11g WIFI spec disallow OFDM rates in 802.11g ADHOC mode
951 // make sure 1,2,5.5,11 are the firt 4 rates in PortCfg.SupportedRates[] array
952 if ((pAd->PortCfg.PhyMode == PHY_11BG_MIXED) && (pAd->PortCfg.AdhocMode == 0))
954 int i;
955 SupportedRatesLen=0;
956 for (i=0;i<pAd->PortCfg.SupportedRatesLen;i++)
958 switch (pAd->PortCfg.SupportedRates[i] & 0x7f)
960 case 2:
961 case 4:
962 case 11:
963 case 22:
964 SupportedRates[SupportedRatesLen] = pAd->PortCfg.SupportedRates[i];
965 SupportedRatesLen ++;
966 break;
967 default:
968 break;
971 // error handling - should never happen
972 if (SupportedRatesLen != 4)
974 SupportedRatesLen = 4;
975 SupportedRates[0] = 0x82;
976 SupportedRates[1] = 0x84;
977 SupportedRates[2] = 0x8b;
978 SupportedRates[3] = 0x96;
981 else
983 SupportedRatesLen = pAd->PortCfg.SupportedRatesLen;
984 NdisMoveMemory(SupportedRates, pAd->PortCfg.SupportedRates, SupportedRatesLen);
987 // allocate and send out ProbeRsp frame
988 NStatus = MlmeAllocateMemory(pAd, (PVOID)&OutBuffer); //Get an unused nonpaged memory
989 if (NStatus != NDIS_STATUS_SUCCESS)
990 return;
992 pAd->PortCfg.AtimWin = 0; // ??????
993 DBGPRINT(RT_DEBUG_TRACE, "SYNC - Send PROBE_RSP to %02x:%02x:%02x:%02x:%02x:%02x...\n",
994 Addr2.Octet[0],Addr2.Octet[1],Addr2.Octet[2],Addr2.Octet[3],Addr2.Octet[4],Addr2.Octet[5] );
995 MgtMacHeaderInit(pAd, &ProbeRspHdr, SUBTYPE_PROBE_RSP, 0, &Addr2, &pAd->PortCfg.Bssid);
997 if (SupportedRatesLen <= 8)
999 MakeOutgoingFrame(OutBuffer, &FrameLen,
1000 MAC_HDR_LEN, &ProbeRspHdr,
1001 TIMESTAMP_LEN, &FakeTimestamp,
1002 2, &pAd->PortCfg.BeaconPeriod,
1003 2, &pAd->PortCfg.CapabilityInfo,
1004 1, &SsidIe,
1005 1, &pAd->PortCfg.SsidLen,
1006 pAd->PortCfg.SsidLen, pAd->PortCfg.Ssid,
1007 1, &SuppIe,
1008 1, &SupportedRatesLen,
1009 SupportedRatesLen, SupportedRates,
1010 1, &DsIe,
1011 1, &DsLen,
1012 1, &pAd->PortCfg.Channel,
1013 1, &IbssIe,
1014 1, &IbssLen,
1015 2, &pAd->PortCfg.AtimWin,
1016 END_OF_ARGS);
1018 else
1020 ExtRatesLen = SupportedRatesLen - 8;
1021 SupportedRatesLen = 8;
1022 MakeOutgoingFrame(OutBuffer, &FrameLen,
1023 MAC_HDR_LEN, &ProbeRspHdr,
1024 TIMESTAMP_LEN, &FakeTimestamp,
1025 2, &pAd->PortCfg.BeaconPeriod,
1026 2, &pAd->PortCfg.CapabilityInfo,
1027 1, &SsidIe,
1028 1, &pAd->PortCfg.SsidLen,
1029 pAd->PortCfg.SsidLen, pAd->PortCfg.Ssid,
1030 1, &SuppIe,
1031 1, &SupportedRatesLen,
1032 SupportedRatesLen, SupportedRates,
1033 1, &DsIe,
1034 1, &DsLen,
1035 1, &pAd->PortCfg.Channel,
1036 1, &IbssIe,
1037 1, &IbssLen,
1038 2, &pAd->PortCfg.AtimWin,
1039 3, ErpIe,
1040 1, &ExtRateIe,
1041 1, &ExtRatesLen,
1042 ExtRatesLen, &SupportedRates[SupportedRatesLen],
1043 END_OF_ARGS);
1045 // If adhoc secruity is set for WPA-None, append the cipher suite IE
1046 if (pAd->PortCfg.AuthMode == Ndis802_11AuthModeWPANone)
1048 ULONG tmp;
1049 UCHAR WpaIe = IE_WPA;
1051 if (pAd->PortCfg.WepStatus == Ndis802_11Encryption2Enabled) // Tkip
1053 MakeOutgoingFrame(OutBuffer + FrameLen, &tmp,
1054 1, &WpaIe,
1055 1, &CipherSuiteWpaNoneTkipLen,
1056 CipherSuiteWpaNoneTkipLen, &CipherSuiteWpaNoneTkip[0],
1057 END_OF_ARGS);
1058 FrameLen += tmp;
1060 else if (pAd->PortCfg.WepStatus == Ndis802_11Encryption3Enabled) // Aes
1062 MakeOutgoingFrame(OutBuffer + FrameLen, &tmp,
1063 1, &WpaIe,
1064 1, &CipherSuiteWpaNoneAesLen,
1065 CipherSuiteWpaNoneAesLen, &CipherSuiteWpaNoneAes[0],
1066 END_OF_ARGS);
1067 FrameLen += tmp;
1070 MiniportMMRequest(pAd, OutBuffer, FrameLen);
1075 VOID BeaconTimeoutAtJoinAction(
1076 IN PRTMP_ADAPTER pAd,
1077 IN MLME_QUEUE_ELEM *Elem)
1079 DBGPRINT(RT_DEBUG_TRACE, "SYNC - BeaconTimeoutAtJoinAction\n");
1080 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
1081 MlmeCntlConfirm(pAd, MT2_JOIN_CONF, MLME_REJ_TIMEOUT);
1085 ==========================================================================
1086 Description:
1087 Scan timeout procedure. basically add channel index by 1 and rescan
1088 ==========================================================================
1090 VOID ScanTimeoutAction(
1091 IN PRTMP_ADAPTER pAd,
1092 IN MLME_QUEUE_ELEM *Elem)
1094 pAd->Mlme.SyncAux.Channel = NextChannel(pAd, pAd->Mlme.SyncAux.Channel);
1095 ScanNextChannel(pAd);
1099 ==========================================================================
1100 Description:
1101 Scan next channel
1102 ==========================================================================
1104 VOID ScanNextChannel(
1105 IN PRTMP_ADAPTER pAd)
1107 MACHDR Hdr;
1108 UCHAR SsidIe = IE_SSID, SuppRateIe = IE_SUPP_RATES;
1109 VOID *OutBuffer = NULL;
1110 VOID *OutBuffer2 = NULL;
1111 NDIS_STATUS NStatus;
1112 ULONG FrameLen = 0;
1113 UCHAR SsidLen = 0;
1115 // DBGPRINT(RT_DEBUG_TRACE, "ScanNextChannel=%X\n", ScanNextChannel);
1116 if (pAd->Mlme.SyncAux.Channel == 0)
1118 DBGPRINT(RT_DEBUG_TRACE, "SYNC - End of SCAN, restore to channel %d\n",pAd->PortCfg.Channel);
1119 AsicSwitchChannel(pAd, pAd->PortCfg.Channel);
1120 AsicLockChannel(pAd, pAd->PortCfg.Channel);
1122 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
1123 MlmeCntlConfirm(pAd, MT2_SCAN_CONF, MLME_SUCCESS);
1125 else
1127 AsicSwitchChannel(pAd, pAd->Mlme.SyncAux.Channel);
1129 // Total SCAN time still limits within 3 sec (DDK constraint).
1130 // TODO: We need more intelligent rules here to further improve out-of-service issue.
1131 // e.g. temporary stop copying NDIS packet to TxRing until SCAN complete
1132 // if (INFRA_ON(pAd) || ADHOC_ON(pAd))
1134 // We need to shorten active scan time in order for WZC connect issue
1135 if (pAd->Mlme.SyncAux.ScanType == SCAN_ACTIVE)
1136 RTMPSetTimer(pAd, &pAd->Mlme.SyncAux.ScanTimer, ACTIVE_SCAN_TIME);
1137 else if (pAd->PortCfg.PhyMode == PHY_11ABG_MIXED)
1138 RTMPSetTimer(pAd, &pAd->Mlme.SyncAux.ScanTimer, MIN_CHANNEL_TIME);
1139 else
1140 RTMPSetTimer(pAd, &pAd->Mlme.SyncAux.ScanTimer, MAX_CHANNEL_TIME);
1142 MgtMacHeaderInit(pAd, &Hdr, SUBTYPE_PROBE_REQ, 0, &pAd->PortCfg.Broadcast, &pAd->PortCfg.Broadcast);
1143 // There is no need to send broadcast probe request if active scan is in effect.
1144 // The same rulr should apply to passive scan also.
1145 if (pAd->Mlme.SyncAux.ScanType == SCAN_PASSIVE)
1147 // Send the first probe request with empty SSID
1148 NStatus = MlmeAllocateMemory(pAd, (PVOID)&OutBuffer); //Get an unused nonpaged memory
1149 if (NStatus != NDIS_STATUS_SUCCESS)
1151 DBGPRINT(RT_DEBUG_TRACE, "SYNC 1- ScanNextChannel() allocate memory fail\n");
1152 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
1153 MlmeCntlConfirm(pAd, MT2_SCAN_CONF, MLME_FAIL_NO_RESOURCE);
1154 return;
1157 DBGPRINT(RT_DEBUG_INFO, "SYNC - send passive ProbeReq @ channel=%d...\n", pAd->Mlme.SyncAux.Channel);
1158 SsidLen = 0;
1159 MakeOutgoingFrame(OutBuffer, &FrameLen,
1160 sizeof(MACHDR), (UCHAR*)&Hdr,
1161 1, &SsidIe,
1162 1, &SsidLen,
1163 1, &SuppRateIe,
1164 1, &pAd->PortCfg.SupportedRatesLen,
1165 pAd->PortCfg.SupportedRatesLen, pAd->PortCfg.SupportedRates,
1166 END_OF_ARGS);
1167 MiniportMMRequest(pAd, OutBuffer, FrameLen);
1169 else if (pAd->Mlme.SyncAux.ScanType == SCAN_ACTIVE)
1171 // Allocate another for probe scan with SSID
1172 NStatus = MlmeAllocateMemory(pAd, (PVOID)&OutBuffer2); //Get an unused nonpaged memory
1173 if (NStatus != NDIS_STATUS_SUCCESS)
1175 DBGPRINT(RT_DEBUG_TRACE, "SYNC 2- ScanNextChannel() allocate memory fail\n");
1176 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
1177 MlmeCntlConfirm(pAd, MT2_SCAN_CONF, MLME_FAIL_NO_RESOURCE);
1178 return;
1180 // make another probe scan with SSID from mlme.cntlaux.ssid
1181 SsidLen = pAd->Mlme.SyncAux.SsidLen;
1182 MakeOutgoingFrame(OutBuffer2, &FrameLen,
1183 sizeof(MACHDR), &Hdr,
1184 1, &SsidIe,
1185 1, &SsidLen,
1186 SsidLen, pAd->Mlme.SyncAux.Ssid,
1187 1, &SuppRateIe,
1188 1, &pAd->PortCfg.SupportedRatesLen,
1189 pAd->PortCfg.SupportedRatesLen, pAd->PortCfg.SupportedRates,
1190 END_OF_ARGS);
1191 MiniportMMRequest(pAd, OutBuffer2, FrameLen);
1193 DBGPRINT(RT_DEBUG_INFO, "SYNC - send active ProbeReq @ channel=%d...\n", pAd->Mlme.SyncAux.Channel);
1196 pAd->Mlme.SyncMachine.CurrState = SCAN_LISTEN;
1201 ==========================================================================
1202 Description:
1203 ==========================================================================
1205 VOID InvalidStateWhenScan(
1206 IN PRTMP_ADAPTER pAd,
1207 IN MLME_QUEUE_ELEM *Elem)
1209 DBGPRINT(RT_DEBUG_TRACE, "AYNC - InvalidStateWhenScan(state=%d). Reset SYNC machine\n", pAd->Mlme.SyncMachine.CurrState);
1210 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
1211 MlmeCntlConfirm(pAd, MT2_SCAN_CONF, MLME_STATE_MACHINE_REJECT);
1215 ==========================================================================
1216 Description:
1217 ==========================================================================
1219 VOID InvalidStateWhenJoin(
1220 IN PRTMP_ADAPTER pAd,
1221 IN MLME_QUEUE_ELEM *Elem)
1223 DBGPRINT(RT_DEBUG_TRACE, "InvalidStateWhenJoin(state=%d). Reset SYNC machine\n", pAd->Mlme.SyncMachine.CurrState);
1224 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
1225 MlmeCntlConfirm(pAd, MT2_JOIN_CONF, MLME_STATE_MACHINE_REJECT);
1229 ==========================================================================
1230 Description:
1231 ==========================================================================
1233 VOID InvalidStateWhenStart(
1234 IN PRTMP_ADAPTER pAd,
1235 IN MLME_QUEUE_ELEM *Elem)
1237 DBGPRINT(RT_DEBUG_TRACE, "InvalidStateWhenStart(state=%d). Reset SYNC machine\n", pAd->Mlme.SyncMachine.CurrState);
1238 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
1239 MlmeCntlConfirm(pAd, MT2_START_CONF, MLME_STATE_MACHINE_REJECT);
1243 ==========================================================================
1244 Description:
1245 ==========================================================================
1247 VOID EnqueuePsPoll(
1248 IN PRTMP_ADAPTER pAd)
1250 NDIS_STATUS NState;
1251 PSPOLL_FRAME *PsFr;
1253 DBGPRINT(RT_DEBUG_TRACE, "SYNC - send PsPoll ...\n");
1255 NState = MlmeAllocateMemory(pAd, (PVOID)&PsFr); //Get an unused nonpaged memory
1256 if (NState == NDIS_STATUS_SUCCESS)
1258 NdisMoveMemory((VOID *)PsFr, (VOID *)&pAd->Mlme.PsFr, sizeof(PSPOLL_FRAME));
1259 MiniportMMRequest(pAd, (VOID *)PsFr, sizeof(PSPOLL_FRAME));
1263 // 2003-04-17 john
1264 // driver force send out a BEACON frame to cover ADHOC mode BEACON starving issue
1265 // that is, in ADHOC mode, driver guarantee itself can send out at least a BEACON
1266 // per a specified duration, even the peer's clock is faster than us and win all the
1267 // hardware-based BEACON TX oppertunity.
1268 // we may remove this software feature once 2560 IC fix this problem in ASIC.
1269 VOID EnqueueBeaconFrame(
1270 IN PRTMP_ADAPTER pAd)
1272 NDIS_STATUS NState;
1273 PTXD_STRUC pTxD = (PTXD_STRUC)pAd->BeaconRing.va_addr;
1274 CHAR *pBeacon;
1275 LARGE_INTEGER Tsf;
1277 NState = MlmeAllocateMemory(pAd, (PVOID)&pBeacon); //Get an unused nonpaged memory
1278 if (NState == NDIS_STATUS_SUCCESS)
1280 DBGPRINT(RT_DEBUG_TRACE, "SYNC - driver sent BEACON (len=%d)...\n",pTxD->DataByteCnt);
1281 RTMP_IO_READ32(pAd, CSR17, &Tsf.u.HighPart);
1282 RTMP_IO_READ32(pAd, CSR16, &Tsf.u.LowPart);
1283 NdisMoveMemory(pBeacon, pAd->BeaconRing.va_data_addr, pTxD->DataByteCnt);
1284 NdisMoveMemory(pBeacon + MAC_HDR_LEN, &Tsf, TIMESTAMP_LEN);
1285 MiniportMMRequest(pAd, (VOID *)pBeacon, pTxD->DataByteCnt);
1290 ==========================================================================
1291 Description:
1292 Send out a NULL frame to AP. The prpose is to inform AP this client
1293 current PSM bit.
1294 NOTE:
1295 This routine should only be used in infrastructure mode.
1296 ==========================================================================
1298 VOID EnqueueNullFrame(
1299 IN PRTMP_ADAPTER pAd,
1300 IN UCHAR TxRate)
1302 NDIS_STATUS NState;
1303 MACHDR *NullFr;
1305 // since TxRate may change, we have to change Duration each time
1306 pAd->Mlme.NullFr.Duration = RTMPCalcDuration(pAd, TxRate, 14);
1307 NState = MlmeAllocateMemory(pAd, (PVOID)&NullFr); //Get an unused nonpaged memory
1308 if (NState == NDIS_STATUS_SUCCESS)
1310 NdisMoveMemory((VOID *)NullFr, (VOID *)&pAd->Mlme.NullFr, sizeof(MACHDR));
1311 RTMPSendNullFrame(pAd, (VOID *)NullFr, sizeof(MACHDR), TxRate);
1316 ==========================================================================
1317 Description:
1318 ==========================================================================
1320 VOID EnqueueProbeRequest(
1321 IN PRTMP_ADAPTER pAd)
1323 NDIS_STATUS NState;
1324 UCHAR SsidIe = IE_SSID, SuppRateIe = IE_SUPP_RATES;
1325 VOID *OutBuffer;
1326 ULONG FrameLen = 0;
1327 MACHDR Hdr;
1329 DBGPRINT(RT_DEBUG_TRACE, "force out a ProbeRequest ...\n");
1331 NState = MlmeAllocateMemory(pAd, (PVOID)&OutBuffer); //Get an unused nonpaged memory
1332 if (NState == NDIS_STATUS_SUCCESS)
1334 MgtMacHeaderInit(pAd, &Hdr, SUBTYPE_PROBE_REQ, 0, &pAd->PortCfg.Broadcast, &pAd->PortCfg.Broadcast);
1336 // this ProbeRequest explicitly specify SSID to reduce unwanted ProbeResponse
1337 MakeOutgoingFrame(OutBuffer, &FrameLen,
1338 sizeof(MACHDR), &Hdr,
1339 1, &SsidIe,
1340 1, &pAd->PortCfg.SsidLen,
1341 pAd->PortCfg.SsidLen, pAd->PortCfg.Ssid,
1342 1, &SuppRateIe,
1343 1, &pAd->PortCfg.SupportedRatesLen,
1344 pAd->PortCfg.SupportedRatesLen, pAd->PortCfg.SupportedRates,
1345 END_OF_ARGS);
1346 MiniportMMRequest(pAd, OutBuffer, FrameLen);
1351 ==========================================================================
1352 Description:
1353 Update PortCfg->ChannelList[] according to 1) Country Region 2) RF IC type,
1354 and 3) PHY-mode user selected.
1355 The outcome is used by driver when doing site survey.
1356 ==========================================================================
1358 VOID BuildChannelList(
1359 IN PRTMP_ADAPTER pAd)
1361 UCHAR i, index = 0;
1362 NdisZeroMemory(pAd->PortCfg.ChannelList, MAX_LEN_OF_CHANNELS);
1364 // if not 11a-only mode, channel list starts from 2.4Ghz band
1365 if (pAd->PortCfg.PhyMode != PHY_11A)
1367 switch (pAd->PortCfg.CountryRegion)
1369 case REGION_FCC: // 1 - 11
1370 NdisMoveMemory(&pAd->PortCfg.ChannelList[index], Ra24Ghz_FCC, sizeof(Ra24Ghz_FCC));
1371 index += sizeof(Ra24Ghz_FCC);
1372 break;
1373 case REGION_IC: // 1 -11
1374 NdisMoveMemory(&pAd->PortCfg.ChannelList[index], Ra24Ghz_IC, sizeof(Ra24Ghz_IC));
1375 index += sizeof(Ra24Ghz_IC);
1376 break;
1377 case REGION_ISRAEL: // 3 - 9
1378 NdisMoveMemory(&pAd->PortCfg.ChannelList[index], Ra24Ghz_ISRAEL, sizeof(Ra24Ghz_ISRAEL));
1379 index += sizeof(Ra24Ghz_ISRAEL);
1380 break;
1381 case REGION_ETSI: // 1 - 13
1382 NdisMoveMemory(&pAd->PortCfg.ChannelList[index], Ra24Ghz_ESTI, sizeof(Ra24Ghz_ESTI));
1383 index += sizeof(Ra24Ghz_ESTI);
1384 break;
1385 case REGION_SPAIN: // 10 - 11
1386 NdisMoveMemory(&pAd->PortCfg.ChannelList[index], Ra24Ghz_SPAIN, sizeof(Ra24Ghz_SPAIN));
1387 index += sizeof(Ra24Ghz_SPAIN);
1388 break;
1389 case REGION_FRANCE: // 10 -13
1390 NdisMoveMemory(&pAd->PortCfg.ChannelList[index], Ra24Ghz_FRANCE, sizeof(Ra24Ghz_FRANCE));
1391 index += sizeof(Ra24Ghz_FRANCE);
1392 break;
1393 case REGION_MKK: // 14
1394 NdisMoveMemory(&pAd->PortCfg.ChannelList[index], Ra24Ghz_MKK, sizeof(Ra24Ghz_MKK));
1395 index += sizeof(Ra24Ghz_MKK);
1396 break;
1397 case REGION_MKK1: // 1 - 14
1398 NdisMoveMemory(&pAd->PortCfg.ChannelList[index], Ra24Ghz_MKK1, sizeof(Ra24Ghz_MKK1));
1399 index += sizeof(Ra24Ghz_MKK1);
1400 break;
1401 default: // Error. should never happen
1402 break;
1406 if ((pAd->PortCfg.PhyMode == PHY_11A) || (pAd->PortCfg.PhyMode == PHY_11ABG_MIXED))
1408 #if 0
1409 switch (pAd->PortCfg.CountryRegion)
1411 case REGION_FCC: // UNII <36,40,44,48,52,56,60,64> <149,153,157,161>
1412 case REGION_IC: // UNII <36,40,44,48,52,56,60,64> <149,153,157,161>
1413 case REGION_ISRAEL: // UNII <36,40,44,48,52,56,60,64> <149,153,157,161>
1414 NdisMoveMemory(&pAd->PortCfg.ChannelList[index], Ra5Ghz_UNII, sizeof(Ra5Ghz_UNII));
1415 index += sizeof(Ra5Ghz_UNII);
1416 break;
1417 case REGION_ETSI: // HiperLAN2 <36,40,44,48,52,56,60,64> <100,104,108,112,116,120,124,128,132,136,140>
1418 case REGION_SPAIN: // HiperLAN2 <36,40,44,48,52,56,60,64> <100,104,108,112,116,120,124,128,132,136,140>
1419 case REGION_FRANCE: // HiperLAN2 <36,40,44,48,52,56,60,64> <100,104,108,112,116,120,124,128,132,136,140>
1420 NdisMoveMemory(&pAd->PortCfg.ChannelList[index], Ra5Ghz_HyperLAN2, sizeof(Ra5Ghz_HyperLAN2));
1421 index += sizeof(Ra5Ghz_HyperLAN2);
1422 break;
1423 case REGION_MKK: // Japan MMAC <34,38,42,46>
1424 case REGION_MKK1: // Japan MMAC <34,38,42,46>
1425 NdisMoveMemory(&pAd->PortCfg.ChannelList[index], Ra5Ghz_MMAC, sizeof(Ra5Ghz_MMAC));
1426 index += sizeof(Ra5Ghz_MMAC);
1427 break;
1428 default: // Error. should never happen
1429 break;
1431 #else
1432 // 2003-10-05 john - use UNII temoparaily for all regulation domains for easy test untill
1433 // RF guys confirm the supported channel plans
1434 NdisMoveMemory(&pAd->PortCfg.ChannelList[index], Ra5Ghz_UNII, sizeof(Ra5Ghz_UNII));
1435 index += sizeof(Ra5Ghz_UNII);
1436 #endif
1439 pAd->PortCfg.ChannelListNum = index;
1440 DBGPRINT(RT_DEBUG_TRACE,"country code=%d, RFIC=%d, PHY mode=%d, support %d channels\n",
1441 pAd->PortCfg.CountryRegion, pAd->PortCfg.RfType, pAd->PortCfg.PhyMode, pAd->PortCfg.ChannelListNum);
1442 for (i=0;i<index;i++)
1444 DBGPRINT(RT_DEBUG_TRACE,"channel #%d\n", pAd->PortCfg.ChannelList[i]);
1449 ==========================================================================
1450 Description:
1451 This routine return the first channel number according to the country
1452 code selection and RF IC selection (signal band or dual band). It is called
1453 whenever driver need to start a site survey of all supported channels.
1454 Return:
1455 ch - the first channel number of current country code setting
1456 ==========================================================================
1458 UCHAR FirstChannel(
1459 IN PRTMP_ADAPTER pAd)
1461 return pAd->PortCfg.ChannelList[0];
1465 ==========================================================================
1466 Description:
1467 This routine returns the next channel number. This routine is called
1468 during driver need to start a site survey of all supported channels.
1469 Return:
1470 next_channel - the next channel number valid in current country code setting.
1471 Note:
1472 return 0 if no more next channel
1473 ==========================================================================
1475 UCHAR NextChannel(
1476 IN PRTMP_ADAPTER pAd,
1477 IN UCHAR channel)
1479 int i;
1480 UCHAR next_channel = 0;
1482 for (i = 0; i < (pAd->PortCfg.ChannelListNum - 1); i++)
1483 if (channel == pAd->PortCfg.ChannelList[i])
1485 next_channel = pAd->PortCfg.ChannelList[i+1];
1486 break;
1488 return next_channel;