1 // Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // Implements the interface to BCA. |
|
15 // |
|
16 // |
|
17 |
|
18 /** |
|
19 @file BcaIoController.cpp |
|
20 */ |
|
21 |
|
22 #include <e32uid.h> |
|
23 #include <nifmbuf.h> |
|
24 |
|
25 #include "Constants.h" |
|
26 #include "BcaIoController.h" |
|
27 #include "Sender.h" |
|
28 #include "Receiver.h" |
|
29 |
|
30 CBcaIoController::CBcaIoController(MControllerObserver& aObserver, |
|
31 CBttLogger* aTheLogger) |
|
32 /** |
|
33 * Constructor. |
|
34 * |
|
35 * @param aObserver Reference to the observer of this state machine |
|
36 * @param aTheLogger The logging object |
|
37 */ |
|
38 : |
|
39 CBcaController(aObserver, aTheLogger), |
|
40 iMBca(NULL), |
|
41 iSender(NULL), |
|
42 iReceiver(NULL), |
|
43 iLoader(NULL) |
|
44 { |
|
45 } |
|
46 |
|
47 CBcaIoController* CBcaIoController::NewL(MControllerObserver& aObserver, CBttLogger* aTheLogger) |
|
48 /** |
|
49 * Two-phase constructor. Creates a new CBcaIoController object, performs |
|
50 * second-phase construction, then returns it. |
|
51 * |
|
52 * @param aObserver The observer, to which events will be reported |
|
53 * @param aTheLogger The logging object |
|
54 * @return A newly constructed CBcaIoController object |
|
55 */ |
|
56 { |
|
57 CBcaIoController* self = new (ELeave) CBcaIoController(aObserver, aTheLogger); |
|
58 CleanupStack::PushL(self); |
|
59 self->ConstructL(); |
|
60 CleanupStack::Pop(self); |
|
61 return self; |
|
62 } |
|
63 |
|
64 void CBcaIoController::ConstructL() |
|
65 /** |
|
66 * Second-phase constructor. Creates all the state objects it owns. |
|
67 */ |
|
68 { |
|
69 _LOG_L1C1(_L8("CBcaIoController::ConstructL")); |
|
70 BaseConstructL(); |
|
71 iSender = new (ELeave) CSender(*this, iTheLogger); |
|
72 iReceiver = new (ELeave) CReceiver(*this, iTheLogger); |
|
73 iLoader = new (ELeave) CBcaControl(*this, iTheLogger); |
|
74 } |
|
75 |
|
76 |
|
77 CBcaIoController::~CBcaIoController() |
|
78 /** |
|
79 * Destructor. |
|
80 */ |
|
81 { |
|
82 delete iReceiver; |
|
83 delete iSender; |
|
84 delete iLoader; |
|
85 |
|
86 } |
|
87 |
|
88 /** sets the BCA Stack name |
|
89 |
|
90 * @param aBcaStack Text composed of bca stack and next bca names |
|
91 */ |
|
92 void CBcaIoController::SetBcaStackAndName(TDesC& aBcaStack) |
|
93 { |
|
94 const TChar stackDelimiter(','); |
|
95 |
|
96 TInt length = aBcaStack.Length(); |
|
97 TInt delimiterLoc = aBcaStack.Locate(stackDelimiter); |
|
98 |
|
99 if(delimiterLoc > 0) |
|
100 { |
|
101 iBcaName.Copy(aBcaStack.Left(delimiterLoc)); |
|
102 |
|
103 if(delimiterLoc < length) |
|
104 { |
|
105 iBcaStack.Copy(aBcaStack.Right(length-delimiterLoc-1)); |
|
106 } |
|
107 } |
|
108 else |
|
109 { |
|
110 iBcaName.Copy(aBcaStack); |
|
111 } |
|
112 } |
|
113 |
|
114 |
|
115 void CBcaIoController::StartL() |
|
116 /** |
|
117 * Used to kick off the initialisation for this module |
|
118 */ |
|
119 { |
|
120 _LOG_L1C1(_L8("CBcaIoController::StartL is called.")); |
|
121 |
|
122 InitialiseBcaL(); |
|
123 } |
|
124 |
|
125 void CBcaIoController::Stop(TInt aError) |
|
126 /** |
|
127 * Used to shutdown this module. This will cancel all the outstanding |
|
128 * requests on the active objects owned by this module and shutdown. |
|
129 * @param aError the passed in error code as to why Stop has been called |
|
130 */ |
|
131 { |
|
132 _LOG_L1C1(_L8("CBcaIoController::Stop is called.")); |
|
133 |
|
134 //Stop all the active objects |
|
135 iReceiver->Cancel(); |
|
136 |
|
137 if(GetSendState() == ESending) |
|
138 { |
|
139 iSender->Cancel(); |
|
140 } |
|
141 |
|
142 // Update module state |
|
143 SendState(EShuttingDown); |
|
144 |
|
145 //It does nothing here. |
|
146 iLoader->Cancel(); |
|
147 MBca* bca = iLoader->Bca(); |
|
148 if(bca) |
|
149 { |
|
150 if(aError == KErrConnectionTerminated ) |
|
151 { |
|
152 _LOG_L1C1(_L8("This is an emergency shutdown, it kills the NIF immediately.")); |
|
153 // It is a emergency shutdown, it kills the NIF immediately. |
|
154 bca->Close(); |
|
155 GetObserver().ShutDown(MControllerObserver::EBcaController, aError); |
|
156 } |
|
157 |
|
158 else |
|
159 { |
|
160 _LOG_L1C1(_L8("This is a graceful termination which takes a while.")); |
|
161 //It is a graceful termination which takes a while. |
|
162 iLoader->ShutdownBca(aError); |
|
163 } |
|
164 } |
|
165 else //nothing to shutdown, just notify linklayer down. |
|
166 { |
|
167 _LOG_L1C1(_L8("Bca is not initialized, bring the linklayer down")); |
|
168 GetObserver().ShutDown(MControllerObserver::EBcaController, aError); |
|
169 } |
|
170 |
|
171 } |
|
172 |
|
173 void CBcaIoController::InitialiseBcaL() |
|
174 /** |
|
175 * Load & Initialise Bca. |
|
176 */ |
|
177 { |
|
178 _LOG_L1C1(_L8("<<CBcaIoController::InitialiseBcaL")); |
|
179 iLoader->StartLoadL(); |
|
180 } |
|
181 |
|
182 void CBcaIoController::BcaProcess(TDesC8& aPdu) |
|
183 /** |
|
184 * This method will pass on the received data to CRawIPNifMain. |
|
185 * |
|
186 * @param aPdu a data packet |
|
187 */ |
|
188 { |
|
189 _LOG_L1C1(_L8(">>CBcaIoController::Process")); |
|
190 |
|
191 Process(aPdu); |
|
192 |
|
193 _LOG_L1C1(_L8("<<CBcaIoController::Process")); |
|
194 } |
|
195 |
|
196 void CBcaIoController::BcaSend(RMBufChain& aPdu) |
|
197 /** |
|
198 * This method is called by CRawIPNifMain in order to send a packet down |
|
199 * to the BCA. The CSender active object will be activated by calling the send |
|
200 * method. |
|
201 * |
|
202 * @param aPdu a data packet |
|
203 */ |
|
204 { |
|
205 _LOG_L1C1(_L8("CBcaIoController::BcaSend")); |
|
206 |
|
207 iSender->Send(aPdu); |
|
208 } |
|
209 |
|
210 TInt CBcaIoController::BcaSendBufferLength() |
|
211 { |
|
212 return iSender->SendBufferLength(); |
|
213 } |
|
214 |
|
215 void CBcaIoController::BcaSendComplete() |
|
216 /** |
|
217 * This method is called after a packet was sent to the board. |
|
218 * If allowed by flow contol flags the NIF can signal the TCP/IP |
|
219 * protocol indicating that is available to send more packets. |
|
220 */ |
|
221 { |
|
222 _LOG_L1C1(_L8("CBcaController::SendComplete")); |
|
223 |
|
224 SendComplete(); |
|
225 } |
|
226 |
|
227 |
|
228 CBcaControl::CBcaControl(CBcaIoController& aObserver, CBttLogger* aTheLogger) |
|
229 /** |
|
230 * Constructor. Performs standard active object initialisation. |
|
231 * |
|
232 * @param aObserver Reference to the observer of this state machine |
|
233 * @param aTheLogger The logging object |
|
234 */ |
|
235 : CActive(EPriorityNormal), |
|
236 iObserver(aObserver), |
|
237 iTheLogger(aTheLogger), |
|
238 iMBca(NULL), |
|
239 iState(EIdling), |
|
240 iError(KErrNone) |
|
241 |
|
242 { |
|
243 CActiveScheduler::Add(this); |
|
244 } |
|
245 |
|
246 CBcaControl::~CBcaControl() |
|
247 /** |
|
248 * Destructor. |
|
249 */ |
|
250 { |
|
251 Cancel(); |
|
252 if(iMBca) |
|
253 { |
|
254 iMBca->Release(); |
|
255 } |
|
256 |
|
257 // Library will be Closed when iBcaDll is destroyed. |
|
258 } |
|
259 |
|
260 void CBcaControl::RunL() |
|
261 /** |
|
262 * Called after request is completed. |
|
263 * |
|
264 */ |
|
265 { |
|
266 _LOG_L1C1(_L8("CBcaControl::RunL() called")); |
|
267 switch (iState) |
|
268 { |
|
269 //in this state, Ioctl is called to set IAP ID, check the result of |
|
270 // Ioctl, then either set the BCA stack with another Ioctl call, |
|
271 // open the BCA (if there's no BCA stack to set), or stop the NIF. |
|
272 case EIdling: |
|
273 { |
|
274 if(iStatus == KErrNone || iStatus == KErrNotSupported) |
|
275 { |
|
276 if(iStatus == KErrNotSupported) |
|
277 { |
|
278 _LOG_L1C1(_L8("This BCA does not support IAPID set")); |
|
279 } |
|
280 else |
|
281 { |
|
282 _LOG_L2C1(_L8("This BCA supports IAPID set")); |
|
283 } |
|
284 |
|
285 TPtrC bcaStack = iObserver.BcaStack(); |
|
286 if(bcaStack.Length()) |
|
287 { |
|
288 TBuf8<KMaxName> remainingBcaStack8; |
|
289 remainingBcaStack8.Copy(bcaStack); |
|
290 iMBca->Ioctl(iStatus, KBcaOptLevelGeneric,KBCASetBcaStack,remainingBcaStack8); |
|
291 } |
|
292 else |
|
293 { |
|
294 TRequestStatus* statusPtr=&iStatus; |
|
295 User::RequestComplete(statusPtr,KErrNone); |
|
296 } |
|
297 iState = EIAPSet; |
|
298 SetActive(); |
|
299 } |
|
300 else |
|
301 { |
|
302 _LOG_L1C2(_L8("ERROR in BCA IAPID set = %d"), iStatus.Int()); |
|
303 iObserver.Stop(iStatus.Int()); |
|
304 } |
|
305 |
|
306 break; |
|
307 } |
|
308 |
|
309 //in this case, we receive the result of Ioctl call to set Bca Stack. |
|
310 // Check the result of Ioctl, then Open the Bca or stop the NIF |
|
311 case EIAPSet: |
|
312 { |
|
313 if(iStatus == KErrNotSupported || iStatus == KErrNone) |
|
314 { |
|
315 if(iStatus == KErrNotSupported) |
|
316 { |
|
317 _LOG_L1C1(_L8("This BCA does not support BCA stacking")); |
|
318 } |
|
319 else |
|
320 { |
|
321 _LOG_L2C1(_L8("This BCA supports BCA stacking")); |
|
322 } |
|
323 iMBca->Open(iStatus, iObserver.Port()); |
|
324 iState = EBcaStackSet; |
|
325 SetActive(); |
|
326 } |
|
327 else |
|
328 { |
|
329 _LOG_L2C2(_L8("ERROR in BCA stack set = %d"), iStatus.Int()); |
|
330 iObserver.Stop(iStatus.Int()); |
|
331 } |
|
332 break; |
|
333 } |
|
334 |
|
335 //in this state, BCA Open is called. Checks the result of Open. |
|
336 // If it is successful,then start the NIF. Otherwise stops the NIF. |
|
337 case EBcaStackSet: |
|
338 { |
|
339 if(iStatus != KErrNone && iStatus != KErrAlreadyExists) |
|
340 { |
|
341 _LOG_L2C2(_L8("ERROR in BCA Open = %d"), iStatus.Int()); |
|
342 iObserver.Stop(iStatus.Int()); |
|
343 } |
|
344 else |
|
345 { |
|
346 iObserver.Receiver().StartListening(); |
|
347 _LOG_L1C1(_L8("CBcaIoController Is Initialised")); |
|
348 TRAPD(err, iObserver.GetObserver().InitialiseL(MRawIPNifObserverBase::EBcaController,KErrNone)); |
|
349 if(err != KErrNone) |
|
350 { |
|
351 _LOG_L2C2(_L8("ERROR in BCA Open Initialise observer = %d"), err); |
|
352 iObserver.Stop(err); |
|
353 } |
|
354 } |
|
355 break; |
|
356 } |
|
357 |
|
358 //in this state, BCA is Shutdown, shutdown the NIF. |
|
359 case EClosing: |
|
360 { |
|
361 // linklayer shutdown |
|
362 iObserver.GetObserver().ShutDown(MControllerObserver::EBcaController, iError); |
|
363 break; |
|
364 } |
|
365 // Wrong state. |
|
366 default: |
|
367 { |
|
368 _LOG_L1C1(_L8("ERROR CBcaControl::RunL(): Unknown state")); |
|
369 _BTT_PANIC(KNifName, KBcaUnkownState); |
|
370 break; |
|
371 } |
|
372 } |
|
373 |
|
374 } |
|
375 |
|
376 void CBcaControl::DoCancel() |
|
377 /** |
|
378 * cancel active request. |
|
379 */ |
|
380 { |
|
381 _LOG_L1C1(_L8("CBcaControl::DoCancel called.")); |
|
382 _LOG_L2C2(_L8("iState value is %d"), iState); |
|
383 switch (iState) |
|
384 { |
|
385 case EIdling: |
|
386 case EIAPSet: |
|
387 if(iMBca) |
|
388 { |
|
389 iMBca->CancelIoctl(); |
|
390 } |
|
391 iState = EIdling; |
|
392 break; |
|
393 case EBcaStackSet: |
|
394 case EClosing: |
|
395 if(iMBca) |
|
396 { |
|
397 iMBca->Close(); |
|
398 } |
|
399 iState = EIdling; |
|
400 break; |
|
401 default: |
|
402 _LOG_L2C1(_L8("ERROR CBcaControl::DoCancel(): Unknown state")); |
|
403 _BTT_PANIC(KNifName, KBcaUnkownState); |
|
404 break; |
|
405 } |
|
406 } |
|
407 |
|
408 void CBcaControl::StartLoadL() |
|
409 /** |
|
410 * This method loads the C32BCA library and uses Ioctl to set the Bca iIapId. |
|
411 */ |
|
412 { |
|
413 _LOG_L1C1(_L8("CBcaControl::StartLoad")); |
|
414 |
|
415 // Loads Bca Dll and creates a Bca instance; |
|
416 User::LeaveIfError(iBcaDll.iObj.Load(iObserver.BcaName())); |
|
417 |
|
418 TNewBcaFactoryL newBcaFactoryProcL = (TNewBcaFactoryL)iBcaDll.iObj.Lookup(1); |
|
419 if (NULL == newBcaFactoryProcL) |
|
420 { |
|
421 _LOG_L1C2(_L8("Library entry point found error %d"), KErrBadLibraryEntryPoint); |
|
422 User::Leave(KErrBadLibraryEntryPoint); |
|
423 } |
|
424 |
|
425 MBcaFactory* bcaFactory = (*newBcaFactoryProcL)(); |
|
426 |
|
427 if(!bcaFactory) |
|
428 { |
|
429 _LOG_L1C2(_L8("BcaFactory creation error %d"), KErrCompletion); |
|
430 User::Leave(KErrCompletion); |
|
431 } |
|
432 CleanupReleasePushL(*bcaFactory); |
|
433 |
|
434 iMBca = bcaFactory->NewBcaL(); |
|
435 CleanupStack::PopAndDestroy(bcaFactory); |
|
436 |
|
437 iObserver.SetBca(iMBca); //Pass BCA pointer. |
|
438 |
|
439 TPckg<TUint32> aOpt(iObserver.IapId()); |
|
440 iMBca->Ioctl(iStatus,KBcaOptLevelGeneric,KBCASetIapId,aOpt); |
|
441 |
|
442 iState = EIdling; |
|
443 SetActive(); |
|
444 } |
|
445 |
|
446 |
|
447 void CBcaControl::ShutdownBca(TInt aError) |
|
448 /** |
|
449 * Bca Shutdown. |
|
450 |
|
451 * @param aError the error code to shutdown the NIF. |
|
452 */ |
|
453 { |
|
454 __ASSERT_DEBUG(iMBca,Panic(KBcaNotExist)); |
|
455 Cancel(); |
|
456 iError = aError; |
|
457 iState = EClosing; |
|
458 if(iMBca) |
|
459 { |
|
460 iMBca->Shutdown(iStatus); |
|
461 SetActive(); |
|
462 } |
|
463 } |
|
464 |
|
465 /** Panic function for RawIpNif |
|
466 |
|
467 * @param aPanic panic code */ |
|
468 void Panic(TRawIPNifPanic aPanic) |
|
469 { |
|
470 _LOG_L2C2(_L8("Panic code for RawIpNif = %d"), aPanic); |
|
471 User::Panic(KNifName,aPanic); |
|
472 |
|
473 } |
|
474 |
|