|
1 // Copyright (c) 2006-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 // |
|
15 |
|
16 /** |
|
17 @file |
|
18 @internalComponent |
|
19 */ |
|
20 |
|
21 #include "ControllerInitialisationPluginImpl.h" |
|
22 #include "ControllerInitialisationCmndParser.h" |
|
23 #include "tiinitialisorutils.h" |
|
24 |
|
25 #include <bluetooth/hci/vendordebugcommand.h> |
|
26 #include <bluetooth/hci/controllerinitialisationobserver.h> |
|
27 #include <bluetooth/hcicommandqueue.h> |
|
28 |
|
29 #include <bluetooth/hci/readlocalversioninfocommand.h> |
|
30 |
|
31 #include <bluetooth/hci/commandcompleteevent.h> |
|
32 #include <bluetooth/hci/readlocalversioninfocompleteevent.h> |
|
33 #include <bluetooth/hci/vendordebugcompleteevent.h> |
|
34 |
|
35 #include <bluetooth/hci/hctlconfiginterface.h> |
|
36 #include <bluetooth/hci/corehci.h> |
|
37 |
|
38 #include <bluetooth/logger.h> |
|
39 |
|
40 #include <es_sock.h> |
|
41 |
|
42 #ifdef __FLOG_ACTIVE |
|
43 _LIT8(KLogComponent, LOG_COMPONENT_INITIALISOR_TI); |
|
44 #endif |
|
45 |
|
46 _LIT(KScriptPath, "z:\\private\\101f7989\\Bluetooth\\"); |
|
47 _LIT(KScriptPathFileFormat, "%Stiinit_%d.%d.%d.bts"); |
|
48 |
|
49 const TUint16 KHciVSUpdateUartHCIBaudRate = 0xFF36; |
|
50 const TUint16 KHciVSEnableSleepMode = 0xFF0C; |
|
51 const TUint16 KHciVSSleepModeConfig = 0xFD0C; // BRF6300 version |
|
52 const TUint16 KHciVSSetBDAddr = 0xFC06; |
|
53 |
|
54 const TUint16 KProjectTypeMask = 0x7C00; // mask needed to extract the project type |
|
55 const TUint16 KProjectTypeShift = 10; // shift needed to extract the project type |
|
56 const TUint16 KMinorVersionMask = 0x007F; |
|
57 const TUint16 KMajorVersionMask = 0x0380; // mask needed to extract the major version |
|
58 const TUint16 KMajorVersionShift = 7; // shift needed to extract the major version |
|
59 const TUint16 KBit15Mask = 0x8000; |
|
60 const TUint16 KBit15Shift = 12; // shift needed to move bit15 to bit3 |
|
61 // (it will be pre-pended as an extra hi-bit for |
|
62 // the 3-bit major version number) |
|
63 |
|
64 |
|
65 /*static*/ CControllerInitialisationPluginImpl* CControllerInitialisationPluginImpl::NewL() |
|
66 { |
|
67 LOG_STATIC_FUNC |
|
68 |
|
69 CControllerInitialisationPluginImpl* self = new (ELeave) CControllerInitialisationPluginImpl(); |
|
70 CleanupStack::PushL(self); |
|
71 self->ConstructL(); |
|
72 CleanupStack::Pop(self); |
|
73 return self; |
|
74 } |
|
75 |
|
76 void CControllerInitialisationPluginImpl::ConstructL() |
|
77 { |
|
78 LOG_FUNC |
|
79 |
|
80 // Add Async Callbacks |
|
81 TCallBack preResetCallBack(AsyncCallBackForPreReset, this); |
|
82 iAsyncCallBackForPreReset = new (ELeave)CAsyncCallBack(preResetCallBack, CActive::EPriorityStandard); |
|
83 TCallBack postResetCallBack(AsyncCallBackForPostReset, this); |
|
84 iAsyncCallBackForPostReset = new (ELeave)CAsyncCallBack(postResetCallBack, CActive::EPriorityStandard); |
|
85 |
|
86 iSleepDisableTimer = CSleepDisableTimer::NewL(*this); |
|
87 } |
|
88 |
|
89 CControllerInitialisationPluginImpl::CControllerInitialisationPluginImpl() |
|
90 : iInitState(EIdle) |
|
91 { |
|
92 LOG_FUNC |
|
93 } |
|
94 |
|
95 CControllerInitialisationPluginImpl::~CControllerInitialisationPluginImpl() |
|
96 { |
|
97 LOG_FUNC |
|
98 |
|
99 delete iCommandParser; |
|
100 // Delete async CallBacks. If running, these should be cancelled by the |
|
101 // d'tor of CAsyncOneShot. |
|
102 delete iAsyncCallBackForPreReset; |
|
103 delete iAsyncCallBackForPostReset; |
|
104 delete iSleepDisableTimer; |
|
105 } |
|
106 |
|
107 |
|
108 /*virtual*/ TAny* CControllerInitialisationPluginImpl::Interface(TUid aUid) |
|
109 { |
|
110 LOG_FUNC |
|
111 |
|
112 TAny* ret = NULL; |
|
113 switch(aUid.iUid) |
|
114 { |
|
115 case KControllerInitialisationInterfaceUid: |
|
116 ret = reinterpret_cast<TAny*>(static_cast<MControllerInitialisationInterface*>(this)); |
|
117 break; |
|
118 |
|
119 default: |
|
120 break; |
|
121 }; |
|
122 return ret; |
|
123 } |
|
124 |
|
125 // Static async CallBack methods. |
|
126 /*static*/ TInt CControllerInitialisationPluginImpl::AsyncCallBackForPreReset(TAny* aInitPlugin) |
|
127 { |
|
128 LOG_STATIC_FUNC |
|
129 |
|
130 CControllerInitialisationPluginImpl* initPlugin = static_cast<CControllerInitialisationPluginImpl*>(aInitPlugin); |
|
131 initPlugin->DoPreReset(); |
|
132 return EFalse; // Don't call back any more. |
|
133 } |
|
134 |
|
135 /*static*/ TInt CControllerInitialisationPluginImpl::AsyncCallBackForPostReset(TAny* aInitPlugin) |
|
136 { |
|
137 LOG_STATIC_FUNC |
|
138 |
|
139 CControllerInitialisationPluginImpl* initPlugin = static_cast<CControllerInitialisationPluginImpl*>(aInitPlugin); |
|
140 initPlugin->DoPostReset(); |
|
141 return EFalse; // Don't call back any more. |
|
142 } |
|
143 |
|
144 void CControllerInitialisationPluginImpl::DoPreReset() |
|
145 { |
|
146 LOG_FUNC |
|
147 |
|
148 iInitState = EIdle; |
|
149 |
|
150 // Inform stack that we have finished |
|
151 iControllerInitialisationObserver->McioPreResetCommandComplete(KErrNone); |
|
152 } |
|
153 |
|
154 void CControllerInitialisationPluginImpl::DoPostReset() |
|
155 { |
|
156 LOG_FUNC |
|
157 |
|
158 // Request local version information. |
|
159 CReadLocalVersionInfoCommand* cmd = NULL; |
|
160 TRAPD(err, cmd = CReadLocalVersionInfoCommand::NewL()); |
|
161 if(err == KErrNone) |
|
162 { |
|
163 TRAP(err, iHCICommandQueue->MhcqAddInitCommandL(cmd, *this)); |
|
164 } |
|
165 |
|
166 if(err != KErrNone) |
|
167 { |
|
168 // Inform the stack of the initialisation status. |
|
169 iControllerInitialisationObserver->McioPostResetCommandComplete(err); |
|
170 } |
|
171 iInitState = EWaitLocalDeviceInfo; |
|
172 } |
|
173 |
|
174 /*virtual*/ void CControllerInitialisationPluginImpl::MciiPreResetCommand() |
|
175 { |
|
176 LOG_FUNC |
|
177 |
|
178 __ASSERT_DEBUG(iControllerInitialisationObserver, PANIC(KTiControllerInitialisorPanic, ENullInitialisationObserver)); |
|
179 |
|
180 // Use async callback |
|
181 iAsyncCallBackForPreReset->CallBack(); |
|
182 } |
|
183 |
|
184 /*virtual*/ void CControllerInitialisationPluginImpl::MciiPostResetCommand() |
|
185 { |
|
186 LOG_FUNC |
|
187 |
|
188 __ASSERT_DEBUG(iControllerInitialisationObserver, PANIC(KTiControllerInitialisorPanic, ENullInitialisationObserver)); |
|
189 |
|
190 // Use async callback |
|
191 iAsyncCallBackForPostReset->CallBack(); |
|
192 } |
|
193 |
|
194 /*virtual*/ void CControllerInitialisationPluginImpl::MciiSetHCICommandQueue(MHCICommandQueue& aHCICommandQueue) |
|
195 { |
|
196 LOG_FUNC |
|
197 |
|
198 __ASSERT_DEBUG(iHCICommandQueue == 0, PANIC(KTiControllerInitialisorPanic, EHciCommandQueueOverwritten)); |
|
199 iHCICommandQueue = &aHCICommandQueue; |
|
200 } |
|
201 |
|
202 /*virtual*/ void CControllerInitialisationPluginImpl::MciiSetControllerInitialisationObserver(MControllerInitialisationObserver& aObserver) |
|
203 { |
|
204 LOG_FUNC |
|
205 |
|
206 __ASSERT_DEBUG(iControllerInitialisationObserver == 0, PANIC(KTiControllerInitialisorPanic, EInitialisationObserverOverwritten)); |
|
207 iControllerInitialisationObserver = &aObserver; |
|
208 } |
|
209 |
|
210 /*virtual*/ void CControllerInitialisationPluginImpl::MciiSetCoreHci(MCoreHci& aCoreHci) |
|
211 { |
|
212 LOG_FUNC |
|
213 |
|
214 __ASSERT_DEBUG(iCoreHci == 0, PANIC(KTiControllerInitialisorPanic, ECoreHciOverwritten)); |
|
215 iCoreHci = &aCoreHci; |
|
216 } |
|
217 |
|
218 void CControllerInitialisationPluginImpl::SendNextScriptFileCommandL() |
|
219 { |
|
220 LOG_FUNC |
|
221 |
|
222 // Create default Vendor command. |
|
223 CVendorDebugCommand* cmd = CVendorDebugCommand::NewL(KVendorDebugOGF); |
|
224 CleanupStack::PushL(cmd); |
|
225 LEAVEIFERRORL(iCommandParser->GetNextVendorCommand(*cmd)); |
|
226 |
|
227 // Make any command specific changes. |
|
228 switch(cmd->Opcode()) |
|
229 { |
|
230 case KHciVSUpdateUartHCIBaudRate: |
|
231 { |
|
232 iDesiredBaudRate = LittleEndian::Get32(cmd->Command().Ptr()); |
|
233 } |
|
234 break; |
|
235 |
|
236 case KHciVSSetBDAddr: |
|
237 { |
|
238 SetLocalBDAddr(cmd->Command()); |
|
239 } |
|
240 break; |
|
241 |
|
242 default: |
|
243 // Nothing to do. |
|
244 break; |
|
245 }; |
|
246 |
|
247 |
|
248 // Send the command. |
|
249 CleanupStack::Pop(); |
|
250 iHCICommandQueue->MhcqAddInitCommandL(cmd, *this); |
|
251 } |
|
252 |
|
253 void CControllerInitialisationPluginImpl::MhcqcCommandEventReceived(const THCIEventBase& aEvent, |
|
254 const CHCICommandBase* /*aRelatedCommand*/) |
|
255 { |
|
256 LOG_FUNC |
|
257 |
|
258 if (aEvent.EventCode() == ECommandCompleteEvent) |
|
259 { |
|
260 // Switch on the opcode. |
|
261 THCICommandCompleteEvent& event = THCICommandCompleteEvent::Cast(aEvent); |
|
262 switch(event.CommandOpcode()) |
|
263 { |
|
264 case KReadLocalVersionInfoOpcode: |
|
265 { |
|
266 TReadLocalVersionInfoCompleteEvent& lvEvent = TReadLocalVersionInfoCompleteEvent::Cast(event); |
|
267 HandleReadLocalVersionInfoCompleteEvent(lvEvent); |
|
268 } |
|
269 break; |
|
270 |
|
271 default: |
|
272 // Check for VS commands. |
|
273 if((event.CommandOpcode() & KVendorDebugOGF) == KVendorDebugOGF) |
|
274 { |
|
275 TVendorDebugCompleteEvent& vEvent = TVendorDebugCompleteEvent::Cast(event); |
|
276 HandleVendorSpecificCompleteEvent(vEvent); |
|
277 } |
|
278 break; |
|
279 } |
|
280 } |
|
281 } |
|
282 |
|
283 void CControllerInitialisationPluginImpl::HandleReadLocalVersionInfoCompleteEvent(const TReadLocalVersionInfoCompleteEvent& aEvent) |
|
284 { |
|
285 LOG_FUNC |
|
286 |
|
287 TInt err = KErrNone; // innocent until proved guilty |
|
288 |
|
289 if (iInitState == EWaitLocalDeviceInfo) |
|
290 { |
|
291 if (aEvent.ErrorCode() != EOK) |
|
292 { |
|
293 err = KHCIErrorBase - aEvent.ErrorCode(); |
|
294 } |
|
295 else |
|
296 { |
|
297 iSubVersion = aEvent.LMPSubversion(); |
|
298 |
|
299 // Attempt to open the script file. |
|
300 TFileName fileName; |
|
301 fileName.Format(KScriptPathFileFormat, |
|
302 &KScriptPath, |
|
303 ((iSubVersion & KProjectTypeMask) >> KProjectTypeShift), |
|
304 ((iSubVersion & KMajorVersionMask) >> KMajorVersionShift) | ((iSubVersion & KBit15Mask) >> KBit15Shift), |
|
305 (iSubVersion & KMinorVersionMask)); |
|
306 |
|
307 TRAP(err, iCommandParser = CCommandParser::NewL(fileName)); |
|
308 } |
|
309 if(err == KErrNone) |
|
310 { |
|
311 iSleepDisableTimer->Start(); |
|
312 iInitState = EWaitForSleepTimerExpiry; |
|
313 } |
|
314 else |
|
315 { |
|
316 iControllerInitialisationObserver->McioPostResetCommandComplete(err); |
|
317 iInitState = EIdle; |
|
318 } |
|
319 } |
|
320 } |
|
321 |
|
322 void CControllerInitialisationPluginImpl::HandleVendorSpecificCompleteEvent(const TVendorDebugCompleteEvent& aEvent) |
|
323 { |
|
324 LOG_FUNC |
|
325 |
|
326 switch(iInitState) |
|
327 { |
|
328 case ESendScriptCommands: |
|
329 { |
|
330 switch(aEvent.CommandOpcode()) |
|
331 { |
|
332 case KHciVSUpdateUartHCIBaudRate: |
|
333 { |
|
334 MHctlConfigInterface* configIf = static_cast<MHctlConfigInterface*>(iCoreHci->MchHctlPluginInterface(TUid::Uid(KHctlConfigInterfaceUid))); |
|
335 __ASSERT_DEBUG(configIf, PANIC(KTiControllerInitialisorPanic, EConfigInterfaceNull)); |
|
336 |
|
337 TInt err = configIf->MhciUpdateBaudRate(iDesiredBaudRate); |
|
338 if(err != KErrNone) |
|
339 { |
|
340 iControllerInitialisationObserver->McioPostResetCommandComplete(err); |
|
341 } |
|
342 } |
|
343 break; |
|
344 |
|
345 case KHciVSEnableSleepMode: |
|
346 case KHciVSSleepModeConfig: |
|
347 { |
|
348 SetSleepProtocol(EFalse); |
|
349 } |
|
350 break; |
|
351 |
|
352 default: |
|
353 break; |
|
354 }; |
|
355 |
|
356 // Send the next command. |
|
357 TRAPD(err, SendNextScriptFileCommandL()); |
|
358 // End of File is not an error that needs to be reported. |
|
359 if(err == KErrEof) |
|
360 { |
|
361 // All commands have been sent. |
|
362 iControllerInitialisationObserver->McioPostResetCommandComplete(KErrNone); |
|
363 } |
|
364 else if(err != KErrNone) |
|
365 { |
|
366 // Inform the stack of the initialisation status. |
|
367 iControllerInitialisationObserver->McioPostResetCommandComplete(err); |
|
368 } |
|
369 } |
|
370 break; |
|
371 |
|
372 case EWaitSleepDisableCompleteEvent: |
|
373 { |
|
374 TUint16 opcode = aEvent.CommandOpcode(); |
|
375 if(opcode == KHciVSEnableSleepMode || |
|
376 opcode == KHciVSSleepModeConfig) |
|
377 { |
|
378 SetSleepProtocol(EFalse); |
|
379 |
|
380 // Response received. Start sending commands from the script file. |
|
381 iInitState = ESendScriptCommands; |
|
382 |
|
383 TRAPD(err, SendNextScriptFileCommandL()); |
|
384 // End of File is not an error that needs to be reported. |
|
385 if(err == KErrEof) |
|
386 { |
|
387 // All commands have been sent. |
|
388 iControllerInitialisationObserver->McioPostResetCommandComplete(KErrNone); |
|
389 } |
|
390 else if(err != KErrNone) |
|
391 { |
|
392 // Inform the stack of the initialisation status. |
|
393 iControllerInitialisationObserver->McioPostResetCommandComplete(err); |
|
394 } |
|
395 } |
|
396 } |
|
397 break; |
|
398 }; |
|
399 } |
|
400 |
|
401 void CControllerInitialisationPluginImpl::MhcqcCommandErrored(TInt aErrorCode, |
|
402 const CHCICommandBase* /*aCommand*/) |
|
403 { |
|
404 LOG_FUNC |
|
405 |
|
406 switch(iInitState) |
|
407 { |
|
408 case EWaitLocalDeviceInfo: |
|
409 case ESendScriptCommands: |
|
410 { |
|
411 // Inform the stack of the initialisation failure. |
|
412 iControllerInitialisationObserver->McioPostResetCommandComplete(aErrorCode); |
|
413 } |
|
414 break; |
|
415 |
|
416 default: |
|
417 PANIC(KTiControllerInitialisorPanic, EInvalidInitialisorState); |
|
418 break; |
|
419 }; |
|
420 } |
|
421 |
|
422 |
|
423 void CControllerInitialisationPluginImpl::SleepDisableTimerExpired() |
|
424 { |
|
425 LOG_FUNC |
|
426 |
|
427 TInt err = KErrNone; |
|
428 CVendorDebugCommand* cmd = NULL; |
|
429 SetSleepProtocol(EFalse); |
|
430 |
|
431 // Send the sleep disable command. |
|
432 if(((iSubVersion & KProjectTypeMask) >> KProjectTypeShift) >= 4) |
|
433 { |
|
434 TRAP(err, cmd = CVendorDebugCommand::NewL(KHciVSSleepModeConfig)); |
|
435 if(err == KErrNone) |
|
436 { |
|
437 // Populate the command. |
|
438 TDes8& cmdData = cmd->Command(); |
|
439 cmdData.FillZ(9); |
|
440 cmdData[3] = 0xff; |
|
441 cmdData[4] = 0xff; |
|
442 cmdData[5] = 0xff; |
|
443 } |
|
444 } |
|
445 else |
|
446 { |
|
447 TRAP(err, cmd = CVendorDebugCommand::NewL(KHciVSEnableSleepMode)); |
|
448 if(err == KErrNone) |
|
449 { |
|
450 // Populate the command. |
|
451 TDes8& cmdData = cmd->Command(); |
|
452 cmdData.FillZ(9); |
|
453 } |
|
454 } |
|
455 |
|
456 if(err == KErrNone) |
|
457 { |
|
458 TRAP(err, iHCICommandQueue->MhcqAddInitCommandL(cmd, *this)); |
|
459 } |
|
460 |
|
461 if(err != KErrNone) |
|
462 { |
|
463 // Inform the stack of the initialisation status. |
|
464 iControllerInitialisationObserver->McioPostResetCommandComplete(err); |
|
465 } |
|
466 iInitState = EWaitSleepDisableCompleteEvent; |
|
467 } |
|
468 |
|
469 void CControllerInitialisationPluginImpl::SetLocalBDAddr(TDes8& /*aVSCommandData*/) const |
|
470 { |
|
471 LOG_FUNC |
|
472 |
|
473 // Update the address from the script file if required. |
|
474 } |
|
475 |
|
476 void CControllerInitialisationPluginImpl::SetSleepProtocol(TBool /*aEnabled*/) |
|
477 { |
|
478 LOG_FUNC |
|
479 |
|
480 // Adjust the controller sleep protocol. |
|
481 } |
|
482 |
|
483 // |
|
484 // |
|
485 CSleepDisableTimer* CSleepDisableTimer::NewL(MSleepDisableTimerEventObserver& aTimerObserver) |
|
486 { |
|
487 LOG_STATIC_FUNC |
|
488 |
|
489 CSleepDisableTimer* self = new (ELeave) CSleepDisableTimer(aTimerObserver); |
|
490 CleanupStack::PushL(self); |
|
491 self->ConstructL(); |
|
492 CleanupStack::Pop(self); |
|
493 return self; |
|
494 } |
|
495 |
|
496 void CSleepDisableTimer::ConstructL() |
|
497 { |
|
498 LOG_FUNC |
|
499 |
|
500 CTimer::ConstructL(); |
|
501 CActiveScheduler::Add(this); |
|
502 } |
|
503 |
|
504 CSleepDisableTimer::CSleepDisableTimer(MSleepDisableTimerEventObserver& aTimerObserver) |
|
505 : CTimer(EPriorityStandard), |
|
506 iTimerObserver(aTimerObserver) |
|
507 { |
|
508 LOG_FUNC |
|
509 } |
|
510 |
|
511 void CSleepDisableTimer::Start() |
|
512 { |
|
513 LOG_FUNC |
|
514 |
|
515 if(!IsActive()) |
|
516 { |
|
517 After(KSleepDisableTimerDuration); |
|
518 } |
|
519 } |
|
520 |
|
521 void CSleepDisableTimer::RunL() |
|
522 { |
|
523 LOG_FUNC |
|
524 |
|
525 iTimerObserver.SleepDisableTimerExpired(); |
|
526 } |