|
1 /* |
|
2 * Copyright (c) 2005-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 WlanDot11Associated class |
|
15 * |
|
16 */ |
|
17 |
|
18 /* |
|
19 * %version: 95 % |
|
20 */ |
|
21 |
|
22 #include "config.h" |
|
23 #include "UmacDot11Associated.h" |
|
24 #include "UmacContextImpl.h" |
|
25 #include "UmacWsaWriteMib.h" |
|
26 #include "umacinternaldefinitions.h" |
|
27 |
|
28 /** |
|
29 * Mask to determine the used encryption from WHA::ReceivePacket's aFlags |
|
30 * parameter |
|
31 */ |
|
32 const TUint32 KReceivePacketEncryptionMask = 0x00038000; |
|
33 |
|
34 |
|
35 // ================= MEMBER FUNCTIONS ======================= |
|
36 |
|
37 // --------------------------------------------------------------------------- |
|
38 // |
|
39 // --------------------------------------------------------------------------- |
|
40 // |
|
41 void WlanDot11Associated::OnBeaconFrameRx( |
|
42 WlanContextImpl& aCtxImpl, |
|
43 const TAny* /*aFrame*/, |
|
44 const TUint32 /*aLength*/, |
|
45 WHA::TRcpi /*aRcpi*/, |
|
46 TUint8* aBuffer ) |
|
47 { |
|
48 // release the Rx buffer |
|
49 aCtxImpl.iUmac.MarkRxBufFree( aBuffer ); |
|
50 } |
|
51 |
|
52 // --------------------------------------------------------------------------- |
|
53 // |
|
54 // --------------------------------------------------------------------------- |
|
55 // |
|
56 void WlanDot11Associated::OnProbeResponseFrameRx( |
|
57 WlanContextImpl& aCtxImpl, |
|
58 const TAny* /*aFrame*/, |
|
59 const TUint32 /*aLength*/, |
|
60 WHA::TRcpi /*aRcpi*/, |
|
61 TUint8* aBuffer ) |
|
62 { |
|
63 // release the Rx buffer |
|
64 aCtxImpl.iUmac.MarkRxBufFree( aBuffer ); |
|
65 } |
|
66 |
|
67 // --------------------------------------------------------------------------- |
|
68 // |
|
69 // --------------------------------------------------------------------------- |
|
70 // |
|
71 void WlanDot11Associated::OnDeauthenticateFrameRx( |
|
72 WlanContextImpl& aCtxImpl, |
|
73 TUint8* aBuffer ) |
|
74 { |
|
75 // release the Rx buffer |
|
76 aCtxImpl.iUmac.MarkRxBufFree( aBuffer ); |
|
77 } |
|
78 |
|
79 // --------------------------------------------------------------------------- |
|
80 // |
|
81 // --------------------------------------------------------------------------- |
|
82 // |
|
83 void WlanDot11Associated::OnDisassociateFrameRx( |
|
84 WlanContextImpl& aCtxImpl, |
|
85 TUint8* aBuffer ) |
|
86 { |
|
87 // release the Rx buffer |
|
88 aCtxImpl.iUmac.MarkRxBufFree( aBuffer ); |
|
89 } |
|
90 |
|
91 // --------------------------------------------------------------------------- |
|
92 // |
|
93 // --------------------------------------------------------------------------- |
|
94 // |
|
95 TSnapStatus WlanDot11Associated::ValiDateSnapHeader( |
|
96 WlanContextImpl& aCtxImpl, |
|
97 const TUint8* aStartOfSnap ) const |
|
98 { |
|
99 TSnapStatus snapStatus( ESnapUnknown ); |
|
100 |
|
101 if ( !os_memcmp( |
|
102 aStartOfSnap, |
|
103 &KEncapsulatingRfc1042SnapHeader, |
|
104 sizeof( KEncapsulatingRfc1042SnapHeader ) ) ) |
|
105 { |
|
106 snapStatus = ESnapDot11Ok; |
|
107 } |
|
108 else if ( !os_memcmp( |
|
109 aStartOfSnap, |
|
110 &KEncapsulating802_1hSnapHeader, |
|
111 sizeof( KEncapsulating802_1hSnapHeader ) ) ) |
|
112 { |
|
113 snapStatus = ESnapDot11Ok; |
|
114 } |
|
115 else |
|
116 { |
|
117 // unknown SNAP. Status already correct. No action needed |
|
118 } |
|
119 |
|
120 if ( snapStatus == ESnapUnknown && |
|
121 aCtxImpl.NetworkOperationMode() == WHA::EBSS && |
|
122 aCtxImpl.GetProprietarySnapHeader() != KUndefinedSnapHeader ) |
|
123 { |
|
124 // SNAP still unknown, but we a are in a infrastructure network and |
|
125 // a proprietary SNAP header has been defined. |
|
126 // Check if the SNAP is this proprietary SNAP header |
|
127 |
|
128 if ( !os_memcmp( |
|
129 aStartOfSnap, |
|
130 &(aCtxImpl.GetProprietarySnapHeader()), |
|
131 sizeof( aCtxImpl.GetProprietarySnapHeader() ) ) ) |
|
132 { |
|
133 snapStatus = ESnapProprietaryOk; |
|
134 } |
|
135 } |
|
136 |
|
137 return snapStatus; |
|
138 } |
|
139 |
|
140 // --------------------------------------------------------------------------- |
|
141 // |
|
142 // --------------------------------------------------------------------------- |
|
143 // |
|
144 inline TBool WlanDot11Associated::RxDataMpduValid( |
|
145 const TUint32 aLength, |
|
146 const SDataFrameHeader& aFrameHeader, |
|
147 TBool aQosData, |
|
148 TBool aAmsdu, |
|
149 TUint aHtControlLen, |
|
150 TUint aSecurityHeaderLen, |
|
151 TUint aSecurityTrailerLen ) const |
|
152 { |
|
153 //======================================================================== |
|
154 // validate frame length |
|
155 //======================================================================== |
|
156 |
|
157 const TUint KMinAcceptableRxDataMpduLen ( |
|
158 MinAcceptableRxDataMpduLen( |
|
159 aQosData, |
|
160 aAmsdu, |
|
161 aHtControlLen, |
|
162 aSecurityHeaderLen, |
|
163 aSecurityTrailerLen ) ); |
|
164 |
|
165 if ( aLength < KMinAcceptableRxDataMpduLen ) |
|
166 { |
|
167 // frame shorter than min acceptable length; reject it |
|
168 OsTracePrint( KRxFrame | KWarningLevel, (TUint8*) |
|
169 ("UMAC: WlanDot11Associated::RxDataMpduValid: WARNING: MPDU rejected because its shorter than min acceptable length of %d"), |
|
170 KMinAcceptableRxDataMpduLen ); |
|
171 |
|
172 return EFalse; |
|
173 } |
|
174 |
|
175 //======================================================================== |
|
176 // validate To DS & From DS bits |
|
177 //======================================================================== |
|
178 |
|
179 if ( !DoIsValidAddressBitCombination( aFrameHeader ) ) |
|
180 { |
|
181 OsTracePrint( KRxFrame, (TUint8*) |
|
182 ("UMAC: WlanDot11Associated::RxDataMpduValid: MPDU rejected because of invalid To DS and/or From DS bit values") ); |
|
183 |
|
184 return EFalse; |
|
185 } |
|
186 |
|
187 return ETrue; |
|
188 } |
|
189 |
|
190 // --------------------------------------------------------------------------- |
|
191 // defines the minimum acceptable Data MPDU length as: |
|
192 // dot11 MAC header length including SNAP and possibly existing HT Control |
|
193 // field |
|
194 // + security header length |
|
195 // + subframe header length if the QoS Data MPDU contains an A-MSDU |
|
196 // + security trailer length |
|
197 // + Ethernet type field length |
|
198 // --------------------------------------------------------------------------- |
|
199 // |
|
200 inline TUint WlanDot11Associated::MinAcceptableRxDataMpduLen( |
|
201 TBool aQosData, |
|
202 TBool aAmsdu, |
|
203 TUint aHtControlLen, |
|
204 TUint aSecurityHeaderLen, |
|
205 TUint aSecurityTrailerLen ) const |
|
206 { |
|
207 return aQosData ? |
|
208 sizeof( SQosDataMpduHeader ) + aHtControlLen |
|
209 + aSecurityHeaderLen |
|
210 + ( aAmsdu ? sizeof( SAmsduSubframeHeader ) : 0 ) |
|
211 + aSecurityTrailerLen |
|
212 + sizeof( SEthernetType ) |
|
213 : |
|
214 sizeof( SDataMpduHeader ) |
|
215 + aSecurityHeaderLen |
|
216 + aSecurityTrailerLen |
|
217 + sizeof( SEthernetType ); |
|
218 } |
|
219 |
|
220 // --------------------------------------------------------------------------- |
|
221 // Note that address 1 is the DA (Destination Address) both in infrastructure |
|
222 // and IBSS network Rx frames |
|
223 // --------------------------------------------------------------------------- |
|
224 // |
|
225 inline TDaType WlanDot11Associated::RxFrameDaType( |
|
226 const SDataFrameHeader& aFrameHeader ) const |
|
227 { |
|
228 if ( IsGroupBitSet( aFrameHeader.iAddress1 ) ) |
|
229 { |
|
230 // a multicast |
|
231 if ( aFrameHeader.iAddress1 == KBroadcastMacAddr ) |
|
232 { |
|
233 // also a brodcast |
|
234 return EBroadcastAddress; |
|
235 } |
|
236 else |
|
237 { |
|
238 // a multicast but not a broadcast |
|
239 return EMulticastAddress; |
|
240 } |
|
241 } |
|
242 else |
|
243 { |
|
244 // a unicast |
|
245 return EUnicastAddress; |
|
246 } |
|
247 } |
|
248 |
|
249 // --------------------------------------------------------------------------- |
|
250 // |
|
251 // --------------------------------------------------------------------------- |
|
252 // |
|
253 inline TBool WlanDot11Associated::RxMsduValid( |
|
254 WlanContextImpl& aCtxImpl, |
|
255 const SDataFrameHeader& aFrameHeader, |
|
256 const SAmsduSubframeHeader* aSubFrameHeader, |
|
257 const TUint8* aStartOfSnap, |
|
258 TUint16 aEtherType, |
|
259 TBool aMulticast, |
|
260 TUint32 aFlags, |
|
261 TSnapStatus& aSnapStatus ) const |
|
262 { |
|
263 //======================================================================== |
|
264 // validate SNAP header |
|
265 //======================================================================== |
|
266 |
|
267 aSnapStatus = ValiDateSnapHeader( aCtxImpl, aStartOfSnap ); |
|
268 |
|
269 if ( aSnapStatus == ESnapUnknown ) |
|
270 { |
|
271 // SNAP header is invalid |
|
272 |
|
273 OsTracePrint( KRxFrame, (TUint8*) |
|
274 ("UMAC: WlanDot11Associated::RxMsduValid: MSDU rejected because of invalid snap:"), |
|
275 aStartOfSnap, aStartOfSnap + sizeof( SSnapHeader ) ); |
|
276 |
|
277 return EFalse; |
|
278 } |
|
279 |
|
280 // determine if SA is our MAC address |
|
281 const TBool KSaIsOurMac ( |
|
282 DoIsRxFrameSAourAddress( aCtxImpl, aFrameHeader, aSubFrameHeader ) ); |
|
283 |
|
284 //======================================================================== |
|
285 // if this is a proprietary test MSDU but not sent by us, its not valid |
|
286 // for us |
|
287 //======================================================================== |
|
288 |
|
289 if ( aEtherType == KBounceType && !KSaIsOurMac ) |
|
290 { |
|
291 #ifndef NDEBUG |
|
292 OsTracePrint( KRxFrame, (TUint8*) |
|
293 ("UMAC: WlanDot11Associated::RxMsduValid: proprietary test MSDU, but not sent by us. MSDU rejected") ); |
|
294 |
|
295 if ( aSubFrameHeader ) |
|
296 { |
|
297 OsTracePrint( KRxFrame, (TUint8*) |
|
298 ("UMAC: Subframe DA:"), aSubFrameHeader->iDa ); |
|
299 OsTracePrint( KRxFrame, (TUint8*) |
|
300 ("UMAC: Subframe SA:"), aSubFrameHeader->iSa ); |
|
301 } |
|
302 else |
|
303 { |
|
304 OsTracePrint( KRxFrame, (TUint8*) |
|
305 ("UMAC: Address1:"), aFrameHeader.iAddress1); |
|
306 OsTracePrint( KRxFrame, (TUint8*) |
|
307 ("UMAC: Address2:"), aFrameHeader.iAddress2); |
|
308 OsTracePrint( KRxFrame, (TUint8*) |
|
309 ("UMAC: Address3:"), aFrameHeader.iAddress3); |
|
310 } |
|
311 #endif |
|
312 |
|
313 return EFalse; |
|
314 } |
|
315 |
|
316 //======================================================================== |
|
317 // non-test multicast MSDUs sent by us are not relevant for us |
|
318 //======================================================================== |
|
319 |
|
320 if ( // SA is our MAC address |
|
321 KSaIsOurMac |
|
322 // AND this is a multicast frame |
|
323 && aMulticast |
|
324 // AND this is not a test frame |
|
325 && aEtherType != KBounceType ) |
|
326 { |
|
327 // we have received a non-test multicast frame that was sent by us. |
|
328 // Ignore it. |
|
329 |
|
330 #ifndef NDEBUG |
|
331 OsTracePrint( KRxFrame, (TUint8*) |
|
332 ("UMAC: WlanDot11Associated::RxMsduValid: MSDU rejected because its a non-test multicast MSDU sent by us")); |
|
333 |
|
334 if ( aSubFrameHeader ) |
|
335 { |
|
336 OsTracePrint( KRxFrame, (TUint8*) |
|
337 ("UMAC: Subframe DA:"), aSubFrameHeader->iDa ); |
|
338 OsTracePrint( KRxFrame, (TUint8*) |
|
339 ("UMAC: Subframe SA:"), aSubFrameHeader->iSa ); |
|
340 } |
|
341 else |
|
342 { |
|
343 OsTracePrint( KRxFrame, (TUint8*) |
|
344 ("UMAC: Address1:"), aFrameHeader.iAddress1); |
|
345 OsTracePrint( KRxFrame, (TUint8*) |
|
346 ("UMAC: Address2:"), aFrameHeader.iAddress2); |
|
347 OsTracePrint( KRxFrame, (TUint8*) |
|
348 ("UMAC: Address3:"), aFrameHeader.iAddress3); |
|
349 } |
|
350 #endif |
|
351 |
|
352 return EFalse; |
|
353 } |
|
354 |
|
355 // determine the encryption of the frame |
|
356 const TUint32 KEncryption ( aFlags & KReceivePacketEncryptionMask ); |
|
357 |
|
358 if ( aSnapStatus != ESnapProprietaryOk ) |
|
359 { |
|
360 //==================================================================== |
|
361 // validate MSDU with the applicable privacy mode filter |
|
362 //==================================================================== |
|
363 if ( !aCtxImpl.ExecuteActivePrivacyModeFilter( |
|
364 aFrameHeader, |
|
365 aCtxImpl.iEnableUserData, |
|
366 aEtherType, |
|
367 aCtxImpl.PairWiseKeyType() != WHA::EKeyNone, |
|
368 ( KEncryption == WHA::KEncryptAes || |
|
369 KEncryption == WHA::KEncryptTkip || |
|
370 KEncryption == WHA::KEncryptWapi ) ) ) |
|
371 { |
|
372 return EFalse; |
|
373 } |
|
374 } |
|
375 |
|
376 // this MSDU has passed all our checks, so it is valid for us |
|
377 return ETrue; |
|
378 } |
|
379 |
|
380 // --------------------------------------------------------------------------- |
|
381 // |
|
382 // --------------------------------------------------------------------------- |
|
383 // |
|
384 inline TUint WlanDot11Associated::RxMsduEthernetPayloadLength( |
|
385 const TUint32 aMpduLength, |
|
386 TUint aSubframeLength, |
|
387 TBool aQosData, |
|
388 TUint aHtControlLen, |
|
389 TUint aSecurityHeaderLen, |
|
390 TUint aSecurityTrailerLen ) const |
|
391 { |
|
392 TUint length ( 0 ); |
|
393 |
|
394 if ( aSubframeLength ) |
|
395 { |
|
396 // this ethernet payload is carried in an A-MSDU subframe |
|
397 |
|
398 length = aSubframeLength - sizeof( SSnapHeader ); |
|
399 |
|
400 OsTracePrint( KRxFrame, (TUint8*) |
|
401 ("UMAC: subframe eth payload len: %d"), |
|
402 length ); |
|
403 } |
|
404 else |
|
405 { |
|
406 // this ethernet payload is carried in a non-A-MSDU frame |
|
407 |
|
408 if ( aQosData ) |
|
409 { |
|
410 length = |
|
411 // total length of the Rx frame |
|
412 aMpduLength |
|
413 // - MAC header length including SNAP |
|
414 - ( sizeof( SQosDataMpduHeader ) + aHtControlLen ) |
|
415 // - security header length |
|
416 - aSecurityHeaderLen |
|
417 // - security trailer length |
|
418 - aSecurityTrailerLen; |
|
419 |
|
420 OsTracePrint( KRxFrame, (TUint8*) |
|
421 ("UMAC: qos data eth payload len: %d"), |
|
422 length ); |
|
423 } |
|
424 else |
|
425 { |
|
426 length = |
|
427 // total length of the Rx frame |
|
428 aMpduLength |
|
429 // MAC header length including SNAP |
|
430 - sizeof( SDataMpduHeader ) |
|
431 // - security header length |
|
432 - aSecurityHeaderLen |
|
433 // - security trailer length |
|
434 - aSecurityTrailerLen; |
|
435 |
|
436 OsTracePrint( KRxFrame, (TUint8*) |
|
437 ("UMAC: non-qos data eth payload len: %d"), |
|
438 length ); |
|
439 } |
|
440 } |
|
441 |
|
442 return length; |
|
443 } |
|
444 |
|
445 // --------------------------------------------------------------------------- |
|
446 // |
|
447 // --------------------------------------------------------------------------- |
|
448 // |
|
449 inline TUint8* WlanDot11Associated::NewBufForMgmtClientRxFrame( |
|
450 WlanContextImpl& aCtxImpl, |
|
451 TBool aProprieatarySnapFrame, |
|
452 TBool aQosFrame, |
|
453 TUint aHtControlLen, |
|
454 TUint aEtherPayloadLength ) const |
|
455 { |
|
456 TUint requiredLength ( 0 ); |
|
457 |
|
458 if ( aProprieatarySnapFrame ) |
|
459 { |
|
460 // forwarded as a Data MPDU |
|
461 |
|
462 requiredLength = aQosFrame ? |
|
463 sizeof( SQosDataFrameHeader ) |
|
464 + aHtControlLen |
|
465 + aEtherPayloadLength : |
|
466 sizeof( SDataFrameHeader ) |
|
467 + aEtherPayloadLength; |
|
468 } |
|
469 else |
|
470 { |
|
471 // forwarded as Ethernet frame |
|
472 |
|
473 requiredLength = 2 * sizeof( TMacAddress ) + aEtherPayloadLength; |
|
474 } |
|
475 |
|
476 // request for a new Rx buffer |
|
477 return aCtxImpl.GetRxBuffer( |
|
478 requiredLength, |
|
479 // tell that this is an internally triggered buffer request |
|
480 ETrue ); |
|
481 } |
|
482 |
|
483 // --------------------------------------------------------------------------- |
|
484 // |
|
485 // --------------------------------------------------------------------------- |
|
486 // |
|
487 inline TBool WlanDot11Associated::RxMsduForUser( |
|
488 TUint16 aEtherType, |
|
489 TSnapStatus aSnapstatus ) const |
|
490 { |
|
491 if ( // not an EAPOL frame AND |
|
492 aEtherType != KEapolType && |
|
493 // not a WAI frame AND |
|
494 aEtherType != KWaiType && |
|
495 // not a WLAN Mgmt Client test frame |
|
496 aEtherType != KBounceType && |
|
497 // not a proprietary SNAP frame |
|
498 aSnapstatus != ESnapProprietaryOk ) |
|
499 { |
|
500 // a user data / protocol stack data frame |
|
501 |
|
502 return ETrue; |
|
503 } |
|
504 else |
|
505 { |
|
506 return EFalse; |
|
507 } |
|
508 } |
|
509 |
|
510 // --------------------------------------------------------------------------- |
|
511 // |
|
512 // --------------------------------------------------------------------------- |
|
513 // |
|
514 inline void WlanDot11Associated::UpdateDataFrameRxStatistics( |
|
515 WlanContextImpl& aCtxImpl, |
|
516 TUint16 aEtherType, |
|
517 TBool aMulticast, |
|
518 WHA::TQueueId aAccessCategory ) const |
|
519 { |
|
520 if ( aEtherType != KBounceType ) |
|
521 { |
|
522 // other than WLAN Mgmt Client test data frame received |
|
523 |
|
524 if ( aMulticast ) |
|
525 { |
|
526 // multicast frame |
|
527 |
|
528 OsTracePrint( KRxFrame, (TUint8*) |
|
529 ("UMAC: inc rx mcast cnt for AC: %d"), |
|
530 aAccessCategory ); |
|
531 |
|
532 // update frame statistics |
|
533 aCtxImpl.IncrementRxMulticastDataFrameCount( aAccessCategory ); |
|
534 } |
|
535 else |
|
536 { |
|
537 // unicast frame |
|
538 |
|
539 OsTracePrint( KRxFrame, (TUint8*) |
|
540 ("UMAC: inc rx unicast cnt for AC: %d"), |
|
541 aAccessCategory ); |
|
542 |
|
543 // update frame statistics |
|
544 aCtxImpl.IncrementRxUnicastDataFrameCount( aAccessCategory ); |
|
545 } |
|
546 } |
|
547 } |
|
548 |
|
549 // --------------------------------------------------------------------------- |
|
550 // |
|
551 // --------------------------------------------------------------------------- |
|
552 // |
|
553 void WlanDot11Associated::OnDataFrameRx( |
|
554 WlanContextImpl& aCtxImpl, |
|
555 const TAny* aFrame, |
|
556 const TUint32 aLength, |
|
557 TUint32 aFlags, |
|
558 WHA::TRcpi aRcpi, |
|
559 TUint8* aBuffer ) |
|
560 { |
|
561 OsTracePrint( KRxFrame, (TUint8*) |
|
562 ("UMAC: WlanDot11Associated::OnDataFrameRx") ); |
|
563 |
|
564 SDataMpduHeader* hdr |
|
565 = reinterpret_cast<SDataMpduHeader*>(const_cast<TAny*>(aFrame)); |
|
566 SQosDataMpduHeader* qoshdr |
|
567 = reinterpret_cast<SQosDataMpduHeader*>(const_cast<TAny*>(aFrame)); |
|
568 |
|
569 // determine the length of the security header (e.g. IV etc.) ... |
|
570 const TUint KSecurityHeaderLen( DecryptHdrOffset( aCtxImpl, aFlags ) ); |
|
571 |
|
572 OsTracePrint( KRxFrame, (TUint8*)("UMAC: KSecurityHeaderLen: %d"), |
|
573 KSecurityHeaderLen ); |
|
574 |
|
575 // ... and the security trailer (e.g. MIC etc.) |
|
576 const TUint KSecurityTrailerLen( DecryptTrailerOffset( aCtxImpl, aFlags ) ); |
|
577 |
|
578 OsTracePrint( KRxFrame, (TUint8*)("UMAC: KSecurityTrailerLen: %d"), |
|
579 KSecurityTrailerLen ); |
|
580 |
|
581 // as the MAC header of a QoS data MPDU has an additional field |
|
582 // we need to take that into account; so make a note if we indeed have |
|
583 // received a QoS data MPDU |
|
584 const TBool KQosData = |
|
585 ( hdr->iHdr.iFrameControl.iType == E802Dot11FrameTypeQosData ) ? |
|
586 ETrue : EFalse; |
|
587 |
|
588 // the MAC header of HT QoS data MPDU also has an additional field, |
|
589 // so determine if that field is present and hence has a non-zero length |
|
590 const TUint KHtControlLen ( |
|
591 KQosData && HtcFieldPresent( aCtxImpl, aFrame, aFlags ) ? |
|
592 KHtControlFieldLength : 0 ); |
|
593 |
|
594 // determine if the MPDU contains an A-MSDU |
|
595 const TBool KAmsdu ( |
|
596 KQosData && qoshdr->iHdr.AmsduPresent() ? ETrue : EFalse ); |
|
597 |
|
598 if ( !RxDataMpduValid( |
|
599 aLength, |
|
600 hdr->iHdr, |
|
601 KQosData, |
|
602 KAmsdu, |
|
603 KHtControlLen, |
|
604 KSecurityHeaderLen, |
|
605 KSecurityTrailerLen ) ) |
|
606 { |
|
607 // the overall MAC MPDU (disregarding the included MSDU(s) at this |
|
608 // point) is not valid for us. Release the Rx buffer & abort |
|
609 aCtxImpl.iUmac.MarkRxBufFree( aBuffer ); |
|
610 return; |
|
611 } |
|
612 |
|
613 TUint8* framePtr ( 0 ); |
|
614 WHA::TQueueId accessCategory( WHA::ELegacy ); |
|
615 |
|
616 // User Priority is regarded as Best Effort (i.e. Legacy, i.e. zero) unless |
|
617 // the received MPDU is a QoS Data MPDU & a different priority is |
|
618 // specified in its MAC header |
|
619 TUint8 userPriority( 0 ); |
|
620 |
|
621 if ( KQosData ) |
|
622 { |
|
623 // a QoS Data MPDU |
|
624 |
|
625 // move framePtr past the MAC header |
|
626 framePtr = reinterpret_cast<TUint8 *>( |
|
627 reinterpret_cast<SQosDataFrameHeader *>( hdr ) + 1 ) |
|
628 + KHtControlLen; |
|
629 |
|
630 // get the User Priority |
|
631 userPriority = qoshdr->iHdr.UserPriority(); |
|
632 |
|
633 // make a note of the Access Category corresponding to the |
|
634 // user priority of the MPDU (note that there's a one to one |
|
635 // mapping between Queue id and Access Category) |
|
636 accessCategory = Queue( userPriority ); |
|
637 } |
|
638 else |
|
639 { |
|
640 // move framePtr past the MAC header |
|
641 framePtr = reinterpret_cast<TUint8 *>( |
|
642 reinterpret_cast<SDataFrameHeader *>( hdr ) + 1 ); |
|
643 } |
|
644 |
|
645 // move after possibly existing security header and possibly existing |
|
646 // A-MSDU subframe header, i.e. beginning of SNAP header |
|
647 framePtr += KAmsdu ? |
|
648 KSecurityHeaderLen + sizeof( SAmsduSubframeHeader ) : |
|
649 KSecurityHeaderLen; |
|
650 TUint8* snapLocation ( framePtr ); |
|
651 |
|
652 // determine the DA type |
|
653 const TDaType KDaType ( RxFrameDaType( hdr->iHdr ) ); |
|
654 |
|
655 TSnapStatus snapstatus( ESnapUnknown ); |
|
656 TDataBuffer* latestValidPacketForUsr ( NULL ); |
|
657 TUint nbrOfpacketsForUsr ( 0 ); |
|
658 TUint nbrOfpacketsForMgmtClient ( 0 ); |
|
659 const TUint KMaxNbrOfPacketsForUsr ( 30 ); |
|
660 const TUint KMaxNbrOfPacketsForMgmtClient ( 10 ); |
|
661 const TDataBuffer* packetsForUsr[KMaxNbrOfPacketsForUsr]; |
|
662 const TDataBuffer* packetsForMgmtClient[KMaxNbrOfPacketsForMgmtClient]; |
|
663 // one byte past the last actual payload byte (so excluding the potentially |
|
664 // present security trailer) of the MPDU |
|
665 const TUint8* const KMpduPayloadEnd ( |
|
666 reinterpret_cast<const TUint8*>(aFrame) |
|
667 + aLength |
|
668 - KSecurityTrailerLen ); |
|
669 TPowerMgmtModeChange powerMgmtModeChange ( ENoChange ); |
|
670 |
|
671 // handle every MSDU contained in this MPDU. If this is not an A-MSDU |
|
672 // there's only a single MSDU in it. |
|
673 do |
|
674 { |
|
675 TUint8* rxBuffer ( aBuffer ); |
|
676 |
|
677 // move after SNAP header to Ethernet type field |
|
678 framePtr += sizeof( SSnapHeader ); |
|
679 const SEthernetType* const KEtherTypeLocation |
|
680 = reinterpret_cast<const SEthernetType*>( framePtr ); |
|
681 |
|
682 // determine Ethernet type |
|
683 const TUint16 KEtherType = KEtherTypeLocation->Type(); |
|
684 |
|
685 OsTracePrint( KRxFrame, (TUint8*) |
|
686 ("UMAC: ether type: 0x%04x"), |
|
687 KEtherType ); |
|
688 |
|
689 // pointer to subframe heaader; or NULL if the MPDU doesn't contain |
|
690 // an A-MSDU |
|
691 const SAmsduSubframeHeader* KSubframeHdr ( KAmsdu ? |
|
692 ( reinterpret_cast<const SAmsduSubframeHeader*>( |
|
693 snapLocation) - 1 ) : |
|
694 NULL ); |
|
695 |
|
696 // determine if this is a multicast MSDU |
|
697 TBool KMulticastMsdu ( EFalse ); |
|
698 if ( KSubframeHdr ) |
|
699 { |
|
700 KMulticastMsdu = IsGroupBitSet( KSubframeHdr->iDa ); |
|
701 } |
|
702 else |
|
703 { |
|
704 KMulticastMsdu = ( KDaType == EUnicastAddress ? EFalse : ETrue ); |
|
705 } |
|
706 |
|
707 // determine subframe length, which can be non-zero only if the MPDU |
|
708 // contains an A-MSDU |
|
709 const TUint KSubframeLen ( KSubframeHdr ? KSubframeHdr->Length() : 0 ); |
|
710 |
|
711 if ( !RxMsduValid( |
|
712 aCtxImpl, |
|
713 hdr->iHdr, |
|
714 KSubframeHdr, |
|
715 snapLocation, |
|
716 KEtherType, |
|
717 KMulticastMsdu, |
|
718 aFlags, |
|
719 snapstatus ) ) |
|
720 { |
|
721 // this MSDU is not valid/relevant for us |
|
722 |
|
723 if ( KAmsdu ) |
|
724 { |
|
725 // move pointer to the SNAP of the possibly existing next |
|
726 // subframe |
|
727 snapLocation += |
|
728 Align4( sizeof( SAmsduSubframeHeader ) + KSubframeLen ); |
|
729 // update frame pointer accordingly |
|
730 framePtr = snapLocation; |
|
731 |
|
732 continue; |
|
733 } |
|
734 else |
|
735 { |
|
736 // this MPDU doesn't contain an A-MSDU, so there cannot be |
|
737 // more than a single MSDU in it |
|
738 break; |
|
739 } |
|
740 } |
|
741 |
|
742 // determine if this MSDU is for user / protocol stack |
|
743 const TBool KMsduForUser ( RxMsduForUser( KEtherType, snapstatus) ); |
|
744 |
|
745 if ( KMsduForUser && !aCtxImpl.iUmac.ProtocolStackSideClientReady() ) |
|
746 { |
|
747 // this MSDU should be forwarded up the protocol stack but the |
|
748 // protocol stack client is not ready. So we need to skip at |
|
749 // least this MSDU. |
|
750 // Move pointer to the SNAP of the possibly existing next subframe |
|
751 snapLocation += |
|
752 Align4( sizeof( SAmsduSubframeHeader ) + KSubframeLen ); |
|
753 // update frame pointer accordingly |
|
754 framePtr = snapLocation; |
|
755 |
|
756 OsTracePrint( KRxFrame | KWarningLevel, (TUint8*) |
|
757 ("UMAC: WARNING: protocol stack client not ready; MSDU ignored") ); |
|
758 |
|
759 continue; |
|
760 } |
|
761 |
|
762 TDataBuffer* metaHdr ( aCtxImpl.GetRxFrameMetaHeader() ); |
|
763 if ( !metaHdr ) |
|
764 { |
|
765 // no memory available for Rx frame meta header. This means that |
|
766 // we are not able to forward to higher layers the current MSDU or |
|
767 // any MSDU(s) that possibly follow it in this same MPDU |
|
768 |
|
769 OsTracePrint( KRxFrame | KWarningLevel, (TUint8*) |
|
770 ("UMAC: WARNING: no memory for Rx frame meta hdr; MSDU ignored") ); |
|
771 break; |
|
772 } |
|
773 |
|
774 const TUint KEtherPayloadLen( RxMsduEthernetPayloadLength( |
|
775 aLength, |
|
776 KSubframeLen, |
|
777 KQosData, |
|
778 KHtControlLen, |
|
779 KSecurityHeaderLen, |
|
780 KSecurityTrailerLen ) ); |
|
781 |
|
782 if ( !KMsduForUser && KAmsdu ) |
|
783 { |
|
784 // an MSDU for WLAN Mgmt Client which is also a part of an |
|
785 // A-MSDU. In this case we need to allocate a new buffer for |
|
786 // this packet and copy it there. This is necessary as an |
|
787 // A-MSDU may contain MSDUs both for the protocol stack side |
|
788 // and for WLAN Mgmt Client. Either one of those clients may |
|
789 // complete the handling of its MSDUs first at which point the |
|
790 // Rx buffer(s) for its MSDU(s) is freed. So we need to make |
|
791 // sure that a buffer is not freed while a client is still |
|
792 // handling MSDU(s) contained in it. We do this by always |
|
793 // copying WLAN Mgmt client MSDU(s) part of an A-MSDU to |
|
794 // new buffers. |
|
795 |
|
796 rxBuffer = NewBufForMgmtClientRxFrame( |
|
797 aCtxImpl, |
|
798 snapstatus == ESnapProprietaryOk, |
|
799 KQosData, |
|
800 KHtControlLen, |
|
801 snapstatus == ESnapProprietaryOk ? |
|
802 KSubframeLen : KEtherPayloadLen ); |
|
803 |
|
804 if ( !rxBuffer ) |
|
805 { |
|
806 // allocation failed so we need to skip at least this MSDU. |
|
807 |
|
808 // Move pointer to the SNAP of the possibly existing next |
|
809 // subframe |
|
810 snapLocation += |
|
811 Align4( sizeof( SAmsduSubframeHeader ) + KSubframeLen ); // update frame pointer accordingly |
|
812 // update frame pointer accordingly |
|
813 framePtr = snapLocation; |
|
814 |
|
815 // also release the meta hdr which was planned to be used for |
|
816 // this MSDU |
|
817 aCtxImpl.FreeRxFrameMetaHeader( metaHdr ); |
|
818 |
|
819 OsTracePrint( KRxFrame | KWarningLevel, (TUint8*) |
|
820 ("UMAC: WARNING: new buf alloc for mgmt client frame failed; MSDU ignored") ); |
|
821 continue; |
|
822 } |
|
823 } |
|
824 |
|
825 // set the offset to the beginning of the Rx buffer from the beginning |
|
826 // of the meta header. Note that this may be also negative |
|
827 metaHdr->KeSetBufferOffset( |
|
828 rxBuffer |
|
829 - reinterpret_cast<TUint8*>(metaHdr) ); |
|
830 |
|
831 if ( snapstatus == ESnapProprietaryOk ) |
|
832 { |
|
833 HandleProprietarySnapRxFrame( |
|
834 *metaHdr, |
|
835 KQosData, |
|
836 aFrame, |
|
837 KSubframeHdr, |
|
838 aLength, |
|
839 KSecurityHeaderLen, |
|
840 KSecurityTrailerLen, |
|
841 KHtControlLen, |
|
842 KAmsdu ? rxBuffer : NULL ); |
|
843 } |
|
844 else |
|
845 { |
|
846 DoBuildEthernetFrame( |
|
847 *metaHdr, |
|
848 *hdr, |
|
849 // start of ethernet payload (includes ether type field) |
|
850 reinterpret_cast<const TUint8*>(KEtherTypeLocation), |
|
851 // length of ethernet payload |
|
852 KEtherPayloadLen, |
|
853 KAmsdu, |
|
854 !KMsduForUser && KAmsdu ? rxBuffer : NULL ); |
|
855 } |
|
856 |
|
857 // set the frame's User Priority to the Rx buffer being passed |
|
858 // to the client |
|
859 metaHdr->SetUserPriority( userPriority ); |
|
860 // set the RCPI |
|
861 metaHdr->KeSetRcpi( aRcpi ); |
|
862 |
|
863 if ( KEtherType == KBounceType ) |
|
864 { |
|
865 metaHdr->FrameType( |
|
866 TDataBuffer::KEthernetTestFrame ); |
|
867 } |
|
868 |
|
869 if ( KMsduForUser ) |
|
870 { |
|
871 // a user data / protocol stack data frame |
|
872 |
|
873 OsTracePrint( KRxFrame, (TUint8*) |
|
874 ("UMAC: data frame rx")); |
|
875 |
|
876 packetsForUsr[nbrOfpacketsForUsr++] = metaHdr; |
|
877 latestValidPacketForUsr = metaHdr; |
|
878 if ( KAmsdu ) |
|
879 { |
|
880 metaHdr->KeSetFlags( TDataBuffer::KDontReleaseBuffer ); |
|
881 } |
|
882 } |
|
883 else |
|
884 { |
|
885 // a WLAN Mgmt Client data frame |
|
886 |
|
887 OsTracePrint( KRxFrame, (TUint8*) |
|
888 ("UMAC: mgmt client frame rx")); |
|
889 |
|
890 packetsForMgmtClient[nbrOfpacketsForMgmtClient++] = metaHdr; |
|
891 } |
|
892 |
|
893 // move pointer to the SNAP of the possibly existing next subframe |
|
894 snapLocation += Align4( sizeof( SAmsduSubframeHeader ) + KSubframeLen ); |
|
895 // update frame pointer accordingly |
|
896 framePtr = snapLocation; |
|
897 |
|
898 UpdateDataFrameRxStatistics( |
|
899 aCtxImpl, |
|
900 KEtherType, |
|
901 KMulticastMsdu, |
|
902 accessCategory ); |
|
903 |
|
904 // inform dynamic power mode mgr about Rx data frame acceptance |
|
905 if ( // if this is not our test frame AND |
|
906 KEtherType != KBounceType && |
|
907 // need to change power mgmt mode hasn't already been detected |
|
908 // based on this received (A-)MSDU |
|
909 powerMgmtModeChange == ENoChange ) |
|
910 { |
|
911 powerMgmtModeChange = aCtxImpl.OnFrameRx( |
|
912 accessCategory, |
|
913 KEtherType, |
|
914 KEtherPayloadLen, |
|
915 KDaType ); |
|
916 } |
|
917 |
|
918 // inform Null Send Controller about data frame Rx |
|
919 aCtxImpl.OnDataRxCompleted( |
|
920 ( KEtherType == KEapolType || KEtherType == KWaiType ) ? |
|
921 // as EAPOL and WAI frames or not really Voice data (they |
|
922 // are just sometimes sent with Voice priority), handle them |
|
923 // here as Best Effort (Legacy) |
|
924 WHA::ELegacy : |
|
925 accessCategory, |
|
926 KEtherPayloadLen ); |
|
927 |
|
928 // for a non-A-MSDU this loop is executed only once |
|
929 } while ( KAmsdu && snapLocation < KMpduPayloadEnd ); |
|
930 |
|
931 if ( nbrOfpacketsForUsr ) |
|
932 { |
|
933 latestValidPacketForUsr->KeClearFlags( |
|
934 TDataBuffer::KDontReleaseBuffer ); |
|
935 |
|
936 // complete user data / protocol stack data frame(s) |
|
937 if ( !aCtxImpl.iUmac.ProtocolStackDataReceiveComplete( |
|
938 packetsForUsr[0], |
|
939 nbrOfpacketsForUsr ) ) |
|
940 { |
|
941 // there's no protocol stack client to whom to complete Rx packets. |
|
942 // (Actually the control should never arrive here as we have |
|
943 // checked the readiness of the protocol stack client already |
|
944 // earlier) |
|
945 nbrOfpacketsForUsr = 0; |
|
946 } |
|
947 } |
|
948 |
|
949 if ( nbrOfpacketsForMgmtClient ) |
|
950 { |
|
951 // complete WLAN Mgmt Client data frame(s) |
|
952 aCtxImpl.iUmac.MgmtDataReceiveComplete( |
|
953 packetsForMgmtClient[0], |
|
954 nbrOfpacketsForMgmtClient ); |
|
955 } |
|
956 |
|
957 if ( ( !nbrOfpacketsForUsr && !nbrOfpacketsForMgmtClient ) || |
|
958 ( KAmsdu && !nbrOfpacketsForUsr ) ) |
|
959 { |
|
960 // the contents of the original Rx buffer are not needed any more, |
|
961 // so deallocate it |
|
962 OsTracePrint( KRxFrame, (TUint8*) |
|
963 ("UMAC: free original Rx buf")); |
|
964 aCtxImpl.iUmac.MarkRxBufFree( aBuffer ); |
|
965 } |
|
966 |
|
967 // if any change is needed regarding our power mgmt mode, |
|
968 // proceed with it |
|
969 PowerMgmtModeChange( aCtxImpl, powerMgmtModeChange ); |
|
970 } |
|
971 |
|
972 // --------------------------------------------------------------------------- |
|
973 // |
|
974 // --------------------------------------------------------------------------- |
|
975 // |
|
976 void WlanDot11Associated::OnManagementActionFrameRx( |
|
977 WlanContextImpl& aCtxImpl, |
|
978 const TAny* aFrame, |
|
979 const TUint32 aLength, |
|
980 WHA::TRcpi aRcpi, |
|
981 TUint8* aBuffer ) const |
|
982 { |
|
983 OsTracePrint( KRxFrame, (TUint8*) |
|
984 ("UMAC: WlanDot11Associated::OnManagementActionFrameRx")); |
|
985 |
|
986 TDataBuffer* metaHdr ( aCtxImpl.GetRxFrameMetaHeader() ); |
|
987 |
|
988 if ( metaHdr ) |
|
989 { |
|
990 // set length and type |
|
991 metaHdr->KeSetLength( aLength ); |
|
992 metaHdr->FrameType( TDataBuffer::KDot11Frame ); |
|
993 // set RCPI |
|
994 metaHdr->KeSetRcpi( aRcpi ); |
|
995 |
|
996 // set the offset to the beginning of the Rx buffer from the beginning |
|
997 // of the meta header. Note that this may be also negative |
|
998 metaHdr->KeSetBufferOffset( |
|
999 aBuffer |
|
1000 - reinterpret_cast<TUint8*>(metaHdr) ); |
|
1001 |
|
1002 // set the offset to the beginning of the actual frame within the |
|
1003 // Rx buffer |
|
1004 metaHdr->KeSetOffsetToFrameBeginning( |
|
1005 reinterpret_cast<const TUint8*>(aFrame) // frame beginning |
|
1006 - aBuffer ); // buffer beginning |
|
1007 |
|
1008 // complete |
|
1009 const TDataBuffer* KMetaHdr ( metaHdr ); |
|
1010 aCtxImpl.iUmac.MgmtDataReceiveComplete( KMetaHdr, 1 ); |
|
1011 } |
|
1012 else |
|
1013 { |
|
1014 // no memory available for the meta header. In this case we have no |
|
1015 // other choice than to discard the received frame. |
|
1016 aCtxImpl.iUmac.MarkRxBufFree( aBuffer ); |
|
1017 OsTracePrint( KWarningLevel | KRxFrame, (TUint8*) |
|
1018 ("UMAC: WlanDot11Associated::OnManagementActionFrameRx: WARNING: no memory for meta hdr => abort rx") ); |
|
1019 } |
|
1020 } |
|
1021 |
|
1022 // --------------------------------------------------------------------------- |
|
1023 // |
|
1024 // --------------------------------------------------------------------------- |
|
1025 // |
|
1026 TAny* WlanDot11Associated::RequestForBuffer( |
|
1027 WlanContextImpl& aCtxImpl, |
|
1028 TUint16 aLength ) |
|
1029 { |
|
1030 return aCtxImpl.GetRxBuffer( aLength ); |
|
1031 } |
|
1032 |
|
1033 // --------------------------------------------------------------------------- |
|
1034 // |
|
1035 // --------------------------------------------------------------------------- |
|
1036 // |
|
1037 void WlanDot11Associated::ReceivePacket( |
|
1038 WlanContextImpl& aCtxImpl, |
|
1039 WHA::TStatus aStatus, |
|
1040 const void* aFrame, |
|
1041 TUint16 aLength, |
|
1042 WHA::TRate /*aRate*/, |
|
1043 WHA::TRcpi aRcpi, |
|
1044 WHA::TChannelNumber /*aChannel*/, |
|
1045 TUint8* aBuffer, |
|
1046 TUint32 aFlags ) |
|
1047 { |
|
1048 SDataMpduHeader* hdr( |
|
1049 reinterpret_cast<SDataMpduHeader*>(const_cast<TAny*>(aFrame)) ); |
|
1050 |
|
1051 if ( aStatus == WHA::KSuccess ) |
|
1052 { |
|
1053 // packet reception success lets see what type of frame we have |
|
1054 OsTracePrint( KRxFrame, |
|
1055 (TUint8*) |
|
1056 ("UMAC: WlanDot11Associated::ReceivePacket:frame receive success, frame type: 0x%02x"), |
|
1057 hdr->iHdr.iFrameControl.iType ); |
|
1058 |
|
1059 if ( ( hdr->iHdr.iFrameControl.iType == E802Dot11FrameTypeData ) |
|
1060 || ( hdr->iHdr.iFrameControl.iType == E802Dot11FrameTypeQosData ) ) |
|
1061 { |
|
1062 OnDataFrameRx( aCtxImpl, aFrame, aLength, aFlags, aRcpi, aBuffer ); |
|
1063 |
|
1064 if ( aCtxImpl.InsertNewRcpiIntoPredictor( os_systemTime(), aRcpi ) ) |
|
1065 { |
|
1066 // indicate WLAN signal loss prediction to WLAN Mgmt Client |
|
1067 OnInDicationEvent( aCtxImpl, ESignalLossPrediction ); |
|
1068 } |
|
1069 } |
|
1070 else if ( hdr->iHdr.iFrameControl.iType |
|
1071 == E802Dot11FrameTypeManagementAction ) |
|
1072 { |
|
1073 OnManagementActionFrameRx( |
|
1074 aCtxImpl, |
|
1075 aFrame, |
|
1076 aLength, |
|
1077 aRcpi, |
|
1078 aBuffer ); |
|
1079 |
|
1080 if ( aCtxImpl.InsertNewRcpiIntoPredictor( os_systemTime(), aRcpi ) ) |
|
1081 { |
|
1082 // indicate WLAN signal loss prediction to WLAN Mgmt Client |
|
1083 OnInDicationEvent( aCtxImpl, ESignalLossPrediction ); |
|
1084 } |
|
1085 } |
|
1086 else if ( hdr->iHdr.iFrameControl.iType |
|
1087 == E802Dot11FrameTypeDeauthentication ) |
|
1088 { |
|
1089 OnDeauthenticateFrameRx( aCtxImpl, aBuffer ); |
|
1090 } |
|
1091 else if ( hdr->iHdr.iFrameControl.iType |
|
1092 == E802Dot11FrameTypeDisassociation ) |
|
1093 { |
|
1094 OnDisassociateFrameRx( aCtxImpl, aBuffer ); |
|
1095 } |
|
1096 else if ( hdr->iHdr.iFrameControl.iType |
|
1097 == E802Dot11FrameTypeBeacon ) |
|
1098 { |
|
1099 OnBeaconFrameRx( aCtxImpl, aFrame, aLength, aRcpi, aBuffer ); |
|
1100 } |
|
1101 else if ( hdr->iHdr.iFrameControl.iType |
|
1102 == E802Dot11FrameTypeProbeResp ) |
|
1103 { |
|
1104 OnProbeResponseFrameRx( aCtxImpl, aFrame, aLength, aRcpi, aBuffer ); |
|
1105 } |
|
1106 else |
|
1107 { |
|
1108 OsTracePrint( KRxFrame | KWarningLevel, (TUint8*) |
|
1109 ("UMAC: WlanDot11Associated::ReceivePacket: unsupported frame type: 0x%02x"), |
|
1110 hdr->iHdr.iFrameControl.iType ); |
|
1111 |
|
1112 // release the Rx buffer |
|
1113 aCtxImpl.iUmac.MarkRxBufFree( aBuffer ); |
|
1114 } |
|
1115 } |
|
1116 else if ( aStatus == WHA::KDecryptFailure ) |
|
1117 { |
|
1118 // decryption error |
|
1119 OsTracePrint( KRxFrame | KWarningLevel, (TUint8*) |
|
1120 ("UMAC: WlanDot11Associated::ReceivePacket: decrypt error for frame:"), hdr->iHdr ); |
|
1121 |
|
1122 OnInDicationEvent( aCtxImpl, EWepDecryptFailure ); |
|
1123 |
|
1124 // release the Rx buffer |
|
1125 aCtxImpl.iUmac.MarkRxBufFree( aBuffer ); |
|
1126 } |
|
1127 else if ( aStatus == WHA::KMicFailure ) |
|
1128 { |
|
1129 // MIC failed |
|
1130 OsTracePrint( KRxFrame | KWarningLevel, (TUint8*) |
|
1131 ("UMAC: WlanDot11Associated::ReceivePacket: MIC error for frame:"), hdr->iHdr ); |
|
1132 |
|
1133 // address 1 is always the DA in our case |
|
1134 OnInDicationEvent( aCtxImpl, |
|
1135 (IsGroupBitSet( hdr->iHdr.iAddress1 )) |
|
1136 ? EGroupKeyMicFailure : EPairwiseKeyMicFailure |
|
1137 ); |
|
1138 |
|
1139 // release the Rx buffer |
|
1140 aCtxImpl.iUmac.MarkRxBufFree( aBuffer ); |
|
1141 } |
|
1142 else |
|
1143 { |
|
1144 // packet rececption failed |
|
1145 OsTracePrint( KRxFrame | KWarningLevel, (TUint8*) |
|
1146 ("UMAC: WlanDot11Associated::ReceivePacket: frame receive failure")); |
|
1147 |
|
1148 // release the Rx buffer |
|
1149 aCtxImpl.iUmac.MarkRxBufFree( aBuffer ); |
|
1150 } |
|
1151 } |
|
1152 |
|
1153 // --------------------------------------------------------------------------- |
|
1154 // |
|
1155 // --------------------------------------------------------------------------- |
|
1156 // |
|
1157 TBool WlanDot11Associated::EncryptTxFrames( |
|
1158 WlanContextImpl& aCtxImpl, |
|
1159 const TDataBuffer& aDataBuffer ) const |
|
1160 { |
|
1161 TBool encrypt ( EFalse ); |
|
1162 |
|
1163 if ( aDataBuffer.KeFlags() & TDataBuffer::KTxFrameMustNotBeEncrypted ) |
|
1164 { |
|
1165 // our client has instructed us not the encrypt this frame under |
|
1166 // any circumstances. EFalse will be returned. |
|
1167 // No further action needed |
|
1168 } |
|
1169 else |
|
1170 { |
|
1171 const WHA::TKeyType pairwiseKey ( aCtxImpl.PairWiseKeyType() ); |
|
1172 const WHA::TKeyType groupKey ( aCtxImpl.GroupKeyType() ); |
|
1173 |
|
1174 if ( pairwiseKey != WHA::EKeyNone ) |
|
1175 { |
|
1176 // pairwise key set => use encryption |
|
1177 encrypt = ETrue; |
|
1178 } |
|
1179 else |
|
1180 { |
|
1181 // pairwise key not set |
|
1182 |
|
1183 if ( groupKey == WHA::EWepGroupKey ) |
|
1184 { |
|
1185 // wep group key set => use encryption |
|
1186 encrypt = ETrue; |
|
1187 } |
|
1188 } |
|
1189 } |
|
1190 |
|
1191 return encrypt; |
|
1192 } |
|
1193 |
|
1194 // --------------------------------------------------------------------------- |
|
1195 // |
|
1196 // --------------------------------------------------------------------------- |
|
1197 // |
|
1198 TUint WlanDot11Associated::DecryptHdrOffset( |
|
1199 WlanContextImpl& aCtxImpl, |
|
1200 TUint32 aFlags ) const |
|
1201 { |
|
1202 TUint offset( 0 ); |
|
1203 |
|
1204 const TUint32 encryption ( aFlags & KReceivePacketEncryptionMask ); |
|
1205 |
|
1206 if ( aCtxImpl.WHASettings().iCapability & WHA::SSettings::KNoSecHdrAndTrailer ) |
|
1207 { |
|
1208 // no security header is present on this sw layer. It is removed |
|
1209 // on lower layers; when necessary. |
|
1210 // We will return zero, so no further actions |
|
1211 } |
|
1212 else |
|
1213 { |
|
1214 // IV and/or Ext IV or CCMP header is present |
|
1215 // on this sw layer; when applicable |
|
1216 |
|
1217 if ( encryption == WHA::KEncryptAes ) |
|
1218 { |
|
1219 offset = KCcmpHeaderLength; |
|
1220 } |
|
1221 else if ( encryption == WHA::KEncryptTkip ) |
|
1222 { |
|
1223 offset = KWepIVLength + KWepExtendedIVLength; |
|
1224 } |
|
1225 else if ( encryption == WHA::KEncryptWep ) |
|
1226 { |
|
1227 offset = KWepIVLength; |
|
1228 } |
|
1229 else if ( encryption == WHA::KEncryptWapi ) |
|
1230 { |
|
1231 offset = KWapiHeaderLength; |
|
1232 } |
|
1233 else |
|
1234 { |
|
1235 // frame not encrypted; returns zero |
|
1236 } |
|
1237 } |
|
1238 |
|
1239 return offset; |
|
1240 } |
|
1241 |
|
1242 // --------------------------------------------------------------------------- |
|
1243 // |
|
1244 // --------------------------------------------------------------------------- |
|
1245 // |
|
1246 TUint WlanDot11Associated::DecryptTrailerOffset( |
|
1247 WlanContextImpl& aCtxImpl, |
|
1248 TUint32 aFlags ) const |
|
1249 { |
|
1250 TUint offset( 0 ); |
|
1251 |
|
1252 const TUint32 encryption ( aFlags & KReceivePacketEncryptionMask ); |
|
1253 |
|
1254 if ( aCtxImpl.WHASettings().iCapability & WHA::SSettings::KNoSecHdrAndTrailer ) |
|
1255 { |
|
1256 // no security trailer is present on this sw layer. It is removed |
|
1257 // on lower layers; when necessary. |
|
1258 // We will return zero, so no further actions |
|
1259 } |
|
1260 else |
|
1261 { |
|
1262 // ICV and/or MIC field is present on this sw layer; when applicable |
|
1263 |
|
1264 if ( encryption == WHA::KEncryptAes ) |
|
1265 { |
|
1266 offset = KMicLength; |
|
1267 } |
|
1268 else if ( encryption == WHA::KEncryptTkip ) |
|
1269 { |
|
1270 offset = KMicLength + KWEPICVLength; |
|
1271 } |
|
1272 else if ( encryption == WHA::KEncryptWep ) |
|
1273 { |
|
1274 offset = KWEPICVLength; |
|
1275 } |
|
1276 else if ( encryption == WHA::KEncryptWapi ) |
|
1277 { |
|
1278 offset = KWapiMicLength; |
|
1279 } |
|
1280 else |
|
1281 { |
|
1282 // frame not encrypted; returns zero |
|
1283 } |
|
1284 } |
|
1285 |
|
1286 return offset; |
|
1287 } |
|
1288 |
|
1289 // --------------------------------------------------------------------------- |
|
1290 // |
|
1291 // --------------------------------------------------------------------------- |
|
1292 // |
|
1293 TUint WlanDot11Associated::ComputeEncryptionOffsetAmount( |
|
1294 const WlanContextImpl& aCtxImpl, |
|
1295 const TDataBuffer& aDataBuffer ) const |
|
1296 { |
|
1297 TUint offset( 0 ); |
|
1298 |
|
1299 if ( // our client has instructed us not the encrypt this frame under |
|
1300 // any circumstances OR |
|
1301 ( aDataBuffer.KeFlags() & TDataBuffer::KTxFrameMustNotBeEncrypted ) || |
|
1302 // no space is reserved for security header on this sw layer. It is |
|
1303 // done on lower layers; when necessary. |
|
1304 ( aCtxImpl.WHASettings().iCapability & |
|
1305 WHA::SSettings::KNoSecHdrAndTrailer ) ) |
|
1306 { |
|
1307 // We will return zero, so no further actions |
|
1308 } |
|
1309 else |
|
1310 { |
|
1311 // encryption is allowed if relevant and |
|
1312 // space is reserved for IV and/or Ext IV or CCMP header |
|
1313 // on this sw layer; when necessary |
|
1314 |
|
1315 const WHA::TKeyType groupKey( aCtxImpl.GroupKeyType() ); |
|
1316 const WHA::TKeyType pairwiseKey( aCtxImpl.PairWiseKeyType() ); |
|
1317 |
|
1318 if ( pairwiseKey == WHA::EAesPairWiseKey ) |
|
1319 { |
|
1320 offset = KCcmpHeaderLength; |
|
1321 } |
|
1322 else if ( pairwiseKey == WHA::ETkipPairWiseKey ) |
|
1323 { |
|
1324 offset = KWepIVLength + KWepExtendedIVLength; |
|
1325 } |
|
1326 else if ( pairwiseKey == WHA::EWepPairWiseKey ) |
|
1327 { |
|
1328 offset = KWepIVLength; |
|
1329 } |
|
1330 else if ( pairwiseKey == WHA::EWapiPairWiseKey ) |
|
1331 { |
|
1332 offset = KWapiHeaderLength; |
|
1333 } |
|
1334 else |
|
1335 { |
|
1336 // don't care of anything else |
|
1337 } |
|
1338 |
|
1339 if ( !offset ) |
|
1340 { |
|
1341 // no encryption used based on pairwise key presence |
|
1342 // check for WEP groupkey presence |
|
1343 if ( groupKey == WHA::EWepGroupKey ) |
|
1344 { |
|
1345 offset = KWepIVLength; |
|
1346 } |
|
1347 else |
|
1348 { |
|
1349 // don't care of anything else as group key encyption is not |
|
1350 // supported for the other key types. For them we always have |
|
1351 // a pairwise key |
|
1352 } |
|
1353 } |
|
1354 } |
|
1355 |
|
1356 return offset; |
|
1357 } |
|
1358 |
|
1359 // --------------------------------------------------------------------------- |
|
1360 // |
|
1361 // --------------------------------------------------------------------------- |
|
1362 // |
|
1363 TUint WlanDot11Associated::EncryptTrailerLength( |
|
1364 WlanContextImpl& aCtxImpl, |
|
1365 const TDataBuffer& aDataBuffer ) const |
|
1366 { |
|
1367 TUint length( 0 ); |
|
1368 |
|
1369 if ( // our client has instructed us not the encrypt this frame under |
|
1370 // any circumstances OR |
|
1371 ( aDataBuffer.KeFlags() & TDataBuffer::KTxFrameMustNotBeEncrypted ) || |
|
1372 // no space is reserved for security header on this sw layer. It is |
|
1373 // done on lower layers; when necessary. |
|
1374 ( aCtxImpl.WHASettings().iCapability & |
|
1375 WHA::SSettings::KNoSecHdrAndTrailer ) ) |
|
1376 { |
|
1377 // We will return zero, so no further actions |
|
1378 } |
|
1379 else |
|
1380 { |
|
1381 // encryption is allowed if relevant and |
|
1382 // space is reserved for ICV and/or MIC |
|
1383 // on this sw layer; when necessary |
|
1384 |
|
1385 const WHA::TKeyType groupKey( aCtxImpl.GroupKeyType() ); |
|
1386 const WHA::TKeyType pairwiseKey( aCtxImpl.PairWiseKeyType() ); |
|
1387 |
|
1388 if ( pairwiseKey == WHA::EAesPairWiseKey ) |
|
1389 { |
|
1390 length = KMicLength; |
|
1391 } |
|
1392 else if ( pairwiseKey == WHA::ETkipPairWiseKey ) |
|
1393 { |
|
1394 length = KMicLength + KWEPICVLength; |
|
1395 } |
|
1396 else if ( pairwiseKey == WHA::EWepPairWiseKey ) |
|
1397 { |
|
1398 length = KWEPICVLength; |
|
1399 } |
|
1400 else if ( pairwiseKey == WHA::EWapiPairWiseKey ) |
|
1401 { |
|
1402 length = KWapiMicLength; |
|
1403 } |
|
1404 else |
|
1405 { |
|
1406 // don't care of anything else |
|
1407 } |
|
1408 |
|
1409 if ( !length ) |
|
1410 { |
|
1411 // no pairwise key present |
|
1412 // check for groupkey |
|
1413 if ( groupKey == WHA::EWepGroupKey ) |
|
1414 { |
|
1415 length = KWEPICVLength; |
|
1416 } |
|
1417 else |
|
1418 { |
|
1419 // don't care of anything else as group key encyption is not |
|
1420 // supported for the other key types. For them we always have |
|
1421 // a pairwise key |
|
1422 } |
|
1423 } |
|
1424 } |
|
1425 |
|
1426 return length; |
|
1427 } |
|
1428 |
|
1429 // --------------------------------------------------------------------------- |
|
1430 // |
|
1431 // --------------------------------------------------------------------------- |
|
1432 // |
|
1433 TUint WlanDot11Associated::ComputeQosOffsetAmount( |
|
1434 WlanContextImpl& aCtxImpl ) const |
|
1435 { |
|
1436 const TUint KNoQosHeader( 0 ); |
|
1437 |
|
1438 if ( aCtxImpl.QosEnabled() ) |
|
1439 { |
|
1440 return sizeof( T802Dot11QosControl ); |
|
1441 } |
|
1442 else |
|
1443 { |
|
1444 return KNoQosHeader; |
|
1445 } |
|
1446 } |
|
1447 |
|
1448 // --------------------------------------------------------------------------- |
|
1449 // |
|
1450 // --------------------------------------------------------------------------- |
|
1451 // |
|
1452 void WlanDot11Associated::EncapsulateEthernetFrame( |
|
1453 WlanContextImpl& aCtxImpl, |
|
1454 TWlanUserTxDataCntx& aDataCntx, |
|
1455 TDataBuffer& aDataBuffer, |
|
1456 TUint16& aEtherType ) const |
|
1457 { |
|
1458 TUint8* etherFrameBeginning ( aDataBuffer.GetBuffer() ); |
|
1459 |
|
1460 OsTracePrint( KWsaTxDetails, (TUint8*) |
|
1461 ("UMAC: WlanDot11Associated::EncapsulateEthernetFrame: supplied ether frame start address: 0x%08x"), |
|
1462 reinterpret_cast<TUint32>(etherFrameBeginning) ); |
|
1463 |
|
1464 // start of dot11 frame |
|
1465 SDataFrameHeader* dot11_dataframe_hdr ( NULL ); |
|
1466 |
|
1467 // start of ethernet frame |
|
1468 const SEthernetHeader* ether_hdr |
|
1469 = reinterpret_cast<const SEthernetHeader*>(etherFrameBeginning); |
|
1470 |
|
1471 // determine Ethernet type |
|
1472 aEtherType = ether_hdr->Type(); |
|
1473 |
|
1474 OsTracePrint( KWsaTxDetails, (TUint8*) |
|
1475 ("UMAC: ether type: 0x%04x"), |
|
1476 aEtherType ); |
|
1477 |
|
1478 // compute space required for encryption header |
|
1479 // after dot11 radio header and before data payload |
|
1480 const TUint encryption_offset = ( |
|
1481 ComputeEncryptionOffsetAmount( aCtxImpl, aDataBuffer ) ); |
|
1482 |
|
1483 OsTracePrint( KWsaTxDetails, (TUint8*) |
|
1484 ("UMAC: encryption_offset: %d"), |
|
1485 encryption_offset ); |
|
1486 |
|
1487 const TUint32 ether_offset = (KMacAddressLength << 1); |
|
1488 |
|
1489 // take a backup copy of the destination and source addresses from the |
|
1490 // ethernet frame as they will get overwritten |
|
1491 |
|
1492 TMacAddress da; |
|
1493 os_memcpy( |
|
1494 reinterpret_cast<TUint8*>(&da), |
|
1495 etherFrameBeginning, |
|
1496 sizeof( TMacAddress ) ); |
|
1497 TMacAddress sa; |
|
1498 os_memcpy( |
|
1499 reinterpret_cast<TUint8*>(&sa), |
|
1500 etherFrameBeginning + sizeof( TMacAddress ), |
|
1501 sizeof( TMacAddress ) ); |
|
1502 |
|
1503 // compute space possibly required at the end of the dot11 mac |
|
1504 // header for the QoS control field, which is required for QoS data frames |
|
1505 // This will be needed (i.e. the qosOffset will be > 0) if QoS is enabled |
|
1506 const TUint qosOffset = ComputeQosOffsetAmount( aCtxImpl ); |
|
1507 // the mac header of HT QoS data frames also has an additional field, |
|
1508 // so determine if that field needs to be present and hence has a non-zero |
|
1509 // length |
|
1510 const TUint KHtControlOffset ( aCtxImpl.HtSupportedByNw() ? |
|
1511 KHtControlFieldLength : 0 ); |
|
1512 |
|
1513 if ( qosOffset ) |
|
1514 { |
|
1515 // a QoS data frame |
|
1516 |
|
1517 OsTracePrint( KWsaTxDetails | KQos, (TUint8*) |
|
1518 ("UMAC: qos data frame")); |
|
1519 |
|
1520 SQosDataFrameHeader* dot11QosDataFrameHdr = |
|
1521 reinterpret_cast<SQosDataFrameHeader*>( |
|
1522 etherFrameBeginning |
|
1523 + ether_offset |
|
1524 - sizeof( KEncapsulatingRfc1042SnapHeader ) |
|
1525 - encryption_offset |
|
1526 - KHtControlOffset |
|
1527 - sizeof( SQosDataFrameHeader ) ); |
|
1528 |
|
1529 // construct the MAC header |
|
1530 new (dot11QosDataFrameHdr) SQosDataFrameHeader; |
|
1531 |
|
1532 // set the frame type |
|
1533 dot11QosDataFrameHdr->iHdr.iFrameControl.iType = E802Dot11FrameTypeQosData; |
|
1534 |
|
1535 // reset the QoS control field |
|
1536 // => ack policy == acknowledge && priority == best effort |
|
1537 dot11QosDataFrameHdr->ResetQosControl(); |
|
1538 |
|
1539 // set the user priority |
|
1540 dot11QosDataFrameHdr->SetUserPriority( aDataBuffer.UserPriority() ); |
|
1541 |
|
1542 dot11_dataframe_hdr = reinterpret_cast<SDataFrameHeader*>( |
|
1543 dot11QosDataFrameHdr); |
|
1544 |
|
1545 if ( KHtControlOffset ) |
|
1546 { |
|
1547 // HT control field is present => order bit needs to be set |
|
1548 dot11QosDataFrameHdr->iHdr.SetOrderBit(); |
|
1549 |
|
1550 // clear the HT Control field, too |
|
1551 reinterpret_cast<SHtQosDataFrameHeader*>( |
|
1552 dot11QosDataFrameHdr)->ResetHtControl(); |
|
1553 } |
|
1554 else |
|
1555 { |
|
1556 // HT control field is not present => order bit needs to be cleared |
|
1557 dot11QosDataFrameHdr->iHdr.ClearOrderBit(); |
|
1558 } |
|
1559 } |
|
1560 else |
|
1561 { |
|
1562 // a non-QoS data frame |
|
1563 |
|
1564 OsTracePrint( KWsaTxDetails, (TUint8*) |
|
1565 ("UMAC: non-qos data frame")); |
|
1566 |
|
1567 dot11_dataframe_hdr = reinterpret_cast<SDataFrameHeader*>( |
|
1568 etherFrameBeginning |
|
1569 + ether_offset |
|
1570 - sizeof( KEncapsulatingRfc1042SnapHeader ) |
|
1571 - encryption_offset |
|
1572 - sizeof( SDataFrameHeader ) ); |
|
1573 |
|
1574 // construct the MAC header. In this case this also sets the frame type |
|
1575 // correctly |
|
1576 new (dot11_dataframe_hdr) SDataFrameHeader; |
|
1577 } |
|
1578 |
|
1579 // set the source address |
|
1580 dot11_dataframe_hdr->iAddress2 = sa; |
|
1581 |
|
1582 // set the destination address |
|
1583 DoSetTxMpduDaAddress( *dot11_dataframe_hdr, da ); |
|
1584 |
|
1585 // set the To DS bit |
|
1586 if ( aCtxImpl.NetworkOperationMode() == WHA::EBSS ) |
|
1587 { |
|
1588 dot11_dataframe_hdr->SetToDsBit(); |
|
1589 // set the BSS ID |
|
1590 dot11_dataframe_hdr->iAddress1 = aCtxImpl.GetBssId(); |
|
1591 } |
|
1592 else |
|
1593 { |
|
1594 dot11_dataframe_hdr->ClearToDsBit(); |
|
1595 // set the BSS ID |
|
1596 dot11_dataframe_hdr->iAddress3 = aCtxImpl.GetBssId(); |
|
1597 } |
|
1598 |
|
1599 // determine if the frame needs to be encrypted |
|
1600 if ( EncryptTxFrames( aCtxImpl, aDataBuffer ) ) |
|
1601 { |
|
1602 dot11_dataframe_hdr->SetWepBit(); |
|
1603 } |
|
1604 else |
|
1605 { |
|
1606 dot11_dataframe_hdr->ClearWepBit(); |
|
1607 } |
|
1608 |
|
1609 // set the snap header to correct location. |
|
1610 os_memcpy( |
|
1611 reinterpret_cast<TUint8*>(dot11_dataframe_hdr) |
|
1612 + sizeof( SDataFrameHeader ) |
|
1613 + qosOffset |
|
1614 + KHtControlOffset |
|
1615 // space occupied by encryption header(s) |
|
1616 + encryption_offset, |
|
1617 &KEncapsulatingRfc1042SnapHeader, |
|
1618 sizeof( KEncapsulatingRfc1042SnapHeader ) ); |
|
1619 |
|
1620 // clear the area reserved for IV etc, when necessary |
|
1621 if ( encryption_offset ) |
|
1622 { |
|
1623 os_memset( |
|
1624 reinterpret_cast<TUint8*>(dot11_dataframe_hdr) |
|
1625 + sizeof( SDataFrameHeader ) |
|
1626 + qosOffset |
|
1627 + KHtControlOffset, |
|
1628 0, |
|
1629 encryption_offset ); |
|
1630 } |
|
1631 |
|
1632 // compute padding required for encryption trailer (ICV, MIC etc) |
|
1633 const TUint encryptTrailerLength = ( |
|
1634 EncryptTrailerLength( aCtxImpl, aDataBuffer ) ); |
|
1635 |
|
1636 // clear the area reserved for encryption trailer, when necessary |
|
1637 if ( encryptTrailerLength ) |
|
1638 { |
|
1639 os_memset( |
|
1640 reinterpret_cast<TUint8*>(dot11_dataframe_hdr) |
|
1641 + sizeof( SDataFrameHeader ) |
|
1642 + qosOffset |
|
1643 + KHtControlOffset |
|
1644 + encryption_offset |
|
1645 + sizeof( SSnapHeader ) |
|
1646 + aDataBuffer.GetLength() - ether_offset, |
|
1647 0, |
|
1648 encryptTrailerLength ); |
|
1649 } |
|
1650 |
|
1651 // calculate frame length |
|
1652 const TUint length_of_frame = |
|
1653 // MAC header length |
|
1654 sizeof( SDataFrameHeader ) |
|
1655 // length of possibly existing QoS control field |
|
1656 + qosOffset |
|
1657 // length of possibly existing HT control field |
|
1658 + KHtControlOffset |
|
1659 // SNAP header length |
|
1660 + sizeof( SSnapHeader ) |
|
1661 // length of ethernet payload (including ether type) |
|
1662 + aDataBuffer.GetLength() - ether_offset |
|
1663 // encryption header length |
|
1664 + encryption_offset |
|
1665 // encryption trailer length |
|
1666 + encryptTrailerLength; |
|
1667 |
|
1668 // we now have a dot11 frame ready to be sent |
|
1669 aDataCntx.Dot11FrameReady( |
|
1670 reinterpret_cast<TUint8*>(dot11_dataframe_hdr), |
|
1671 length_of_frame ); |
|
1672 |
|
1673 OsTracePrint( KWsaTxDetails, (TUint8*) |
|
1674 ("UMAC: length_of_frame (excl. fcs): %d"), |
|
1675 length_of_frame ); |
|
1676 OsTracePrint( KWsaTxDetails, (TUint8*) |
|
1677 ("UMAC: frame start address: 0x%08x"), |
|
1678 reinterpret_cast<TUint32>(dot11_dataframe_hdr) ); |
|
1679 } |
|
1680 |
|
1681 // --------------------------------------------------------------------------- |
|
1682 // |
|
1683 // --------------------------------------------------------------------------- |
|
1684 // |
|
1685 void WlanDot11Associated::EncapsulateSnapFrame( |
|
1686 WlanContextImpl& aCtxImpl, |
|
1687 TWlanUserTxDataCntx& aDataCntx, |
|
1688 TDataBuffer& aDataBuffer, |
|
1689 TBool aEncrypt, |
|
1690 TUint aEncryptionOffset, |
|
1691 TUint aEncryptTrailerLength, |
|
1692 TUint aQosOffset, |
|
1693 TUint aHtControlOffset ) const |
|
1694 { |
|
1695 // extract start of frame. The frame starts with a SNAP header |
|
1696 TUint8* snapFrameBeginning ( aDataBuffer.GetBuffer() ); |
|
1697 |
|
1698 // start of dot11 frame |
|
1699 SDataFrameHeader* dot11_dataframe_hdr( NULL ); |
|
1700 |
|
1701 if ( aQosOffset ) |
|
1702 { |
|
1703 OsTracePrint( KWsaTxDetails | KQos, (TUint8*) |
|
1704 ("UMAC: qos data frame")); |
|
1705 |
|
1706 SQosDataFrameHeader* dot11QosDataFrameHdr( |
|
1707 reinterpret_cast<SQosDataFrameHeader*>( |
|
1708 snapFrameBeginning |
|
1709 - aEncryptionOffset |
|
1710 - aHtControlOffset |
|
1711 - sizeof( SQosDataFrameHeader )) ); |
|
1712 |
|
1713 // construct the MAC header |
|
1714 new (dot11QosDataFrameHdr) SQosDataFrameHeader; |
|
1715 |
|
1716 // set the frame type |
|
1717 dot11QosDataFrameHdr->iHdr.iFrameControl.iType = E802Dot11FrameTypeQosData; |
|
1718 |
|
1719 // reset the QoS control field |
|
1720 // => ack policy == acknowledge && priority == best effort |
|
1721 dot11QosDataFrameHdr->ResetQosControl(); |
|
1722 |
|
1723 // set the user priority |
|
1724 dot11QosDataFrameHdr->SetUserPriority( aDataBuffer.UserPriority() ); |
|
1725 |
|
1726 dot11_dataframe_hdr = reinterpret_cast<SDataFrameHeader*>( |
|
1727 dot11QosDataFrameHdr); |
|
1728 |
|
1729 if ( aHtControlOffset ) |
|
1730 { |
|
1731 // HT control field is present => order bit needs to be set |
|
1732 dot11QosDataFrameHdr->iHdr.SetOrderBit(); |
|
1733 // clear the HT Control field, too |
|
1734 reinterpret_cast<SHtQosDataFrameHeader*>( |
|
1735 dot11QosDataFrameHdr)->ResetHtControl(); |
|
1736 } |
|
1737 else |
|
1738 { |
|
1739 // HT control field is not present => order bit needs to be cleared |
|
1740 dot11QosDataFrameHdr->iHdr.ClearOrderBit(); |
|
1741 } |
|
1742 } |
|
1743 else |
|
1744 { |
|
1745 OsTracePrint( KWsaTxDetails | KQos, (TUint8*) |
|
1746 ("UMAC: non-qos data frame")); |
|
1747 |
|
1748 dot11_dataframe_hdr = reinterpret_cast<SDataFrameHeader*>( |
|
1749 snapFrameBeginning |
|
1750 - aEncryptionOffset |
|
1751 - sizeof( SDataFrameHeader ) ); |
|
1752 |
|
1753 // construct the MAC header. In this case this also sets the frame type |
|
1754 // correctly |
|
1755 new (dot11_dataframe_hdr) SDataFrameHeader; |
|
1756 } |
|
1757 |
|
1758 // set the source address |
|
1759 dot11_dataframe_hdr->iAddress2 = aCtxImpl.iWlanMib.dot11StationId; |
|
1760 |
|
1761 // set the destination address |
|
1762 DoSetTxMpduDaAddress( *dot11_dataframe_hdr, |
|
1763 aDataBuffer.KeDestinationAddress() ); |
|
1764 |
|
1765 // set the To DS bit |
|
1766 if ( aCtxImpl.NetworkOperationMode() == WHA::EBSS ) |
|
1767 { |
|
1768 dot11_dataframe_hdr->SetToDsBit(); |
|
1769 // set the BSS ID |
|
1770 dot11_dataframe_hdr->iAddress1 = aCtxImpl.GetBssId(); |
|
1771 } |
|
1772 else |
|
1773 { |
|
1774 dot11_dataframe_hdr->ClearToDsBit(); |
|
1775 // set the BSS ID |
|
1776 dot11_dataframe_hdr->iAddress3 = aCtxImpl.GetBssId(); |
|
1777 } |
|
1778 |
|
1779 // determine if the frame needs to be encrypted |
|
1780 if ( aEncrypt ) |
|
1781 { |
|
1782 dot11_dataframe_hdr->SetWepBit(); |
|
1783 } |
|
1784 else |
|
1785 { |
|
1786 dot11_dataframe_hdr->ClearWepBit(); |
|
1787 } |
|
1788 |
|
1789 // clear the area reserved for IV etc, when necessary |
|
1790 if ( aEncryptionOffset ) |
|
1791 { |
|
1792 os_memset( |
|
1793 reinterpret_cast<TUint8*>(dot11_dataframe_hdr) |
|
1794 + sizeof( SDataFrameHeader ) |
|
1795 + aQosOffset |
|
1796 + aHtControlOffset, |
|
1797 0, |
|
1798 aEncryptionOffset ); |
|
1799 } |
|
1800 |
|
1801 // clear the area reserved for encryption trailer, when necessary |
|
1802 if ( aEncryptTrailerLength ) |
|
1803 { |
|
1804 os_memset( |
|
1805 reinterpret_cast<TUint8*>(dot11_dataframe_hdr) |
|
1806 + sizeof( SDataFrameHeader ) |
|
1807 + aQosOffset |
|
1808 + aHtControlOffset |
|
1809 + aEncryptionOffset |
|
1810 + aDataBuffer.GetLength(), |
|
1811 0, |
|
1812 aEncryptTrailerLength ); |
|
1813 } |
|
1814 |
|
1815 // calculate frame length |
|
1816 const TUint length_of_frame = |
|
1817 // MAC header length |
|
1818 sizeof( SDataFrameHeader ) + |
|
1819 // length of possibly existing QoS control field |
|
1820 aQosOffset + |
|
1821 // length of possibly existing HT control field |
|
1822 aHtControlOffset + |
|
1823 // payload (including SNAP header) |
|
1824 aDataBuffer.GetLength() |
|
1825 // encryption header length |
|
1826 + aEncryptionOffset |
|
1827 // encryption trailer length |
|
1828 + aEncryptTrailerLength; |
|
1829 |
|
1830 // we now have a dot11 frame ready to be sent |
|
1831 aDataCntx.Dot11FrameReady( |
|
1832 reinterpret_cast<TUint8*>(dot11_dataframe_hdr), |
|
1833 length_of_frame ); |
|
1834 |
|
1835 OsTracePrint( KWsaTxDetails, (TUint8*) |
|
1836 ("UMAC: length_of_frame: %d"), |
|
1837 length_of_frame ); |
|
1838 OsTracePrint( KWsaTxDetails, (TUint8*) |
|
1839 ("UMAC: frame start address: 0x%08x"), |
|
1840 reinterpret_cast<TUint32>(dot11_dataframe_hdr) ); |
|
1841 // trace the dot11 frame header |
|
1842 OsTracePrint( KWsaTxDetails, (TUint8*) |
|
1843 ("UMAC: Encapsulated prorietary SNAP Tx frame:"), |
|
1844 *(reinterpret_cast<Sdot11MacHeader*>(dot11_dataframe_hdr))); |
|
1845 } |
|
1846 |
|
1847 // --------------------------------------------------------------------------- |
|
1848 // |
|
1849 // --------------------------------------------------------------------------- |
|
1850 // |
|
1851 void WlanDot11Associated::SetDot11FrameToTxBuffer( |
|
1852 const WlanContextImpl& aCtxImpl, |
|
1853 TWlanUserTxDataCntx& aDataCntx, |
|
1854 TDataBuffer& aDataBuffer ) const |
|
1855 { |
|
1856 OsTracePrint( KWsaTxDetails, (TUint8*) |
|
1857 ("UMAC: WlanDot11Associated::SetDot11FrameToTxBuffer") ); |
|
1858 |
|
1859 if ( aCtxImpl.HtSupportedByNw() && aCtxImpl.QosEnabled() ) |
|
1860 { |
|
1861 // in this case we need to insert the HT Control field to the |
|
1862 // otherwise ready 802.11 MAC frame |
|
1863 |
|
1864 const TUint KOrigLengthOfFrame = aDataBuffer.GetLength(); |
|
1865 const TUint KMgmtFrameMacHdrLen = sizeof( SManagementFrameHeader ); |
|
1866 TUint8* KFrameStart = aDataBuffer.GetBuffer(); |
|
1867 |
|
1868 os_memcpy( |
|
1869 KFrameStart + |
|
1870 KMgmtFrameMacHdrLen + |
|
1871 KHtControlFieldLength, |
|
1872 KFrameStart + |
|
1873 KMgmtFrameMacHdrLen, |
|
1874 KOrigLengthOfFrame - KMgmtFrameMacHdrLen ); |
|
1875 |
|
1876 // clear the added HT Control field |
|
1877 reinterpret_cast<SHtManagementFrameHeader*>( |
|
1878 KFrameStart)->ResetHtControl(); |
|
1879 // update frame length |
|
1880 aDataBuffer.KeSetLength( KOrigLengthOfFrame + KHtControlFieldLength ); |
|
1881 // as the HT control field is present the order bit needs to be set |
|
1882 reinterpret_cast<SHtManagementFrameHeader*>( |
|
1883 KFrameStart)->iMgmtFrameHdr.SetOrderBit(); |
|
1884 } |
|
1885 |
|
1886 // we now have a dot11 frame ready to be sent |
|
1887 aDataCntx.Dot11FrameReady( |
|
1888 aDataBuffer.GetBuffer(), |
|
1889 aDataBuffer.GetLength() ); |
|
1890 } |
|
1891 |
|
1892 // --------------------------------------------------------------------------- |
|
1893 // |
|
1894 // --------------------------------------------------------------------------- |
|
1895 // |
|
1896 void WlanDot11Associated::EncapsulateFrame( |
|
1897 WlanContextImpl& aCtxImpl, |
|
1898 TWlanUserTxDataCntx& aDataCntx, |
|
1899 TDataBuffer& aDataBuffer, |
|
1900 TUint16& aEtherType ) |
|
1901 { |
|
1902 const TDataBuffer::TFrameType KFrameType( aDataBuffer.FrameType() ); |
|
1903 |
|
1904 OsTracePrint( KWsaTx, (TUint8*) |
|
1905 ("UMAC: WlanDot11Associated::EncapsulateFrame: frame type: %d"), |
|
1906 KFrameType ); |
|
1907 |
|
1908 if ( KFrameType == TDataBuffer::KEthernetFrame || |
|
1909 KFrameType == TDataBuffer::KEthernetTestFrame ) |
|
1910 { |
|
1911 // ethernet II frame in the buffer for tx |
|
1912 |
|
1913 EncapsulateEthernetFrame( |
|
1914 aCtxImpl, |
|
1915 aDataCntx, |
|
1916 aDataBuffer, |
|
1917 aEtherType ); |
|
1918 } |
|
1919 else if ( KFrameType == TDataBuffer::KSnapFrame ) |
|
1920 { |
|
1921 // frame beginning with a SNAP header in the buffer for tx |
|
1922 |
|
1923 EncapsulateSnapFrame( |
|
1924 aCtxImpl, |
|
1925 aDataCntx, |
|
1926 aDataBuffer, |
|
1927 EncryptTxFrames( aCtxImpl, aDataBuffer ), |
|
1928 ComputeEncryptionOffsetAmount( aCtxImpl, aDataBuffer ), |
|
1929 EncryptTrailerLength( aCtxImpl, aDataBuffer ), |
|
1930 ComputeQosOffsetAmount( aCtxImpl ), |
|
1931 aCtxImpl.HtSupportedByNw() ? |
|
1932 KHtControlFieldLength : |
|
1933 0 ); |
|
1934 } |
|
1935 else if ( KFrameType == TDataBuffer::KDot11Frame ) |
|
1936 { |
|
1937 // ready made 802.11 frame in the buffer for tx |
|
1938 |
|
1939 SetDot11FrameToTxBuffer( aCtxImpl, aDataCntx, aDataBuffer ); |
|
1940 } |
|
1941 else |
|
1942 { |
|
1943 // not supported |
|
1944 OsTracePrint( KErrorLevel, (TUint8*)("UMAC: frame_type: %d"), |
|
1945 KFrameType ); |
|
1946 OsAssert( (TUint8*)("UMAC: panic"),(TUint8*)(WLAN_FILE), __LINE__ ); |
|
1947 } |
|
1948 } |
|
1949 |
|
1950 // --------------------------------------------------------------------------- |
|
1951 // |
|
1952 // --------------------------------------------------------------------------- |
|
1953 // |
|
1954 TBool WlanDot11Associated::TxData( |
|
1955 WlanContextImpl& aCtxImpl, |
|
1956 TDataBuffer& aDataBuffer, |
|
1957 TBool aMore ) |
|
1958 { |
|
1959 TWlanUserTxDataCntx& data_cntx( aCtxImpl.GetTxDataCntx() ); |
|
1960 |
|
1961 TBool stateChange( EFalse ); |
|
1962 |
|
1963 if ( (aCtxImpl.ProtocolStackTxDataAllowed()) ) |
|
1964 { |
|
1965 // protocol stack tx data allowed |
|
1966 // now construct a dot11 frame from databuffer to storage |
|
1967 |
|
1968 TUint16 etherType( 0 ); // initial value: not relevant |
|
1969 |
|
1970 // construct the frame |
|
1971 EncapsulateFrame( aCtxImpl, data_cntx, aDataBuffer, etherType ); |
|
1972 |
|
1973 // dot11 frame ready to be sent so push it to the packet sceduler |
|
1974 |
|
1975 // start of dot11 frame to send |
|
1976 const TUint8* start_of_frame( |
|
1977 data_cntx.StartOfFrame() ); |
|
1978 |
|
1979 // select correct tx queue |
|
1980 const WHA::TQueueId queue_id( |
|
1981 QueueId( aCtxImpl, start_of_frame ) ); |
|
1982 |
|
1983 // push the frame to packet scheduler for transmission |
|
1984 aCtxImpl.PushPacketToPacketScheduler( |
|
1985 start_of_frame, |
|
1986 data_cntx.LengthOfFrame(), |
|
1987 queue_id, |
|
1988 E802Dot11FrameTypeData, |
|
1989 &aDataBuffer, |
|
1990 aMore, |
|
1991 OutgoingMulticastDataFrame( |
|
1992 reinterpret_cast<const SDataFrameHeader*>( start_of_frame ) ) ); |
|
1993 // now just wait for the scheduler to call completion methods |
|
1994 |
|
1995 // check if we need to change power mgmt mode because of frame Tx |
|
1996 const TPowerMgmtModeChange KPowerMgmtModeChange ( |
|
1997 aCtxImpl.OnFrameTx( queue_id, etherType ) ); |
|
1998 |
|
1999 // if any change change is needed regarding our power mgmt mode, |
|
2000 // proceed with it |
|
2001 stateChange = PowerMgmtModeChange( aCtxImpl, KPowerMgmtModeChange ); |
|
2002 } |
|
2003 else |
|
2004 { |
|
2005 // protocol stack tx data not allowed |
|
2006 |
|
2007 #ifndef NDEBUG |
|
2008 // programming error |
|
2009 OsTracePrint( KErrorLevel, (TUint8*) |
|
2010 ("UMAC: Tx attempted when it's not allowed") ); |
|
2011 OsAssert( (TUint8*)("UMAC: panic"), (TUint8*)(WLAN_FILE), __LINE__ ); |
|
2012 #else |
|
2013 aCtxImpl.iUmac.OnTxProtocolStackDataComplete( |
|
2014 KErrNone, |
|
2015 &aDataBuffer ); |
|
2016 #endif |
|
2017 } |
|
2018 |
|
2019 return stateChange; |
|
2020 } |
|
2021 |
|
2022 // --------------------------------------------------------------------------- |
|
2023 // |
|
2024 // --------------------------------------------------------------------------- |
|
2025 // |
|
2026 void WlanDot11Associated::OnPacketSendComplete( |
|
2027 WlanContextImpl& aCtxImpl, |
|
2028 WHA::TStatus aStatus, |
|
2029 TUint32 aPacketId, |
|
2030 WHA::TRate aRate, |
|
2031 TUint32 /*aPacketQueueDelay*/, |
|
2032 TUint32 aMediaDelay, |
|
2033 TUint aTotalTxDelay, |
|
2034 TUint8 aAckFailures, |
|
2035 WHA::TQueueId aQueueId, |
|
2036 WHA::TRate aRequestedRate, |
|
2037 TBool aMulticastData ) |
|
2038 { |
|
2039 if ( aPacketId == E802Dot11FrameTypeData || |
|
2040 aPacketId == E802Dot11FrameTypeDataEapol ) |
|
2041 { |
|
2042 // update data frame statistics |
|
2043 UpdateTxDataFrameStatistics( |
|
2044 aCtxImpl, |
|
2045 aQueueId, |
|
2046 aStatus, |
|
2047 aMulticastData, |
|
2048 aAckFailures, |
|
2049 aMediaDelay, |
|
2050 aTotalTxDelay ); |
|
2051 } |
|
2052 else if ( aPacketId == E802Dot11FrameTypeQosDataNull ) |
|
2053 { |
|
2054 // inform Null Data frame sending controller of QoS Null data Tx |
|
2055 // completion; successful or not |
|
2056 aCtxImpl.OnQosNullDataTxCompleted(); |
|
2057 } |
|
2058 else if ( aPacketId == E802Dot11FrameTypeDataNull ) |
|
2059 { |
|
2060 // inform Null Data frame sending controller of Null data Tx |
|
2061 // completion; successful or not |
|
2062 aCtxImpl.OnNullDataTxCompleted(); |
|
2063 } |
|
2064 |
|
2065 if ( aStatus == WHA::KSuccess ) |
|
2066 { |
|
2067 aCtxImpl.OnTxCompleted( aRate, ETrue, aQueueId, aRequestedRate ); |
|
2068 |
|
2069 aCtxImpl.ResetFailedTxPacketCount(); |
|
2070 DoRegainedBSSIndication( aCtxImpl ); |
|
2071 |
|
2072 if ( aPacketId == E802Dot11FrameTypeData || |
|
2073 aPacketId == E802Dot11FrameTypeDataEapol || |
|
2074 aPacketId == E802Dot11FrameTypeTestFrame ) |
|
2075 { |
|
2076 // inform Null Data frame sending controller of successful |
|
2077 // data frame Tx completion |
|
2078 aCtxImpl.OnDataTxCompleted( |
|
2079 aPacketId == E802Dot11FrameTypeDataEapol ? |
|
2080 // as EAPOL and WAI frames or not really Voice data (we just |
|
2081 // send them with Voice priority in WMM nw), handle them |
|
2082 // here as Best Effort (Legacy) |
|
2083 WHA::ELegacy : |
|
2084 aQueueId ); |
|
2085 } |
|
2086 } |
|
2087 else if ( aStatus == WHA::KErrorLifetimeExceeded && !aAckFailures ) |
|
2088 { |
|
2089 // the packet was discarded by WLAN PDD without any Tx attempts |
|
2090 // So this is not a Tx failure and we don't need to take |
|
2091 // any further actions |
|
2092 OsTracePrint( KWsaTxDetails, (TUint8*) |
|
2093 ("UMAC: WlanDot11Associated::OnPacketSendComplete: packet expired in PDD without any Tx attempts)")); |
|
2094 } |
|
2095 else |
|
2096 { |
|
2097 // an actual Tx failure has occurred |
|
2098 |
|
2099 aCtxImpl.OnTxCompleted( aRate, EFalse, aQueueId, aRequestedRate ); |
|
2100 |
|
2101 aCtxImpl.IncrementFailedTxPacketCount(); |
|
2102 |
|
2103 // if we have failed to send more than threshold number of |
|
2104 // consecutive packets, send Consecutive Tx Failures indication to |
|
2105 // WLAN Mgmt Client - unless already sent |
|
2106 if ( aCtxImpl.FailedTxPacketCount() > |
|
2107 aCtxImpl.iWlanMib.iFailedTxPacketCountThreshold ) |
|
2108 { |
|
2109 DoConsecutiveTxFailuresIndication( aCtxImpl ); |
|
2110 aCtxImpl.ResetFailedTxPacketCount(); |
|
2111 } |
|
2112 } |
|
2113 |
|
2114 aCtxImpl.iUmac.OnTxDataSent(); |
|
2115 } |
|
2116 |
|
2117 // --------------------------------------------------------------------------- |
|
2118 // |
|
2119 // --------------------------------------------------------------------------- |
|
2120 // |
|
2121 void WlanDot11Associated::DoConsecutiveBeaconsLostIndication( |
|
2122 WlanContextImpl& aCtxImpl ) |
|
2123 { |
|
2124 if ( aCtxImpl.OnConsecutiveBeaconsLost() ) |
|
2125 { |
|
2126 OnInDicationEvent( aCtxImpl, EConsecutiveBeaconsLost ); |
|
2127 } |
|
2128 } |
|
2129 |
|
2130 // ----------------------------------------------------------------------------- |
|
2131 // |
|
2132 // ----------------------------------------------------------------------------- |
|
2133 // |
|
2134 void WlanDot11Associated::DoConsecutiveTxFailuresIndication( |
|
2135 WlanContextImpl& aCtxImpl ) |
|
2136 { |
|
2137 if ( aCtxImpl.OnConsecutiveTxFailures() ) |
|
2138 { |
|
2139 OnInDicationEvent( aCtxImpl, EConsecutiveTxFailures ); |
|
2140 } |
|
2141 } |
|
2142 |
|
2143 // --------------------------------------------------------------------------- |
|
2144 // |
|
2145 // --------------------------------------------------------------------------- |
|
2146 // |
|
2147 void WlanDot11Associated::DoRegainedBSSIndication( |
|
2148 WlanContextImpl& aCtxImpl ) |
|
2149 { |
|
2150 if ( aCtxImpl.OnBssRegained() ) |
|
2151 { |
|
2152 OnInDicationEvent( aCtxImpl, EBSSRegained ); |
|
2153 } |
|
2154 } |
|
2155 |
|
2156 // --------------------------------------------------------------------------- |
|
2157 // |
|
2158 // --------------------------------------------------------------------------- |
|
2159 // |
|
2160 TBool WlanDot11Associated::AddMulticastAddr( |
|
2161 WlanContextImpl& aCtxImpl, |
|
2162 const TMacAddress& aMacAddr ) |
|
2163 { |
|
2164 TBool stateTransitionOccurred( EFalse ); |
|
2165 |
|
2166 OsTracePrint( |
|
2167 KWlmCmdDetails, |
|
2168 (TUint8*) |
|
2169 ("UMAC: WlanDot11Associated::AddMulticastAddr(): addr to be added:"), |
|
2170 aMacAddr); |
|
2171 |
|
2172 if ( aCtxImpl.MulticastFilteringDisAllowed() ) |
|
2173 { |
|
2174 OsTracePrint( |
|
2175 KWlmCmdDetails, |
|
2176 (TUint8*) |
|
2177 ("UMAC: WlanDot11Associated::AddMulticastAddr(): Multicast filtering disallowed")); |
|
2178 |
|
2179 OnOidComplete( aCtxImpl, KErrGeneral ); |
|
2180 } |
|
2181 else |
|
2182 { |
|
2183 if ( aCtxImpl.WHASettings().iNumOfGroupTableEntrys > |
|
2184 aCtxImpl.MulticastAddressCount() ) |
|
2185 { |
|
2186 // wha layer is able to take in an address |
|
2187 |
|
2188 // 1st try to add the address to our own internal bookkeeping |
|
2189 WlanContextImpl::TGroupAddStatus addStatus = |
|
2190 aCtxImpl.AddMulticastAddress( aMacAddr ); |
|
2191 |
|
2192 switch ( addStatus ) |
|
2193 { |
|
2194 case WlanContextImpl::EOk: |
|
2195 OsTracePrint( |
|
2196 KWlmCmdDetails, |
|
2197 (TUint8*) |
|
2198 ("UMAC: WlanDot11Associated::AddMulticastAddr(): Address will be added to the MIB")); |
|
2199 // the address needed to be added and adding went ok. |
|
2200 // Now update the group addresses MIB |
|
2201 stateTransitionOccurred = SetGroupAddressesTableMib( aCtxImpl ); |
|
2202 break; |
|
2203 case WlanContextImpl::EAlreadyExists: |
|
2204 OsTracePrint( |
|
2205 KWlmCmdDetails, |
|
2206 (TUint8*) |
|
2207 ("UMAC: WlanDot11Associated::AddMulticastAddr(): Address already exists")); |
|
2208 // the specified address already exists so there's no need |
|
2209 // to update the group addresses MIB |
|
2210 // just complete the request with OK status |
|
2211 OnOidComplete( aCtxImpl ); |
|
2212 stateTransitionOccurred = EFalse; |
|
2213 break; |
|
2214 case WlanContextImpl::EFull: |
|
2215 OsTracePrint( |
|
2216 KWlmCmdDetails, |
|
2217 (TUint8*) |
|
2218 ("UMAC: WlanDot11Associated::AddMulticastAddr(): Internal address table full; disallow multicast filtering")); |
|
2219 // we are not able to take in any more addresses. |
|
2220 // We will totally disable the multicast filtering |
|
2221 // and we won't allow it to be enabled any more during |
|
2222 // the current nw connection |
|
2223 // |
|
2224 aCtxImpl.ResetMulticastAddresses(); |
|
2225 aCtxImpl.MulticastFilteringDisAllowed( ETrue ); |
|
2226 stateTransitionOccurred = |
|
2227 SetGroupAddressesTableMib( aCtxImpl ); |
|
2228 break; |
|
2229 default: |
|
2230 // programming error |
|
2231 OsTracePrint( KErrorLevel, (TUint8*) |
|
2232 ("UMAC: addStatus: %d"), addStatus ); |
|
2233 OsAssert( (TUint8*)("UMAC: panic"), |
|
2234 (TUint8*)(WLAN_FILE), __LINE__ ); |
|
2235 } |
|
2236 } |
|
2237 else |
|
2238 { |
|
2239 OsTracePrint( |
|
2240 KWlmCmdDetails, |
|
2241 (TUint8*) |
|
2242 ("UMAC: WlanDot11Associated::AddMulticastAddr(): WHA not able to accept address; disallow multicast filtering")); |
|
2243 // wha layer is not able to take in an address. Either this is one |
|
2244 // address too many, or it doesn't support even a single address. |
|
2245 // In either case we will totally disable the multicast filtering |
|
2246 // and we won't allow it to be enabled any more during the current |
|
2247 // nw connection |
|
2248 aCtxImpl.ResetMulticastAddresses(); |
|
2249 aCtxImpl.MulticastFilteringDisAllowed( ETrue ); |
|
2250 stateTransitionOccurred = SetGroupAddressesTableMib( aCtxImpl ); |
|
2251 } |
|
2252 } |
|
2253 |
|
2254 // signal caller whether a state transition occurred or not |
|
2255 return stateTransitionOccurred; |
|
2256 } |
|
2257 |
|
2258 // --------------------------------------------------------------------------- |
|
2259 // |
|
2260 // --------------------------------------------------------------------------- |
|
2261 // |
|
2262 TBool WlanDot11Associated::RemoveMulticastAddr( |
|
2263 WlanContextImpl& aCtxImpl, |
|
2264 TBool aRemoveAll, |
|
2265 const TMacAddress& aMacAddr ) |
|
2266 { |
|
2267 TBool stateTransitionOccurred( EFalse ); |
|
2268 |
|
2269 OsTracePrint( |
|
2270 KWlmCmdDetails, |
|
2271 (TUint8*) |
|
2272 ("UMAC: WlanDot11Associated::RemoveMulticastAddr(): addr to be removed:"), |
|
2273 aMacAddr); |
|
2274 |
|
2275 if ( aCtxImpl.MulticastFilteringDisAllowed() ) |
|
2276 { |
|
2277 OsTracePrint( |
|
2278 KWlmCmdDetails, |
|
2279 (TUint8*) |
|
2280 ("UMAC: WlanDot11Associated::RemoveMulticastAddr(): Multicast filtering disallowed")); |
|
2281 // filtering is not allowed currently so there can't be any addresses |
|
2282 // to remove. Just complete the request with OK status |
|
2283 OnOidComplete( aCtxImpl ); |
|
2284 } |
|
2285 else |
|
2286 { |
|
2287 if ( aRemoveAll ) |
|
2288 { |
|
2289 OsTracePrint( |
|
2290 KWlmCmdDetails, |
|
2291 (TUint8*) |
|
2292 ("UMAC: WlanDot11Associated::RemoveMulticastAddr(): remove all")); |
|
2293 // remove all addresses; naturally will also disable filtering |
|
2294 aCtxImpl.ResetMulticastAddresses(); |
|
2295 stateTransitionOccurred = SetGroupAddressesTableMib( aCtxImpl ); |
|
2296 } |
|
2297 else |
|
2298 { |
|
2299 // 1st remove the specified address from our own internal |
|
2300 // bookkeeping, if it exists |
|
2301 if ( aCtxImpl.RemoveMulticastAddress( aMacAddr ) ) |
|
2302 { |
|
2303 OsTracePrint( |
|
2304 KWlmCmdDetails, |
|
2305 (TUint8*) |
|
2306 ("UMAC: WlanDot11Associated::RemoveMulticastAddr(): removing the specified address")); |
|
2307 // it existed, so update the group addresses MIB, too |
|
2308 stateTransitionOccurred = SetGroupAddressesTableMib( aCtxImpl ); |
|
2309 } |
|
2310 else |
|
2311 { |
|
2312 OsTracePrint( |
|
2313 KWlmCmdDetails, |
|
2314 (TUint8*) |
|
2315 ("UMAC: WlanDot11Associated::RemoveMulticastAddr(): specified address doesn't exist, nothing to do")); |
|
2316 // it did't exist, so there's nothing to remove |
|
2317 // Just complete the request with OK status |
|
2318 OnOidComplete( aCtxImpl ); |
|
2319 } |
|
2320 } |
|
2321 } |
|
2322 |
|
2323 // signal caller whether a state transition occurred or not |
|
2324 return stateTransitionOccurred; |
|
2325 } |
|
2326 |
|
2327 // --------------------------------------------------------------------------- |
|
2328 // |
|
2329 // --------------------------------------------------------------------------- |
|
2330 // |
|
2331 TBool WlanDot11Associated::AddBroadcastWepKey( |
|
2332 WlanContextImpl& aCtxImpl, |
|
2333 TUint32 aKeyIndex, |
|
2334 TBool aUseAsDefaulKey, |
|
2335 TUint32 aKeyLength, |
|
2336 const TUint8 aKey[KMaxWEPKeyLength], |
|
2337 const TMacAddress& aMac ) |
|
2338 { |
|
2339 return OnAddBroadcastWepKey( aCtxImpl, aKeyIndex, aUseAsDefaulKey, |
|
2340 EFalse, // do NOT set as PTK |
|
2341 aKeyLength, aKey, aMac ); |
|
2342 } |
|
2343 |
|
2344 // ----------------------------------------------------------------------------- |
|
2345 // |
|
2346 // ----------------------------------------------------------------------------- |
|
2347 // |
|
2348 TBool WlanDot11Associated::ConfigureTxQueueIfNecessary( |
|
2349 WlanContextImpl& aCtxImpl, |
|
2350 TQueueId aQueueId, |
|
2351 TUint16 aMediumTime, |
|
2352 TUint32 aMaxTxMSDULifetime ) |
|
2353 { |
|
2354 // this cast is safe as the types are effectively the same |
|
2355 const WHA::TQueueId whaQueueId = static_cast<WHA::TQueueId>(aQueueId); |
|
2356 |
|
2357 if ( aMediumTime != aCtxImpl.iWlanMib.iMediumTime[whaQueueId] || |
|
2358 aMaxTxMSDULifetime != |
|
2359 aCtxImpl.iWlanMib.dot11MaxTransmitMSDULifetime[whaQueueId] ) |
|
2360 { |
|
2361 // at least one of the parameters for this queue is changed => a |
|
2362 // reconfiguration is needed |
|
2363 |
|
2364 // update the queue parameters. These values will be used in the |
|
2365 // queue reconfiguration |
|
2366 |
|
2367 aCtxImpl.iWlanMib.iMediumTime[aQueueId] = aMediumTime; |
|
2368 aCtxImpl.iWlanMib.dot11MaxTransmitMSDULifetime[whaQueueId] = |
|
2369 aMaxTxMSDULifetime; |
|
2370 |
|
2371 OsTracePrint( KUmacDetails, (TUint8*) |
|
2372 ("UMAC: WlanDot11Associated::ConfigureTxQueueIfNecessary: reconfiguring the queue is necessary") ); |
|
2373 |
|
2374 // reconfigure the queue. Also request the WLAN mgmt client request |
|
2375 // to be completed |
|
2376 return ConfigureTxQueue( aCtxImpl, whaQueueId, ETrue ); |
|
2377 } |
|
2378 else |
|
2379 { |
|
2380 // the provided queue parameters have not changed, so no need to |
|
2381 // reconfigure the queue |
|
2382 |
|
2383 OsTracePrint( KUmacDetails, (TUint8*) |
|
2384 ("UMAC: WlanDot11Associated::ConfigureTxQueueIfNecessary: no queue reconfigure is necessary") ); |
|
2385 |
|
2386 // complete the WLAN Mgmt Client request |
|
2387 OnOidComplete( aCtxImpl, KErrNone ); |
|
2388 |
|
2389 // signal caller that no state transition occurred |
|
2390 return EFalse; |
|
2391 } |
|
2392 } |
|
2393 |
|
2394 // --------------------------------------------------------------------------- |
|
2395 // |
|
2396 // --------------------------------------------------------------------------- |
|
2397 // |
|
2398 TBool WlanDot11Associated::SetGroupAddressesTableMib( |
|
2399 WlanContextImpl& aCtxImpl ) |
|
2400 { |
|
2401 const TMacAddress* multicastAddresses( NULL ); |
|
2402 const TUint32 nbrOfAddrs( |
|
2403 aCtxImpl.GetMulticastAddresses( multicastAddresses ) ); |
|
2404 |
|
2405 TUint32 mibLength( |
|
2406 // mib header length |
|
2407 WHA::Sdot11GroupAddressesTable::KHeaderSize |
|
2408 // + mib data length |
|
2409 + ( sizeof( TMacAddress ) * nbrOfAddrs ) ); |
|
2410 |
|
2411 // align length of MIB to 4-byte boundary |
|
2412 mibLength = Align4( mibLength ); |
|
2413 |
|
2414 OsTracePrint( |
|
2415 KWlmCmdDetails, |
|
2416 (TUint8*) |
|
2417 ("UMAC: WlanDot11Associated::SetGroupAddressesTableMib(): mibLength: %d"), |
|
2418 mibLength ); |
|
2419 |
|
2420 // allocate memory for the mib to write |
|
2421 WHA::Sdot11GroupAddressesTable* mib |
|
2422 = static_cast<WHA::Sdot11GroupAddressesTable*> |
|
2423 (os_alloc( mibLength )); |
|
2424 |
|
2425 if ( !mib ) |
|
2426 { |
|
2427 // allocation failed |
|
2428 // simulate macnotresponding error |
|
2429 OsTracePrint( KWarningLevel, (TUint8*) |
|
2430 ("UMAC: WlanDot11Associated::SetGroupAddressesTableMib(): memory allocating failed") ); |
|
2431 return DoErrorIndication( aCtxImpl, WHA::KErrorMacNotResponding ); |
|
2432 } |
|
2433 |
|
2434 if ( nbrOfAddrs ) |
|
2435 { |
|
2436 // at least one address exists, so enable multicast address filtering |
|
2437 mib->iEnable = ETrue; |
|
2438 } |
|
2439 else |
|
2440 { |
|
2441 // no addresses, so disable filtering |
|
2442 mib->iEnable = EFalse; |
|
2443 OsTracePrint( KWlmCmdDetails, (TUint8*) |
|
2444 ("UMAC: WlanDot11Associated::SetGroupAddressesTableMib(): no addresses; disable filtering") ); |
|
2445 } |
|
2446 |
|
2447 mib->iNumOfAddrs = nbrOfAddrs; |
|
2448 |
|
2449 // copy the multicast addresses after the mib header |
|
2450 os_memcpy( mib->iAddrData, |
|
2451 reinterpret_cast<TUint8*>(const_cast<TMacAddress*>( |
|
2452 multicastAddresses)), |
|
2453 ( sizeof( TMacAddress ) * nbrOfAddrs ) ); |
|
2454 |
|
2455 WlanWsaWriteMib& wha_cmd = aCtxImpl.WsaWriteMib(); |
|
2456 |
|
2457 wha_cmd.Set( |
|
2458 aCtxImpl, |
|
2459 WHA::KMibDot11GroupAddressesTable, |
|
2460 mibLength, |
|
2461 mib ); |
|
2462 |
|
2463 // change global state: entry procedure triggers action |
|
2464 ChangeState( aCtxImpl, |
|
2465 *this, // prev state |
|
2466 wha_cmd, // next state |
|
2467 // the ACT |
|
2468 KCompleteManagementRequest |
|
2469 ); |
|
2470 |
|
2471 os_free( mib ); // release the allocated memory |
|
2472 |
|
2473 // signal caller that a state transition occurred |
|
2474 return ETrue; |
|
2475 } |
|
2476 |
|
2477 // --------------------------------------------------------------------------- |
|
2478 // |
|
2479 // --------------------------------------------------------------------------- |
|
2480 // |
|
2481 TBool WlanDot11Associated::PowerMgmtModeChange( |
|
2482 WlanContextImpl& aCtxImpl, |
|
2483 TPowerMgmtModeChange aPowerMgmtModeChange ) |
|
2484 { |
|
2485 TBool stateChange ( EFalse ); |
|
2486 |
|
2487 if ( aPowerMgmtModeChange != ENoChange ) |
|
2488 { |
|
2489 // power mgmt mode change needed |
|
2490 |
|
2491 if ( aPowerMgmtModeChange == EToActive ) |
|
2492 { |
|
2493 aCtxImpl.DesiredDot11PwrMgmtMode( WHA::KPsDisable ); |
|
2494 } |
|
2495 else if ( aPowerMgmtModeChange == EToLightPs ) |
|
2496 { |
|
2497 aCtxImpl.DesiredDot11PwrMgmtMode( WHA::KPsEnable ); |
|
2498 aCtxImpl.SetDesiredPsModeConfig( |
|
2499 aCtxImpl.ClientLightPsModeConfig() ); |
|
2500 } |
|
2501 else // aPowerMgmtModeChange == EToDeepPs |
|
2502 { |
|
2503 aCtxImpl.DesiredDot11PwrMgmtMode( WHA::KPsEnable ); |
|
2504 aCtxImpl.SetDesiredPsModeConfig( |
|
2505 aCtxImpl.ClientDeepPsModeConfig() ); |
|
2506 } |
|
2507 |
|
2508 if ( !(aCtxImpl.WsaCmdActive()) ) |
|
2509 { |
|
2510 // proceed with the power mgmt mode change |
|
2511 stateChange = ChangePowerMgmtMode( aCtxImpl ); |
|
2512 } |
|
2513 else |
|
2514 { |
|
2515 // WHA command is in progress so we must defer this access |
|
2516 aCtxImpl.RegisterEvent( KPowerMgmtTransition ); |
|
2517 |
|
2518 OsTracePrint( KEventDispatcher | KPwrStateTransition, |
|
2519 (TUint8*)("UMAC: WlanDot11Associated::PowerMgmtModeChange: power mgmt mode change event registered")); |
|
2520 } |
|
2521 } |
|
2522 |
|
2523 return stateChange; |
|
2524 } |
|
2525 |
|
2526 // --------------------------------------------------------------------------- |
|
2527 // |
|
2528 // --------------------------------------------------------------------------- |
|
2529 // |
|
2530 void WlanDot11Associated::HandleProprietarySnapRxFrame( |
|
2531 TDataBuffer& aBuffer, |
|
2532 TBool aQosData, |
|
2533 const TAny* const aFrame, |
|
2534 const SAmsduSubframeHeader* aSubFrameHeader, |
|
2535 TUint aLength, |
|
2536 TUint aDecryptHeaderLen, |
|
2537 TUint aDecryptTrailerLen, |
|
2538 TUint aHtControlLen, |
|
2539 TUint8* aCopyBuffer ) const |
|
2540 { |
|
2541 OsTracePrint( KRxFrame, (TUint8*) |
|
2542 ("UMAC: WlanDot11Associated::HandleProprietarySnapRxFrame")); |
|
2543 |
|
2544 // prepare received frame with proprietary SNAP header for wlan mgmt client |
|
2545 // Remove the possibly existing security header & trailer before |
|
2546 // passing the frame up |
|
2547 |
|
2548 const TUint8* frameBeginning = reinterpret_cast<const TUint8*>(aFrame); |
|
2549 const TUint KMacHdrLen( aQosData ? |
|
2550 sizeof( SQosDataFrameHeader ) + aHtControlLen : |
|
2551 sizeof( SDataFrameHeader ) ); |
|
2552 // subframe header length is non-zero only if the frame is part of an |
|
2553 // A-MSDU, i.e. if aCopyBuffer is not NULL |
|
2554 const TUint KSubframeHdrLen ( |
|
2555 aCopyBuffer ? sizeof( SAmsduSubframeHeader ) : 0 ); |
|
2556 // determine subframe length |
|
2557 const TUint KSubframeLen ( |
|
2558 aSubFrameHeader ? aSubFrameHeader->Length() : 0 ); |
|
2559 |
|
2560 if ( aCopyBuffer ) |
|
2561 { |
|
2562 // the frame needs to be copied to the copy buffer, which means |
|
2563 // that it is part of an A-MSDU |
|
2564 |
|
2565 // 1st copy the MAC header |
|
2566 os_memcpy( aCopyBuffer, frameBeginning, KMacHdrLen ); |
|
2567 |
|
2568 // then copy the subframe body following the subframe header |
|
2569 os_memcpy( |
|
2570 aCopyBuffer |
|
2571 + KMacHdrLen, |
|
2572 reinterpret_cast<const TUint8*>(aSubFrameHeader) + KSubframeHdrLen, |
|
2573 KSubframeLen ); |
|
2574 |
|
2575 // update to point to the new location |
|
2576 frameBeginning = aCopyBuffer; |
|
2577 } |
|
2578 else |
|
2579 { |
|
2580 // no copying to the copy buffer is required |
|
2581 |
|
2582 if ( aDecryptHeaderLen ) |
|
2583 { |
|
2584 // decrypt header exists. Shift the MAC header so that it |
|
2585 // overwrites the decrypt header, thus removing it |
|
2586 |
|
2587 TUint8* dest( const_cast<TUint8*>(frameBeginning) |
|
2588 + aDecryptHeaderLen ); |
|
2589 |
|
2590 TUint copyBlockSize( aQosData ? |
|
2591 sizeof( SQosDataFrameHeader ) + aHtControlLen : |
|
2592 sizeof( SDataFrameHeader ) ); |
|
2593 |
|
2594 os_memcpy( dest, frameBeginning, copyBlockSize ); |
|
2595 |
|
2596 // update to point to the new location |
|
2597 frameBeginning = dest; |
|
2598 } |
|
2599 } |
|
2600 |
|
2601 #ifndef NDEBUG |
|
2602 OsTracePrint( KRxFrame, (TUint8*) |
|
2603 ("UMAC: WlanDot11Associated::HandleProprietarySnapRxFrame: MPDU header:"), |
|
2604 *(reinterpret_cast<const Sdot11MacHeader*>( |
|
2605 frameBeginning))); |
|
2606 #endif |
|
2607 |
|
2608 // set the frame length |
|
2609 if ( aCopyBuffer ) |
|
2610 { |
|
2611 aBuffer.KeSetLength( KMacHdrLen + KSubframeLen ); |
|
2612 } |
|
2613 else |
|
2614 { |
|
2615 aBuffer.KeSetLength( |
|
2616 aLength - aDecryptHeaderLen - aDecryptTrailerLen ); |
|
2617 } |
|
2618 // set the frame type |
|
2619 aBuffer.FrameType( TDataBuffer::KDot11Frame ); |
|
2620 // set the offset to the beginning of the actual frame within the |
|
2621 // Rx buffer |
|
2622 aBuffer.KeSetOffsetToFrameBeginning( |
|
2623 frameBeginning // frame beginning |
|
2624 - aBuffer.KeGetBufferStart() ); // buffer beginning |
|
2625 } |
|
2626 |
|
2627 // --------------------------------------------------------------------------- |
|
2628 // |
|
2629 // --------------------------------------------------------------------------- |
|
2630 // |
|
2631 TBool WlanDot11Associated::ConfigureTxRatePolicies( |
|
2632 WlanContextImpl& aCtxImpl, |
|
2633 const TTxRatePolicy& aRatePolicy, |
|
2634 const TQueue2RateClass& aQueue2RateClass, |
|
2635 const TInitialMaxTxRate4RateClass& aInitialMaxTxRate4RateClass, |
|
2636 const TTxAutoRatePolicy& aAutoRatePolicy, |
|
2637 const THtMcsPolicy& aHtMcsPolicy ) |
|
2638 { |
|
2639 OsTracePrint( KTxRateAdapt, (TUint8*) |
|
2640 ("UMAC: WlanDot11Associated::ConfigureTxRatePolicies")); |
|
2641 |
|
2642 TBool stateChange( EFalse ); |
|
2643 |
|
2644 if ( aCtxImpl.ProtocolStackTxDataAllowed() ) |
|
2645 { |
|
2646 // store the provided information ... |
|
2647 StoreTxRatePolicyInfo( |
|
2648 aCtxImpl, |
|
2649 aRatePolicy, |
|
2650 aQueue2RateClass, |
|
2651 aInitialMaxTxRate4RateClass, |
|
2652 aAutoRatePolicy, |
|
2653 aHtMcsPolicy ); |
|
2654 |
|
2655 // ... take it into use; and specify that the mgmt client request needs |
|
2656 // to be completed when doing it |
|
2657 stateChange = WlanDot11State::ConfigureTxRatePolicies( aCtxImpl, |
|
2658 ETrue ); |
|
2659 if ( !stateChange ) |
|
2660 { |
|
2661 // a fatal error occurred. Simulate MAC Not Responding error |
|
2662 // Note that the Mgmt Client request will be completed when |
|
2663 // entering the dot11error state |
|
2664 stateChange = DoErrorIndication( |
|
2665 aCtxImpl, |
|
2666 WHA::KErrorMacNotResponding ); |
|
2667 } |
|
2668 } |
|
2669 else |
|
2670 { |
|
2671 // as user data is not allowed currently, it means that WLAN Mgmt client |
|
2672 // will request us to connect to a new nw shortly and this policy is for |
|
2673 // that new nw. So we shouldn't take the new rate policy into use yet, |
|
2674 // as we don't know which rates the new nw will be supporting. We just |
|
2675 // store the provided information for later use |
|
2676 stateChange = WlanDot11State::ConfigureTxRatePolicies( |
|
2677 aCtxImpl, |
|
2678 aRatePolicy, |
|
2679 aQueue2RateClass, |
|
2680 aInitialMaxTxRate4RateClass, |
|
2681 aAutoRatePolicy, |
|
2682 aHtMcsPolicy ); |
|
2683 } |
|
2684 |
|
2685 return stateChange; |
|
2686 } |
|
2687 |
|
2688 // ----------------------------------------------------------------------------- |
|
2689 // |
|
2690 // ----------------------------------------------------------------------------- |
|
2691 // |
|
2692 TBool WlanDot11Associated::ConfigurePwrModeMgmtTrafficOverride( |
|
2693 WlanContextImpl& aCtxImpl, |
|
2694 TBool aStayInPsDespiteUapsdVoiceTraffic, |
|
2695 TBool aStayInPsDespiteUapsdVideoTraffic, |
|
2696 TBool aStayInPsDespiteUapsdBestEffortTraffic, |
|
2697 TBool aStayInPsDespiteUapsdBackgroundTraffic, |
|
2698 TBool aStayInPsDespiteLegacyVoiceTraffic, |
|
2699 TBool aStayInPsDespiteLegacyVideoTraffic, |
|
2700 TBool aStayInPsDespiteLegacyBestEffortTraffic, |
|
2701 TBool aStayInPsDespiteLegacyBackgroundTraffic ) |
|
2702 { |
|
2703 OsTracePrint( KUmacDetails, (TUint8*) |
|
2704 ("UMAC: WlanDot11Associated::ConfigurePwrModeMgmtTrafficOverride")); |
|
2705 |
|
2706 aCtxImpl.ConfigurePwrModeMgmtTrafficOverride( |
|
2707 aStayInPsDespiteUapsdVoiceTraffic, |
|
2708 aStayInPsDespiteUapsdVideoTraffic, |
|
2709 aStayInPsDespiteUapsdBestEffortTraffic, |
|
2710 aStayInPsDespiteUapsdBackgroundTraffic, |
|
2711 aStayInPsDespiteLegacyVoiceTraffic, |
|
2712 aStayInPsDespiteLegacyVideoTraffic, |
|
2713 aStayInPsDespiteLegacyBestEffortTraffic, |
|
2714 aStayInPsDespiteLegacyBackgroundTraffic ); |
|
2715 |
|
2716 // as we are already connected and aware of the network capabilities, we |
|
2717 // also need to freeze the dynamic power mode mgmt traffic |
|
2718 // override/ignoration settings so that they become immediately effective |
|
2719 aCtxImpl.FreezePwrModeMgmtTrafficOverride(); |
|
2720 |
|
2721 OnOidComplete( aCtxImpl, KErrNone ); |
|
2722 |
|
2723 // signal caller that no state transition occurred |
|
2724 return EFalse; |
|
2725 } |