|
1 /* |
|
2 * Copyright (c) 2007-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 * |
|
16 */ |
|
17 |
|
18 #include "tbatterycharging.h" |
|
19 #include "musbdevicenotify.h" |
|
20 |
|
21 #include <e32svr.h> |
|
22 #include <e32base.h> |
|
23 #include <e32std.h> |
|
24 #include <usbman.rsg> |
|
25 #include <f32file.h> |
|
26 #include <barsc.h> |
|
27 #include <barsread.h> |
|
28 #include <bautils.h> |
|
29 #include "UsbUtils.h" |
|
30 |
|
31 |
|
32 #include"tbatterychargingdefinitions.h" |
|
33 |
|
34 |
|
35 LOCAL_C void ConsoleMainL(); |
|
36 |
|
37 GLDEF_C TInt E32Main() |
|
38 { |
|
39 __UHEAP_MARK; |
|
40 CTrapCleanup* cleanup=CTrapCleanup::New(); // get clean-up stack |
|
41 |
|
42 TRAPD(error, ConsoleMainL() ); |
|
43 |
|
44 __ASSERT_ALWAYS(!error,User::Panic(_L("UsbChargingTest"), error)); |
|
45 delete cleanup; // destroy clean-up stack |
|
46 __UHEAP_MARKEND; |
|
47 return KErrNone; |
|
48 } |
|
49 |
|
50 void ConsoleMainL() |
|
51 { |
|
52 CActiveScheduler* myScheduler = new(ELeave) CActiveScheduler; |
|
53 CleanupStack::PushL(myScheduler); |
|
54 CActiveScheduler::Install(myScheduler); |
|
55 |
|
56 CDummyUsbDevice* device = CDummyUsbDevice::NewL(); |
|
57 CleanupStack::PushL(device); |
|
58 device->DoTestsL(); |
|
59 CActiveScheduler::Start(); |
|
60 |
|
61 CleanupStack::PopAndDestroy(2, myScheduler); |
|
62 } |
|
63 |
|
64 CDummyUsbDevice* CDummyUsbDevice::NewL() |
|
65 /** |
|
66 * Constructs a CDummyUsbDevice object. |
|
67 * |
|
68 * @return A new CDummyUsbDevice object |
|
69 */ |
|
70 { |
|
71 CDummyUsbDevice* r = new (ELeave) CDummyUsbDevice(); |
|
72 CleanupStack::PushL(r); |
|
73 r->ConstructL(); |
|
74 CleanupStack::Pop(); |
|
75 return r; |
|
76 } |
|
77 |
|
78 CDummyUsbDevice::~CDummyUsbDevice() |
|
79 /** |
|
80 * Destructor. |
|
81 */ |
|
82 { |
|
83 // Cancel any outstanding asynchronous operation. |
|
84 Cancel(); |
|
85 iTimer.Close(); |
|
86 //delete iRepository; |
|
87 iExtensionPlugins.ResetAndDestroy(); |
|
88 |
|
89 if(iEcom) |
|
90 iEcom->Close(); |
|
91 REComSession::FinalClose(); |
|
92 |
|
93 // Free any memory allocated to the list of observers. Note that |
|
94 // we don't want to call ResetAndDestroy, because we don't own |
|
95 // the observers themselves. |
|
96 iObservers.Reset(); |
|
97 delete iText; |
|
98 iTest.Close(); |
|
99 |
|
100 iProperty.Close(); |
|
101 iPropertyWriteToRepositoryAck.Close(); |
|
102 iPropertyReadChargingCurrentAck.Close(); |
|
103 |
|
104 } |
|
105 |
|
106 CDummyUsbDevice::CDummyUsbDevice() |
|
107 : CActive(EPriorityStandard), iTest(_L("Usb Charging Plugin Test")), iPtr(0,200), iLine(0,200) |
|
108 /** |
|
109 * Constructor. |
|
110 */ |
|
111 { |
|
112 CActiveScheduler::Add(this); |
|
113 } |
|
114 |
|
115 void CDummyUsbDevice::ConstructL() |
|
116 /** |
|
117 * Performs 2nd phase construction of the USB device. |
|
118 */ |
|
119 { |
|
120 iEcom = &(REComSession::OpenL()); |
|
121 |
|
122 InstantiateExtensionPluginsL(); |
|
123 |
|
124 if (iExtensionPlugins.Count() != 1) |
|
125 { |
|
126 User::Panic(KUsbChargingTestPanic, EUsbChargingTestPanicIncorrectPlugin); |
|
127 } |
|
128 |
|
129 iPlugin = iExtensionPlugins[0]; |
|
130 |
|
131 iDummyLdd.Initialise(); |
|
132 //iRepository = CRepository::NewL(KUsbBatteryChargingCentralRepositoryUid); |
|
133 User::LeaveIfError(iTimer.CreateLocal()); |
|
134 |
|
135 DefinePropertyL(KBattChargWriteRepositoryUid, KBattChargWriteRepositoryKey,RProperty::EInt); |
|
136 DefinePropertyL(KBattChargReadPropertyCurrentUid,KBattChargReadCurrentChargingKey,RProperty::EInt); |
|
137 |
|
138 User::LeaveIfError(iPropertyWriteToRepositoryAck.Attach(TUid::Uid(KBattChargWriteRepositoryUid), KBattChargWriteRepositoryAckKey)); |
|
139 User::LeaveIfError(iPropertyReadChargingCurrentAck.Attach(TUid::Uid(KBattChargReadPropertyCurrentUid), KBattChargReadCurrentChargingAckKey)); |
|
140 |
|
141 User::LeaveIfError(StartPropertyBatteryCharging()); |
|
142 |
|
143 } |
|
144 |
|
145 void CDummyUsbDevice::DefinePropertyL(const TInt32 aCategory, TUint aKey,RProperty::TType eType) |
|
146 { |
|
147 |
|
148 _LIT_SECURITY_POLICY_PASS(KAlwaysPass); |
|
149 |
|
150 TInt err = iProperty.Define(TUid::Uid(aCategory), |
|
151 aKey, |
|
152 eType, |
|
153 KAlwaysPass, |
|
154 KAlwaysPass |
|
155 ); |
|
156 if ( err != KErrAlreadyExists ) |
|
157 { |
|
158 User::LeaveIfError(err); |
|
159 } |
|
160 } |
|
161 |
|
162 |
|
163 |
|
164 void CDummyUsbDevice::InstantiateExtensionPluginsL() |
|
165 { |
|
166 const TUid KUidExtensionPluginInterface = TUid::Uid(KUsbmanExtensionPluginInterfaceUid); |
|
167 RImplInfoPtrArray implementations; |
|
168 const TEComResolverParams noResolverParams; |
|
169 REComSession::ListImplementationsL(KUidExtensionPluginInterface, noResolverParams, KRomOnlyResolverUid, implementations); |
|
170 CleanupResetAndDestroyPushL(implementations); |
|
171 |
|
172 for (TInt i=0; i<implementations.Count(); i++) |
|
173 { |
|
174 const TUid KTestPluginUid = {0x1020DEA8}; |
|
175 if (implementations[i]->ImplementationUid() == KTestPluginUid) |
|
176 { |
|
177 CUsbmanExtensionPlugin* plugin = CUsbmanExtensionPlugin::NewL(implementations[i]->ImplementationUid(), *this); |
|
178 CleanupStack::PushL(plugin); |
|
179 // there will most likely be two plugins - the standard one, and the test one (which |
|
180 // is an extension of the standard one, to include the interface |
|
181 // MUsbBatteryChargingTestPluginInterface2. So check, and only keep the test one: |
|
182 MUsbBatteryChargingTestPluginInterface2* pluginIf |
|
183 = reinterpret_cast<MUsbBatteryChargingTestPluginInterface2*>( |
|
184 plugin->GetInterface(KUidUsbBatteryChargingTestPluginInterface2)); |
|
185 |
|
186 if (pluginIf) |
|
187 { |
|
188 iExtensionPlugins.AppendL(plugin); // transfer ownership to iExtensionPlugins |
|
189 CleanupStack::Pop(plugin); |
|
190 } |
|
191 else |
|
192 { // destroy it - it's the standard plugin. |
|
193 CleanupStack::PopAndDestroy(plugin); |
|
194 iObservers.Remove(iObservers.Count() - 1); |
|
195 } |
|
196 } |
|
197 } |
|
198 CleanupStack::PopAndDestroy(&implementations); |
|
199 } |
|
200 |
|
201 void CDummyUsbDevice::RegisterObserverL(MUsbDeviceNotify& aObserver) |
|
202 /** |
|
203 * Register an observer of the device. |
|
204 * Presently, the device supports watching state. |
|
205 * |
|
206 * @param aObserver New Observer of the device |
|
207 */ |
|
208 { |
|
209 User::LeaveIfError(iObservers.Append(&aObserver)); |
|
210 } |
|
211 |
|
212 |
|
213 void CDummyUsbDevice::DeRegisterObserver(MUsbDeviceNotify& aObserver) |
|
214 /** |
|
215 * De-registers an existing device observer. |
|
216 * |
|
217 * @param aObserver The existing device observer to be de-registered |
|
218 */ |
|
219 { |
|
220 TInt index = iObservers.Find(&aObserver); |
|
221 |
|
222 if (index >= 0) |
|
223 iObservers.Remove(index); |
|
224 } |
|
225 |
|
226 void CDummyUsbDevice::RunL() |
|
227 { |
|
228 DoCheck(); |
|
229 if (GetNextLine() < 0) |
|
230 { |
|
231 iTest.End(); |
|
232 iTest.Getch(); |
|
233 CActiveScheduler::Stop(); |
|
234 } |
|
235 else |
|
236 { |
|
237 iLineNumber++; |
|
238 iTest.Next(_L("")); |
|
239 InterpretLine(); |
|
240 DoCommand(); |
|
241 DoAsyncOp(); |
|
242 } |
|
243 } |
|
244 |
|
245 void CDummyUsbDevice::DoCancel() |
|
246 { |
|
247 iTimer.Cancel(); |
|
248 } |
|
249 |
|
250 TInt CDummyUsbDevice::RunError(TInt /*aError*/) |
|
251 { |
|
252 |
|
253 return KErrNone; |
|
254 } |
|
255 |
|
256 RDevUsbcClient& CDummyUsbDevice::MuepoDoDevUsbcClient() |
|
257 /** |
|
258 * Inherited from MUsbmanExtensionPluginObserver - Function used by plugins to |
|
259 * retrieve our handle to the LDD |
|
260 * |
|
261 * @return The LDD handle |
|
262 */ |
|
263 { |
|
264 return iDummyLdd; |
|
265 } |
|
266 |
|
267 void CDummyUsbDevice::MuepoDoRegisterStateObserverL(MUsbDeviceNotify& aObserver) |
|
268 /** |
|
269 * Inherited from MUsbmanExtensionPluginObserver - Function used by plugins to |
|
270 * register themselves for notifications of device/service state changes. |
|
271 * |
|
272 * @param aObserver New Observer of the device |
|
273 */ |
|
274 { |
|
275 RegisterObserverL(aObserver); |
|
276 } |
|
277 |
|
278 void CDummyUsbDevice::UpdatePluginInfo() |
|
279 { |
|
280 // we can assume our plugin does support this interface.... |
|
281 reinterpret_cast<MUsbBatteryChargingTestPluginInterface2*>(iPlugin->GetInterface(KUidUsbBatteryChargingTestPluginInterface2))->GetPluginInfo(iInfo); |
|
282 } |
|
283 |
|
284 void CDummyUsbDevice::DoTestsL() |
|
285 { |
|
286 iTest.SetLogged(ETrue); |
|
287 iTest.Title(); |
|
288 OpenFileL(); |
|
289 TInt length = GetNextLine(); |
|
290 if (length <= 0) |
|
291 { |
|
292 User::Panic(KUsbChargingTestPanic, EUsbChargingTestPanicBadInputData); |
|
293 } |
|
294 iLineNumber = 1; |
|
295 iTest.Start(_L("test")); |
|
296 InterpretLine(); |
|
297 DoCommand(); |
|
298 DoAsyncOp(); |
|
299 } |
|
300 |
|
301 void CDummyUsbDevice::InterpretLine() |
|
302 { |
|
303 TLex8 lex(iLine); |
|
304 lex.SkipCharacters(); |
|
305 iCommand = GetCommand(iLine.Left(lex.Offset())); |
|
306 lex.SkipSpace(); |
|
307 lex.Val(iCommandValue); |
|
308 lex.SkipSpace(); |
|
309 TInt pos = lex.Offset(); |
|
310 lex.SkipCharacters(); |
|
311 iAsyncOp = GetAsyncOp(iLine.Mid(pos,lex.Offset()-pos)); |
|
312 lex.SkipSpace(); |
|
313 lex.Val(iAsyncOpValue); |
|
314 lex.SkipSpace(); |
|
315 pos = lex.Offset(); |
|
316 lex.SkipCharacters(); |
|
317 iCheck = GetCheck(iLine.Mid(pos,lex.Offset()-pos)); |
|
318 lex.SkipSpace(); |
|
319 lex.Val(iCheckValue); |
|
320 } |
|
321 |
|
322 void CDummyUsbDevice::OpenFileL() |
|
323 { |
|
324 RFs fs; |
|
325 User::LeaveIfError(fs.Connect()); |
|
326 CleanupClosePushL(fs); |
|
327 |
|
328 TFindFile ff(fs); |
|
329 User::LeaveIfError(ff.FindByDir(_L("\\system\\data\\t_charging.txt"),KNullDesC)); |
|
330 |
|
331 RFile file; |
|
332 TInt size; |
|
333 User::LeaveIfError(file.Open(fs,ff.File(),EFileStreamText|EFileRead|EFileShareReadersOnly)); |
|
334 CleanupClosePushL(file); |
|
335 |
|
336 User::LeaveIfError(file.Size(size)); |
|
337 |
|
338 iText = REINTERPRET_CAST(TText8*, User::AllocL(size)); |
|
339 iPtr.Set(iText, size/sizeof(TText8), size/sizeof(TText8)); |
|
340 TPtr8 dest(REINTERPRET_CAST(TUint8*,iText), 0, size); |
|
341 User::LeaveIfError(file.Read(dest)); |
|
342 |
|
343 CleanupStack::PopAndDestroy(); // file |
|
344 CleanupStack::PopAndDestroy(); // fs |
|
345 } |
|
346 |
|
347 TInt CDummyUsbDevice::GetNextLine() |
|
348 { |
|
349 TInt newLineOffset = (iPtr.Mid(iFileOffset)).Locate(13);//Find(_L("\r\n")); |
|
350 if (newLineOffset < 0) |
|
351 { |
|
352 return newLineOffset; |
|
353 } |
|
354 if (newLineOffset == 0) |
|
355 { |
|
356 iFileOffset += 2; |
|
357 return GetNextLine(); |
|
358 } |
|
359 iLine.Set(iPtr.MidTPtr(iFileOffset, newLineOffset)); |
|
360 iFileOffset += (newLineOffset + 2); |
|
361 if (iLine.Find(_L8("//")) == 0) // i.e. line begins with "//" |
|
362 { |
|
363 return GetNextLine(); |
|
364 } |
|
365 if (iLine.Find(_L8("**")) == 0) // line begins with **, so display it |
|
366 { |
|
367 TBuf<100> buf; // max length 100 for test messages |
|
368 buf.Copy(iLine); |
|
369 iTest.Printf(_L("\n%S\n\n"),&buf); |
|
370 return GetNextLine(); |
|
371 }; |
|
372 return newLineOffset; |
|
373 } |
|
374 |
|
375 TInt CDummyUsbDevice::GetCommand(const TDesC8& aDes) |
|
376 { |
|
377 if (aDes.MatchF(_L8("none")) != KErrNotFound) |
|
378 return EUsbChargingTestCommandNone; |
|
379 if (aDes.MatchF(_L8("devicestate")) != KErrNotFound) |
|
380 return EUsbChargingTestCommandDeviceState; |
|
381 if (aDes.MatchF(_L8("usersetting")) != KErrNotFound) |
|
382 return EUsbChargingTestCommandUserSetting; |
|
383 User::Panic(KUsbChargingTestPanic, EUsbChargingTestPanicBadInputData); |
|
384 return -1; |
|
385 } |
|
386 |
|
387 TInt CDummyUsbDevice::GetAsyncOp(const TDesC8& aDes) |
|
388 { |
|
389 if (aDes.MatchF(_L8("none")) != KErrNotFound) |
|
390 return EUsbChargingTestAsyncOpNone; |
|
391 if (aDes.MatchF(_L8("delay")) != KErrNotFound) |
|
392 return EUsbChargingTestAsyncOpDelay; |
|
393 User::Panic(KUsbChargingTestPanic, EUsbChargingTestPanicBadInputData); |
|
394 return -1; |
|
395 } |
|
396 |
|
397 TInt CDummyUsbDevice::GetCheck(const TDesC8& aDes) |
|
398 { |
|
399 if (aDes.MatchF(_L8("none")) != KErrNotFound) |
|
400 return EUsbChargingTestCheckNone; |
|
401 if (aDes.MatchF(_L8("pluginstate")) != KErrNotFound) |
|
402 return EUsbChargingTestCheckPluginState; |
|
403 if (aDes.MatchF(_L8("milliamps")) != KErrNotFound) |
|
404 return EUsbChargingTestCheckMilliAmps; |
|
405 if (aDes.MatchF(_L8("charging")) != KErrNotFound) |
|
406 return EUsbChargingTestCheckCharging; |
|
407 User::Panic(KUsbChargingTestPanic, EUsbChargingTestPanicBadInputData); |
|
408 return -1; |
|
409 } |
|
410 |
|
411 void CDummyUsbDevice::DoCommand() |
|
412 { |
|
413 switch (iCommand) |
|
414 { |
|
415 case EUsbChargingTestCommandNone: |
|
416 { |
|
417 // do nothing |
|
418 } |
|
419 break; |
|
420 case EUsbChargingTestCommandDeviceState: |
|
421 { |
|
422 iObservers[0]->UsbDeviceStateChange(KErrNone, iDeviceState, TUsbDeviceState(iCommandValue)); |
|
423 iDeviceState = TUsbDeviceState(iCommandValue); |
|
424 } |
|
425 break; |
|
426 case EUsbChargingTestCommandUserSetting: |
|
427 { |
|
428 TInt err = WriteToRepositoryProperty(iCommandValue); |
|
429 |
|
430 //TInt err = iRepository->Set(KUsbBatteryChargingKeyEnabledUserSetting, iCommandValue); |
|
431 iTest(err == KErrNone); |
|
432 } |
|
433 break; |
|
434 default: |
|
435 User::Panic(KUsbChargingTestPanic, EUsbChargingTestPanicBadCommand); |
|
436 } |
|
437 } |
|
438 |
|
439 void CDummyUsbDevice::DoAsyncOp() |
|
440 { |
|
441 switch (iAsyncOp) |
|
442 { |
|
443 case EUsbChargingTestAsyncOpNone: |
|
444 { |
|
445 SetActive(); |
|
446 TRequestStatus* status = &iStatus; |
|
447 User::RequestComplete(status, KErrNone); |
|
448 } |
|
449 break; |
|
450 case EUsbChargingTestAsyncOpDelay: |
|
451 { |
|
452 iTimer.After(iStatus, TTimeIntervalMicroSeconds32(iAsyncOpValue)); |
|
453 SetActive(); |
|
454 } |
|
455 break; |
|
456 default: |
|
457 User::Panic(KUsbChargingTestPanic, EUsbChargingTestPanicBadAsyncOp); |
|
458 } |
|
459 } |
|
460 |
|
461 void CDummyUsbDevice::DoCheck() |
|
462 { |
|
463 UpdatePluginInfo(); |
|
464 switch (iCheck) |
|
465 { |
|
466 case EUsbChargingTestCheckNone: |
|
467 { |
|
468 // do nothing |
|
469 } |
|
470 break; |
|
471 case EUsbChargingTestCheckPluginState: |
|
472 { |
|
473 iTest(iInfo.iPluginState == iCheckValue); |
|
474 } |
|
475 break; |
|
476 case EUsbChargingTestCheckMilliAmps: |
|
477 { |
|
478 iTest(iInfo.iRequestedCurrentValue == iCheckValue); |
|
479 } |
|
480 break; |
|
481 case EUsbChargingTestCheckCharging: |
|
482 { |
|
483 TInt current; |
|
484 TInt err = GetChargingCurrentFromProperty(current); |
|
485 |
|
486 //TInt err = RProperty::Get(KPropertyUidUsbBatteryChargingCategory, |
|
487 // KPropertyUidUsbBatteryChargingChargingCurrent, current); |
|
488 iTest(err == KErrNone); |
|
489 iTest(current == iCheckValue); |
|
490 } |
|
491 break; |
|
492 default: |
|
493 User::Panic(KUsbChargingTestPanic, EUsbChargingTestPanicBadCheck); |
|
494 } |
|
495 } |
|
496 |
|
497 TInt CDummyUsbDevice::GetChargingCurrentFromProperty(TInt &aCurrent) |
|
498 { |
|
499 |
|
500 TRequestStatus stat; |
|
501 iPropertyReadChargingCurrentAck.Subscribe(stat); |
|
502 |
|
503 TInt err = iProperty.Set(TUid::Uid(KBattChargReadPropertyCurrentUid), |
|
504 KBattChargReadCurrentChargingKey, |
|
505 1); |
|
506 ASSERT(!err); |
|
507 User::WaitForRequest(stat); |
|
508 |
|
509 TBufC8<50> value; |
|
510 TPtr8 myPtr(value.Des()); |
|
511 TInt error = iPropertyReadChargingCurrentAck.Get(myPtr); |
|
512 ASSERT(!error); |
|
513 |
|
514 TDataFromPropBattChargToTBatteryCharging received; |
|
515 TPckg<TDataFromPropBattChargToTBatteryCharging>tmp(received); |
|
516 tmp.Copy(value); |
|
517 aCurrent = received.iCurrent; |
|
518 return received.iError; |
|
519 |
|
520 } |
|
521 |
|
522 TInt CDummyUsbDevice::WriteToRepositoryProperty(TInt iCommandValue) |
|
523 { |
|
524 TRequestStatus stat; |
|
525 iPropertyWriteToRepositoryAck.Subscribe(stat); |
|
526 |
|
527 TInt err = iProperty.Set(TUid::Uid(KBattChargWriteRepositoryUid), |
|
528 KBattChargWriteRepositoryKey, |
|
529 iCommandValue); |
|
530 ASSERT(!err); |
|
531 User::WaitForRequest(stat); |
|
532 TInt value; |
|
533 err = iPropertyWriteToRepositoryAck.Get(value); |
|
534 ASSERT(!err); |
|
535 return value; |
|
536 } |
|
537 |
|
538 TInt CDummyUsbDevice::StartPropertyBatteryCharging() |
|
539 { |
|
540 const TUidType serverUid(KNullUid, KNullUid, KBatteryChargingTUid); |
|
541 RProcess server; |
|
542 TInt err = server.Create(KBattChargingImg, KNullDesC, serverUid); |
|
543 if ( err != KErrNone ) |
|
544 { |
|
545 return err; |
|
546 } |
|
547 TRequestStatus stat; |
|
548 server.Rendezvous(stat); |
|
549 |
|
550 if ( stat != KRequestPending ) |
|
551 { |
|
552 server.Kill(0); // abort startup |
|
553 } |
|
554 else |
|
555 { |
|
556 server.Resume(); // logon OK - start the server |
|
557 } |
|
558 |
|
559 User::WaitForRequest(stat); // wait for start or death |
|
560 |
|
561 // we can't use the 'exit reason' if the server panicked as this |
|
562 // is the panic 'reason' and may be '0' which cannot be distinguished |
|
563 // from KErrNone |
|
564 |
|
565 err = (server.ExitType() == EExitPanic) ? KErrServerTerminated : stat.Int(); |
|
566 |
|
567 server.Close(); |
|
568 |
|
569 return err; |
|
570 |
|
571 } |
|
572 |
|
573 |