|
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 "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: |
|
15 * CSyncService.h |
|
16 * |
|
17 */ |
|
18 |
|
19 |
|
20 |
|
21 #include <stdio.h> |
|
22 #include <crtdbg.h> |
|
23 #include <time.h> |
|
24 |
|
25 #include "CSyncService.h" |
|
26 #include "CUCCIniFile.h" |
|
27 |
|
28 // Parameters names |
|
29 const char KSharedDataName[] = { "NAME" }; |
|
30 const char KSharedDataValue[] = { "VALUE" }; |
|
31 |
|
32 |
|
33 // Sync Service ini file |
|
34 const char KSyncServiceIni[] = { ".\\SyncService.ini" }; |
|
35 const char KIniSectionName[] = { "SyncService" }; |
|
36 const char KIniConnection[] = { "Connection" }; |
|
37 const char KIniSerialPort[] = { "SerialPort" }; |
|
38 const char KIniIPAddress[] = { "IPAddress" }; |
|
39 const char KSerial[] = { "serial" }; |
|
40 const char KInfrared[] = { "ir" }; |
|
41 const char KBluetooth[] = { "bt" }; |
|
42 const char KSocket[] = { "tcp" }; |
|
43 const char KTimeout[] = { "Timeout" }; |
|
44 const char KPoll[] = { "Poll" }; |
|
45 const char KSTATLocation[] = { "STAT" }; |
|
46 |
|
47 // Timeout defaults (in seconds) |
|
48 const int KDefaultTimeout = 120; |
|
49 const int KDefaultPollInterval = 10; |
|
50 |
|
51 // STAT DLL Location |
|
52 #ifdef _DEBUG |
|
53 const char KDefaultSTATDLLLocation[] = { "\\epoc32\\tools\\stat\\statd.dll" }; |
|
54 #else |
|
55 const char KDefaultSTATDLLLocation[] = { "\\epoc32\\tools\\stat\\stat.dll" }; |
|
56 #endif |
|
57 |
|
58 // STAT Sync calls |
|
59 const char KStartSyncTestCase[] = { "<B><OTEFStatus,4><E>" }; |
|
60 const char KStartSyncComplete[] = { "<B><OTEFStatus,2><E>" }; |
|
61 const char KRetrieveSyncTestCaseResult[] = { "<B><NTEFResult><E>" }; |
|
62 const char KRetrieveSyncTestCaseStatus[] = { "<B><NTEFStatus><E>" }; |
|
63 const char KSetSharedData[] = { "<B><O" }; |
|
64 const char KCommandTerminate[] = { "><E>" }; |
|
65 const char KComma[] = { "," }; |
|
66 |
|
67 const int KMaxSharedDataLength = 2048; |
|
68 |
|
69 // Possible TEF synchronised test case error codes |
|
70 const int EPass = 0; |
|
71 const int EFail = 106; |
|
72 const int EInconclusive = 107; |
|
73 const int ETestSuiteError = 108; |
|
74 const int EAbort = 109; |
|
75 const int EIgnore = 110; |
|
76 |
|
77 // TEF Sync Status codes |
|
78 enum TSyncStatus |
|
79 { |
|
80 ETEFSyncUnknown = 0, |
|
81 ETEFSyncRunning = 1, |
|
82 ETEFSyncComplete = 2, |
|
83 ETEFSyncWaiting = 3, |
|
84 ETEFSyncContinue = 4, |
|
85 ETEFRetrieveResult = 5 |
|
86 }; |
|
87 |
|
88 CService* Service() { return new CSyncService(); } |
|
89 |
|
90 CSyncService::CSyncService() |
|
91 : ihLib(NULL), iptrConnect(NULL), iptrDisconnect(NULL), iptrSendRawCommand(NULL), |
|
92 iptrGetTEFSharedData(NULL), iConnection(0), iTimeout(KDefaultTimeout), |
|
93 iPollInterval(KDefaultPollInterval), iSTATDLLLocation(KDefaultSTATDLLLocation) |
|
94 { |
|
95 } |
|
96 |
|
97 CSyncService::~CSyncService() |
|
98 { |
|
99 // Free the STAT DLL library |
|
100 if( ihLib != NULL ) |
|
101 { |
|
102 ::FreeLibrary( ihLib ); |
|
103 ihLib = NULL; |
|
104 } |
|
105 } |
|
106 |
|
107 bool CSyncService::Setup() |
|
108 { |
|
109 bool ret = true; |
|
110 |
|
111 ret = RetrieveCommsInfo(); |
|
112 if(!ret) |
|
113 return ret; |
|
114 |
|
115 // Load the STAT DLL library. |
|
116 ihLib = ::LoadLibrary( iSTATDLLLocation.c_str() ); |
|
117 iptrConnect = reinterpret_cast<PROC_CONNECT>(::GetProcAddress( ihLib, ProcConnect )); |
|
118 iptrDisconnect = reinterpret_cast<PROC_DISCONNECT>(::GetProcAddress( ihLib, ProcDisconnect )); |
|
119 iptrSendRawCommand = reinterpret_cast<PROC_SENDRAWCOMMAND>(::GetProcAddress( ihLib, ProcSendRawCommand )); |
|
120 iptrGetTEFSharedData = reinterpret_cast<PROC_GETTEFSHAREDDATA>(::GetProcAddress( ihLib, ProcGetTEFSharedData )); |
|
121 |
|
122 if( ihLib == NULL || |
|
123 iptrConnect == NULL || |
|
124 iptrDisconnect == NULL || |
|
125 iptrSendRawCommand == NULL || |
|
126 iptrGetTEFSharedData == NULL ) |
|
127 { |
|
128 ret = false; |
|
129 } |
|
130 return ret; |
|
131 } |
|
132 |
|
133 int CSyncService::RunCommand( const CCall& aCall ) |
|
134 { |
|
135 int ret = ERR_NONE; |
|
136 |
|
137 // Connect to the device via STAT |
|
138 if( !iConnection ) |
|
139 { |
|
140 if( iConnectionType == SymbianSerial || |
|
141 iConnectionType == SymbianInfrared || |
|
142 iConnectionType == SymbianBluetooth ) |
|
143 { |
|
144 iConnection = (iptrConnect)(iConnectionType,iComPort.c_str(),NULL,NULL); |
|
145 } |
|
146 else if( iConnectionType == SymbianSocket ) |
|
147 { |
|
148 iConnection = (iptrConnect)(iConnectionType,iIPAddress.c_str(),NULL,NULL); |
|
149 } |
|
150 } |
|
151 |
|
152 if( !iConnection ) |
|
153 { |
|
154 ret = ERR_STAT; |
|
155 } |
|
156 |
|
157 int callID = -1; |
|
158 if( aCall.CallID( callID ) && ret == ERR_NONE ) |
|
159 { |
|
160 switch( callID ) |
|
161 { |
|
162 case 1: // StartSyncTestCase |
|
163 { |
|
164 ret = StartSyncTestCase( aCall ); |
|
165 } |
|
166 break; |
|
167 case 2: // RetrieveSyncTestCaseResult |
|
168 { |
|
169 ret = RetrieveSyncTestCaseResult( aCall ); |
|
170 } |
|
171 break; |
|
172 case 3: // SetSharedData |
|
173 { |
|
174 ret = SetSharedData( aCall ); |
|
175 } |
|
176 break; |
|
177 default: |
|
178 { |
|
179 #ifdef _DEBUG |
|
180 printf( "Unknown CallID\n" ); |
|
181 #endif |
|
182 ret = ERR_INVALID_CALL; |
|
183 } |
|
184 } |
|
185 } |
|
186 else |
|
187 { |
|
188 ret = ERR_GENERAL; |
|
189 } |
|
190 |
|
191 // Disconnect the device via STAT |
|
192 if( iConnection ) |
|
193 { |
|
194 int disconnectOK; |
|
195 disconnectOK = (iptrDisconnect)(iConnection); |
|
196 if( !disconnectOK ) |
|
197 { |
|
198 ret = ERR_STAT; |
|
199 } |
|
200 else |
|
201 { |
|
202 iConnection = 0; |
|
203 } |
|
204 } |
|
205 |
|
206 return ret; |
|
207 } |
|
208 |
|
209 bool CSyncService::RetrieveCommsInfo() |
|
210 { |
|
211 bool ret = false; |
|
212 |
|
213 // Load the configuration information file |
|
214 CUCCIniFile iniFile( KSyncServiceIni ); |
|
215 |
|
216 // Retrieve the connection type |
|
217 string connectionType; |
|
218 if( iniFile.KeyValue(KIniConnection, KIniSectionName, connectionType) ) |
|
219 { |
|
220 if( connectionType == KSerial ) |
|
221 { |
|
222 iConnectionType = SymbianSerial; |
|
223 ret = true; |
|
224 } |
|
225 else if( connectionType == KInfrared ) |
|
226 { |
|
227 iConnectionType = SymbianInfrared; |
|
228 ret = true; |
|
229 } |
|
230 else if( connectionType == KBluetooth ) |
|
231 { |
|
232 iConnectionType = SymbianBluetooth; |
|
233 ret = true; |
|
234 } |
|
235 else if( connectionType == KSocket ) |
|
236 { |
|
237 iConnectionType = SymbianSocket; |
|
238 ret = true; |
|
239 } |
|
240 else |
|
241 { |
|
242 iConnectionType = SymbianInvalid; |
|
243 } |
|
244 } |
|
245 else |
|
246 { |
|
247 ret = false; |
|
248 } |
|
249 |
|
250 // Retrieve either the com port or the ip address |
|
251 if( ret ) |
|
252 { |
|
253 if( iConnectionType == SymbianSerial || |
|
254 iConnectionType == SymbianInfrared || |
|
255 iConnectionType == SymbianBluetooth ) |
|
256 { |
|
257 if( !iniFile.KeyValue(KIniSerialPort, KIniSectionName, iComPort) ) |
|
258 { |
|
259 ret = false; |
|
260 } |
|
261 } |
|
262 else if( iConnectionType == SymbianSocket ) |
|
263 { |
|
264 if( !iniFile.KeyValue(KIniIPAddress, KIniSectionName, iIPAddress) ) |
|
265 { |
|
266 ret = false; |
|
267 } |
|
268 } |
|
269 } |
|
270 |
|
271 // Finally retrieve the timeout, poll interval and STAT DLL location values (all optional) |
|
272 if( ret ) |
|
273 { |
|
274 // Timeout |
|
275 int timeout = 0; |
|
276 if( iniFile.KeyValue(KTimeout, KIniSectionName, timeout) ) |
|
277 { |
|
278 if( timeout > 0 ) |
|
279 { |
|
280 iTimeout = timeout; |
|
281 } |
|
282 } |
|
283 |
|
284 // Poll Interval |
|
285 int pollInterval = 0; |
|
286 if( iniFile.KeyValue(KPoll, KIniSectionName, pollInterval) ) |
|
287 { |
|
288 if( pollInterval > 0 ) |
|
289 { |
|
290 iPollInterval = pollInterval; |
|
291 } |
|
292 } |
|
293 |
|
294 // STAT DLL Location |
|
295 string statDLLLocation; |
|
296 if( iniFile.KeyValue(KSTATLocation, KIniSectionName, statDLLLocation) ) |
|
297 { |
|
298 if( statDLLLocation.length() > 0 ) |
|
299 { |
|
300 iSTATDLLLocation.erase(); |
|
301 iSTATDLLLocation = statDLLLocation; |
|
302 } |
|
303 } |
|
304 } |
|
305 |
|
306 return ret; |
|
307 } |
|
308 |
|
309 int CSyncService::StartSyncTestCase( const CCall& aCall ) |
|
310 { |
|
311 int ret = ERR_NONE; |
|
312 |
|
313 printf( "StartSyncTestCase call\n" ); |
|
314 |
|
315 // Wait until the status is set to WAITING |
|
316 // ie. The next test case is waiting |
|
317 // Make the RetrieveSyncTestCaseStatus call |
|
318 |
|
319 // Poll for the TEF Sync Status |
|
320 bool tefContinue = false; |
|
321 int sendRawOK = (iptrSendRawCommand)( iConnection, |
|
322 KRetrieveSyncTestCaseStatus, |
|
323 NULL); |
|
324 |
|
325 TSyncStatus TEFstatus = ETEFSyncUnknown; |
|
326 if( sendRawOK == ITS_OK ) |
|
327 { |
|
328 const char* result = (iptrGetTEFSharedData)( iConnection ); |
|
329 if( result != NULL ) |
|
330 { |
|
331 TEFstatus = (TSyncStatus)atoi( result ); |
|
332 if( TEFstatus == ETEFSyncWaiting ) |
|
333 { |
|
334 tefContinue = true; |
|
335 } |
|
336 } |
|
337 } |
|
338 |
|
339 // Poll for the test case status |
|
340 time_t end_time, cur_time; |
|
341 time(&cur_time); |
|
342 end_time = cur_time + iTimeout; |
|
343 while( !tefContinue && end_time-cur_time > 0 ) |
|
344 { |
|
345 // Delay before next attempt |
|
346 Sleep( iPollInterval * 1000 ); |
|
347 |
|
348 // Make the RetrieveSyncTestCaseStatus call (poll) |
|
349 sendRawOK = (iptrSendRawCommand)( iConnection, |
|
350 KRetrieveSyncTestCaseStatus, |
|
351 NULL); |
|
352 if( sendRawOK == ITS_OK ) |
|
353 { |
|
354 const char* result = (iptrGetTEFSharedData)( iConnection ); |
|
355 if( result != NULL ) |
|
356 { |
|
357 TEFstatus = (TSyncStatus)atoi( result ); |
|
358 if( TEFstatus == ETEFSyncWaiting ) |
|
359 { |
|
360 tefContinue = true; |
|
361 } |
|
362 } |
|
363 } |
|
364 |
|
365 // Update the current time |
|
366 time(&cur_time); |
|
367 } |
|
368 |
|
369 if( sendRawOK == ITS_OK && TEFstatus == ETEFSyncWaiting ) |
|
370 { |
|
371 // Make the StartSyncTestCase call |
|
372 int sendRawOK = (iptrSendRawCommand)( iConnection, |
|
373 KStartSyncTestCase, |
|
374 NULL); |
|
375 if( sendRawOK != ITS_OK ) |
|
376 { |
|
377 ret = ERR_STAT_START_SYNC_TEST_CASE; |
|
378 } |
|
379 } |
|
380 else |
|
381 { |
|
382 ret = ERR_STAT_RETRIEVE_SYNC_TEST_STATUS; |
|
383 } |
|
384 |
|
385 return ret; |
|
386 } |
|
387 |
|
388 int CSyncService::RetrieveSyncTestCaseResult( const CCall& aCall ) |
|
389 { |
|
390 int ret = ERR_NONE; |
|
391 |
|
392 printf( "RetrieveSyncTestCaseResult call\n" ); |
|
393 |
|
394 // Wait until the status is set to either COMPLETE or WAITING |
|
395 // ie. The sync test case has completed or the next one is waiting |
|
396 // Make the RetrieveSyncTestCaseStatus call |
|
397 |
|
398 // Poll for the TEF Sync Status |
|
399 bool tefContinue = false; |
|
400 int sendRawOK = (iptrSendRawCommand)( iConnection, |
|
401 KRetrieveSyncTestCaseStatus, |
|
402 NULL); |
|
403 |
|
404 TSyncStatus TEFstatus = ETEFSyncUnknown; |
|
405 if( sendRawOK == ITS_OK ) |
|
406 { |
|
407 const char* result = (iptrGetTEFSharedData)( iConnection ); |
|
408 if( result != NULL ) |
|
409 { |
|
410 TEFstatus = (TSyncStatus)atoi( result ); |
|
411 if( TEFstatus == ETEFRetrieveResult ) |
|
412 { |
|
413 tefContinue = true; |
|
414 } |
|
415 } |
|
416 } |
|
417 |
|
418 // Poll for the test case status |
|
419 time_t end_time, cur_time; |
|
420 time(&cur_time); |
|
421 end_time = cur_time + iTimeout; |
|
422 while( !tefContinue && (end_time-cur_time > 0) ) |
|
423 { |
|
424 // Delay before next attempt |
|
425 Sleep( iPollInterval * 1000 ); |
|
426 |
|
427 // Make the RetrieveSyncTestCaseStatus call (poll) |
|
428 sendRawOK = (iptrSendRawCommand)( iConnection, |
|
429 KRetrieveSyncTestCaseStatus, |
|
430 NULL); |
|
431 if( sendRawOK == ITS_OK ) |
|
432 { |
|
433 const char* result = (iptrGetTEFSharedData)( iConnection ); |
|
434 if( result != NULL ) |
|
435 { |
|
436 TEFstatus = (TSyncStatus)atoi( result ); |
|
437 if( TEFstatus == ETEFRetrieveResult ) |
|
438 { |
|
439 tefContinue = true; |
|
440 } |
|
441 } |
|
442 } |
|
443 |
|
444 // Update the current time |
|
445 time(&cur_time); |
|
446 } |
|
447 |
|
448 if( sendRawOK == ITS_OK && TEFstatus == ETEFRetrieveResult ) |
|
449 { |
|
450 // Make the RetrieveSyncTestCaseResult call |
|
451 int sendRawOK = (iptrSendRawCommand)( iConnection, |
|
452 KRetrieveSyncTestCaseResult, |
|
453 NULL); |
|
454 |
|
455 // Check what was returned from TEF |
|
456 if( sendRawOK == ITS_OK ) |
|
457 { |
|
458 // Now retrieve the TEF Shared data from STAT |
|
459 // In the is case the shared data stores the synchronised |
|
460 // test case result as an integer. |
|
461 // Set the ret value to equal to this. |
|
462 const char* result = (iptrGetTEFSharedData)( iConnection ); |
|
463 int TEFret = EInconclusive; |
|
464 if( result != NULL ) |
|
465 { |
|
466 TEFret = atoi( result ); |
|
467 } |
|
468 |
|
469 // Map the code onto the return value |
|
470 switch( TEFret ) |
|
471 { |
|
472 case EPass: |
|
473 case EFail: |
|
474 case EInconclusive: |
|
475 case ETestSuiteError: |
|
476 case EAbort: |
|
477 case EIgnore: |
|
478 { |
|
479 ret = TEFret; |
|
480 } |
|
481 break; |
|
482 default: |
|
483 { |
|
484 ret = EFail; |
|
485 } |
|
486 break; |
|
487 } |
|
488 |
|
489 // Update the status so TEF can continue |
|
490 int sendRawOK = (iptrSendRawCommand)( iConnection, |
|
491 KStartSyncComplete, |
|
492 NULL); |
|
493 if( sendRawOK != ITS_OK ) |
|
494 { |
|
495 ret = ERR_STAT_START_SYNC_TEST_CASE; |
|
496 } |
|
497 } |
|
498 else |
|
499 { |
|
500 ret = ERR_STAT_RETRIEVE_SYNC_TEST_RESULT; |
|
501 } |
|
502 } |
|
503 else |
|
504 { |
|
505 ret = ERR_STAT_RETRIEVE_SYNC_TEST_STATUS; |
|
506 } |
|
507 |
|
508 return ret; |
|
509 } |
|
510 |
|
511 int CSyncService::SetSharedData( const CCall& aCall ) |
|
512 { |
|
513 int ret = ERR_NONE; |
|
514 |
|
515 #ifdef _DEBUG |
|
516 printf( "SetSharedData call\n" ); |
|
517 #endif |
|
518 |
|
519 int numParams = 0; |
|
520 bool callRet = aCall.Params( numParams ); |
|
521 if( numParams == 2 ) |
|
522 { |
|
523 string paramName; |
|
524 string sharedDataName; |
|
525 string paramValue; |
|
526 string sharedDataValue; |
|
527 |
|
528 // Retrieve the shared data name |
|
529 if( aCall.Name(0, paramName) && aCall.Value(0, sharedDataName) ) |
|
530 { |
|
531 if( paramName != KSharedDataName ) |
|
532 { |
|
533 ret = ERR_INVALIDARG; |
|
534 } |
|
535 } |
|
536 else |
|
537 { |
|
538 ret = ERR_INVALIDARG; |
|
539 } |
|
540 |
|
541 // Retrieve the shared data value |
|
542 if( ret == 0 ) |
|
543 { |
|
544 if( aCall.Name(1, paramValue) && aCall.Value(1, sharedDataValue) ) |
|
545 { |
|
546 if( paramValue != KSharedDataValue ) |
|
547 { |
|
548 ret = ERR_INVALIDARG; |
|
549 } |
|
550 } |
|
551 else |
|
552 { |
|
553 ret = ERR_INVALIDARG; |
|
554 } |
|
555 } |
|
556 |
|
557 // Send the shared data (name and value) via STAT |
|
558 if( ret == 0 ) |
|
559 { |
|
560 if( sharedDataValue.size() > 0 ) |
|
561 { |
|
562 // Construct the call |
|
563 string sharedDataCall; |
|
564 sharedDataCall += KSetSharedData; |
|
565 sharedDataCall += sharedDataName; |
|
566 sharedDataCall += KComma; |
|
567 sharedDataCall += sharedDataValue; |
|
568 sharedDataCall += KCommandTerminate; |
|
569 |
|
570 // Make the SetSharedData call |
|
571 int sendRawOK = (iptrSendRawCommand)( iConnection, |
|
572 sharedDataCall.c_str(), |
|
573 NULL); |
|
574 if( sendRawOK != ITS_OK ) |
|
575 { |
|
576 ret = ERR_STAT_SET_SHARED_DATA; |
|
577 } |
|
578 } |
|
579 else |
|
580 { |
|
581 ret = ERR_INVALIDARG; |
|
582 } |
|
583 } |
|
584 } |
|
585 else |
|
586 { |
|
587 ret = ERR_INVALIDARG; |
|
588 } |
|
589 |
|
590 return ret; |
|
591 } |