bluetooth/btstack/linkmgr/hcifacade.cpp
branchRCL_3
changeset 22 9f17f914e828
parent 13 20fda83a6398
child 45 99439b07e980
equal deleted inserted replaced
18:f8503e232b0c 22:9f17f914e828
    33 
    33 
    34 #include <bluetooth/hcicommandqueue.h>
    34 #include <bluetooth/hcicommandqueue.h>
    35 #include <bluetooth/hcicommandqitem.h>
    35 #include <bluetooth/hcicommandqitem.h>
    36 #include <bluetooth/hcicmdqcontroller.h>
    36 #include <bluetooth/hcicmdqcontroller.h>
    37 
    37 
       
    38 #include <bluetooth/hci/hciopcodes.h>
       
    39 
    38 #include <bluetooth/hci/controllerinitialisationinterface.h>
    40 #include <bluetooth/hci/controllerinitialisationinterface.h>
    39 #include <bluetooth/hci/hcidataframer.h>
    41 #include <bluetooth/hci/hcidataframer.h>
    40 #include <bluetooth/hci/readlocalsupportedfeaturescommand.h>
    42 #include <bluetooth/hci/readlocalsupportedfeaturescommand.h>
    41 #include <bluetooth/hci/hostbuffersizecommand.h>
       
    42 #include <bluetooth/hci/resetcommand.h>
    43 #include <bluetooth/hci/resetcommand.h>
    43 #include <bluetooth/hci/readbdaddrcommand.h>
    44 #include <bluetooth/hci/readbdaddrcommand.h>
    44 #include <bluetooth/hci/readlocalversioninfocommand.h>
    45 #include <bluetooth/hci/readlocalversioninfocommand.h>
    45 #include <bluetooth/hci/writeconnectionaccepttimeoutcommand.h>
    46 #include <bluetooth/hci/writeconnectionaccepttimeoutcommand.h>
    46 #include <bluetooth/hci/writevoicesettingcommand.h>
    47 #include <bluetooth/hci/writevoicesettingcommand.h>
   190 	iLastPowerState = EBTOn;
   191 	iLastPowerState = EBTOn;
   191 	
   192 	
   192 	// used later to ensure that we have enough data to call SetEventMask
   193 	// used later to ensure that we have enough data to call SetEventMask
   193 	iReadLocalSupportedFeaturesComplete = EFalse;
   194 	iReadLocalSupportedFeaturesComplete = EFalse;
   194 	iReadLocalVersionComplete           = EFalse;
   195 	iReadLocalVersionComplete           = EFalse;
   195 			
       
   196 #ifdef HOSTCONTROLLER_TO_HOST_FLOW_CONTROL
       
   197 	iMBufPool = CHostMBufPool::NewL(*this);
       
   198 #endif
       
   199 	}
   196 	}
   200 	
   197 	
   201 void CHCIFacade::SetLinkMuxer(CLinkMuxer& aLinkMuxer)
   198 void CHCIFacade::SetLinkMuxer(CLinkMuxer& aLinkMuxer)
   202 	{
   199 	{
   203 	LOG_FUNC
   200 	LOG_FUNC
   317 
   314 
   318 CHCIFacade::~CHCIFacade()
   315 CHCIFacade::~CHCIFacade()
   319 	{
   316 	{
   320 	LOG_FUNC
   317 	LOG_FUNC
   321 	delete iAFHTimer;
   318 	delete iAFHTimer;
   322 	#ifdef HOSTCONTROLLER_TO_HOST_FLOW_CONTROL
       
   323 	delete iMBufPool;
       
   324 	#endif
       
   325 
   319 
   326 	delete iCoreHciPlugin;
   320 	delete iCoreHciPlugin;
   327 	
   321 	
   328 	if(iCmdController)
   322 	if(iCmdController)
   329 		{
   323 		{
   428 		// Ensure that no command or data messages are output by blocking all channels
   422 		// Ensure that no command or data messages are output by blocking all channels
   429 		//
   423 		//
   430 		iLinkMgrProtocol.LinkMuxer().ChannelsClosed(KHCITransportAllChannels);
   424 		iLinkMgrProtocol.LinkMuxer().ChannelsClosed(KHCITransportAllChannels);
   431 		iLinkMgrProtocol.Error(KErrHardwareNotAvailable);
   425 		iLinkMgrProtocol.Error(KErrHardwareNotAvailable);
   432 		// Reset UI
   426 		// Reset UI
       
   427 		//
   433 		iLinkMgrProtocol.SetUIConnecting(EFalse);
   428 		iLinkMgrProtocol.SetUIConnecting(EFalse);
   434 		iLinkMgrProtocol.SetUINumPhysicalLinks(0);
   429 		iLinkMgrProtocol.SetUINumPhysicalLinks(0);
   435 		// The h/w CoD has been reset, so we need to clear our persistent value, to reflect this
   430 		// The h/w has been (or will be) reset, so we need to clear our locally cached data
       
   431 		//
       
   432 		iLinkMgrProtocol.LinkMuxer().ResetFlowControlMode();
   436 		iLinkMgrProtocol.ClearPendingLocalDeviceSettingsCod();
   433 		iLinkMgrProtocol.ClearPendingLocalDeviceSettingsCod();
   437 		
   434 		
   438 		// Removes any pending AFH Channel Classification command 
   435 		// Removes any pending AFH Channel Classification command 
   439 		// and cancels timer.
   436 		// and cancels timer.
   440 		// NB This ensures AFH host channel classification command blocking is 
   437 		// NB This ensures AFH host channel classification command blocking is 
   527 	ETwoWayFlowControlEnabled, then it is the responsibility of the HCI client
   524 	ETwoWayFlowControlEnabled, then it is the responsibility of the HCI client
   528 	to issue the appropriate HostBufferSize(..) command.
   525 	to issue the appropriate HostBufferSize(..) command.
   529 */
   526 */
   530 	{
   527 	{
   531 	LOG_FUNC
   528 	LOG_FUNC
       
   529 	
   532 	switch (aMode)
   530 	switch (aMode)
   533 		{
   531 		{
   534 		case ENoFlowControl:
   532 	case ENoFlowControl:
   535 			{
   533 	case EFlowControlToHostControllerOnly:
   536 #ifndef _DEBUG
   534 	case EFlowControlFromHostControllerOnly:
   537 			Panic(ELinkMgrBadFlowControlSetInReleaseBuild);
   535 	case ETwoWayFlowControlEnabled:
   538 #endif
   536 		// a valid argument has been provided
   539 			break;
   537 		break;
   540 			}
   538 	default:
   541 		case EFlowControlToHostControllerOnly:
   539 		Panic(ELinkMgrNoSuchFlowControlMode);
   542 			{
   540 		break;
   543 			// the host will not tell the Controller about its buffers
   541 		}
   544 
   542 	
   545 			User::LeaveIfError(
   543 	TBool ctrlerToHostFlowControl = (aMode == ETwoWayFlowControlEnabled) || (aMode == EFlowControlFromHostControllerOnly);
   546 				SendInitialisationCommand(CReadBufferSizeCommand::NewL()));
   544 	TBool hostToCtrlerFlowControl = (aMode == ETwoWayFlowControlEnabled) || (aMode == EFlowControlToHostControllerOnly);
   547 			break;
   545 	
   548 			}
   546 	if(hostToCtrlerFlowControl)
   549 		case EFlowControlFromHostControllerOnly:
   547 		{
   550 			{
   548 		LEAVEIFERRORL(SendInitialisationCommand(CReadBufferSizeCommand::NewL()));
   551 #ifdef _DEBUG
   549 		}
   552 			CHCICommandBase *command = CHostBufferSizeCommand::NewL(KLinkMgrIncomingBufferSize,
   550 	
   553 											 KStackSCOBuffersSize, KStackACLBuffersNum,
   551 	if(ctrlerToHostFlowControl)
   554 											 KStackSCOBuffersNum);
   552 		{
   555 
   553 		static const TUint8 KControllerToHostFlowControlAclOnSyncOff = 0x01; 
   556 			User::LeaveIfError(SendInitialisationCommand(command));
   554 		CHCICommandBase* command = 
   557 
   555 			CSetControllerToHostFlowControlCommand::NewL(KControllerToHostFlowControlAclOnSyncOff);
   558 			command = CSetControllerToHostFlowControlCommand::NewL(ETrue);
   556 		LEAVEIFERRORL(SendInitialisationCommand(command));
   559 
   557 		// When this command successfully completes then host buffer size command will be issued.
   560 			User::LeaveIfError(SendInitialisationCommand(command));
   558 		}
   561 
   559 	else
   562 #else
   560 		{
   563 			Panic(ELinkMgrBadFlowControlSetInReleaseBuild);
   561 		iLinkMuxer->RecordHostControllerToHostFlowControl(EFalse);
   564 #endif
       
   565 			break;
       
   566 			}
       
   567 		case ETwoWayFlowControlEnabled:
       
   568 			{
       
   569 			CHCICommandBase *command = CHostBufferSizeCommand::NewL(KLinkMgrIncomingBufferSize,
       
   570 											 KStackSCOBuffersSize, KStackACLBuffersNum,
       
   571 											 KStackSCOBuffersNum);
       
   572 
       
   573 			User::LeaveIfError(SendInitialisationCommand(command));
       
   574 
       
   575 			command = CSetControllerToHostFlowControlCommand::NewL(ETrue);
       
   576 
       
   577 			User::LeaveIfError(SendInitialisationCommand(command));
       
   578 
       
   579 			break;
       
   580 			}
       
   581 		default:
       
   582 			Panic(ELinkMgrNoSuchFlowControlMode);
       
   583 			break;
       
   584 		}
   562 		}
   585 	}
   563 	}
   586 
   564 
   587 
   565 
   588 // simple forwarding functions so that all stack usage to HCI is via Facade.
   566 // simple forwarding functions so that all stack usage to HCI is via Facade.
   637 	{
   615 	{
   638 	LOG_FUNC
   616 	LOG_FUNC
   639 	return 0;
   617 	return 0;
   640 	}
   618 	}
   641 
   619 
   642 #ifdef HOSTCONTROLLER_TO_HOST_FLOW_CONTROL
       
   643 RMBufChain CHCIFacade::TakeInboundACLDataBufferFromPool(const THCIConnHandle& aForConnHandle)
       
   644 	{
       
   645 	LOG_FUNC
       
   646 	return iMBufPool->TakeBuffer(aForConnHandle);
       
   647 	}
       
   648 #endif
       
   649 
       
   650 // MControllerInitialisationObserver
   620 // MControllerInitialisationObserver
   651 void CHCIFacade::McioPreResetCommandComplete(TInt aError)
   621 void CHCIFacade::McioPreResetCommandComplete(TInt aError)
   652 	{
   622 	{
   653 	LOG_FUNC
   623 	LOG_FUNC
   654 	CHCICommandBase* command(NULL);
   624 	CHCICommandBase* command(NULL);
  1096 	{
  1066 	{
  1097 	LOG_FUNC
  1067 	LOG_FUNC
  1098 	return KErrNone;
  1068 	return KErrNone;
  1099 	}
  1069 	}
  1100 
  1070 
  1101 #ifdef HOSTCONTROLLER_TO_HOST_FLOW_CONTROL
       
  1102 
       
  1103 CHostMBufPool* CHostMBufPool::NewL(CHCIFacade& aHCIFacade)
       
  1104 	{
       
  1105 	LOG_FUNC
       
  1106 	CHostMBufPool* self = new (ELeave) CHostMBufPool(aHCIFacade);
       
  1107 	CleanupStack::PushL(self);
       
  1108 	self->ConstructL();
       
  1109 	CleanupStack::Pop(self);
       
  1110 	return self;
       
  1111 	}
       
  1112 	
       
  1113 void CHostMBufPool::DeletePool(TSglQue<TPoolBuffer>& aQueue)
       
  1114 	{
       
  1115 	LOG_FUNC
       
  1116 	TPoolBuffer* tmpItem = NULL;
       
  1117 	TSglQueIter<TPoolBuffer> iter(aQueue);
       
  1118 	while(iter)
       
  1119 		{
       
  1120 		tmpItem=iter++;
       
  1121 		aQueue.Remove(*tmpItem);
       
  1122 		delete tmpItem;
       
  1123 		}
       
  1124 	}
       
  1125 	
       
  1126 CHostMBufPool::~CHostMBufPool()
       
  1127 	{
       
  1128 	LOG_FUNC
       
  1129 	Cancel();
       
  1130 	DeletePool(iBufferPool);
       
  1131 	DeletePool(iWaitingAllocPool);
       
  1132 	}
       
  1133 	
       
  1134 CHostMBufPool::CHostMBufPool(CHCIFacade& aHCIFacade) :
       
  1135 	CActive(0),iHCIFacade(aHCIFacade),iBufferPool(_FOFF(TPoolBuffer,iLink)),
       
  1136 	iWaitingAllocPool(_FOFF(TPoolBuffer,iLink)),iCurrAckHandle(KErrNotFound),iCurrCompletedPackets(0)
       
  1137 	{
       
  1138 	LOG_FUNC
       
  1139 	}
       
  1140 	
       
  1141 void CHostMBufPool::ConstructL()
       
  1142 /**
       
  1143 2nd phase constructor for the Host MBuf Pool.
       
  1144 
       
  1145 This method will attempt to reserve enough MBufs from the global pool
       
  1146 for bluetooth use.
       
  1147 @leave KErrNoMemory If the required number of MBufs couldn't be reserved
       
  1148 */
       
  1149 	{
       
  1150 	LOG_FUNC
       
  1151 	LOG2(_L("CHostMBufPool: now reserving %d size %d MBufChains"),KStackACLBuffersNum,KLinkMgrIncomingBufferSize);
       
  1152 			
       
  1153 	for (TInt i=0;i<=KStackACLBuffersNum-1;i++)
       
  1154 		{
       
  1155 		TPoolBuffer* thisBuffer = new (ELeave) TPoolBuffer();
       
  1156 		CleanupStack::PushL(thisBuffer);
       
  1157 		thisBuffer->iCurrentHandle=KErrNotFound; //we assert on this later
       
  1158 		thisBuffer->iMBufChain.AllocL(KLinkMgrIncomingBufferSize);
       
  1159 		iBufferPool.AddFirst(*thisBuffer);
       
  1160 		CleanupStack::Pop(thisBuffer);
       
  1161 		}
       
  1162 		
       
  1163 	CActiveScheduler::Add(this);
       
  1164 	}
       
  1165 	
       
  1166 void CHostMBufPool::DoCancel()
       
  1167 	{
       
  1168 	LOG_FUNC
       
  1169 	iMBufRequester.Cancel();
       
  1170 	}
       
  1171 	
       
  1172 RMBufChain CHostMBufPool::TakeBuffer(const THCIConnHandle& aConnHandle)
       
  1173 /**
       
  1174 Takes a buffer from the pool and schedules an asynchronous allocation
       
  1175 of the next buffer.	 Only when that allocation has succeeded will the host
       
  1176 controller be signalled with a host_number_of_completed_packets.  Hence,
       
  1177 if we cannot allocate a buffer from the global MBuf pool, the host controller
       
  1178 will be flowed off and no data will be lost.
       
  1179 */
       
  1180 	{
       
  1181 	LOG_FUNC
       
  1182 	TPoolBuffer* ready = iBufferPool.First();
       
  1183 	iBufferPool.Remove(*ready);
       
  1184 	__ASSERT_DEBUG(!ready->iMBufChain.IsEmpty(),Panic(ELinkMgrHostControllerHasOverflowedHost));
       
  1185 	__ASSERT_DEBUG(ready->iCurrentHandle==KErrNotFound,Panic(ELinkMgrHostControllerHasOverflowedHost));
       
  1186 	ready->iCurrentHandle = aConnHandle;
       
  1187 	
       
  1188 	RMBufChain retChain;
       
  1189 	retChain.Assign(ready->iMBufChain);
       
  1190 	
       
  1191 	if (IsActive())
       
  1192 		{
       
  1193 		//This buffer will be reclaimed from the global pool
       
  1194 		//after the one(s) we're currently trying to reclaim
       
  1195 		LOG(_L("CHostMBufPool: TakeBuffer, buffer taken while alloc outstanding: queued alloc"));
       
  1196 		iWaitingAllocPool.AddLast(*ready);
       
  1197 		}
       
  1198 	else
       
  1199 		{
       
  1200 		LOG(_L("CHostMBufPool: TakeBuffer, buffer taken"));
       
  1201 		iBufferPool.AddLast(*ready); //NB the Controller cannot use this
       
  1202 									//buffer until it is alloced as it will
       
  1203 									//be flowed off.
       
  1204 		iMBufRequester.Alloc(ready->iMBufChain,KLinkMgrIncomingBufferSize,iStatus);
       
  1205 		SetActive();
       
  1206 		}
       
  1207 		
       
  1208 	return retChain;
       
  1209 	}
       
  1210 	
       
  1211 void CHostMBufPool::RunL()
       
  1212 	{
       
  1213 	LOG_FUNC
       
  1214 	if (iStatus.Int()!=KErrNone)
       
  1215 		{
       
  1216 		LOG1(_L("Error! CHostMBufPool:: RunL %d"),iStatus.Int());
       
  1217 		__DEBUGGER();
       
  1218 		}
       
  1219 	else
       
  1220 		{
       
  1221 		TPoolBuffer* justAllocd = iBufferPool.Last();
       
  1222 		
       
  1223 		
       
  1224 		if (iCurrAckHandle==KErrNotFound)
       
  1225 			{
       
  1226 			//This is the first completion we have ever seen
       
  1227 			iCurrAckHandle=justAllocd->iCurrentHandle;
       
  1228 			}
       
  1229 		
       
  1230 		TBool ackNow=((justAllocd->iCurrentHandle!=iCurrAckHandle));
       
  1231 		
       
  1232 		if (!ackNow)
       
  1233 			{
       
  1234 			iCurrCompletedPackets++;
       
  1235 			LOG2(_L("CHostMBufPool: CompletedPackets++ for conn: %d [->%d]"),justAllocd->iCurrentHandle,iCurrCompletedPackets);
       
  1236 			
       
  1237 			if (iCurrCompletedPackets>=KStackACLBuffersTideMarkNum)
       
  1238 				{
       
  1239 				ackNow=ETrue;
       
  1240 				}
       
  1241 			}
       
  1242 			
       
  1243 		if (ackNow)
       
  1244 			{
       
  1245 			TInt err=KErrNone;
       
  1246 			
       
  1247 			if (iCurrCompletedPackets>0)
       
  1248 				{
       
  1249 				LOG2(_L("CHostMBufPool: Sending HostNumberOfCompletedPackets for conn: %d [%d completed]"),iCurrAckHandle,iCurrCompletedPackets);
       
  1250 				//Acknowledge the completed packets
       
  1251 				TRAP(err, iHCIFacade.HostNumberOfCompletedPacketsL(iCurrAckHandle,iCurrCompletedPackets));
       
  1252 				//if this failed we probably couldn't alloc the memory for the command frame,
       
  1253 				//the HC is still flowed off.
       
  1254 				__ASSERT_DEBUG(err==KErrNone,Panic(ELinkMgrCouldNotSendHostNumberOfCompletedPackets));
       
  1255 				}
       
  1256 			
       
  1257 			iCurrCompletedPackets= (justAllocd->iCurrentHandle!=iCurrAckHandle) ? 1:0;
       
  1258 			iCurrAckHandle=justAllocd->iCurrentHandle;
       
  1259 			}
       
  1260 		
       
  1261 		justAllocd->iCurrentHandle=KErrNotFound;
       
  1262 		
       
  1263 		if (!iWaitingAllocPool.IsEmpty())
       
  1264 			{
       
  1265 			TPoolBuffer* needsAlloc = iWaitingAllocPool.First();
       
  1266 			iBufferPool.AddLast(*needsAlloc);
       
  1267 			iWaitingAllocPool.Remove(*needsAlloc);
       
  1268 			iMBufRequester.Alloc(needsAlloc->iMBufChain,KLinkMgrIncomingBufferSize,iStatus);
       
  1269 			SetActive();
       
  1270 			}
       
  1271 		}
       
  1272 	}
       
  1273 	
       
  1274 #endif