24
|
1 |
// Copyright (c) 2000-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 |
// \file mnetwork.cpp
|
|
15 |
// Basic GSM Network and Operator information Implementation file.
|
|
16 |
// This file contains the implementation of the CATNetworkInfo, CATDetectNetwork,
|
|
17 |
// CNotifyNetworkRegistrationStatusChange and CCurrentNetworkChangedNotify classes.
|
|
18 |
// Find the current Network Operator in Numeric, Long and Short formats.
|
|
19 |
// NB - Some phones do not fully support all the formats, if any. The commands are
|
|
20 |
// sent in sequence starting with the query command (AT+COPS?). All the phones currently
|
|
21 |
// supported implement this command. Valid responses are set in the TMobilePhoneLocationAreaV1
|
|
22 |
// and the TMobilePhoneNetworkInfoV1 structures and the Network's status is set to Current.
|
|
23 |
//
|
|
24 |
//
|
|
25 |
|
|
26 |
#include <et_phone.h>
|
|
27 |
#include "mnetwork.h"
|
|
28 |
#include "mSLOGGER.H"
|
|
29 |
#include "ATIO.H"
|
|
30 |
#include "Matstd.h"
|
|
31 |
#include "mPHONE.H"
|
|
32 |
|
|
33 |
const TInt KSettlingPause=1; //< This pause is used at the end of the network information queries. The Nokia 8210 has been shown to require this, if it is not to error the next command.
|
|
34 |
|
|
35 |
_LIT8(KSetAndReadOperatorCommandNumeric, "AT+COPS=3,2;+COPS?\r");
|
|
36 |
_LIT8(KSetAndReadOperatorCommandShort, "AT+COPS=3,1;+COPS?\r");
|
|
37 |
_LIT8(KSetAndReadOperatorCommandLong, "AT+COPS=3,0;+COPS?\r");
|
|
38 |
|
|
39 |
_LIT8(KGetCurrentOperatorCommand, "AT+COPS?\r");
|
|
40 |
_LIT8(KOperatorResponse,"+COPS:");
|
|
41 |
|
|
42 |
_LIT8(KDetectNetworkCommand,"AT+COPS=?");
|
|
43 |
|
|
44 |
|
|
45 |
static TInt NetworkIdL(const TDesC8& aCode,
|
|
46 |
RMobilePhone::TMobilePhoneNetworkCountryCode& aCountryCode,
|
|
47 |
RMobilePhone::TMobilePhoneNetworkIdentity& aNetworkIdentity)
|
|
48 |
{
|
|
49 |
/**
|
|
50 |
* Utility function to translate the 5 digit ASCII network identification returned by the ME
|
|
51 |
* into Mobile Country Code (aCountryCode) and a Mobile Network Code (aNetworkIdentity) strings.
|
|
52 |
* Tbe format returned by the ME is XXXYY, where XXX represents the Mobile Country Code and YY
|
|
53 |
* represents the Mobile Network Code.
|
|
54 |
*/
|
|
55 |
if (aCode.Length()!=5)
|
|
56 |
{
|
|
57 |
return KErrGeneral;
|
|
58 |
}
|
|
59 |
|
|
60 |
aCountryCode.SetLength(3);
|
|
61 |
aCountryCode[0] = aCode[0];
|
|
62 |
aCountryCode[1] = aCode[1];
|
|
63 |
aCountryCode[2] = aCode[2];
|
|
64 |
|
|
65 |
aNetworkIdentity.SetLength(2);
|
|
66 |
aNetworkIdentity[0] = aCode[3];
|
|
67 |
aNetworkIdentity[1] = aCode[4];
|
|
68 |
return KErrNone;
|
|
69 |
}
|
|
70 |
|
|
71 |
|
|
72 |
CATNetworkInfo* CATNetworkInfo::NewL(CATIO* aIo,CTelObject* aTelObject,CATInit* aInit,CPhoneGlobals* aPhoneGlobals)
|
|
73 |
/**
|
|
74 |
* Standard two-phase constructor.
|
|
75 |
*/
|
|
76 |
{
|
|
77 |
CATNetworkInfo* netInfo = new(ELeave) CATNetworkInfo(aIo, aTelObject, aInit, aPhoneGlobals);
|
|
78 |
CleanupStack::PushL(netInfo);
|
|
79 |
netInfo->ConstructL();
|
|
80 |
CleanupStack::Pop();
|
|
81 |
return netInfo;
|
|
82 |
}
|
|
83 |
|
|
84 |
CATNetworkInfo::CATNetworkInfo(CATIO* aIo, CTelObject* aTelObject, CATInit* aInit,CPhoneGlobals* aPhoneGlobals)
|
|
85 |
: CATCommands(aIo,aTelObject,aInit,aPhoneGlobals)
|
|
86 |
,iPhoneGlobals(aPhoneGlobals)
|
|
87 |
{}
|
|
88 |
|
|
89 |
CATNetworkInfo::~CATNetworkInfo()
|
|
90 |
/**
|
|
91 |
* Standard Destructor.
|
|
92 |
* Note the NULLing of the iATNetworkInfo pointer. This should prevent any unwanted calling
|
|
93 |
* of this function from the "end of command" sequence after the class' destruction.
|
|
94 |
*/
|
|
95 |
{
|
|
96 |
iIo->RemoveExpectStrings(this);
|
|
97 |
iPhoneGlobals->iATNetworkInfo=NULL;
|
|
98 |
}
|
|
99 |
|
|
100 |
void CATNetworkInfo::Start(TTsyReqHandle aTsyReqHandle,TAny* aParam)
|
|
101 |
/**
|
|
102 |
* This is the standard entry point for retrieving the Network Information.
|
|
103 |
*/
|
|
104 |
{
|
|
105 |
LOGTEXT(_L8("MMTsy:\tCATNetworkInfo:\tStarting Operator Info."));
|
|
106 |
iReqHandle = aTsyReqHandle;
|
|
107 |
if (aParam!=NULL)
|
|
108 |
{
|
|
109 |
TTsyNetworkInfo* info = static_cast<TTsyNetworkInfo*>(aParam);
|
|
110 |
iNetworkInfo.iNetworkInfoPckg = info->iNetworkInfoPckg;
|
|
111 |
iNetworkInfo.iArea = info->iArea;
|
|
112 |
}
|
|
113 |
|
|
114 |
//
|
|
115 |
// This object is not always started thru the CATBase::ExecuteCommand
|
|
116 |
// So we sometimes have to manually control the flow control of iEventSignalActive
|
|
117 |
iPhoneGlobals->iEventSignalActive = ETrue;
|
|
118 |
iCancelled=EFalse;
|
|
119 |
|
|
120 |
if (iReqHandle==0)
|
|
121 |
iTelObject->FlowControlSuspend();
|
|
122 |
StartGetOperator();
|
|
123 |
}
|
|
124 |
|
|
125 |
void CATNetworkInfo::CheckOperator()
|
|
126 |
/**
|
|
127 |
* This function is called whenever an EventSignal Completes. It is a second entry point for the command.
|
|
128 |
* It checks CPhoneGlobals iPhoneStatus.iNetworkChanged and calls this function if it detects that the
|
|
129 |
* networking information has changed and therefore the CPhoneGlobals data may be out of date and needs
|
|
130 |
* to be refreshed.
|
|
131 |
*/
|
|
132 |
{
|
|
133 |
Start(0,0);
|
|
134 |
}
|
|
135 |
|
|
136 |
|
|
137 |
void CATNetworkInfo::EventSignal(TEventSource aSource)
|
|
138 |
/**
|
|
139 |
* This function contains the state machine for the command. The states flow consecutively and are
|
|
140 |
* described below.
|
|
141 |
*
|
|
142 |
* \par EATGetCurrentOperatorWriteComplete
|
|
143 |
* Wait for the "AT+COPS?" write to complete
|
|
144 |
*
|
|
145 |
* \par EATGetCurrentOperatorReadComplete
|
|
146 |
* Parse the "AT+COPS?" response. If it gets an "ERROR" back it assume that no COPS commands are
|
|
147 |
* supported, so complete the request with an error. If it is supported, parse the result and proceed
|
|
148 |
* to retrieve the numeric network code with "AT+COPS=3,2;+COPS?"
|
|
149 |
*
|
|
150 |
* \par EATNumericOperatorWaitForWriteComplete
|
|
151 |
* Wait for the "AT+COPS=3,2;+COPS?" to complete
|
|
152 |
*
|
|
153 |
* \par EATSetNumericOperatorReadComplete
|
|
154 |
* Parse the numeric network code if available. Proceed to retrieve the short network code with
|
|
155 |
* "AT+COPS=3,1;+COPS?".
|
|
156 |
*
|
|
157 |
* \par EATShortOperatorWaitForWriteComplete
|
|
158 |
* Wait for the "AT+COPS=3,1;+COPS?" write to complete.
|
|
159 |
*
|
|
160 |
* \par EATSetShortOperatorReadComplete
|
|
161 |
* Parse the short network name if available. Proceed to retrieve the long network name with
|
|
162 |
* "AT+COPS=3,0;+COPS?".
|
|
163 |
*
|
|
164 |
* \par EATLongOperatorWaitForWriteComplete
|
|
165 |
* Wait for the "AT+COPS=3,0;+COPS?" write to complete.
|
|
166 |
*
|
|
167 |
* \par EATSetLongOperatorReadComplete
|
|
168 |
* Parse the long network name if available. Proceed to complete the request.
|
|
169 |
* Check for outstanding current network operator notifications at this point.
|
|
170 |
*
|
|
171 |
* \par EATWaitForStopState
|
|
172 |
* This state is used when stopping the state machine to ensure that a pending modem response has been
|
|
173 |
* retrieved before freeing up the Multimode TSY to send more commands. Prematurely stopping the state machine
|
|
174 |
* is usually forced by a client cancel request.
|
|
175 |
*
|
|
176 |
* \par EATWaitForSettlingTimeout
|
|
177 |
* This state is used to provide a pause at the end of the network information queries. The Nokia 8210
|
|
178 |
* has been shown to require this, if it is not to arbitrarily error the next command.
|
|
179 |
*/
|
|
180 |
{
|
|
181 |
if ((aSource==ETimeOutCompletion)&&(iState!=EATWaitForSettlingTimeout))
|
|
182 |
{
|
|
183 |
LOGTEXT(_L8("MMTsy:\tCATNetworkInfo:\tTimeout Error during Operator read"));
|
|
184 |
RemoveStdExpectStrings();
|
|
185 |
Complete(KErrTimedOut,aSource);
|
|
186 |
return;
|
|
187 |
}
|
|
188 |
|
|
189 |
switch(iState)
|
|
190 |
{
|
|
191 |
case EATGetCurrentOperatorWriteComplete:
|
|
192 |
__ASSERT_ALWAYS(aSource==EWriteCompletion,Panic(EATCommand_IllegalCompletionWriteExpected));
|
|
193 |
{
|
|
194 |
iIo->WriteAndTimerCancel(this);
|
|
195 |
StandardWriteCompletionHandler(aSource, 5);
|
|
196 |
iState=EATGetCurrentOperatorReadComplete;
|
|
197 |
}
|
|
198 |
break;
|
|
199 |
|
|
200 |
case EATGetCurrentOperatorReadComplete:
|
|
201 |
__ASSERT_ALWAYS(aSource==EReadCompletion,Panic(EATCommand_IllegalCompletionReadExpected));
|
|
202 |
{
|
|
203 |
iIo->WriteAndTimerCancel(this);
|
|
204 |
TInt ret(ValidateExpectString());
|
|
205 |
RemoveStdExpectStrings();
|
|
206 |
if (ret != KErrNone)
|
|
207 |
{
|
|
208 |
LOGTEXT(_L8("MMTsy:\tCATNetworkInfo:\t+COPS? not supported"));
|
|
209 |
LOGTEXT(_L8("MMTsy:\tCATNetworkInfo:\tSet Operator Command not supported")); // An assumption
|
|
210 |
Complete(ret, aSource); // No point in sending the Set Command.
|
|
211 |
}
|
|
212 |
else if (iCancelled)
|
|
213 |
{
|
|
214 |
Complete(KErrCancel, aSource); // Cancel state machine in safe place
|
|
215 |
}
|
|
216 |
else
|
|
217 |
{
|
|
218 |
LOGTEXT(_L8("MMTsy:\tCATNetworkInfo:\t+COPS? supported"));
|
|
219 |
TRAPD(ret,ParseOperatorResponseL());
|
|
220 |
if (ret != KErrNone)
|
|
221 |
{
|
|
222 |
LOGTEXT(_L8("MMTsy:\tCATNetworkInfo:\tError parsing +COPS?"));
|
|
223 |
}
|
|
224 |
iTxBuffer.Copy(KSetAndReadOperatorCommandNumeric); // AT+COPS=3,2;+COPS?
|
|
225 |
iIo->Write(this, iTxBuffer);
|
|
226 |
iIo->SetTimeOut(this, 5000);
|
|
227 |
iState=EATNumericOperatorWaitForWriteComplete;
|
|
228 |
}
|
|
229 |
}
|
|
230 |
break;
|
|
231 |
|
|
232 |
case EATNumericOperatorWaitForWriteComplete:
|
|
233 |
__ASSERT_ALWAYS(aSource==EWriteCompletion,Panic(EATCommand_IllegalCompletionWriteExpected));
|
|
234 |
{
|
|
235 |
iIo->WriteAndTimerCancel(this);
|
|
236 |
StandardWriteCompletionHandler(aSource, 5);
|
|
237 |
iState=EATSetNumericOperatorReadComplete;
|
|
238 |
}
|
|
239 |
break;
|
|
240 |
|
|
241 |
case EATSetNumericOperatorReadComplete:
|
|
242 |
__ASSERT_ALWAYS(aSource==EReadCompletion,Panic(EATCommand_IllegalCompletionReadExpected));
|
|
243 |
{
|
|
244 |
iIo->WriteAndTimerCancel(this);
|
|
245 |
TInt ret(ValidateExpectString());
|
|
246 |
RemoveStdExpectStrings();
|
|
247 |
if (iCancelled)
|
|
248 |
{
|
|
249 |
Complete(KErrCancel, aSource); // Cancel state machine in safe place
|
|
250 |
return;
|
|
251 |
}
|
|
252 |
else if (ret != KErrNone)
|
|
253 |
{
|
|
254 |
LOGTEXT(_L8("MMTsy:\tCATNetworkInfo:\tAT+COPS=3,2 not supported"));
|
|
255 |
}
|
|
256 |
else // Set Operator Command was successful, Read the Current Operator
|
|
257 |
{
|
|
258 |
LOGTEXT(_L8("MMTsy:\tCATNetworkInfo:\t AT+COPS=3,2 supported"));
|
|
259 |
TRAPD(ret,ParseOperatorResponseL());
|
|
260 |
if (ret != KErrNone)
|
|
261 |
{
|
|
262 |
LOGTEXT(_L8("MMTsy:\tCATNetworkInfo:\tError parsing +COPS=3,2"));
|
|
263 |
}
|
|
264 |
}
|
|
265 |
iTxBuffer.Copy(KSetAndReadOperatorCommandShort); // AT+COPS=3,1;+COPS?
|
|
266 |
iIo->Write(this, iTxBuffer);
|
|
267 |
iIo->SetTimeOut(this, 5000);
|
|
268 |
iState=EATShortOperatorWaitForWriteComplete;
|
|
269 |
}
|
|
270 |
break;
|
|
271 |
|
|
272 |
case EATShortOperatorWaitForWriteComplete:
|
|
273 |
__ASSERT_ALWAYS(aSource==EWriteCompletion,Panic(EATCommand_IllegalCompletionWriteExpected));
|
|
274 |
{
|
|
275 |
iIo->WriteAndTimerCancel(this);
|
|
276 |
StandardWriteCompletionHandler(aSource, 5);
|
|
277 |
iState=EATSetShortOperatorReadComplete;
|
|
278 |
}
|
|
279 |
break;
|
|
280 |
|
|
281 |
case EATSetShortOperatorReadComplete:
|
|
282 |
__ASSERT_ALWAYS(aSource==EReadCompletion,Panic(EATCommand_IllegalCompletionReadExpected));
|
|
283 |
{
|
|
284 |
iIo->WriteAndTimerCancel(this);
|
|
285 |
TInt ret(ValidateExpectString());
|
|
286 |
RemoveStdExpectStrings();
|
|
287 |
if (iCancelled)
|
|
288 |
{
|
|
289 |
Complete(KErrCancel, aSource); // Cancel state machine in safe place
|
|
290 |
return;
|
|
291 |
}
|
|
292 |
else if (ret != KErrNone)
|
|
293 |
{
|
|
294 |
LOGTEXT(_L8("MMTsy:\tCATNetworkInfo:\tAT+COPS=3,1 not supported"));
|
|
295 |
}
|
|
296 |
else// Set Operator Command was successful, Read the Current Operator
|
|
297 |
{
|
|
298 |
LOGTEXT(_L8("MMTsy:\tCATNetworkInfo:\t AT+COPS=3,1 supported"));
|
|
299 |
TRAPD(ret,ParseOperatorResponseL());
|
|
300 |
if (ret != KErrNone)
|
|
301 |
{
|
|
302 |
LOGTEXT(_L8("MMTsy:\tCATNetworkInfo:\tError parsing +COPS=3,1"));
|
|
303 |
}
|
|
304 |
}
|
|
305 |
iTxBuffer.Copy(KSetAndReadOperatorCommandLong); // AT+COPS=3,0;+COPS?
|
|
306 |
iIo->Write(this, iTxBuffer);
|
|
307 |
iIo->SetTimeOut(this, 5000);
|
|
308 |
iState=EATLongOperatorWaitForWriteComplete;
|
|
309 |
}
|
|
310 |
break;
|
|
311 |
|
|
312 |
case EATLongOperatorWaitForWriteComplete:
|
|
313 |
__ASSERT_ALWAYS(aSource==EWriteCompletion,Panic(EATCommand_IllegalCompletionWriteExpected));
|
|
314 |
{
|
|
315 |
iIo->WriteAndTimerCancel(this);
|
|
316 |
StandardWriteCompletionHandler(aSource, 5);
|
|
317 |
iState=EATSetLongOperatorReadComplete;
|
|
318 |
}
|
|
319 |
break;
|
|
320 |
|
|
321 |
case EATSetLongOperatorReadComplete:
|
|
322 |
__ASSERT_ALWAYS(aSource==EReadCompletion,Panic(EATCommand_IllegalCompletionReadExpected));
|
|
323 |
{
|
|
324 |
iIo->WriteAndTimerCancel(this);
|
|
325 |
TInt ret(ValidateExpectString());
|
|
326 |
RemoveStdExpectStrings();
|
|
327 |
if (ret != KErrNone)
|
|
328 |
{
|
|
329 |
LOGTEXT(_L8("MMTsy:\tCATNetworkInfo:\t+COPS=3,0 not supported"));
|
|
330 |
}
|
|
331 |
else // Set Operator cmd was successful, Read the Current Operator
|
|
332 |
{
|
|
333 |
LOGTEXT(_L8("MMTsy:\tCATNetworkInfo:\tAT+COPS=3,0 supported"));
|
|
334 |
TRAPD(ret,ParseOperatorResponseL());
|
|
335 |
if (ret != KErrNone)
|
|
336 |
{
|
|
337 |
LOGTEXT(_L8("MMTsy:\tCATNetworkInfo:\tError parsing +COPS=3,0"));
|
|
338 |
}
|
|
339 |
}
|
|
340 |
|
|
341 |
// Check outstanding current network operator notifications
|
|
342 |
iPhoneGlobals->iNotificationStore->CheckNotification(iTelObject,ECurrentNetworkChanged);
|
|
343 |
|
|
344 |
iIo->SetTimeOut(this, KSettlingPause*1000);
|
|
345 |
iState=EATWaitForSettlingTimeout;
|
|
346 |
}
|
|
347 |
break;
|
|
348 |
|
|
349 |
case EATWaitForSettlingTimeout:
|
|
350 |
__ASSERT_ALWAYS((aSource==ETimeOutCompletion),Panic(EATCommand_IllegalCompletionWriteExpected));
|
|
351 |
Complete(KErrNone,aSource);
|
|
352 |
break;
|
|
353 |
|
|
354 |
case EATWaitForStopState:
|
|
355 |
__ASSERT_ALWAYS(aSource==EReadCompletion, Panic(EATCommand_IllegalCompletionReadExpected));
|
|
356 |
{
|
|
357 |
iIo->WriteAndTimerCancel(this);
|
|
358 |
Complete(KErrCancel, aSource);
|
|
359 |
}
|
|
360 |
break;
|
|
361 |
|
|
362 |
default:
|
|
363 |
break;
|
|
364 |
}//switch
|
|
365 |
}//EventSignal
|
|
366 |
|
|
367 |
void CATNetworkInfo::Stop(TTsyReqHandle aTsyReqHandle)
|
|
368 |
/**
|
|
369 |
* This function is used to prematurely stop the state machine. This would usually occur following a
|
|
370 |
* client cancel request.
|
|
371 |
*/
|
|
372 |
{
|
|
373 |
__ASSERT_ALWAYS(aTsyReqHandle == iReqHandle, Panic(EIllegalTsyReqHandle));
|
|
374 |
LOGTEXT(_L8("MMTsy:\tCATNetworkInfo:\tCancel called."));
|
|
375 |
iCancelled=ETrue;
|
|
376 |
}
|
|
377 |
|
|
378 |
|
|
379 |
void CATNetworkInfo::Complete(TInt aError,TEventSource aSource)
|
|
380 |
/**
|
|
381 |
* This function completes the client's request.
|
|
382 |
*/
|
|
383 |
{
|
|
384 |
iIo->WriteAndTimerCancel(this);
|
|
385 |
iIo->RemoveExpectStrings(this);
|
|
386 |
iOKExpectString = NULL;
|
|
387 |
iErrorExpectString = NULL;
|
|
388 |
if (aSource==EWriteCompletion)
|
|
389 |
iIo->Read();
|
|
390 |
iState = EATNotInProgress;
|
|
391 |
LOGTEXT2(_L8("MMTsy:CATNetworkInfo:\tCATNetworkInfo completed with error code : %d"), aError);
|
|
392 |
//
|
|
393 |
// BEWARE: The next command will be started from inside ReqCompleted or FlowControlResume
|
|
394 |
//
|
|
395 |
//
|
|
396 |
// This object is not always started thru the CATBase::ExecuteCommand
|
|
397 |
// So we sometimes have to manually control the flow control of iEventSignalActive
|
|
398 |
iPhoneGlobals->iEventSignalActive = EFalse;
|
|
399 |
|
|
400 |
if (iReqHandle)
|
|
401 |
{
|
|
402 |
// Explicit call from a client
|
|
403 |
if (aError==KErrNone)
|
|
404 |
{
|
|
405 |
GetCurrentNetworkInfo(&iNetworkInfo);
|
|
406 |
}
|
|
407 |
iTelObject->ReqCompleted(iReqHandle, aError);
|
|
408 |
}
|
|
409 |
else
|
|
410 |
{
|
|
411 |
// CheckOperator() call from CATCommands::Complete
|
|
412 |
iTelObject->FlowControlResume();
|
|
413 |
}
|
|
414 |
CATCommands::Complete(aError,aSource);
|
|
415 |
}
|
|
416 |
|
|
417 |
void CATNetworkInfo::CompleteWithIOError(TEventSource /*aSource*/,TInt aStatus)
|
|
418 |
/**
|
|
419 |
* This function handles I/O errors that may occur during any of the stages of the state machine.
|
|
420 |
*/
|
|
421 |
{
|
|
422 |
if (iState!=EATNotInProgress)
|
|
423 |
{
|
|
424 |
iIo->WriteAndTimerCancel(this);
|
|
425 |
if (iReqHandle)
|
|
426 |
{
|
|
427 |
iTelObject->ReqCompleted(iReqHandle, aStatus);
|
|
428 |
}
|
|
429 |
else
|
|
430 |
{
|
|
431 |
// CheckOperator() call from CATCommands::Complete
|
|
432 |
iTelObject->FlowControlResume();
|
|
433 |
}
|
|
434 |
iState = EATNotInProgress;
|
|
435 |
}
|
|
436 |
}
|
|
437 |
|
|
438 |
void CATNetworkInfo::StartGetOperator()
|
|
439 |
/**
|
|
440 |
* This function kicks off the state machine by transmitting the first command, "AT+COPS?" and
|
|
441 |
* setting the state.
|
|
442 |
*/
|
|
443 |
{
|
|
444 |
iPhoneGlobals->iPhoneStatus.iNetworkChanged=EFalse;
|
|
445 |
InitializeNetworkInfo(); // Initialize the TNetworkInfo struct that will contain the mobile's responses
|
|
446 |
iTxBuffer.Copy(KGetCurrentOperatorCommand);
|
|
447 |
iIo->Write(this, iTxBuffer);
|
|
448 |
iIo->SetTimeOut(this, 5000);
|
|
449 |
iState=EATGetCurrentOperatorWriteComplete;
|
|
450 |
}
|
|
451 |
|
|
452 |
void CATNetworkInfo::InitializeNetworkInfo()
|
|
453 |
/**
|
|
454 |
* This function is used to initialize (to zero) the network information elements in the CPhoneGlobals
|
|
455 |
* structure.
|
|
456 |
*/
|
|
457 |
{
|
|
458 |
RMobilePhone::TMobilePhoneNetworkInfoV1& networkinfo = iPhoneGlobals->iPhoneStatus.iCurrentNetwork;
|
|
459 |
|
|
460 |
networkinfo.iMode = RMobilePhone::ENetworkModeUnknown;
|
|
461 |
networkinfo.iCountryCode.Zero(); // Unknown, MCC
|
|
462 |
networkinfo.iNetworkId.Zero(); // MNC
|
|
463 |
networkinfo.iCdmaSID.Zero(); // Unused CDMA field
|
|
464 |
networkinfo.iAnalogSID.Zero(); // Unused CDMA field
|
|
465 |
networkinfo.iShortName.Zero();
|
|
466 |
networkinfo.iLongName.Zero();
|
|
467 |
networkinfo.iStatus = RMobilePhone::ENetworkStatusUnknown;
|
|
468 |
networkinfo.iDisplayTag.Zero();
|
|
469 |
}
|
|
470 |
|
|
471 |
void CATNetworkInfo::ParseOperatorResponseL()
|
|
472 |
/**
|
|
473 |
* This function is used to parse the ME responses to commands to retrieve numeric, short name
|
|
474 |
* or long name network information. Possible responses are:
|
|
475 |
* +COPS: mode, 0, "long format name"
|
|
476 |
* +COPS: mode, 1, "short format name"
|
|
477 |
* +COPS: mode, 2, "operator ID in hex"
|
|
478 |
* +COPS: mode (no network information available)
|
|
479 |
*
|
|
480 |
* Relevant information is retrieved and written into the CPhoneGlobals class.
|
|
481 |
*/
|
|
482 |
{
|
|
483 |
RMobilePhone::TMobilePhoneNetworkInfoV1& networkInfo = iPhoneGlobals->iPhoneStatus.iCurrentNetwork;
|
|
484 |
|
|
485 |
ParseBufferLC(); // Parse the buffer and create a linked list with the phone's response
|
|
486 |
|
|
487 |
CATParamListEntry* entry;
|
|
488 |
TDblQueIter<CATParamListEntry> iter(iRxResults);
|
|
489 |
|
|
490 |
// The 1st item in the list should be the +COPS: response
|
|
491 |
entry=iter++;
|
|
492 |
if (entry && entry->iResultPtr.MatchF(KOperatorResponse)!=0)
|
|
493 |
User::Leave(KErrGeneral);
|
|
494 |
|
|
495 |
// The next item is the mode (this information is not used)
|
|
496 |
entry=iter++;
|
|
497 |
if (!entry)
|
|
498 |
User::Leave(KErrGeneral);
|
|
499 |
|
|
500 |
// The next item should be the format. If there is no network information then this item
|
|
501 |
// would be empty. The network status is consequently updated.
|
|
502 |
entry=iter++;
|
|
503 |
if (!entry) // Not connected, so the response is "+COPS: 0"
|
|
504 |
networkInfo.iStatus=RMobilePhone::ENetworkStatusUnknown;
|
|
505 |
else
|
|
506 |
{
|
|
507 |
TInt format=CATParamListEntry::EntryValL(entry);
|
|
508 |
|
|
509 |
// If the format is available, the network name is the next item in the list
|
|
510 |
entry=iter++;
|
|
511 |
if (!entry)
|
|
512 |
User::Leave(KErrGeneral);
|
|
513 |
switch (format)
|
|
514 |
{
|
|
515 |
case 0:
|
|
516 |
if((entry->iResultPtr).Length() > networkInfo.iLongName.MaxLength())
|
|
517 |
networkInfo.iLongName.Copy((entry->iResultPtr).Mid(0,networkInfo.iLongName.MaxLength()));
|
|
518 |
else
|
|
519 |
networkInfo.iLongName.Copy(entry->iResultPtr);
|
|
520 |
break;
|
|
521 |
case 1:
|
|
522 |
if((entry->iResultPtr).Length() > networkInfo.iShortName.MaxLength())
|
|
523 |
networkInfo.iShortName.Copy((entry->iResultPtr).Mid(0,networkInfo.iShortName.MaxLength()));
|
|
524 |
else
|
|
525 |
networkInfo.iShortName.Copy(entry->iResultPtr);
|
|
526 |
break;
|
|
527 |
case 2:
|
|
528 |
User::LeaveIfError(NetworkIdL(entry->iResultPtr,networkInfo.iCountryCode, networkInfo.iNetworkId));
|
|
529 |
break;
|
|
530 |
default:
|
|
531 |
User::Leave(KErrGeneral);
|
|
532 |
break;
|
|
533 |
}
|
|
534 |
|
|
535 |
// We've got an answer, so this must be the current network
|
|
536 |
networkInfo.iStatus=RMobilePhone::ENetworkStatusCurrent;
|
|
537 |
}
|
|
538 |
CleanupStack::PopAndDestroy();
|
|
539 |
}
|
|
540 |
|
|
541 |
void CATNetworkInfo::GetCurrentNetworkInfo(CATNetworkInfo::TTsyNetworkInfo* aNetworkInfo)
|
|
542 |
/**
|
|
543 |
* This function checks to see if the network registration information in CPhoneGlobals is valid,
|
|
544 |
* and, if it is, it copies the CPhoneGlobals network information into the waiting client request
|
|
545 |
* buffer.
|
|
546 |
*/
|
|
547 |
{
|
|
548 |
RMobilePhone::TMobilePhoneNetworkInfoV1& networkInfo = (*(aNetworkInfo->iNetworkInfoPckg))();
|
|
549 |
RMobilePhone::TMobilePhoneLocationAreaV1& areaInfo = *(aNetworkInfo->iArea);
|
|
550 |
RMobilePhone::TMobilePhoneRegistrationStatus status = iPhoneGlobals->iPhoneStatus.iRegistrationStatus;
|
|
551 |
|
|
552 |
if (status == RMobilePhone::ERegisteredOnHomeNetwork
|
|
553 |
|| status == RMobilePhone::ERegisteredRoaming
|
|
554 |
|| status == RMobilePhone::ERegistrationUnknown) // AT+CREG? is not supported, but info obtained during initialization is still valid. NickyM
|
|
555 |
{
|
|
556 |
RMobilePhone::TMobilePhoneNetworkInfoV1& info = iPhoneGlobals->iPhoneStatus.iCurrentNetwork;
|
|
557 |
RMobilePhone::TMobilePhoneLocationAreaV1& locationInfo = iPhoneGlobals->iPhoneStatus.iLocationArea;
|
|
558 |
|
|
559 |
networkInfo.iStatus = info.iStatus;
|
|
560 |
networkInfo.iCountryCode = info.iCountryCode;
|
|
561 |
networkInfo.iNetworkId = info.iNetworkId;
|
|
562 |
networkInfo.iCdmaSID = info.iCdmaSID; // for CDMA
|
|
563 |
networkInfo.iAnalogSID = info.iAnalogSID; // for CDMA
|
|
564 |
networkInfo.iShortName = info.iShortName;
|
|
565 |
networkInfo.iLongName = info.iLongName;
|
|
566 |
networkInfo.iDisplayTag = info.iLongName; // This TSY handles the display tag as the same as longname
|
|
567 |
networkInfo.iMode = iPhoneGlobals->iNetworkMode;
|
|
568 |
areaInfo.iAreaKnown = locationInfo.iAreaKnown;
|
|
569 |
areaInfo.iLocationAreaCode = locationInfo.iLocationAreaCode;
|
|
570 |
areaInfo.iCellId = locationInfo.iCellId;
|
|
571 |
}
|
|
572 |
else
|
|
573 |
{
|
|
574 |
networkInfo.iStatus = RMobilePhone::ENetworkStatusUnknown;
|
|
575 |
networkInfo.iShortName.Zero(); // Should this be .Zero() ?
|
|
576 |
networkInfo.iLongName.Zero(); // Should this be .Zero() ?
|
|
577 |
areaInfo.iAreaKnown = EFalse;
|
|
578 |
areaInfo.iLocationAreaCode = 0;
|
|
579 |
areaInfo.iCellId = 0;
|
|
580 |
|
|
581 |
}
|
|
582 |
return;
|
|
583 |
}
|
|
584 |
|
|
585 |
|
|
586 |
// class CNotifyNetworkRegistrationStatusChange
|
|
587 |
|
|
588 |
CNotifyNetworkRegistrationStatusChange* CNotifyNetworkRegistrationStatusChange::NewL(TTsyReqHandle aReqHandle,CTelObject* aTelObject,
|
|
589 |
RMobilePhone::TMobilePhoneRegistrationStatus* aRegStatus)
|
|
590 |
{
|
|
591 |
return new(ELeave) CNotifyNetworkRegistrationStatusChange(aReqHandle,aTelObject,aRegStatus);
|
|
592 |
}
|
|
593 |
|
|
594 |
CNotifyNetworkRegistrationStatusChange::CNotifyNetworkRegistrationStatusChange(TTsyReqHandle aReqHandle,CTelObject* aTelObject,
|
|
595 |
RMobilePhone::TMobilePhoneRegistrationStatus* aRegStatus)
|
|
596 |
: CNotifyBase(aReqHandle,aTelObject)
|
|
597 |
{
|
|
598 |
iRegStatus = aRegStatus;
|
|
599 |
}
|
|
600 |
|
|
601 |
CNotifyNetworkRegistrationStatusChange::~CNotifyNetworkRegistrationStatusChange()
|
|
602 |
{}
|
|
603 |
|
|
604 |
TBool CNotifyNetworkRegistrationStatusChange::CheckAndCompleteNotification(CTelObject* aTelObject, TEvent aEvent, TEvent /*aLastEvent*/)
|
|
605 |
/**
|
|
606 |
* This function completes a Registration status Notification.
|
|
607 |
*/
|
|
608 |
{
|
|
609 |
if (aEvent!=ERegistrationStatusChanged)
|
|
610 |
return EFalse;
|
|
611 |
|
|
612 |
LOGTEXT2(_L8("Event %d:\tRegistration Status Changed Notification completed"),aEvent);
|
|
613 |
*iRegStatus = reinterpret_cast<CPhoneMobile*>(aTelObject)->RegistrationStatus();
|
|
614 |
iTelObject->ReqCompleted(iReqHandle,KErrNone);
|
|
615 |
return ETrue;
|
|
616 |
}
|
|
617 |
|
|
618 |
// class CCurrentNetworkChangedNotify
|
|
619 |
|
|
620 |
CNotifyCurrentNetworkChange* CNotifyCurrentNetworkChange::NewL(TTsyReqHandle aReqHandle,CTelObject* aTelObject,TInt* aInfo)
|
|
621 |
{
|
|
622 |
return new(ELeave) CNotifyCurrentNetworkChange(aReqHandle,aTelObject,aInfo);
|
|
623 |
}
|
|
624 |
|
|
625 |
CNotifyCurrentNetworkChange::CNotifyCurrentNetworkChange(TTsyReqHandle aReqHandle,CTelObject* aTelObject,TInt* aInfo)
|
|
626 |
: CNotifyBase(aReqHandle,aTelObject)
|
|
627 |
{
|
|
628 |
CATNetworkInfo::TTsyNetworkInfo* info = reinterpret_cast<CATNetworkInfo::TTsyNetworkInfo*>(aInfo);
|
|
629 |
iNetworkInfo.iNetworkInfoPckg = info->iNetworkInfoPckg;
|
|
630 |
iNetworkInfo.iArea = info->iArea;
|
|
631 |
}
|
|
632 |
|
|
633 |
CNotifyCurrentNetworkChange::~CNotifyCurrentNetworkChange()
|
|
634 |
{}
|
|
635 |
|
|
636 |
TBool CNotifyCurrentNetworkChange::CheckAndCompleteNotification(CTelObject* aTelObject,TEvent aEvent,TEvent /*aLastEvent*/)
|
|
637 |
/**
|
|
638 |
* This function completes a Current Network Change Notification.
|
|
639 |
*/
|
|
640 |
{
|
|
641 |
if (aEvent!=ECurrentNetworkChanged)
|
|
642 |
return EFalse;
|
|
643 |
|
|
644 |
LOGTEXT2(_L8("Event %d:\tCurrent Network Changed Notification completed"),aEvent);
|
|
645 |
// REINTERPRET_CAST(CPhoneMobile*,aTelObject)->CurrentNetworkInfo(&iNetworkInfo);
|
|
646 |
reinterpret_cast<CPhoneMobile*>(aTelObject)->CurrentNetworkInfo(&iNetworkInfo);
|
|
647 |
iTelObject->ReqCompleted(iReqHandle,KErrNone);
|
|
648 |
return ETrue;
|
|
649 |
}
|
|
650 |
|
|
651 |
// Class CATDetectNetwork
|
|
652 |
//
|
|
653 |
// Detect all available networks.
|
|
654 |
|
|
655 |
CATDetectNetwork::CATDetectNetwork(CATIO* aIo, CTelObject* aTelObject, CATInit* aInit,CPhoneGlobals* aPhoneGlobals)
|
|
656 |
: CATCommands(aIo,aTelObject,aInit,aPhoneGlobals)
|
|
657 |
{}
|
|
658 |
|
|
659 |
CATDetectNetwork* CATDetectNetwork::NewL(CATIO* aIo,CTelObject* aTelObject,CATInit* aInit,CPhoneGlobals* aPhoneGlobals)
|
|
660 |
/**
|
|
661 |
* Standard 2 phase constructor.
|
|
662 |
*/
|
|
663 |
{
|
|
664 |
CATDetectNetwork* self = new(ELeave) CATDetectNetwork(aIo, aTelObject, aInit, aPhoneGlobals);
|
|
665 |
CleanupStack::PushL(self);
|
|
666 |
self->ConstructL();
|
|
667 |
CleanupStack::Pop();
|
|
668 |
return self;
|
|
669 |
}
|
|
670 |
|
|
671 |
CATDetectNetwork::~CATDetectNetwork()
|
|
672 |
/**
|
|
673 |
* Destructor.
|
|
674 |
*/
|
|
675 |
{
|
|
676 |
iIo->RemoveExpectStrings(this);
|
|
677 |
}
|
|
678 |
|
|
679 |
void CATDetectNetwork::Start(TTsyReqHandle aTsyReqHandle,TAny* aParam)
|
|
680 |
/**
|
|
681 |
* This is the standard entry point for retrieving the detected Operator Information.
|
|
682 |
*/
|
|
683 |
{
|
|
684 |
LOGTEXT(_L8("MMTsy:\tCATDetectNetwork:\tStarting Network detection"));
|
|
685 |
if (aParam != NULL)
|
|
686 |
{
|
|
687 |
TTsyDetectedNetworks* info = static_cast<TTsyDetectedNetworks* >(aParam);
|
|
688 |
iDetectedNetworks.iBufSize = info->iBufSize;
|
|
689 |
iDetectedNetworks.iBufPtr = info->iBufPtr;
|
|
690 |
}
|
|
691 |
|
|
692 |
iReqHandle = aTsyReqHandle;
|
|
693 |
|
|
694 |
WriteExpectingResults(KDetectNetworkCommand, 3);
|
|
695 |
__ASSERT_ALWAYS(iIo->AddExpectString(this,KNotifyMeIfErrorString) != NULL,Panic(EGeneral));
|
|
696 |
iState=EATDetectWaitForWriteComplete;
|
|
697 |
}
|
|
698 |
|
|
699 |
void CATDetectNetwork::EventSignal(TEventSource aSource)
|
|
700 |
/**
|
|
701 |
* This function contains the state machine for the command. The states flow consecutively and are
|
|
702 |
* described below.
|
|
703 |
*
|
|
704 |
* \par EATDetectWaitForWriteComplete
|
|
705 |
* Wait for the "AT+COPS=?" write to complete
|
|
706 |
*
|
|
707 |
* \par EATDetectReadComplete
|
|
708 |
* Reads the Modem's response to the AT+COPS=? command. If it gets an "ERROR" back it resets the
|
|
709 |
* timer and sets a new state (EATDetectExtendedReadComplete) and waits for another response.
|
|
710 |
*
|
|
711 |
* \par EATDetectExtendedReadComplete
|
|
712 |
* Reads the phone's response to the AT+COPS=? command and parses the response. Completes the
|
|
713 |
* request.
|
|
714 |
*
|
|
715 |
* \par EATWaitForStopState
|
|
716 |
* This state is used when stopping the state machine to ensure that a pending modem response has been
|
|
717 |
* retrieved before freeing up the Multimode TSY to send more commands. Prematurely stopping the state machine
|
|
718 |
* is usually forced by a client cancel request.
|
|
719 |
*/
|
|
720 |
{
|
|
721 |
if (aSource==ETimeOutCompletion)
|
|
722 |
{
|
|
723 |
if (iState!=EATDetectExtendedReadComplete)
|
|
724 |
{
|
|
725 |
LOGTEXT(_L8("MmTsy:\tCATDetectNetwork:\tTimeout Error during Network Detect read"));
|
|
726 |
RemoveStdExpectStrings();
|
|
727 |
Complete(KErrTimedOut,aSource);
|
|
728 |
return;
|
|
729 |
}
|
|
730 |
else
|
|
731 |
{
|
|
732 |
// the phone really does not support +COPS=?, so report that error
|
|
733 |
RemoveStdExpectStrings();
|
|
734 |
Complete(KErrNotSupported,EReadCompletion);
|
|
735 |
return;
|
|
736 |
}
|
|
737 |
}
|
|
738 |
|
|
739 |
switch(iState)
|
|
740 |
{
|
|
741 |
case EATDetectWaitForWriteComplete:
|
|
742 |
__ASSERT_ALWAYS(aSource==EWriteCompletion,Panic(EATCommand_IllegalCompletionWriteExpected));
|
|
743 |
{
|
|
744 |
iIo->WriteAndTimerCancel(this);
|
|
745 |
iIo->SetTimeOut(this,45 * KOneSecondPause); // Some phones take a long time to detect all the networks
|
|
746 |
AddStdExpectStrings();
|
|
747 |
iState=EATDetectReadComplete;
|
|
748 |
}
|
|
749 |
break;
|
|
750 |
|
|
751 |
case EATDetectReadComplete:
|
|
752 |
__ASSERT_ALWAYS(aSource==EReadCompletion,Panic(EATCommand_IllegalCompletionReadExpected));
|
|
753 |
iIo->WriteAndTimerCancel(this);
|
|
754 |
if (iIo->FoundChatString()==iErrorExpectString)
|
|
755 |
{
|
|
756 |
LOGTEXT(_L8("Modem returned ERROR - waiting for further response"));
|
|
757 |
iIo->ClearCurrentLine();
|
|
758 |
iIo->SetTimeOut(this,45 * KOneSecondPause);
|
|
759 |
iState = EATDetectExtendedReadComplete;
|
|
760 |
break;
|
|
761 |
}
|
|
762 |
// fall through ...
|
|
763 |
|
|
764 |
case EATDetectExtendedReadComplete:
|
|
765 |
__ASSERT_ALWAYS(aSource==EReadCompletion,Panic(EATCommand_IllegalCompletionReadExpected));
|
|
766 |
iIo->WriteAndTimerCancel(this);
|
|
767 |
{
|
|
768 |
TInt ret(ValidateExpectString());
|
|
769 |
RemoveStdExpectStrings();
|
|
770 |
if (ret==KErrNone)
|
|
771 |
TRAP(ret,ParseResponseL());
|
|
772 |
Complete(ret,aSource); // The return value is set in the Complete methode
|
|
773 |
}
|
|
774 |
break;
|
|
775 |
|
|
776 |
case EATWaitForStopState:
|
|
777 |
__ASSERT_ALWAYS(aSource==EReadCompletion, Panic(EATCommand_IllegalCompletionReadExpected));
|
|
778 |
{
|
|
779 |
iIo->WriteAndTimerCancel(this);
|
|
780 |
Complete(KErrCancel, aSource);
|
|
781 |
}
|
|
782 |
break;
|
|
783 |
|
|
784 |
default:
|
|
785 |
break;
|
|
786 |
}//switch
|
|
787 |
}//EventSignal
|
|
788 |
|
|
789 |
void CATDetectNetwork::Stop(TTsyReqHandle aTsyReqHandle)
|
|
790 |
/**
|
|
791 |
* This function is used to prematurely stop the state machine. This would usually occur following a
|
|
792 |
* client cancel request.
|
|
793 |
*/
|
|
794 |
{
|
|
795 |
__ASSERT_ALWAYS(aTsyReqHandle == iReqHandle, Panic(EIllegalTsyReqHandle));
|
|
796 |
LOGTEXT(_L8("MMTsy:\tCATDetectNetwork:\tCancel called."));
|
|
797 |
switch(iState)
|
|
798 |
{
|
|
799 |
case EATNotInProgress:
|
|
800 |
case EATDetectWaitForWriteComplete:
|
|
801 |
{
|
|
802 |
LOGTEXT2(_L8("Current state TSY is cancelling from %d"), iState);
|
|
803 |
Complete(KErrCancel, EReadCompletion);
|
|
804 |
}
|
|
805 |
break;
|
|
806 |
|
|
807 |
default:
|
|
808 |
{
|
|
809 |
LOGTEXT(_L8("MmTsy:\tCATDetectNetwork:\tStop, now waiting for expected modem response"));
|
|
810 |
AddStdExpectStrings();
|
|
811 |
iIo->SetTimeOut(this);
|
|
812 |
iState = EATWaitForStopState;
|
|
813 |
}
|
|
814 |
break;
|
|
815 |
}
|
|
816 |
}
|
|
817 |
|
|
818 |
|
|
819 |
void CATDetectNetwork::Complete(TInt aError,TEventSource aSource)
|
|
820 |
/**
|
|
821 |
* This function completes the client request.
|
|
822 |
*/
|
|
823 |
{
|
|
824 |
iState = EATNotInProgress;
|
|
825 |
iIo->WriteAndTimerCancel(this);
|
|
826 |
iIo->RemoveExpectStrings(this);
|
|
827 |
iOKExpectString = NULL;
|
|
828 |
iErrorExpectString = NULL;
|
|
829 |
CATCommands::Complete(aError,aSource);
|
|
830 |
|
|
831 |
LOGTEXT2(_L8("MMTsy:CATDetectNetwork:\tCATDetectNetwork completed with error code : %d"), aError);
|
|
832 |
if (aError==KErrCancel)
|
|
833 |
{
|
|
834 |
CPhoneMobile* phone = static_cast<CPhoneMobile*>(iTelObject);
|
|
835 |
phone->CompleteDetectedNetworksCancel(iReqHandle);
|
|
836 |
}
|
|
837 |
else
|
|
838 |
iTelObject->ReqCompleted(iReqHandle, aError);
|
|
839 |
}
|
|
840 |
|
|
841 |
void CATDetectNetwork::CompleteWithIOError(TEventSource /*aSource*/,TInt aStatus)
|
|
842 |
/**
|
|
843 |
* This function handles I/O errors that may occur during any of the stages of the state machine.
|
|
844 |
*/
|
|
845 |
{
|
|
846 |
if (iState!=EATNotInProgress)
|
|
847 |
{
|
|
848 |
iIo->WriteAndTimerCancel(this);
|
|
849 |
iState = EATNotInProgress;
|
|
850 |
iTelObject->ReqCompleted(iReqHandle, aStatus);
|
|
851 |
}
|
|
852 |
}
|
|
853 |
|
|
854 |
void CATDetectNetwork::ParseResponseL()
|
|
855 |
/**
|
|
856 |
* This function parses the phone's response to the Detect Networks command.
|
|
857 |
*/
|
|
858 |
{
|
|
859 |
// should be
|
|
860 |
//
|
|
861 |
// +COPS: (status,"longname","shortname",code),... ,,(list),(list)
|
|
862 |
//
|
|
863 |
// but SH888 gives
|
|
864 |
//
|
|
865 |
// +COPS: (status,"longname","shortname",code)<cr><lf>
|
|
866 |
// +COPS: ...
|
|
867 |
//
|
|
868 |
|
|
869 |
CMobilePhoneNetworkList* list=CMobilePhoneNetworkList::NewL();
|
|
870 |
CleanupStack::PushL(list);
|
|
871 |
|
|
872 |
ParseBufferLC();
|
|
873 |
|
|
874 |
RMobilePhone::TMobilePhoneNetworkInfoV1 info;
|
|
875 |
// This TSY only supports GSM mode so we can hardcode this
|
|
876 |
info.iMode=RMobilePhone::ENetworkModeGsm;
|
|
877 |
TDblQueIter<CATParamListEntry> iter(iRxResults);
|
|
878 |
CATParamListEntry* entry=iter++;
|
|
879 |
if (entry)
|
|
880 |
{
|
|
881 |
if (entry->iResultPtr!=KOperatorResponse)
|
|
882 |
User::Leave(KErrGeneral);
|
|
883 |
//
|
|
884 |
entry=iter++;
|
|
885 |
if (!entry)
|
|
886 |
User::Leave(KErrGeneral);
|
|
887 |
for (;;)
|
|
888 |
{
|
|
889 |
info.iStatus = RMobilePhone::TMobilePhoneNetworkStatus(CATParamListEntry::EntryValL(entry));
|
|
890 |
//
|
|
891 |
entry=iter++;
|
|
892 |
if (!entry)
|
|
893 |
User::Leave(KErrGeneral);
|
|
894 |
info.iLongName.Copy(entry->iResultPtr);
|
|
895 |
//
|
|
896 |
entry=iter++;
|
|
897 |
if (!entry)
|
|
898 |
User::Leave(KErrGeneral);
|
|
899 |
if((entry->iResultPtr).Length() > info.iShortName.MaxLength())
|
|
900 |
info.iShortName.Copy((entry->iResultPtr).Mid(0,info.iShortName.MaxLength()));
|
|
901 |
else
|
|
902 |
info.iShortName.Copy(entry->iResultPtr);
|
|
903 |
//
|
|
904 |
entry=iter++;
|
|
905 |
if (!entry)
|
|
906 |
User::Leave(KErrGeneral);
|
|
907 |
User::LeaveIfError(NetworkIdL(entry->iResultPtr,info.iCountryCode, info.iNetworkId)); // MNC and MCC
|
|
908 |
|
|
909 |
list->AddEntryL(info);
|
|
910 |
|
|
911 |
entry=iter++;
|
|
912 |
if (!entry)
|
|
913 |
break;
|
|
914 |
if (entry->iResultPtr.Length()==0)
|
|
915 |
break;
|
|
916 |
if (entry->iResultPtr!=KOperatorResponse)
|
|
917 |
continue;
|
|
918 |
entry=iter++;
|
|
919 |
if (!entry)
|
|
920 |
break;
|
|
921 |
}
|
|
922 |
}
|
|
923 |
|
|
924 |
CleanupStack::PopAndDestroy(); // results
|
|
925 |
|
|
926 |
*(iDetectedNetworks.iBufPtr) = list->StoreLC(); // Stream the list to optimice the size of it.
|
|
927 |
*(iDetectedNetworks.iBufSize) = (*(iDetectedNetworks.iBufPtr))->Size(); // Store the size of the streamed list to be passed back to the client.
|
|
928 |
|
|
929 |
CleanupStack::Pop(); // pop the CBufBase allocated by StoreLC
|
|
930 |
CleanupStack::PopAndDestroy(); // pop AND detroy the list.
|
|
931 |
|
|
932 |
} // End of ParseResponseL()
|
|
933 |
|
|
934 |
|
|
935 |
|