|
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 = CSender::NewL(*this, iTheLogger, iMaxPacketSise); |
|
72 iReceiver = CReceiver::NewL(*this, iTheLogger, iMaxPacketSise); |
|
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(const TDesC& aBcaStack, const TDesC& aBcaName) |
|
93 { |
|
94 iBcaName.Set(aBcaName); |
|
95 iBcaName.Set(aBcaStack); |
|
96 } |
|
97 |
|
98 |
|
99 void CBcaIoController::StartL() |
|
100 /** |
|
101 * Used to kick off the initialisation for this module |
|
102 */ |
|
103 { |
|
104 _LOG_L1C1(_L8("CBcaIoController::StartL is called.")); |
|
105 |
|
106 InitialiseBcaL(); |
|
107 } |
|
108 |
|
109 void CBcaIoController::Stop(TInt aError) |
|
110 /** |
|
111 * Used to shutdown this module. This will cancel all the outstanding |
|
112 * requests on the active objects owned by this module and shutdown. |
|
113 * @param aError the passed in error code as to why Stop has been called |
|
114 */ |
|
115 { |
|
116 _LOG_L1C1(_L8("CBcaIoController::Stop is called.")); |
|
117 |
|
118 //Stop all the active objects |
|
119 iReceiver->Cancel(); |
|
120 |
|
121 if(GetSendState() == ESending) |
|
122 { |
|
123 iSender->Cancel(); |
|
124 } |
|
125 |
|
126 // Update module state |
|
127 SendState(EShuttingDown); |
|
128 |
|
129 //It does nothing here. |
|
130 iLoader->Cancel(); |
|
131 MBca* bca = iLoader->Bca(); |
|
132 if(bca) |
|
133 { |
|
134 if(aError == KErrConnectionTerminated ) |
|
135 { |
|
136 _LOG_L1C1(_L8("This is an emergency shutdown, it kills the NIF immediately.")); |
|
137 // It is a emergency shutdown, it kills the NIF immediately. |
|
138 bca->Close(); |
|
139 GetObserver().ShutDown(MControllerObserver::EBcaController, aError); |
|
140 } |
|
141 |
|
142 else |
|
143 { |
|
144 _LOG_L1C1(_L8("This is a graceful termination which takes a while.")); |
|
145 //It is a graceful termination which takes a while. |
|
146 iLoader->ShutdownBca(aError); |
|
147 } |
|
148 } |
|
149 else //nothing to shutdown, just notify linklayer down. |
|
150 { |
|
151 _LOG_L1C1(_L8("Bca is not initialized, bring the linklayer down")); |
|
152 GetObserver().ShutDown(MControllerObserver::EBcaController, aError); |
|
153 } |
|
154 |
|
155 } |
|
156 |
|
157 void CBcaIoController::InitialiseBcaL() |
|
158 /** |
|
159 * Load & Initialise Bca. |
|
160 */ |
|
161 { |
|
162 _LOG_L1C1(_L8("<<CBcaIoController::InitialiseBcaL")); |
|
163 iLoader->StartLoadL(); |
|
164 } |
|
165 |
|
166 void CBcaIoController::BcaProcess(TDesC8& aPdu) |
|
167 /** |
|
168 * This method will pass on the received data to CRawIPNifMain. |
|
169 * |
|
170 * @param aPdu a data packet |
|
171 */ |
|
172 { |
|
173 _LOG_L1C1(_L8(">>CBcaIoController::Process")); |
|
174 |
|
175 Process(aPdu); |
|
176 |
|
177 _LOG_L1C1(_L8("<<CBcaIoController::Process")); |
|
178 } |
|
179 |
|
180 void CBcaIoController::BcaSend(RMBufChain& aPdu) |
|
181 /** |
|
182 * This method is called by CRawIPNifMain in order to send a packet down |
|
183 * to the BCA. The CSender active object will be activated by calling the send |
|
184 * method. |
|
185 * |
|
186 * @param aPdu a data packet |
|
187 */ |
|
188 { |
|
189 _LOG_L1C1(_L8("CBcaIoController::BcaSend")); |
|
190 |
|
191 iSender->Send(aPdu); |
|
192 } |
|
193 |
|
194 TInt CBcaIoController::BcaSendBufferLength() |
|
195 { |
|
196 return iSender->SendBufferLength(); |
|
197 } |
|
198 |
|
199 void CBcaIoController::BcaSendComplete() |
|
200 /** |
|
201 * This method is called after a packet was sent to the board. |
|
202 * If allowed by flow contol flags the NIF can signal the TCP/IP |
|
203 * protocol indicating that is available to send more packets. |
|
204 */ |
|
205 { |
|
206 _LOG_L1C1(_L8("CBcaController::SendComplete")); |
|
207 |
|
208 SendComplete(); |
|
209 } |
|
210 |
|
211 |
|
212 CBcaControl::CBcaControl(CBcaIoController& aObserver, CBttLogger* aTheLogger) |
|
213 /** |
|
214 * Constructor. Performs standard active object initialisation. |
|
215 * |
|
216 * @param aObserver Reference to the observer of this state machine |
|
217 * @param aTheLogger The logging object |
|
218 */ |
|
219 : CActive(EPriorityStandard), |
|
220 iObserver(aObserver), |
|
221 iTheLogger(aTheLogger), |
|
222 iMBca(NULL), |
|
223 iState(EIdling), |
|
224 iError(KErrNone) |
|
225 |
|
226 { |
|
227 CActiveScheduler::Add(this); |
|
228 } |
|
229 |
|
230 CBcaControl::~CBcaControl() |
|
231 /** |
|
232 * Destructor. |
|
233 */ |
|
234 { |
|
235 Cancel(); |
|
236 if(iMBca) |
|
237 { |
|
238 iMBca->Release(); |
|
239 } |
|
240 |
|
241 // Library will be Closed when iBcaDll is destroyed. |
|
242 } |
|
243 |
|
244 void CBcaControl::RunL() |
|
245 /** |
|
246 * Called after request is completed. |
|
247 * |
|
248 */ |
|
249 { |
|
250 _LOG_L1C1(_L8("CBcaControl::RunL() called")); |
|
251 switch (iState) |
|
252 { |
|
253 //in this state, Ioctl is called to set IAP ID, check the result of |
|
254 // Ioctl, then either set the BCA stack with another Ioctl call, |
|
255 // open the BCA (if there's no BCA stack to set), or stop the NIF. |
|
256 case EIdling: |
|
257 { |
|
258 if(iStatus == KErrNone || iStatus == KErrNotSupported) |
|
259 { |
|
260 if(iStatus == KErrNotSupported) |
|
261 { |
|
262 _LOG_L1C1(_L8("This BCA does not support IAPID set")); |
|
263 } |
|
264 else |
|
265 { |
|
266 _LOG_L2C1(_L8("This BCA supports IAPID set")); |
|
267 } |
|
268 |
|
269 TPtrC bcaStack = iObserver.BcaStack(); |
|
270 if(bcaStack.Length()) |
|
271 { |
|
272 TBuf8<KMaxName> remainingBcaStack8; |
|
273 remainingBcaStack8.Copy(bcaStack); |
|
274 iMBca->Ioctl(iStatus, KBcaOptLevelGeneric,KBCASetBcaStack,remainingBcaStack8); |
|
275 } |
|
276 else |
|
277 { |
|
278 TRequestStatus* statusPtr=&iStatus; |
|
279 User::RequestComplete(statusPtr,KErrNone); |
|
280 } |
|
281 iState = EIAPSet; |
|
282 SetActive(); |
|
283 } |
|
284 else |
|
285 { |
|
286 _LOG_L1C2(_L8("ERROR in BCA IAPID set = %d"), iStatus.Int()); |
|
287 iObserver.Stop(iStatus.Int()); |
|
288 } |
|
289 |
|
290 break; |
|
291 } |
|
292 |
|
293 //in this case, we receive the result of Ioctl call to set Bca Stack. |
|
294 // Check the result of Ioctl, then Open the Bca or stop the NIF |
|
295 case EIAPSet: |
|
296 { |
|
297 if(iStatus == KErrNotSupported || iStatus == KErrNone) |
|
298 { |
|
299 if(iStatus == KErrNotSupported) |
|
300 { |
|
301 _LOG_L1C1(_L8("This BCA does not support BCA stacking")); |
|
302 } |
|
303 else |
|
304 { |
|
305 _LOG_L2C1(_L8("This BCA supports BCA stacking")); |
|
306 } |
|
307 iMBca->Open(iStatus, iObserver.Port()); |
|
308 iState = EBcaStackSet; |
|
309 SetActive(); |
|
310 } |
|
311 else |
|
312 { |
|
313 _LOG_L2C2(_L8("ERROR in BCA stack set = %d"), iStatus.Int()); |
|
314 iObserver.Stop(iStatus.Int()); |
|
315 } |
|
316 break; |
|
317 } |
|
318 |
|
319 //in this state, BCA Open is called. Checks the result of Open. |
|
320 // If it is successful,then start the NIF. Otherwise stops the NIF. |
|
321 case EBcaStackSet: |
|
322 { |
|
323 if(iStatus != KErrNone && iStatus != KErrAlreadyExists) |
|
324 { |
|
325 _LOG_L2C2(_L8("ERROR in BCA Open = %d"), iStatus.Int()); |
|
326 iObserver.Stop(iStatus.Int()); |
|
327 } |
|
328 else |
|
329 { |
|
330 iObserver.Receiver().StartListening(); |
|
331 _LOG_L1C1(_L8("CBcaIoController Is Initialised")); |
|
332 TRAPD(err, iObserver.GetObserver().InitialiseL(MRawIPObserverBase::EBcaController,KErrNone)); |
|
333 if(err != KErrNone) |
|
334 { |
|
335 _LOG_L2C2(_L8("ERROR in BCA Open Initialise observer = %d"), err); |
|
336 iObserver.Stop(err); |
|
337 } |
|
338 } |
|
339 break; |
|
340 } |
|
341 |
|
342 //in this state, BCA is Shutdown, shutdown the NIF. |
|
343 case EClosing: |
|
344 { |
|
345 // linklayer shutdown |
|
346 iObserver.GetObserver().ShutDown(MControllerObserver::EBcaController, iError); |
|
347 break; |
|
348 } |
|
349 // Wrong state. |
|
350 default: |
|
351 { |
|
352 _LOG_L1C1(_L8("ERROR CBcaControl::RunL(): Unknown state")); |
|
353 _BTT_PANIC(KNifName, KBcaUnkownState); |
|
354 break; |
|
355 } |
|
356 } |
|
357 |
|
358 } |
|
359 |
|
360 void CBcaControl::DoCancel() |
|
361 /** |
|
362 * cancel active request. |
|
363 */ |
|
364 { |
|
365 _LOG_L1C1(_L8("CBcaControl::DoCancel called.")); |
|
366 _LOG_L2C2(_L8("iState value is %d"), iState); |
|
367 switch (iState) |
|
368 { |
|
369 case EIdling: |
|
370 case EIAPSet: |
|
371 if(iMBca) |
|
372 { |
|
373 iMBca->CancelIoctl(); |
|
374 } |
|
375 iState = EIdling; |
|
376 break; |
|
377 case EBcaStackSet: |
|
378 case EClosing: |
|
379 if(iMBca) |
|
380 { |
|
381 iMBca->Close(); |
|
382 } |
|
383 iState = EIdling; |
|
384 break; |
|
385 default: |
|
386 _LOG_L2C1(_L8("ERROR CBcaControl::DoCancel(): Unknown state")); |
|
387 _BTT_PANIC(KNifName, KBcaUnkownState); |
|
388 break; |
|
389 } |
|
390 } |
|
391 |
|
392 void CBcaControl::StartLoadL() |
|
393 /** |
|
394 * This method loads the C32BCA library and uses Ioctl to set the Bca iIapId. |
|
395 */ |
|
396 { |
|
397 _LOG_L1C1(_L8("CBcaControl::StartLoad")); |
|
398 |
|
399 // Loads Bca Dll and creates a Bca instance; |
|
400 User::LeaveIfError(iBcaDll.iObj.Load(iObserver.BcaName())); |
|
401 |
|
402 TNewBcaFactoryL newBcaFactoryProcL = (TNewBcaFactoryL)iBcaDll.iObj.Lookup(1); |
|
403 if (NULL == newBcaFactoryProcL) |
|
404 { |
|
405 _LOG_L1C2(_L8("Library entry point found error %d"), KErrBadLibraryEntryPoint); |
|
406 User::Leave(KErrBadLibraryEntryPoint); |
|
407 } |
|
408 |
|
409 MBcaFactory* bcaFactory = (*newBcaFactoryProcL)(); |
|
410 |
|
411 if(!bcaFactory) |
|
412 { |
|
413 _LOG_L1C2(_L8("BcaFactory creation error %d"), KErrCompletion); |
|
414 User::Leave(KErrCompletion); |
|
415 } |
|
416 CleanupReleasePushL(*bcaFactory); |
|
417 |
|
418 iMBca = bcaFactory->NewBcaL(); |
|
419 CleanupStack::PopAndDestroy(bcaFactory); |
|
420 |
|
421 iObserver.SetBca(iMBca); //Pass BCA pointer. |
|
422 |
|
423 TPckg<TUint32> aOpt(iObserver.IapId()); |
|
424 iMBca->Ioctl(iStatus,KBcaOptLevelGeneric,KBCASetIapId,aOpt); |
|
425 |
|
426 iState = EIdling; |
|
427 SetActive(); |
|
428 } |
|
429 |
|
430 |
|
431 void CBcaControl::ShutdownBca(TInt aError) |
|
432 /** |
|
433 * Bca Shutdown. |
|
434 |
|
435 * @param aError the error code to shutdown the NIF. |
|
436 */ |
|
437 { |
|
438 __ASSERT_DEBUG(iMBca,Panic(KBcaNotExist)); |
|
439 Cancel(); |
|
440 iError = aError; |
|
441 iState = EClosing; |
|
442 if(iMBca) |
|
443 { |
|
444 iMBca->Shutdown(iStatus); |
|
445 SetActive(); |
|
446 } |
|
447 } |
|
448 |
|
449 /** Panic function for RawIpNif |
|
450 |
|
451 * @param aPanic panic code */ |
|
452 void Panic(TRawIPNifPanic aPanic) |
|
453 { |
|
454 User::Panic(KNifName,aPanic); |
|
455 } |
|
456 |