bthci/bthci2/hcicmdq/src/HciCmdQController.cpp
changeset 51 20ac952a623c
parent 33 4e80e1b997a8
--- a/bthci/bthci2/hcicmdq/src/HciCmdQController.cpp	Thu Sep 23 17:06:47 2010 +0300
+++ b/bthci/bthci2/hcicmdq/src/HciCmdQController.cpp	Wed Oct 13 16:20:29 2010 +0300
@@ -119,7 +119,7 @@
 	__ASSERT_ALWAYS(iResendCommandQ.IsEmpty(), PANIC(KHCICmdQPanic, EResendCommandQNotEmptyInDestructor));
 		
 	delete iQStarvationTimer;
-	delete iSendingCommand;
+	DeleteCommand(iSendingCommand);
 	delete iQdpPlugin;
 
 	// Delete async CallBacks.	If running, these should be cancelled by the
@@ -693,7 +693,7 @@
 		{
 
 		const THCICommandCompleteEvent& event(THCICommandCompleteEvent::Cast(aEvent));
-		UpdateCommandCredits(event.NumHCICommandPackets());
+		UpdateCommandCredits(event.NumHCICommandPackets(), event.CommandOpcode() == KNopOpcode);
 
 		if (event.CommandOpcode() == KNopOpcode)
 			{
@@ -709,7 +709,7 @@
 	else if (eventCode == ECommandStatusEvent)
 		{
 		TCommandStatusEvent& event = TCommandStatusEvent::Cast(aEvent);
-		UpdateCommandCredits(event.NumHCICommandPackets());
+		UpdateCommandCredits(event.NumHCICommandPackets(), event.CommandOpcode() == KNopOpcode);
 
 		if (event.CommandOpcode() == KNopOpcode)
 			{
@@ -955,10 +955,42 @@
 /**
 Updates the command credits counter and maintains the EInsufficientCreditBlock
 */
-inline void CHCICmdQController::UpdateCommandCredits(TUint8 aCommandCredits)
+inline void CHCICmdQController::UpdateCommandCredits(TUint8 aCommandCredits, TBool aNOP)
 	{
-	iCommandCredits = aCommandCredits;
-	
+	// Assume no credits until we decide otherwise
+	iCommandCredits = 0;
+
+	if (aCommandCredits > 0)
+		{
+		// We need to workaround a problem with multiple command credits to ensure that
+		// we don't update the credits before the controller has processed all of the 
+		// commands we have sent it.
+		TDblQueIter<CHCICommandQItem> qIter(iSentCommandQ);
+		CHCICommandQItem* cmd = NULL;
+		TUint count = 0;
+
+		while (qIter != NULL)
+			{
+			// Count all the commands that we have sent that expect a command status but
+			// haven't had one yet or expects a command complete event.
+			cmd = qIter++;
+			if ((cmd->Command().ExpectsCommandStatusEvent() && !cmd->ReceivedCmdStatusEvent()) || 
+				cmd->Command().ExpectsCommandCompleteEvent())
+				{
+				count++;
+				}
+			}
+
+		if (((count == 0) && aNOP) || ((count == 1) && !aNOP))
+			{
+			// The credits are updated before the matching command is removed from the sent
+			// queue and therefore we only update the credits when we have 1 command that has
+			// not yet been processed or we have 0 commands and this update is due to a NOP
+			// event.
+			iCommandCredits = aCommandCredits;
+			}
+		}
+
 	if (iCommandCredits > 0)
 		{
 		// We clear block flags when sending priority commands, so there may be some
@@ -1717,7 +1749,8 @@
 	// Ensure we are in a state that allows commands to be added.
 	if(!CanAddCommands())
 		{
-		delete &aQueItem;
+	    CHCICommandQItem* pQueItem = &aQueItem;
+        DeleteCommand(pQueItem);
 		User::Leave(KErrHardwareNotAvailable);
 		}