|
1 /* |
|
2 * Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of the License "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: Implementation of the WlanDot11InfrastructureMode class |
|
15 * |
|
16 */ |
|
17 |
|
18 /* |
|
19 * %version: 63 % |
|
20 */ |
|
21 |
|
22 #include "config.h" |
|
23 #include "UmacDot11InfrastructureMode.h" |
|
24 #include "UmacWsaAddKey.h" |
|
25 #include "umacaddbroadcastwepkey.h" |
|
26 #include "UmacContextImpl.h" |
|
27 #include "UmacWsaKeyIndexMapper.h" |
|
28 #include "UmacWsaWriteMib.h" |
|
29 #include "umacelementlocator.h" |
|
30 #include "umacwhaconfigureac.h" |
|
31 #include "FrameXferBlock.h" |
|
32 |
|
33 |
|
34 // ================= MEMBER FUNCTIONS ======================= |
|
35 |
|
36 |
|
37 // --------------------------------------------------------------------------- |
|
38 // |
|
39 // --------------------------------------------------------------------------- |
|
40 // |
|
41 TBool WlanDot11InfrastructureMode::Connect( |
|
42 WlanContextImpl& aCtxImpl, |
|
43 const TSSID& aSSID, |
|
44 const TMacAddress& aBSSID, |
|
45 TUint16 aAuthAlgorithmNbr, |
|
46 TEncryptionStatus aEncryptionStatus, |
|
47 TBool /*aIsInfra*/, |
|
48 TUint16 aScanResponseFrameBodyLength, |
|
49 const TUint8* aScanResponseFrameBody, |
|
50 const TUint8* aIeData, |
|
51 TUint16 aIeDataLength ) |
|
52 { |
|
53 // store data for later access. |
|
54 // Pointers supplied are valid to the point the |
|
55 // corresponding completion method is called |
|
56 |
|
57 aCtxImpl.SetScanResponseFrameBody( aScanResponseFrameBody ); |
|
58 aCtxImpl.SetScanResponseFrameBodyLength( aScanResponseFrameBodyLength ); |
|
59 aCtxImpl.IeData( aIeData ); |
|
60 aCtxImpl.IeDataLength( aIeDataLength ); |
|
61 |
|
62 return Connect( |
|
63 aCtxImpl, |
|
64 aSSID, |
|
65 aBSSID, |
|
66 aAuthAlgorithmNbr, |
|
67 aEncryptionStatus |
|
68 ); |
|
69 } |
|
70 |
|
71 // --------------------------------------------------------------------------- |
|
72 // |
|
73 // --------------------------------------------------------------------------- |
|
74 // |
|
75 TBool WlanDot11InfrastructureMode::Connect( |
|
76 WlanContextImpl& aCtxImpl, |
|
77 const TSSID& aSSID, |
|
78 const TMacAddress& aBSSID, |
|
79 TUint16 aAuthAlgorithmNbr, |
|
80 TEncryptionStatus aEncryptionStatus ) |
|
81 { |
|
82 // construct disassociation frame |
|
83 // note that we don't have to set SA because we have already set it |
|
84 // in the initialize phase of the dot11 state machine |
|
85 // |
|
86 |
|
87 // set the BSSID of the existing network |
|
88 (aCtxImpl.GetDisassociationFrame()).iHeader.iBSSID = aCtxImpl.GetBssId(); |
|
89 (aCtxImpl.GetHtDisassociationFrame()).iHeader.iBSSID = aCtxImpl.GetBssId(); |
|
90 // set the DA |
|
91 (aCtxImpl.GetDisassociationFrame()).iHeader.iDA = aCtxImpl.GetBssId(); |
|
92 (aCtxImpl.GetHtDisassociationFrame()).iHeader.iDA = aCtxImpl.GetBssId(); |
|
93 |
|
94 // set current BSSID in reassociation request frame |
|
95 (aCtxImpl.GetReassociationRequestFrame()).iFixedFields.iCurrentApAddress = |
|
96 aCtxImpl.GetBssId(); |
|
97 (aCtxImpl.GetHtReassociationRequestFrame()).iFixedFields.iCurrentApAddress = |
|
98 aCtxImpl.GetBssId(); |
|
99 |
|
100 // ... and make a note that we need to perform reassociation |
|
101 // instead of association later on towards the new AP |
|
102 aCtxImpl.Reassociate( ETrue ); |
|
103 |
|
104 |
|
105 // Store parameters of the new BSS to connect to |
|
106 // |
|
107 (aCtxImpl.GetBssId())= aBSSID; |
|
108 (aCtxImpl.GetSsId()) = aSSID; |
|
109 (aCtxImpl.EncryptionStatus()) = aEncryptionStatus; |
|
110 |
|
111 // set values in authentication frame |
|
112 // |
|
113 (aCtxImpl.AuthenticationAlgorithmNumber()) = aAuthAlgorithmNbr; |
|
114 // set the BSSID field |
|
115 (aCtxImpl.GetAuthenticationFrame()).iHeader.iBSSID = aBSSID; |
|
116 (aCtxImpl.GetHtAuthenticationFrame()).iHeader.iBSSID = aBSSID; |
|
117 // set the DA field |
|
118 (aCtxImpl.GetAuthenticationFrame()).iHeader.iDA = aBSSID; |
|
119 (aCtxImpl.GetHtAuthenticationFrame()).iHeader.iDA = aBSSID; |
|
120 // set the SA field |
|
121 (aCtxImpl.GetAuthenticationFrame()).iHeader.iSA |
|
122 = aCtxImpl.iWlanMib.dot11StationId; |
|
123 (aCtxImpl.GetHtAuthenticationFrame()).iHeader.iSA |
|
124 = aCtxImpl.iWlanMib.dot11StationId; |
|
125 aCtxImpl.NetworkOperationMode( WHA::EBSS ); |
|
126 |
|
127 if ( aCtxImpl.DisassociatedByAp() ) |
|
128 { |
|
129 // if the AP has already sent us a disassociation or deauthentication |
|
130 // frame, we won't send it a disassociation frame any more. So in this |
|
131 // case we skip the dot11DisassociationPending state and go directly to |
|
132 // dot11Synchronize state. |
|
133 |
|
134 aCtxImpl.DisassociatedByAp( EFalse ); // also reset the flag |
|
135 |
|
136 ChangeState( aCtxImpl, |
|
137 *this, // prev state |
|
138 aCtxImpl.iStates.iSynchronizeState // next state |
|
139 ); |
|
140 } |
|
141 else |
|
142 { |
|
143 // the most common case, i.e. we are still associated with the current |
|
144 // AP. So make a state change to dot11DisassociationPending |
|
145 ChangeState( aCtxImpl, |
|
146 *this, // prev state |
|
147 aCtxImpl.iStates.iDisassociationPendingState // next state |
|
148 ); |
|
149 } |
|
150 |
|
151 // signal caller that state transition occurred |
|
152 return ETrue; |
|
153 } |
|
154 |
|
155 // --------------------------------------------------------------------------- |
|
156 // |
|
157 // --------------------------------------------------------------------------- |
|
158 // |
|
159 TBool WlanDot11InfrastructureMode::SetRcpiTriggerLevel( |
|
160 WlanContextImpl& aCtxImpl, |
|
161 TUint32 aRcpiTrigger) |
|
162 { |
|
163 OsTracePrint( KUmacDetails, (TUint8*) |
|
164 ("UMAC: WlanDot11InfrastructureMode::SetRcpiTriggerLevel: aRcpiTrigger: %d"), |
|
165 aRcpiTrigger ); |
|
166 |
|
167 // update the MIB. Also request the WLAN mgmt client request |
|
168 // to be completed |
|
169 return SetRcpiTriggerLevelMib(aCtxImpl, aRcpiTrigger, ETrue ); |
|
170 } |
|
171 |
|
172 // ----------------------------------------------------------------------------- |
|
173 // |
|
174 // ----------------------------------------------------------------------------- |
|
175 // |
|
176 TBool WlanDot11InfrastructureMode::SetRcpiTriggerLevelMib( |
|
177 WlanContextImpl& aCtxImpl, |
|
178 TUint32 aRcpiTrigger, |
|
179 TBool aCompleteManagementRequest ) |
|
180 { |
|
181 OsTracePrint( KUmacDetails, (TUint8*) |
|
182 ("UMAC: WlanDot11InfrastructureMode::SetRcpiTriggerLevelMib: aRcpiTrigger: %d"), |
|
183 aRcpiTrigger ); |
|
184 OsTracePrint( KUmacDetails, (TUint8*) |
|
185 ("UMAC: WlanDot11InfrastructureMode::SetRcpiTriggerLevelMib: aCompleteManagementRequest: %d"), |
|
186 aCompleteManagementRequest ); |
|
187 |
|
188 // allocate memory for the mib to write |
|
189 WHA::SrcpiThreshold* mib = static_cast<WHA::SrcpiThreshold*> |
|
190 (os_alloc( sizeof(WHA::SrcpiThreshold) )); |
|
191 |
|
192 if ( !mib ) |
|
193 { |
|
194 // allocation failed |
|
195 // simulate macnotresponding error |
|
196 OsTracePrint( KWarningLevel, (TUint8*) |
|
197 ("UMAC: WlanDot11InfrastructureMode::SetRcpiTriggerLevelMib: abort") ); |
|
198 return DoErrorIndication( aCtxImpl, WHA::KErrorMacNotResponding ); |
|
199 } |
|
200 |
|
201 mib->iThreshold = aRcpiTrigger; |
|
202 |
|
203 WlanWsaWriteMib& wha_cmd = aCtxImpl.WsaWriteMib(); |
|
204 |
|
205 wha_cmd.Set( aCtxImpl, WHA::KMibRcpiThreshold, sizeof(*mib), mib ); |
|
206 |
|
207 const TUint32 KNoNeedToCompleteManagementRequest = 0; |
|
208 |
|
209 // change global state: entry procedure triggers action |
|
210 ChangeState( aCtxImpl, |
|
211 *this, // prev state |
|
212 wha_cmd, // next state |
|
213 aCompleteManagementRequest ? KCompleteManagementRequest : |
|
214 KNoNeedToCompleteManagementRequest |
|
215 ); |
|
216 |
|
217 os_free( mib ); // release the memory |
|
218 |
|
219 // signal caller that a state transition occurred |
|
220 return ETrue; |
|
221 } |
|
222 |
|
223 // --------------------------------------------------------------------------- |
|
224 // |
|
225 // --------------------------------------------------------------------------- |
|
226 // |
|
227 void WlanDot11InfrastructureMode::OnDeauthenticateFrameRx( |
|
228 WlanContextImpl& aCtxImpl, |
|
229 TUint8* aBuffer ) |
|
230 { |
|
231 // note that the AP has disassociated us (as the AP deauthenticated us |
|
232 // we are also disassociated) |
|
233 aCtxImpl.DisassociatedByAp( ETrue ); |
|
234 aCtxImpl.StopVoiceOverWlanCallMaintenance(); |
|
235 aCtxImpl.StopKeepAlive(); |
|
236 OnInDicationEvent( aCtxImpl, EMediaDisconnect ); |
|
237 |
|
238 // release the Rx buffer |
|
239 aCtxImpl.iUmac.MarkRxBufFree( aBuffer ); |
|
240 } |
|
241 |
|
242 // --------------------------------------------------------------------------- |
|
243 // |
|
244 // --------------------------------------------------------------------------- |
|
245 // |
|
246 void WlanDot11InfrastructureMode::OnDisassociateFrameRx( |
|
247 WlanContextImpl& aCtxImpl, |
|
248 TUint8* aBuffer ) |
|
249 { |
|
250 // note that the AP has disassociated us |
|
251 aCtxImpl.DisassociatedByAp( ETrue ); |
|
252 aCtxImpl.StopVoiceOverWlanCallMaintenance(); |
|
253 aCtxImpl.StopKeepAlive(); |
|
254 OnInDicationEvent( aCtxImpl, EMediaDisconnect ); |
|
255 |
|
256 // release the Rx buffer |
|
257 aCtxImpl.iUmac.MarkRxBufFree( aBuffer ); |
|
258 } |
|
259 |
|
260 // --------------------------------------------------------------------------- |
|
261 // |
|
262 // --------------------------------------------------------------------------- |
|
263 // |
|
264 void WlanDot11InfrastructureMode::OnBeaconFrameRx( |
|
265 WlanContextImpl& aCtxImpl, |
|
266 const TAny* aFrame, |
|
267 const TUint32 aLength, |
|
268 WHA::TRcpi /*aRcpi*/, |
|
269 TUint8* aBuffer ) |
|
270 { |
|
271 OsTracePrint( KRxFrame, (TUint8*) |
|
272 ("UMAC: WlanDot11InfrastructureMode::OnBeaconFrameRx()")); |
|
273 |
|
274 // buffer begin |
|
275 const TUint8* ptr = reinterpret_cast<const TUint8*>(aFrame); |
|
276 |
|
277 // bypass mac header, timestamp fixed field, beacon interval fixed field |
|
278 // and capability fixed field |
|
279 const TUint8 offset = |
|
280 KMacHeaderLength |
|
281 + KTimeStampFixedFieldLength |
|
282 + KBeaconIntervalFixedFieldLength |
|
283 + KCapabilityInformationFixedFieldLength; |
|
284 ptr += offset; // we now point to the beginning of IEs |
|
285 |
|
286 if ( aLength > offset ) |
|
287 { |
|
288 //================================================================= |
|
289 // Check if any dynamic nw parameters, that we are monitoring, have |
|
290 // changed. If they have, take the new parameters into use |
|
291 //================================================================= |
|
292 |
|
293 WlanElementLocator elementLocator( ptr, aLength - offset ); |
|
294 |
|
295 ValidateErpParams( aCtxImpl, elementLocator ); |
|
296 |
|
297 if ( aCtxImpl.QosEnabled() ) |
|
298 { |
|
299 ValidateAcParams( aCtxImpl, elementLocator ); |
|
300 } |
|
301 else |
|
302 { |
|
303 // this is not a QoS connection => not relevant to check |
|
304 // for AC parameter changes |
|
305 } |
|
306 |
|
307 if ( aCtxImpl.HtSupportedByNw() ) |
|
308 { |
|
309 ValidateHtBssOperationParams( aCtxImpl, elementLocator ); |
|
310 } |
|
311 else |
|
312 { |
|
313 // this is not a HT connection => not relevant to check |
|
314 // for HT operation parameter changes |
|
315 } |
|
316 } |
|
317 else |
|
318 { |
|
319 // frame too short to contain any IEs => ignore it |
|
320 OsTracePrint( KRxFrame | KWarningLevel, (TUint8*) |
|
321 ("UMAC: WlanDot11InfrastructureMode::OnBeaconFrameRx: WARNING: frame too short to contain any IEs => ignored") ); |
|
322 } |
|
323 |
|
324 // release the Rx buffer |
|
325 aCtxImpl.iUmac.MarkRxBufFree( aBuffer); |
|
326 } |
|
327 |
|
328 // --------------------------------------------------------------------------- |
|
329 // |
|
330 // --------------------------------------------------------------------------- |
|
331 // |
|
332 void WlanDot11InfrastructureMode::ValidateErpParams( |
|
333 WlanContextImpl& aCtxImpl, |
|
334 WlanElementLocator& aElementLocator ) |
|
335 { |
|
336 TUint8 length( 0 ); |
|
337 const TUint8* elementData( NULL ); |
|
338 |
|
339 if ( WlanElementLocator::EWlanLocateOk == |
|
340 aElementLocator.InformationElement( |
|
341 E802Dot11ErpInformationIE, |
|
342 length, |
|
343 &elementData ) ) |
|
344 { |
|
345 // ERP IE found |
|
346 OsTracePrint( KInfoLevel, (TUint8*) |
|
347 ("UMAC: WlanDot11InfrastructureMode::ValidateErpParams(): ERP IE present")); |
|
348 |
|
349 if ( ( *elementData & KUseProtectionMask ) != aCtxImpl.ProtectionBitSet() ) |
|
350 { |
|
351 OsTracePrint( KInfoLevel, (TUint8*) |
|
352 ("UMAC: WlanDot11InfrastructureMode::ValidateErpParams(): use protection setting changed, is now: %d"), |
|
353 *elementData & KUseProtectionMask ); |
|
354 |
|
355 // use protection setting has changed, update the setting & |
|
356 // re-set the MIB |
|
357 // |
|
358 aCtxImpl.ProtectionBitSet( *elementData & KUseProtectionMask ); |
|
359 |
|
360 if ( !(aCtxImpl.WsaCmdActive()) ) |
|
361 { |
|
362 SetCtsToSelfMib( aCtxImpl ); |
|
363 } |
|
364 else |
|
365 { |
|
366 // WHA command is in progress so we must defer this access |
|
367 aCtxImpl.RegisterEvent( KSetCtsToSelf ); |
|
368 } |
|
369 } |
|
370 } |
|
371 } |
|
372 |
|
373 // --------------------------------------------------------------------------- |
|
374 // |
|
375 // --------------------------------------------------------------------------- |
|
376 // |
|
377 void WlanDot11InfrastructureMode::ValidateAcParams( |
|
378 WlanContextImpl& aCtxImpl, |
|
379 WlanElementLocator& aElementLocator ) |
|
380 { |
|
381 TUint8 length( 0 ); |
|
382 const TUint8* elementData( NULL ); |
|
383 |
|
384 // is WMM Parameter Element present |
|
385 if ( aElementLocator.InformationElement( |
|
386 E802Dot11VendorSpecificIE, |
|
387 KWmmElemOui, |
|
388 KWmmElemOuiType, |
|
389 KWmmParamElemOuiSubtype, |
|
390 length, |
|
391 &elementData ) |
|
392 == WlanElementLocator::EWlanLocateOk ) |
|
393 { |
|
394 // element found |
|
395 OsTracePrint( KQos, (TUint8*) |
|
396 ("UMAC: WlanDot11InfrastructureMode::ValidateAcParams(): WMM param elem present")); |
|
397 |
|
398 if ( (reinterpret_cast<const SWmmParamElemData*>(elementData))->ParameterSetCount() |
|
399 != aCtxImpl.WmmParameterSetCount() ) |
|
400 { |
|
401 // AC parameters have changed => parse them again |
|
402 // |
|
403 OsTracePrint( KQos, (TUint8*) |
|
404 ("UMAC: WlanDot11InfrastructureMode::ValidateAcParams(): WMM param set count changed (value: %d) => params changed"), |
|
405 (reinterpret_cast<const SWmmParamElemData*>(elementData))->ParameterSetCount() ); |
|
406 |
|
407 ParseAcParameters( aCtxImpl, |
|
408 reinterpret_cast<const SWmmParamElemData&>(*elementData ) ); |
|
409 |
|
410 // we also need to configure the ACs again |
|
411 // |
|
412 if ( !(aCtxImpl.WsaCmdActive()) ) |
|
413 { |
|
414 ConfigureAcParams( aCtxImpl ); |
|
415 } |
|
416 else |
|
417 { |
|
418 // WHA command is in progress so we must defer this access |
|
419 aCtxImpl.RegisterEvent( KAcParamUpdate ); |
|
420 } |
|
421 } |
|
422 } |
|
423 } |
|
424 |
|
425 // --------------------------------------------------------------------------- |
|
426 // |
|
427 // --------------------------------------------------------------------------- |
|
428 // |
|
429 void WlanDot11InfrastructureMode::ValidateHtBssOperationParams( |
|
430 WlanContextImpl& aCtxImpl, |
|
431 WlanElementLocator& aElementLocator ) |
|
432 { |
|
433 TUint8 length( 0 ); |
|
434 const TUint8* elementData( NULL ); |
|
435 |
|
436 if ( WlanElementLocator::EWlanLocateOk == |
|
437 aElementLocator.InformationElement( |
|
438 E802Dot11HtOperationIE, |
|
439 length, |
|
440 &elementData ) ) |
|
441 { |
|
442 // HT Operation element found |
|
443 OsTracePrint( KInfoLevel, (TUint8*) |
|
444 ("UMAC: WlanDot11InfrastructureMode::ValidateHtBssOperationParams: element present")); |
|
445 |
|
446 if ( os_memcmp( |
|
447 elementData, |
|
448 &(aCtxImpl.GetNwHtOperationIe().iData), |
|
449 sizeof( SHtOperationIeData ) ) ) |
|
450 { |
|
451 // content of the element has changed |
|
452 OsTracePrint( KInfoLevel, (TUint8*) |
|
453 ("UMAC: element changed")); |
|
454 |
|
455 // store the changed element content to our context |
|
456 aCtxImpl.GetNwHtOperationIe().SetIeData( |
|
457 elementData, |
|
458 length ); |
|
459 |
|
460 // inform the lower layers about the new HT operation |
|
461 // configuration |
|
462 if ( !(aCtxImpl.WsaCmdActive()) ) |
|
463 { |
|
464 ConfigureHtBssOperation( aCtxImpl ); |
|
465 } |
|
466 else |
|
467 { |
|
468 // WHA command is in progress so we must defer this access |
|
469 aCtxImpl.RegisterEvent( KSetHtBssOperation ); |
|
470 } |
|
471 } |
|
472 } |
|
473 } |
|
474 |
|
475 // --------------------------------------------------------------------------- |
|
476 // |
|
477 // --------------------------------------------------------------------------- |
|
478 // |
|
479 void WlanDot11InfrastructureMode::DoSetTxMpduDaAddress( |
|
480 SDataFrameHeader& aDataFrameHeader, |
|
481 const TMacAddress& aMac ) const |
|
482 { |
|
483 aDataFrameHeader.iAddress3 = aMac; |
|
484 } |
|
485 |
|
486 // --------------------------------------------------------------------------- |
|
487 // |
|
488 // --------------------------------------------------------------------------- |
|
489 // |
|
490 TBool WlanDot11InfrastructureMode::DoIsRxFrameSAourAddress( |
|
491 WlanContextImpl& aCtxImpl, |
|
492 const SDataFrameHeader& aFrameHeader, |
|
493 const SAmsduSubframeHeader* aSubFrameHeader ) const |
|
494 { |
|
495 if ( aSubFrameHeader ) |
|
496 { |
|
497 // the MSDU is part of an A-MSDU and the caller wants to use the |
|
498 // SA in the subframe header for this check |
|
499 return aSubFrameHeader->iSa == aCtxImpl.iWlanMib.dot11StationId; |
|
500 } |
|
501 else |
|
502 { |
|
503 // the caller wants to use the SA in the MAC header for this check |
|
504 return aFrameHeader.iAddress3 == aCtxImpl.iWlanMib.dot11StationId; |
|
505 } |
|
506 } |
|
507 |
|
508 // --------------------------------------------------------------------------- |
|
509 // |
|
510 // --------------------------------------------------------------------------- |
|
511 // |
|
512 TBool WlanDot11InfrastructureMode::DoIsValidAddressBitCombination( |
|
513 const SDataFrameHeader& aFrameHeader ) const |
|
514 { |
|
515 return (aFrameHeader.IsFromDsBitSet() && !(aFrameHeader.IsToDsBitSet())); |
|
516 } |
|
517 |
|
518 // --------------------------------------------------------------------------- |
|
519 // |
|
520 // --------------------------------------------------------------------------- |
|
521 // |
|
522 void WlanDot11InfrastructureMode::DoBuildEthernetFrame( |
|
523 TDataBuffer& aBuffer, |
|
524 const SDataMpduHeader& aDot11DataMpdu, |
|
525 const TUint8* aStartOfEtherPayload, |
|
526 TUint aEtherPayloadLength, |
|
527 TBool aAmsdu, |
|
528 TUint8* aCopyBuffer ) |
|
529 { |
|
530 OsTracePrint( KUmacDetails, (TUint8*) |
|
531 ("UMAC: WlanDot11InfrastructureMode::DoBuildEthernetFrame")); |
|
532 |
|
533 TUint8* realEtherPayloadStart ( const_cast<TUint8*>(aStartOfEtherPayload) ); |
|
534 |
|
535 if ( aCopyBuffer ) |
|
536 { |
|
537 // the frame needs to be copied to the copy buffer |
|
538 |
|
539 // update to point to the new location |
|
540 realEtherPayloadStart = aCopyBuffer + ( 2 * sizeof( TMacAddress ) ); |
|
541 |
|
542 os_memcpy( |
|
543 realEtherPayloadStart, |
|
544 aStartOfEtherPayload, |
|
545 aEtherPayloadLength ); |
|
546 } |
|
547 |
|
548 if ( aAmsdu ) |
|
549 { |
|
550 // this MSDU is part of an A-MSDU. Assign SA and DA from subframe |
|
551 // header |
|
552 const SAmsduSubframeHeader* KSubframeHeader ( |
|
553 reinterpret_cast<const SAmsduSubframeHeader*>( |
|
554 aStartOfEtherPayload |
|
555 - sizeof( SSnapHeader ) |
|
556 - sizeof( SAmsduSubframeHeader ) ) ); |
|
557 |
|
558 // copy SA to the correct location. |
|
559 // We do that first so that it doesn't get overwritten by DA |
|
560 os_memcpy( |
|
561 const_cast<TUint8*>(realEtherPayloadStart) - sizeof( TMacAddress ), |
|
562 reinterpret_cast<const TUint8*>(KSubframeHeader->iSa.iMacAddress), |
|
563 sizeof( TMacAddress ) ); |
|
564 |
|
565 // copy DA to the correct location. |
|
566 os_memcpy( |
|
567 const_cast<TUint8*>(realEtherPayloadStart) |
|
568 - ( 2 * sizeof( TMacAddress ) ), |
|
569 reinterpret_cast<const TUint8*>(KSubframeHeader->iDa.iMacAddress ), |
|
570 sizeof( TMacAddress ) ); |
|
571 |
|
572 } |
|
573 else |
|
574 { |
|
575 // assign SA and DA from MAC header |
|
576 |
|
577 // copy SA to the correct location. |
|
578 // We do that first so that it doesn't get overwritten by DA |
|
579 os_memcpy( |
|
580 const_cast<TUint8*>(realEtherPayloadStart) - sizeof( TMacAddress ), |
|
581 reinterpret_cast<const TUint8*>( |
|
582 aDot11DataMpdu.iHdr.iAddress3.iMacAddress ), |
|
583 sizeof( TMacAddress ) ); |
|
584 |
|
585 // copy DA to the correct location. |
|
586 os_memcpy( |
|
587 const_cast<TUint8*>(realEtherPayloadStart) |
|
588 - ( 2 * sizeof( TMacAddress ) ), |
|
589 reinterpret_cast<const TUint8*>( |
|
590 aDot11DataMpdu.iHdr.iAddress1.iMacAddress ), |
|
591 sizeof( TMacAddress ) ); |
|
592 } |
|
593 |
|
594 // set the length |
|
595 aBuffer.KeSetLength( |
|
596 aEtherPayloadLength |
|
597 + ( sizeof( TMacAddress ) * 2 ) ); |
|
598 |
|
599 // set the frame type |
|
600 aBuffer.FrameType( TDataBuffer::KEthernetFrame ); |
|
601 |
|
602 // set the offset to the beginning of the ready ethernet frame |
|
603 // from the beginning of the Rx buf |
|
604 aBuffer.KeSetOffsetToFrameBeginning( |
|
605 realEtherPayloadStart - ( 2 * sizeof( TMacAddress ) ) // frame beginning |
|
606 - aBuffer.KeGetBufferStart() ); // buffer beginning |
|
607 |
|
608 OsTracePrint( KUmacDetails, (TUint8*) |
|
609 ("UMAC: WlanDot11InfrastructureMode::DoBuildEthernetFrame: offset to frame beginning: %d"), |
|
610 aBuffer.KeOffsetToFrameBeginning()); |
|
611 } |
|
612 |
|
613 // ----------------------------------------------------------------------------- |
|
614 // |
|
615 // ----------------------------------------------------------------------------- |
|
616 // |
|
617 void WlanDot11InfrastructureMode::DoConsecutivePwrModeSetFailuresIndication( |
|
618 WlanContextImpl& aCtxImpl ) |
|
619 { |
|
620 if ( aCtxImpl.OnConsecutivePwrModeSetFailures() ) |
|
621 { |
|
622 OnInDicationEvent( aCtxImpl, EConsecutivePwrModeSetFailures ); |
|
623 } |
|
624 } |
|
625 |
|
626 // --------------------------------------------------------------------------- |
|
627 // |
|
628 // --------------------------------------------------------------------------- |
|
629 // |
|
630 TBool WlanDot11InfrastructureMode::Disconnect( WlanContextImpl& aCtxImpl ) |
|
631 { |
|
632 OsTracePrint( KInfoLevel, (TUint8*)("UMAC: WlanDot11InfrastructureMode::Disconnect():")); |
|
633 |
|
634 // set completion code to idle state |
|
635 // as it does the request completion |
|
636 |
|
637 aCtxImpl.iStates.iIdleState.Set( KErrNone ); |
|
638 ChangeState( aCtxImpl, |
|
639 *this, // prev state |
|
640 aCtxImpl.iStates.iDeauthPendingState // next state |
|
641 ); |
|
642 |
|
643 // signal caller that state transition occurred |
|
644 return ETrue; |
|
645 } |
|
646 |
|
647 // --------------------------------------------------------------------------- |
|
648 // |
|
649 // --------------------------------------------------------------------------- |
|
650 // |
|
651 TBool WlanDot11InfrastructureMode::RealScan( |
|
652 WlanContextImpl& aCtxImpl, |
|
653 TScanMode aMode, |
|
654 const TSSID& aSSID, |
|
655 TUint32 aScanRate, |
|
656 SChannels& aChannels, |
|
657 TUint32 aMinChannelTime, |
|
658 TUint32 aMaxChannelTime, |
|
659 TBool aSplitScan ) |
|
660 { |
|
661 // scanning mode requested |
|
662 // set parameters |
|
663 // NOTE: OID command parameters are guaranteed to be valid |
|
664 // to the point a correcponding completion method is called |
|
665 |
|
666 aCtxImpl.iStates.iInfrastructureScanningMode.Set( |
|
667 aMode, aSSID, aScanRate, aChannels, |
|
668 aMinChannelTime, aMaxChannelTime, aSplitScan ); |
|
669 |
|
670 ChangeState( aCtxImpl, |
|
671 *this, // prev state |
|
672 aCtxImpl.iStates.iInfrastructureScanningMode // next state |
|
673 ); |
|
674 |
|
675 return ETrue; // global statemachine transition will occur |
|
676 } |
|
677 |
|
678 // --------------------------------------------------------------------------- |
|
679 // |
|
680 // --------------------------------------------------------------------------- |
|
681 // |
|
682 void WlanDot11InfrastructureMode::TxMgmtData( |
|
683 WlanContextImpl& aCtxImpl, |
|
684 TDataBuffer& aDataBuffer ) |
|
685 { |
|
686 TWlanUserTxDataCntx& data_cntx( aCtxImpl.GetMgmtTxDataCntx() ); |
|
687 |
|
688 // make a note of the frame type |
|
689 const TDataBuffer::TFrameType frameType( aDataBuffer.FrameType() ); |
|
690 |
|
691 TUint16 etherType( 0 ); // initial value: not relevant |
|
692 |
|
693 // construct a dot11 frame from databuffer to storage |
|
694 EncapsulateFrame( aCtxImpl, data_cntx, aDataBuffer, etherType ); |
|
695 |
|
696 // start of dot11 frame to send |
|
697 const TUint8* start_of_frame( data_cntx.StartOfFrame() ); |
|
698 |
|
699 // select correct tx queue |
|
700 const WHA::TQueueId queue_id( |
|
701 QueueId( aCtxImpl, start_of_frame ) ); |
|
702 |
|
703 T802Dot11FrameControlTypeMask dot11FrameType ( E802Dot11FrameTypeDataEapol ); |
|
704 TBool useSpecialTxAutoRatePolicy( EFalse ); |
|
705 |
|
706 switch ( frameType ) |
|
707 { |
|
708 case TDataBuffer::KEthernetFrame: |
|
709 // dot11FrameType already correct |
|
710 |
|
711 // request special Tx autorate policy use for EAPOL and WAI frames |
|
712 useSpecialTxAutoRatePolicy = ETrue; |
|
713 break; |
|
714 case TDataBuffer::KDot11Frame: |
|
715 dot11FrameType = E802Dot11FrameTypeManagementAction; |
|
716 break; |
|
717 case TDataBuffer::KSnapFrame: |
|
718 // these frames have the same Tx completion handling as Eapol |
|
719 // frames so we use the same dot11FrameType value - which is |
|
720 // already correct - for them, too |
|
721 break; |
|
722 case TDataBuffer::KEthernetTestFrame: |
|
723 dot11FrameType = E802Dot11FrameTypeTestFrame; |
|
724 break; |
|
725 default: |
|
726 // programming error |
|
727 OsTracePrint( KErrorLevel, (TUint8*) |
|
728 ("UMAC: unsupported frame type: %d"), frameType ); |
|
729 OsAssert( (TUint8*)("UMAC: panic"), |
|
730 (TUint8*)(WLAN_FILE), __LINE__ ); |
|
731 } |
|
732 |
|
733 // push the frame to packet scheduler for transmission |
|
734 aCtxImpl.PushPacketToPacketScheduler( |
|
735 start_of_frame, |
|
736 data_cntx.LengthOfFrame(), |
|
737 queue_id, |
|
738 dot11FrameType, |
|
739 &aDataBuffer, |
|
740 EFalse, |
|
741 EFalse, |
|
742 useSpecialTxAutoRatePolicy ); |
|
743 |
|
744 // now just wait for the scheduler to call completion methods |
|
745 |
|
746 if ( frameType == TDataBuffer::KEthernetFrame ) |
|
747 { |
|
748 // check if we need to change power mgmt mode because of the frame Tx |
|
749 |
|
750 const TPowerMgmtModeChange KPowerMgmtModeChange ( |
|
751 aCtxImpl.OnFrameTx( queue_id, etherType ) ); |
|
752 |
|
753 // if any change change is needed regarding our power mgmt mode, |
|
754 // proceed with it |
|
755 PowerMgmtModeChange( aCtxImpl, KPowerMgmtModeChange ); |
|
756 } |
|
757 } |
|
758 |
|
759 // --------------------------------------------------------------------------- |
|
760 // |
|
761 // --------------------------------------------------------------------------- |
|
762 // |
|
763 void WlanDot11InfrastructureMode::DoRcpiIndication( |
|
764 WlanContextImpl& aCtxImpl, |
|
765 WHA::TRcpi aRcpi ) |
|
766 { |
|
767 OsTracePrint( KWlmIndication, (TUint8*) |
|
768 ("UMAC: WlanDot11InfrastructureMode::DoRcpiIndication: rcpi: %d"), |
|
769 aRcpi ); |
|
770 |
|
771 OnInDicationEvent( aCtxImpl, ERcpiTrigger ); |
|
772 |
|
773 // restore the MIB back to its default value, i.e. zero. |
|
774 // This means that no further RCPI indications should arrive from WHA |
|
775 // layer until the RCPI threshold is set again by WLAN Mgmt Client |
|
776 if ( !(aCtxImpl.WsaCmdActive()) ) |
|
777 { |
|
778 SetRcpiTriggerLevelMib( aCtxImpl, WHA::KRcpiThresholdDefault, EFalse ); |
|
779 } |
|
780 else |
|
781 { |
|
782 // WHA command is in progress so we must defer this access |
|
783 aCtxImpl.RegisterEvent( KSetRcpiTriggerLevel ); |
|
784 } |
|
785 } |
|
786 |
|
787 // --------------------------------------------------------------------------- |
|
788 // |
|
789 // --------------------------------------------------------------------------- |
|
790 // |
|
791 void WlanDot11InfrastructureMode::DoPsModeErrorIndication( |
|
792 WlanContextImpl& aCtxImpl ) |
|
793 { |
|
794 OsTracePrint( KWlmIndication, (TUint8*) |
|
795 ("UMAC: WlanDot11InfrastructureMode::DoPsModeErrorIndication") ); |
|
796 |
|
797 OnInDicationEvent( aCtxImpl, EPsModeError ); |
|
798 } |
|
799 |
|
800 // --------------------------------------------------------------------------- |
|
801 // |
|
802 // --------------------------------------------------------------------------- |
|
803 // |
|
804 TBool WlanDot11InfrastructureMode::OnVoiceCallEntryTimerTimeout( |
|
805 WlanContextImpl& aCtxImpl ) |
|
806 { |
|
807 aCtxImpl.OnVoiceCallEntryTimerTimeout(); |
|
808 |
|
809 return EFalse; |
|
810 } |
|
811 |
|
812 // --------------------------------------------------------------------------- |
|
813 // |
|
814 // --------------------------------------------------------------------------- |
|
815 // |
|
816 TBool WlanDot11InfrastructureMode::OnNullTimerTimeout( |
|
817 WlanContextImpl& aCtxImpl ) |
|
818 { |
|
819 aCtxImpl.OnNullTimerTimeout(); |
|
820 |
|
821 return EFalse; |
|
822 } |
|
823 |
|
824 // --------------------------------------------------------------------------- |
|
825 // |
|
826 // --------------------------------------------------------------------------- |
|
827 // |
|
828 TBool WlanDot11InfrastructureMode::OnNoVoiceTimerTimeout( |
|
829 WlanContextImpl& aCtxImpl ) |
|
830 { |
|
831 aCtxImpl.OnNoVoiceTimerTimeout(); |
|
832 |
|
833 return EFalse; |
|
834 } |
|
835 |
|
836 // --------------------------------------------------------------------------- |
|
837 // |
|
838 // --------------------------------------------------------------------------- |
|
839 // |
|
840 TBool WlanDot11InfrastructureMode::OnKeepAliveTimerTimeout( |
|
841 WlanContextImpl& aCtxImpl ) |
|
842 { |
|
843 aCtxImpl.OnKeepAliveTimerTimeout(); |
|
844 |
|
845 return EFalse; |
|
846 } |
|
847 |
|
848 // --------------------------------------------------------------------------- |
|
849 // |
|
850 // --------------------------------------------------------------------------- |
|
851 // |
|
852 TBool WlanDot11InfrastructureMode::OnWlanWakeUpIntervalChange( |
|
853 WlanContextImpl& aCtxImpl ) |
|
854 { |
|
855 OsTracePrint( KPwrStateTransition, (TUint8*) |
|
856 ("UMAC: : WlanDot11InfrastructureMode::OnWlanWakeUpIntervalChange")); |
|
857 |
|
858 WHA::SwlanWakeUpInterval* mib |
|
859 = static_cast<WHA::SwlanWakeUpInterval*> |
|
860 (os_alloc( sizeof( WHA::SwlanWakeUpInterval ) )); |
|
861 |
|
862 if ( !mib ) |
|
863 { |
|
864 // allocation failed |
|
865 // simulate macnotresponding error |
|
866 OnOidComplete( aCtxImpl ); // complete also |
|
867 OsTracePrint( KWarningLevel, |
|
868 (TUint8*)("UMAC: WlanDot11InfrastructureMode::OnWlanWakeUpIntervalChange: alloc failed, abort") ); |
|
869 return DoErrorIndication( aCtxImpl, WHA::KErrorMacNotResponding ); |
|
870 } |
|
871 |
|
872 // determine the desired new wake-up setting |
|
873 const TDot11PsModeWakeupSetting KDesiredPsModeConfig ( |
|
874 aCtxImpl.DesiredPsModeConfig() ); |
|
875 |
|
876 // take it into use |
|
877 |
|
878 mib->iMode = KDesiredPsModeConfig.iWakeupMode; |
|
879 mib->iListenInterval = KDesiredPsModeConfig.iListenInterval; |
|
880 |
|
881 WlanWsaWriteMib& wha_cmd = aCtxImpl.WsaWriteMib(); |
|
882 |
|
883 wha_cmd.Set( |
|
884 aCtxImpl, WHA::KMibWlanWakeUpInterval, sizeof(*mib), mib ); |
|
885 |
|
886 OsTracePrint( KPwrStateTransition, |
|
887 (TUint8*)("UMAC: WlanDot11InfrastructureMode::OnWlanWakeUpIntervalChange: desired mode: %d"), |
|
888 mib->iMode ); |
|
889 OsTracePrint( KPwrStateTransition, (TUint8*) |
|
890 ("UMAC: WlanDot11InfrastructureMode::OnWlanWakeUpIntervalChange: desired listen interval: %d"), |
|
891 mib->iListenInterval ); |
|
892 |
|
893 // store the new setting also locally |
|
894 aCtxImpl.iWlanMib.iWlanWakeupInterval = mib->iMode; |
|
895 aCtxImpl.iWlanMib.iWlanListenInterval = mib->iListenInterval; |
|
896 |
|
897 // change global state: entry procedure triggers action |
|
898 ChangeState( aCtxImpl, |
|
899 *this, // prev state |
|
900 wha_cmd, // next state |
|
901 // the ACT signals that this operation should be completed to user |
|
902 WlanDot11State::KCompleteManagementRequest |
|
903 ); |
|
904 |
|
905 // as the parameters have been supplied we can now deallocate |
|
906 os_free( mib ); |
|
907 |
|
908 // signal state transition change |
|
909 return ETrue; |
|
910 } |
|
911 |
|
912 // --------------------------------------------------------------------------- |
|
913 // |
|
914 // --------------------------------------------------------------------------- |
|
915 // |
|
916 TBool WlanDot11InfrastructureMode::TxNullDataFrame( |
|
917 WlanContextImpl& aCtxImpl, |
|
918 TBool aQosNull ) |
|
919 { |
|
920 OsTracePrint( KWsaTxDetails, (TUint8*) |
|
921 ("UMAC: WlanDot11InfrastructureMode::TxNullDataFrame: aQosNull: %d"), |
|
922 aQosNull ); |
|
923 |
|
924 TBool status ( ETrue ); |
|
925 |
|
926 TUint32 lengthOfFrame( 0 ); |
|
927 T802Dot11FrameControlTypeMask frameType( E802Dot11FrameTypeDataNull ); |
|
928 |
|
929 // copy Null Data frame to tx-buffer to correct offset |
|
930 // client doesn't need to take care of the tx buffer header space |
|
931 // as the method below does it by itself |
|
932 TUint8* start_of_frame = aCtxImpl.TxBuffer(); |
|
933 |
|
934 if ( start_of_frame ) |
|
935 { |
|
936 if ( aQosNull ) |
|
937 { |
|
938 // transmit of QoS Null Data Frame requested |
|
939 |
|
940 lengthOfFrame = aCtxImpl.QosNullDataFrameLength(); |
|
941 frameType = E802Dot11FrameTypeQosDataNull; |
|
942 |
|
943 os_memcpy( |
|
944 start_of_frame, |
|
945 &(aCtxImpl.QosNullDataFrame()), |
|
946 lengthOfFrame ); |
|
947 |
|
948 // as this needs to be a trigger frame for Voice AC, set the User |
|
949 // Priority of the frame accordingly |
|
950 |
|
951 const TUint8 K802Dot1dPriorityVoice = 6; |
|
952 SQosDataFrameHeader* qosHdr = |
|
953 reinterpret_cast<SQosDataFrameHeader*>(start_of_frame); |
|
954 qosHdr->SetUserPriority( K802Dot1dPriorityVoice ); |
|
955 |
|
956 // note that the Order bit of the Frame Control field of the QoS |
|
957 // Null data frame has already been given the correct value in |
|
958 // WlanMacActionState::OnDot11InfrastructureModeStateSpaceEntry() |
|
959 // method |
|
960 } |
|
961 else |
|
962 { |
|
963 // transmit of Null Data Frame requested |
|
964 |
|
965 lengthOfFrame = sizeof( SNullDataFrame ); |
|
966 // frame type is already correct for this case |
|
967 |
|
968 os_memcpy( |
|
969 start_of_frame, |
|
970 &(aCtxImpl.NullDataFrame()), |
|
971 lengthOfFrame ); |
|
972 } |
|
973 |
|
974 // determine Tx queue |
|
975 const WHA::TQueueId queue_id( QueueId( aCtxImpl, start_of_frame ) ); |
|
976 |
|
977 // send the Null Data frame by pushing it to packet scheduler |
|
978 aCtxImpl.PushPacketToPacketScheduler( |
|
979 start_of_frame, |
|
980 lengthOfFrame, |
|
981 queue_id, |
|
982 frameType, |
|
983 NULL, |
|
984 EFalse, |
|
985 EFalse ); |
|
986 } |
|
987 else |
|
988 { |
|
989 // we didn't get a Tx buffer so we can't submit a frame send request. |
|
990 status = EFalse; |
|
991 } |
|
992 |
|
993 return status; |
|
994 } |