diff -r 22de2e391156 -r 20ac952a623c bthci/bthci2/hcicmdq/src/HciCmdQController.cpp --- 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 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); }