bthci/hci2implementations/qdps/symbian/src/hcisymbianqdp.cpp
changeset 0 29b1cd4cb562
child 1 b4a7eebaaebf
equal deleted inserted replaced
-1:000000000000 0:29b1cd4cb562
       
     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 "hcisymbianqdp.h"
       
    22 #include "hcieventmodifiable.h"
       
    23 #include <bluetooth/hcicommandqitem.h>
       
    24 #include <bluetooth/hci/hciopcodes.h>
       
    25 #include <bluetooth/hci/hciconsts.h>
       
    26 #include <bluetooth/hci/command.h>
       
    27 #include <bluetooth/hci/event.h>
       
    28 #include <bluetooth/hci/commandcompleteevent.h>
       
    29 #include <bluetooth/hci/disconnectioncompleteevent.h>
       
    30 #include <bluetooth/hci/readclockoffsetevent.h>
       
    31 #include <bluetooth/hci/authenticationcompleteevent.h>
       
    32 #include <bluetooth/hci/readlocalversioninfocompleteevent.h>
       
    33 #include <bluetooth/logger.h>
       
    34 
       
    35 #ifdef __FLOG_ACTIVE
       
    36 _LIT8(KLogComponent, LOG_COMPONENT_QDP_SYMBIAN);
       
    37 #endif
       
    38 
       
    39 /*static*/ CHCISymbianQdp* CHCISymbianQdp::NewL()
       
    40 	{
       
    41 	LOG_STATIC_FUNC
       
    42 	
       
    43 	CHCISymbianQdp* self = new (ELeave) CHCISymbianQdp();
       
    44 	return self;
       
    45 	}
       
    46 
       
    47 // Private constructor.
       
    48 CHCISymbianQdp::CHCISymbianQdp()
       
    49 	{
       
    50 	LOG_FUNC
       
    51 	}
       
    52 
       
    53 TAny* CHCISymbianQdp::Interface(TUid aUid)
       
    54 	{
       
    55 	TAny* ret = NULL;
       
    56 	
       
    57 	switch(aUid.iUid)
       
    58 		{
       
    59 		case KHCICmdQueueDecisionInterfaceUid:
       
    60 			ret = reinterpret_cast<TAny*>(static_cast<MHCICmdQueueDecisionInterface*>(this));
       
    61 			break;
       
    62 		case KHCICmdQueueDecisionEventModifierInterfaceUid:
       
    63 			ret = reinterpret_cast<TAny*>(static_cast<MHCICmdQueueEventModifierInterface*>(this));
       
    64 			break;
       
    65 		case KHCICmdQueueUtilityUserUid:
       
    66 			ret = reinterpret_cast<TAny*>(static_cast<MHCICmdQueueUtilityUser*>(this));
       
    67 			break;
       
    68 		default:
       
    69 			break;
       
    70 		};
       
    71 
       
    72 	return ret;
       
    73 	}
       
    74 
       
    75 // MHCICmdQueueDecisionInterface
       
    76 TBool CHCISymbianQdp::MhcqdiDoesCommandRequireWorkaround(const CHCICommandQItem& /* aParent */)
       
    77 	{
       
    78 	LOG_FUNC
       
    79 	
       
    80 	// No Workarounds required.
       
    81 	return EFalse;
       
    82 	}
       
    83 	
       
    84 CHCICommandQItem* CHCISymbianQdp::MhcqdiGetPreChildCommand(const CHCICommandQItem& /* aParent */, 
       
    85 														   const CHCICommandQItem* /* aPreviousWorkaroundCmd */,
       
    86 														   const THCIEventBase* /*aPreviousCmdResult*/)
       
    87 	{
       
    88 	LOG_FUNC
       
    89 	
       
    90 	// No Workarounds required (see MhcqdiDoesCommandRequireWorkaround), should never be called.
       
    91 	return NULL;
       
    92 	}
       
    93 
       
    94 CHCICommandQItem* CHCISymbianQdp::MhcqdiGetPostChildCommand(const CHCICommandQItem& /* aParent */, 
       
    95 															const CHCICommandQItem* /* aPreviousPostChild */, 
       
    96 															const THCIEventBase* /*aPreviousCmdResult*/)
       
    97 	{
       
    98 	LOG_FUNC
       
    99 	
       
   100 	// No Workarounds required (see MhcqdiDoesCommandRequireWorkaround), should never be called.
       
   101 	return NULL;
       
   102 	}
       
   103 	
       
   104 THCIEventBase* CHCISymbianQdp::MhcqdiGetFakedUnsolicitedEvent(const CHCICommandQItem& /*aParent*/,
       
   105 															  const THCIEventBase* /*aPreviousFakedEvent*/)
       
   106 	{
       
   107 	LOG_FUNC
       
   108 	
       
   109 	// No Workarounds required (see MhcqdiDoesCommandRequireWorkaround), should never be called.
       
   110 	return NULL;
       
   111 	}
       
   112 	
       
   113 void CHCISymbianQdp::MhcqdiCommandAboutToBeDeleted(const CHCICommandQItem& /*aDyingCmd*/)
       
   114 	{
       
   115 	LOG_FUNC
       
   116 	
       
   117 	// Notification function. No need to do anything.
       
   118 	}
       
   119 	
       
   120 TInt CHCISymbianQdp::MhcqdiCanSend(CHCICommandQItem& /*aCommand*/, const TDblQue<const CHCICommandQItem>& aSentCommands)
       
   121 	{
       
   122 	LOG_FUNC
       
   123 
       
   124    if (!aSentCommands.IsEmpty())
       
   125    		{
       
   126         // Def088959 - The following unhandled commands are blocked to avoid operational errors.
       
   127         // Note: This workaround currently resides in this Symbian QDP, but may require further
       
   128         // modification or placement depending on target hardware characteristics. This workaround
       
   129         // may not be required for all controllers.
       
   130         
       
   131         THCIOpcode opcode=aSentCommands.Last()->Command().Opcode();
       
   132         if (opcode == KHoldModeOpcode ||
       
   133         			opcode == KSniffModeOpcode ||
       
   134         			opcode == KExitSniffModeOpcode ||
       
   135         			opcode == KSwitchRoleOpcode ||
       
   136         			opcode == KParkModeOpcode ||
       
   137         			opcode == KExitParkModeOpcode)
       
   138 	        {
       
   139         	return EBlock;
       
   140 	        }
       
   141    		}
       
   142    //otherwise allow command queue to proceed   
       
   143 	return EContinue;
       
   144 	}
       
   145 	
       
   146 TUint CHCISymbianQdp::MhcqdiTimeoutRequired(const CHCICommandQItem& /* aCmdAboutToBeSent */)
       
   147 	{
       
   148 	LOG_FUNC
       
   149 	
       
   150 	// No timeout required.
       
   151 	return MHCICmdQueueDecisionInterface::KNoTimeoutRequired;
       
   152 	}
       
   153 	
       
   154 void CHCISymbianQdp::MhcqdiMatchedEventReceived(const THCIEventBase& aEvent, const CHCICommandQItem& /*aRelatedCommand*/)
       
   155 	{
       
   156 	LOG_FUNC
       
   157 	
       
   158 	// Cache the HCI version number of the controller. This allows
       
   159 	// us to ignore errors from specific versions of controllers
       
   160 	if (   aEvent.EventCode() == ECommandCompleteEvent
       
   161 		&& THCICommandCompleteEvent::Cast(aEvent).CommandOpcode() == KReadLocalVersionInfoOpcode)
       
   162 		{
       
   163 		const TReadLocalVersionInfoCompleteEvent& readLocalVersionCompleteEvent = TReadLocalVersionInfoCompleteEvent::Cast(aEvent);
       
   164 		iHCIVersion = readLocalVersionCompleteEvent.Version();
       
   165 		}
       
   166 	}
       
   167 
       
   168 void CHCISymbianQdp::MhcqemiMatchedEventReceived(THCIEventBase& aEvent, const CHCICommandQItem& aRelatedCommand)
       
   169 	{
       
   170 	LOG_FUNC
       
   171 	
       
   172 #ifdef BROKEN_CASIRA_1_1
       
   173 	FirmwareFixIgnoreErrorOnSetEventMaskForCasira(aEvent);
       
   174 #endif // BROKEN_CASIRA_1_1
       
   175 	
       
   176 #ifdef BROKEN_BELKIN_2_1
       
   177 	FirmwareFixFakeCompletionEventsOnDisconnectionForBelkin(aEvent);
       
   178 #endif // BROKEN_BELKIN_2_1
       
   179 
       
   180 	MhcqdiMatchedEventReceived(aEvent, aRelatedCommand);
       
   181 	}
       
   182 
       
   183 
       
   184 MHCICmdQueueDecisionInterface::TCommandErroredAction CHCISymbianQdp::MhcqdiMatchedErrorEventReceived(const THCIEventBase& /*aErrorEvent*/, 
       
   185 																									 const CHCICommandQItem& /*aRelatedCommand*/)
       
   186 	{
       
   187 	LOG_FUNC
       
   188 	
       
   189 	// Never resend.
       
   190 	return MHCICmdQueueDecisionInterface::EContinueWithError;
       
   191 	}
       
   192 	
       
   193 void CHCISymbianQdp::MhcqdiUnmatchedEventReceived(const THCIEventBase& /*aEvent*/)
       
   194 	{
       
   195 	LOG_FUNC
       
   196 	
       
   197 	// Notification function. No need to do anything.
       
   198 	}
       
   199 
       
   200 void CHCISymbianQdp::FirmwareFixIgnoreErrorOnSetEventMaskForCasira(THCIEventBase& aEvent)
       
   201 	{
       
   202 	LOG_FUNC
       
   203 	// Casiras with 1.1 firmware return an EInvalidHCIParameter error
       
   204 	// when SetEventMask is called. We still want to call SetEventMask but
       
   205 	// on this (old/buggy) firmware, ignore the returned EInvalidHCIParameter
       
   206 	
       
   207 	if (    aEvent.ErrorCode() == EInvalidHCIParameter
       
   208 	    &&  aEvent.EventCode() == ECommandCompleteEvent
       
   209 		&& KSetEventMaskOpcode == THCICommandCompleteEvent::Cast(aEvent).CommandOpcode()
       
   210 		&&         iHCIVersion == EHWHCIv1_1)
       
   211 		{
       
   212 		THCIEventBase& modevent = const_cast<THCIEventBase&>(aEvent);
       
   213 		THCIEventModifiable& event = reinterpret_cast<THCIEventModifiable&>(modevent);
       
   214 		event.SetErrorCode(EOK);
       
   215 		}
       
   216 	}
       
   217 
       
   218 void CHCISymbianQdp::FirmwareFixFakeCompletionEventsOnDisconnectionForBelkin(THCIEventBase& aEvent)
       
   219 	{
       
   220 	LOG_FUNC
       
   221 	// For Belkin 2.1 controllers, if we receive a "Disconnection Complete Event"
       
   222 	// then look for a "Authentication Requested" command or "Read Clock Offset" on
       
   223 	// the sent queue, and if found, then fake up an completion event (with reason
       
   224 	// code copied from the Disconnection Complete Event) and inject this into the
       
   225 	// queue. This is because the Belkin 2.1 controllers fail to send a completion
       
   226 	// event for "Read Clock Offset" and "Request Authentication" (and maybe others)
       
   227 	// themselves (i.e. these are firmware bugs we're working around)
       
   228 
       
   229 	if (aEvent.EventCode() == EDisconnectionCompleteEvent && iHCIVersion == EHWHCIv2_1)
       
   230 		{
       
   231 		const TDisconnectionCompleteEvent& disconnEvent = TDisconnectionCompleteEvent::Cast(aEvent);
       
   232 		THCIConnectionHandle handle = disconnEvent.ConnectionHandle();
       
   233 		THCIErrorCode reason = static_cast<THCIErrorCode>(disconnEvent.Reason());
       
   234 		
       
   235 		if (iProvider->FindOutstandingCommand(KAuthenticationRequestedOpcode) != NULL)
       
   236 			{
       
   237 			TBuf8<KHCIMaxEventSize> eventBuf1;
       
   238 			TAuthenticationCompleteEvent authenticationCompleteEvent(reason, handle, eventBuf1);
       
   239 			iProvider->InjectEvent(authenticationCompleteEvent);
       
   240 			}
       
   241 		
       
   242 		if (iProvider->FindOutstandingCommand(KReadClockOffsetOpcode) != NULL)
       
   243 			{
       
   244 			TBuf8<KHCIMaxEventSize> eventBuf2;
       
   245 			THCIClockOffset clockOffset = 0;
       
   246 			TReadClockOffsetEvent readClockOffsetEvent(reason, handle, clockOffset, eventBuf2);
       
   247 			iProvider->InjectEvent(readClockOffsetEvent);
       
   248 			}
       
   249 		}
       
   250 	}
       
   251 
       
   252 void CHCISymbianQdp::MhcqemiUnmatchedEventReceived(THCIEventBase& aEvent)
       
   253 	{
       
   254 	LOG_FUNC
       
   255 	
       
   256 #ifdef BROKEN_BELKIN_2_1
       
   257 	FirmwareFixFakeCompletionEventsOnDisconnectionForBelkin(aEvent);
       
   258 #endif // BROKEN_BELKIN_2_1
       
   259 	
       
   260 	MhcqdiUnmatchedEventReceived(aEvent);
       
   261 	}
       
   262 	
       
   263 MHCICmdQueueDecisionInterface::TCommandTimedOutAction CHCISymbianQdp::MhcqdiCommandTimedOut(const CHCICommandQItem& /*aCommand*/,
       
   264 																							const TDblQue<const CHCICommandQItem>& /*aSentCommands*/,
       
   265 																							TUint /*aCurrentCommandCredits*/,
       
   266 																							TUint& aCreditsToBeRefunded)
       
   267 	{
       
   268 	LOG_FUNC
       
   269 	
       
   270 	// No Timeout ever set, should never be called.
       
   271 	aCreditsToBeRefunded = KHCIDefaultCmdCredits;
       
   272 	return EContinueWithTimeoutEvent;
       
   273 	}
       
   274 	
       
   275 void CHCISymbianQdp::MhcqdiSetPhysicalLinksState(const MPhysicalLinksState& /*aPhysicalLinkState*/)
       
   276 	{
       
   277 	LOG_FUNC
       
   278 	}
       
   279 	
       
   280 void CHCISymbianQdp::MhcqdiSetHardResetInitiator(const MHardResetInitiator& /*aHardResetInitiator*/)
       
   281 	{
       
   282 	LOG_FUNC
       
   283 	}
       
   284 	
       
   285 void CHCISymbianQdp::MhcqdiSetHCICommandQueue(MHCICommandQueue& /*aHCICommandQueue*/)
       
   286 	{
       
   287 	LOG_FUNC
       
   288 	}
       
   289 
       
   290 void CHCISymbianQdp::MhcqdiSetTimeouts(TUint /*aQueueStarvationTimeout*/,
       
   291                                        TUint /*aMaxHciCommandTimeout*/)
       
   292 	{
       
   293 	LOG_FUNC
       
   294 	}
       
   295 	
       
   296 TUint CHCISymbianQdp::MhcqdiReset()
       
   297 	{
       
   298 	LOG_FUNC
       
   299 	
       
   300 	// Return the initial number of command credits for the queue.
       
   301 	return KHCIDefaultCmdCredits;
       
   302 	}
       
   303 
       
   304 void CHCISymbianQdp::MhcquuSetUtilitiesProvider(MHCICmdQueueUtilities& aProvider)
       
   305 	{
       
   306 	LOG_FUNC
       
   307 	
       
   308 	iProvider = &aProvider;
       
   309 	}