|
1 // Copyright (c) 2003-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 // This file contains the implementation of the |
|
15 // handling of MIP handovers in a CDMA2000 network. |
|
16 // |
|
17 // |
|
18 |
|
19 /** |
|
20 @file mipcdma.cpp |
|
21 */ |
|
22 |
|
23 #include "MipCdma.h" |
|
24 #include "PSDAGTBase.h" |
|
25 #include <comms-infras/nifprvar.h> |
|
26 |
|
27 /** |
|
28 @internalComponent |
|
29 */ |
|
30 const TInt K10Seconds = 10000000; |
|
31 |
|
32 /** |
|
33 @internalComponent |
|
34 */ |
|
35 _LIT(KTsyNameExtension,".tsy"); |
|
36 |
|
37 CMipCdmaHandoverHandler* CMipCdmaHandoverHandler::NewLC(CPSDAgent& aAgent, CCommsDbAccess& aDb) |
|
38 /** |
|
39 2 Phase constructor |
|
40 |
|
41 This function creates the whole CDMA2000 MIP Handover handler object, including the subclass |
|
42 CMIPCdmaEtelZoneChangeRequest. |
|
43 |
|
44 @param aAgent Reference to owner of this class |
|
45 @param aDb access to CommDB. |
|
46 @exception Leaves if no memory is available |
|
47 @return A newly created CMipCdmaHandoverHandler object |
|
48 */ |
|
49 { |
|
50 CMipCdmaHandoverHandler* self = new(ELeave) CMipCdmaHandoverHandler(aAgent, aDb); |
|
51 CleanupStack::PushL(self); |
|
52 self->ConstructL(); |
|
53 return self; |
|
54 } |
|
55 |
|
56 CMipCdmaHandoverHandler* CMipCdmaHandoverHandler::NewL(CPSDAgent& aAgent, CCommsDbAccess& aDb) |
|
57 /** |
|
58 2 Phase constructor |
|
59 |
|
60 This function creates the whole MIP Handover handler object, including the subclass |
|
61 CMIPCdmaEtelZoneChangeRequest. |
|
62 |
|
63 @param aAgent Reference to owner of this class |
|
64 @param aDb access to CommDB. |
|
65 @exception Leaves if no memory is available |
|
66 @return A newly created CMipCdmaHandoverHandler object |
|
67 */ |
|
68 { |
|
69 CMipCdmaHandoverHandler* self = NewLC(aAgent, aDb); |
|
70 CleanupStack::Pop(); //self |
|
71 return self; |
|
72 } |
|
73 |
|
74 CMipCdmaHandoverHandler::CMipCdmaHandoverHandler(CPSDAgent& aAgent, CCommsDbAccess& aDb) |
|
75 : CActive(CActive::EPriorityStandard), |
|
76 iAgent(aAgent), iDb(aDb) |
|
77 /** |
|
78 Constructor |
|
79 |
|
80 Adds itself to the Active Sceduler. Also initalizes all member data. |
|
81 |
|
82 @param aAgent Reference to owner of this class |
|
83 @param aDb access to CommDB. |
|
84 */ |
|
85 { |
|
86 CActiveScheduler::Add(this); |
|
87 } |
|
88 |
|
89 void CMipCdmaHandoverHandler::ConstructL() |
|
90 /** |
|
91 2nd phase Constructor |
|
92 |
|
93 Creates an ETEL Zone change listener object. |
|
94 Resets the timer object. |
|
95 |
|
96 @exception Leaves if no memory is available |
|
97 */ |
|
98 { |
|
99 //Create ETEL Zone Listener Object |
|
100 iMipCdmaEtelZoneChanger = CMIPCdmaEtelZoneChangeRequest::NewL(*this, iAgent, iDb); |
|
101 |
|
102 //Reset the timer (initialize the timer) |
|
103 (void)iTimer.CreateLocal(); |
|
104 } |
|
105 |
|
106 CMipCdmaHandoverHandler::~CMipCdmaHandoverHandler() |
|
107 /** |
|
108 Destructor |
|
109 |
|
110 Calls cancel on the Active object which will cancel the timer. |
|
111 Deletes the ETEL Zone change listener object. |
|
112 */ |
|
113 { |
|
114 Cancel(); //Cancel potential outstanding timer request. |
|
115 iTimer.Close(); //Needed to free resources on server side. |
|
116 delete iMipCdmaEtelZoneChanger; |
|
117 } |
|
118 |
|
119 TInt CMipCdmaHandoverHandler::StartListening() |
|
120 /** |
|
121 This function is called when the link is brought up. It is responsible to |
|
122 start this object and start listening to incoming events from both PPP and ETEL. |
|
123 |
|
124 @return Returns whether the starting of the object went ok or not. |
|
125 */ |
|
126 { |
|
127 TInt err = KErrNone; |
|
128 TBool val; |
|
129 if(iAgent.ReadBool(TPtrC(CDMA_MIP), val)==KErrNone && val) |
|
130 { |
|
131 err = iMipCdmaEtelZoneChanger->StartListening(); |
|
132 } |
|
133 return err; |
|
134 } |
|
135 |
|
136 void CMipCdmaHandoverHandler::StopListening() |
|
137 /** |
|
138 This function is called when the link is brought down. It is responsible to |
|
139 stop this object and its listener. |
|
140 */ |
|
141 { |
|
142 iMipCdmaEtelZoneChanger->StopListening(); |
|
143 } |
|
144 |
|
145 TBool CMipCdmaHandoverHandler::PPPLinkDownEvent() |
|
146 /** |
|
147 This function is called from the Reconnect() method in the CPSDAgent. |
|
148 It will report back to the CPSDAgent if we are using MIP or not. |
|
149 It will also start a timer that if it expires will force a manual reconnect of the link. |
|
150 If an ETEL notification event comes in before, or has already come in, an autmatic reconnect takes place. |
|
151 |
|
152 @return ETrue if we are using MIP else EFalse. |
|
153 */ |
|
154 { |
|
155 TBool val; |
|
156 if(iAgent.ReadBool(TPtrC(CDMA_MIP), val)==KErrNone && val) |
|
157 { |
|
158 //We are using MIP |
|
159 iPPPLinkDownEvent = ETrue; |
|
160 if (iETELChangedZoneEvent) |
|
161 { |
|
162 Cancel(); |
|
163 RestartPPP(); |
|
164 } |
|
165 else |
|
166 { |
|
167 //If timer is already started, cancel it and start it again. |
|
168 Cancel(); //Will only cancel the timer if the AO is active. |
|
169 StartTimer(); |
|
170 } |
|
171 return ETrue; |
|
172 } |
|
173 else |
|
174 { |
|
175 //We are NOT using MIP |
|
176 return EFalse; |
|
177 } |
|
178 } |
|
179 |
|
180 void CMipCdmaHandoverHandler::ETELChangedZoneEvent() |
|
181 /** |
|
182 This function is called from the RunL() method in the CMIPCdmaEtelZoneChangeRequest. |
|
183 It will also start a timer that if it expires will force a manual reconnect of the link. |
|
184 If an PPP Link Down event comes in before, or has already come in, an autmatic reconnect takes place. |
|
185 */ |
|
186 { |
|
187 iETELChangedZoneEvent = ETrue; |
|
188 if (iPPPLinkDownEvent) |
|
189 { |
|
190 Cancel(); |
|
191 // Notify nifman of the Changed Zone Event |
|
192 iAgent.AgentEvent(EEtelEvent,ECurrentNetworkChangeEvent,KNullDesC8); |
|
193 // Reconnect PPP |
|
194 RunL(); |
|
195 } |
|
196 else |
|
197 { |
|
198 //If timer is already started, cancel it and start it again. |
|
199 Cancel(); //Will only cancel the timer if the AO is active. |
|
200 StartTimer(); |
|
201 } |
|
202 } |
|
203 |
|
204 void CMipCdmaHandoverHandler::StartTimer() |
|
205 /** |
|
206 Help function that will start the active object. E.g. it will start the timer and activate the object. |
|
207 */ |
|
208 { |
|
209 TUint32 time; |
|
210 if(iAgent.ReadInt(TPtrC(CDMA_MIP_TIMEOUT), time)==KErrNone && time) |
|
211 { |
|
212 iTimer.After(iStatus, time); |
|
213 } |
|
214 else //default |
|
215 { |
|
216 iTimer.After(iStatus, K10Seconds); |
|
217 } |
|
218 |
|
219 SetActive(); |
|
220 } |
|
221 |
|
222 void CMipCdmaHandoverHandler::RestartPPP() |
|
223 /** |
|
224 This function is responsible to do an automatic reconnect of the link. Will also "zero" the state variables |
|
225 */ |
|
226 { |
|
227 iPPPLinkDownEvent = EFalse; |
|
228 iETELChangedZoneEvent = EFalse; |
|
229 |
|
230 //Notify client to restart PPP silently |
|
231 iAgent.MDPOReconnectComplete(KErrNone); |
|
232 } |
|
233 |
|
234 void CMipCdmaHandoverHandler::DoCancel() |
|
235 /** |
|
236 Inherited from the CActive class. Will cancel the timer request. |
|
237 */ |
|
238 { |
|
239 // Cancel the timer request |
|
240 iTimer.Cancel(); |
|
241 } |
|
242 |
|
243 void CMipCdmaHandoverHandler::RunL() |
|
244 /** |
|
245 Inherited from the CActive class. Will "zero" the state variables and restart the link manually. |
|
246 */ |
|
247 { |
|
248 iPPPLinkDownEvent = EFalse; |
|
249 iETELChangedZoneEvent = EFalse; |
|
250 //Notify client to restart PPP as we would in a normal Simple IP scenario |
|
251 iAgent.Reconnect(); |
|
252 } |
|
253 |
|
254 CMIPCdmaEtelZoneChangeRequest* CMIPCdmaEtelZoneChangeRequest::NewLC(CMipCdmaHandoverHandler& aHandoverHandler, CPSDAgent& aAgent, CCommsDbAccess& aDb) |
|
255 /** |
|
256 2 Phase constructor |
|
257 |
|
258 This function creates a ETEL Zone Change Listener object. |
|
259 |
|
260 @param aHandoverHandler Reference to owner of this class |
|
261 @param aAgent Reference to the Controller |
|
262 @param aDb access to CommDB. |
|
263 @exception Leaves if no memory is available |
|
264 @return A newly created CMIPCdmaEtelZoneChangeRequest object |
|
265 */ |
|
266 { |
|
267 CMIPCdmaEtelZoneChangeRequest* self = new(ELeave) CMIPCdmaEtelZoneChangeRequest(aHandoverHandler, aAgent, aDb); |
|
268 CleanupStack::PushL(self); |
|
269 self->ConstructL(); |
|
270 return self; |
|
271 } |
|
272 |
|
273 CMIPCdmaEtelZoneChangeRequest* CMIPCdmaEtelZoneChangeRequest::NewL(CMipCdmaHandoverHandler& aHandoverHandler, CPSDAgent& aAgent, CCommsDbAccess& aDb) |
|
274 /** |
|
275 2 Phase constructor |
|
276 |
|
277 This function creates a ETEL Zone Change Listener object. |
|
278 |
|
279 @param aHandoverHandler Reference to owner of this class |
|
280 @param aAgent Reference to the Agent |
|
281 @param aDb access to CommDB. |
|
282 @exception Leaves if no memory is available |
|
283 @return A newly created CMIPCdmaEtelZoneChangeRequest object |
|
284 */ |
|
285 { |
|
286 CMIPCdmaEtelZoneChangeRequest* self = NewLC(aHandoverHandler, aAgent, aDb); |
|
287 CleanupStack::Pop(); //self |
|
288 return self; |
|
289 } |
|
290 |
|
291 CMIPCdmaEtelZoneChangeRequest::CMIPCdmaEtelZoneChangeRequest(CMipCdmaHandoverHandler& aHandoverHandler, CPSDAgent& aAgent, CCommsDbAccess& aDb) |
|
292 : CActive(CActive::EPriorityStandard), iFirstTime(ETrue), |
|
293 iHandoverHandler(aHandoverHandler), iAgent(aAgent), iDb(aDb), |
|
294 iPhoneNetworkInfoPckg(iAsyncCurrentNetwork) |
|
295 /** |
|
296 Constructor |
|
297 |
|
298 Adds itself to the Active Sceduler. Also initalizes all member data. |
|
299 |
|
300 @param aHandoverHandler Reference to owner of this class |
|
301 @param aAgent Reference to the Agent |
|
302 */ |
|
303 { |
|
304 CActiveScheduler::Add(this); |
|
305 } |
|
306 |
|
307 void CMIPCdmaEtelZoneChangeRequest::ConstructL() |
|
308 /** |
|
309 2nd phase Constructor |
|
310 */ |
|
311 { |
|
312 } |
|
313 |
|
314 CMIPCdmaEtelZoneChangeRequest::~CMIPCdmaEtelZoneChangeRequest() |
|
315 /** |
|
316 Destructor |
|
317 |
|
318 Calls cancel on the Active object which will cancel the outstanding request to ETEL. |
|
319 Closes the ETEL phone and server. |
|
320 */ |
|
321 { |
|
322 StopListening(); |
|
323 } |
|
324 |
|
325 TInt CMIPCdmaEtelZoneChangeRequest::StartListening() |
|
326 /** |
|
327 This function is called when the link is brought up. |
|
328 It is responsible to initiate and create a phone object. |
|
329 |
|
330 @return Returns whether the starting of the object and phone went ok or not. |
|
331 */ |
|
332 { |
|
333 if (!iStarted) |
|
334 { |
|
335 iStarted = ETrue; |
|
336 TRAPD(err, InitPhoneL()); |
|
337 if(err != KErrNone) |
|
338 { |
|
339 return err; |
|
340 } |
|
341 |
|
342 //Start request for notification |
|
343 iFirstTime = ETrue; |
|
344 StartRequest(); |
|
345 } |
|
346 return KErrNone; |
|
347 } |
|
348 |
|
349 void CMIPCdmaEtelZoneChangeRequest::StopListening() |
|
350 /** |
|
351 This function is called when the link is brought down. It is responsible to stop |
|
352 the phone object and the phone server |
|
353 */ |
|
354 { |
|
355 if(iStarted) |
|
356 { |
|
357 iStarted=EFalse; |
|
358 Cancel(); |
|
359 |
|
360 iMmPhone.Close(); |
|
361 (void)iTelServer.UnloadPhoneModule(*iTsyName); |
|
362 delete iTsyName; |
|
363 iTsyName = NULL; |
|
364 iTelServer.Close(); |
|
365 } |
|
366 } |
|
367 |
|
368 void CMIPCdmaEtelZoneChangeRequest::InitPhoneL() |
|
369 /** |
|
370 This function is help function that creates and intializes a phone object |
|
371 |
|
372 @exception Leaves if no memory is available or if initiation of phone or server failed. |
|
373 */ |
|
374 { |
|
375 TFileName tsyName; |
|
376 iDb.GetTsyNameL(tsyName); |
|
377 if (tsyName.Right(4).CompareF(KTsyNameExtension) == 0) |
|
378 tsyName = tsyName.Left(tsyName.Length() - 4); |
|
379 |
|
380 // Connect to ETel |
|
381 (void)User::LeaveIfError(iTelServer.Connect()); |
|
382 |
|
383 TInt err = iTelServer.LoadPhoneModule(tsyName); |
|
384 if(err == KErrNotFound) |
|
385 User::Leave(KErrNone); |
|
386 else if(err != KErrNone) |
|
387 User::Leave(err); |
|
388 |
|
389 // Remember the tsy name so it can be unloaded |
|
390 iTsyName = tsyName.AllocL(); |
|
391 |
|
392 // Find out how many phones are supported e.g. how many TSYs |
|
393 TInt count = 0; |
|
394 (void)User::LeaveIfError(iTelServer.EnumeratePhones(count)); |
|
395 if (count <= 0) |
|
396 User::Leave(KErrNotFound); |
|
397 |
|
398 RTelServer::TPhoneInfo info; |
|
399 TBool found = EFalse; |
|
400 |
|
401 // Loop through all the phones and find correct TSY |
|
402 for (TInt i = 0; i < count; i++) |
|
403 { |
|
404 TBuf<KCommsDbSvrMaxFieldLength> currentTsyName; |
|
405 (void)User::LeaveIfError(iTelServer.GetTsyName(i, currentTsyName)); |
|
406 // If the loaded object has .tsy extension, compare the name |
|
407 // with aTsyName |
|
408 if (currentTsyName.Right(4).CompareF(KTsyNameExtension) == 0) |
|
409 currentTsyName = currentTsyName.Left(currentTsyName.Length() - 4); |
|
410 if (currentTsyName.CompareF(tsyName) == 0) |
|
411 { |
|
412 // Get phone info from the TSY |
|
413 (void)User::LeaveIfError(iTelServer.GetPhoneInfo(i, info)); |
|
414 found = ETrue; |
|
415 break; |
|
416 } |
|
417 } |
|
418 if (!found) |
|
419 User::Leave(KErrNotFound); |
|
420 // Open multimode phone object |
|
421 (void)User::LeaveIfError(iMmPhone.Open(iTelServer,info.iName)); |
|
422 } |
|
423 |
|
424 void CMIPCdmaEtelZoneChangeRequest::StartRequest() |
|
425 /** |
|
426 Trigger function. Will start the request for notifications for a zone change event from ETEL. |
|
427 |
|
428 If it is the first time the object is called we will get the network information and store it locally |
|
429 After the initial request we will only ask to get notfied when there is a change in network information. |
|
430 */ |
|
431 { |
|
432 if (iFirstTime) |
|
433 { |
|
434 //Get current netowrk status |
|
435 iMmPhone.GetCurrentNetwork(iStatus, iPhoneNetworkInfoPckg, iAsyncLocArea); |
|
436 } |
|
437 else |
|
438 { |
|
439 //start etel request for notifications |
|
440 iMmPhone.NotifyCurrentNetworkChange(iStatus, iPhoneNetworkInfoPckg, iAsyncLocArea); |
|
441 } |
|
442 |
|
443 SetActive(); |
|
444 } |
|
445 |
|
446 void CMIPCdmaEtelZoneChangeRequest::DoCancel() |
|
447 /** |
|
448 Inherited from the CActive class. Will cancel the ETEL request. |
|
449 */ |
|
450 { |
|
451 if (iFirstTime) |
|
452 { |
|
453 iMmPhone.CancelAsyncRequest(EMobilePhoneGetCurrentNetwork); |
|
454 } |
|
455 else |
|
456 { |
|
457 // Cancel the ETEL Request |
|
458 iMmPhone.CancelAsyncRequest(EMobilePhoneNotifyCurrentNetworkChange); |
|
459 } |
|
460 } |
|
461 |
|
462 void CMIPCdmaEtelZoneChangeRequest::RunL() |
|
463 /** |
|
464 Inherited from the CActive class. Will notify the owner that a notification has ben received. |
|
465 Will requeue itself, e.g. will re-request notifications from ETEL. |
|
466 */ |
|
467 { |
|
468 if (iFirstTime) |
|
469 { |
|
470 iCurrentCdmaSID = iPhoneNetworkInfoPckg().iCdmaSID; |
|
471 iCurrentNetworkId = iPhoneNetworkInfoPckg().iNetworkId; |
|
472 iFirstTime = EFalse; |
|
473 } |
|
474 else |
|
475 { |
|
476 if ((iPhoneNetworkInfoPckg().iCdmaSID !=iCurrentCdmaSID) || (iPhoneNetworkInfoPckg().iNetworkId !=iCurrentNetworkId)) |
|
477 iHandoverHandler.ETELChangedZoneEvent(); |
|
478 } |
|
479 |
|
480 //Requeue |
|
481 StartRequest(); |
|
482 } |
|
483 |