117 |
117 |
118 __ASSERT_ALWAYS(iSentCommandQ.IsEmpty(), PANIC(KHCICmdQPanic, ESentCommandQNotEmptyInDestructor)); |
118 __ASSERT_ALWAYS(iSentCommandQ.IsEmpty(), PANIC(KHCICmdQPanic, ESentCommandQNotEmptyInDestructor)); |
119 __ASSERT_ALWAYS(iResendCommandQ.IsEmpty(), PANIC(KHCICmdQPanic, EResendCommandQNotEmptyInDestructor)); |
119 __ASSERT_ALWAYS(iResendCommandQ.IsEmpty(), PANIC(KHCICmdQPanic, EResendCommandQNotEmptyInDestructor)); |
120 |
120 |
121 delete iQStarvationTimer; |
121 delete iQStarvationTimer; |
122 delete iSendingCommand; |
122 DeleteCommand(iSendingCommand); |
123 delete iQdpPlugin; |
123 delete iQdpPlugin; |
124 |
124 |
125 // Delete async CallBacks. If running, these should be cancelled by the |
125 // Delete async CallBacks. If running, these should be cancelled by the |
126 // d'tor of CAsyncOneShot. |
126 // d'tor of CAsyncOneShot. |
127 delete iAsyncCallBackForReset; |
127 delete iAsyncCallBackForReset; |
691 THCIEventCode eventCode(aEvent.EventCode()); |
691 THCIEventCode eventCode(aEvent.EventCode()); |
692 if (eventCode == ECommandCompleteEvent) |
692 if (eventCode == ECommandCompleteEvent) |
693 { |
693 { |
694 |
694 |
695 const THCICommandCompleteEvent& event(THCICommandCompleteEvent::Cast(aEvent)); |
695 const THCICommandCompleteEvent& event(THCICommandCompleteEvent::Cast(aEvent)); |
696 UpdateCommandCredits(event.NumHCICommandPackets()); |
696 UpdateCommandCredits(event.NumHCICommandPackets(), event.CommandOpcode() == KNopOpcode); |
697 |
697 |
698 if (event.CommandOpcode() == KNopOpcode) |
698 if (event.CommandOpcode() == KNopOpcode) |
699 { |
699 { |
700 // This is a special command complete event that does not |
700 // This is a special command complete event that does not |
701 // complete an event. Command_Opcode, 0x0000 is a NOP, and |
701 // complete an event. Command_Opcode, 0x0000 is a NOP, and |
707 } |
707 } |
708 } |
708 } |
709 else if (eventCode == ECommandStatusEvent) |
709 else if (eventCode == ECommandStatusEvent) |
710 { |
710 { |
711 TCommandStatusEvent& event = TCommandStatusEvent::Cast(aEvent); |
711 TCommandStatusEvent& event = TCommandStatusEvent::Cast(aEvent); |
712 UpdateCommandCredits(event.NumHCICommandPackets()); |
712 UpdateCommandCredits(event.NumHCICommandPackets(), event.CommandOpcode() == KNopOpcode); |
713 |
713 |
714 if (event.CommandOpcode() == KNopOpcode) |
714 if (event.CommandOpcode() == KNopOpcode) |
715 { |
715 { |
716 // Same as above for NOP command complete event. |
716 // Same as above for NOP command complete event. |
717 |
717 |
953 } |
953 } |
954 |
954 |
955 /** |
955 /** |
956 Updates the command credits counter and maintains the EInsufficientCreditBlock |
956 Updates the command credits counter and maintains the EInsufficientCreditBlock |
957 */ |
957 */ |
958 inline void CHCICmdQController::UpdateCommandCredits(TUint8 aCommandCredits) |
958 inline void CHCICmdQController::UpdateCommandCredits(TUint8 aCommandCredits, TBool aNOP) |
959 { |
959 { |
960 iCommandCredits = aCommandCredits; |
960 // Assume no credits until we decide otherwise |
961 |
961 iCommandCredits = 0; |
|
962 |
|
963 if (aCommandCredits > 0) |
|
964 { |
|
965 // We need to workaround a problem with multiple command credits to ensure that |
|
966 // we don't update the credits before the controller has processed all of the |
|
967 // commands we have sent it. |
|
968 TDblQueIter<CHCICommandQItem> qIter(iSentCommandQ); |
|
969 CHCICommandQItem* cmd = NULL; |
|
970 TUint count = 0; |
|
971 |
|
972 while (qIter != NULL) |
|
973 { |
|
974 // Count all the commands that we have sent that expect a command status but |
|
975 // haven't had one yet or expects a command complete event. |
|
976 cmd = qIter++; |
|
977 if ((cmd->Command().ExpectsCommandStatusEvent() && !cmd->ReceivedCmdStatusEvent()) || |
|
978 cmd->Command().ExpectsCommandCompleteEvent()) |
|
979 { |
|
980 count++; |
|
981 } |
|
982 } |
|
983 |
|
984 if (((count == 0) && aNOP) || ((count == 1) && !aNOP)) |
|
985 { |
|
986 // The credits are updated before the matching command is removed from the sent |
|
987 // queue and therefore we only update the credits when we have 1 command that has |
|
988 // not yet been processed or we have 0 commands and this update is due to a NOP |
|
989 // event. |
|
990 iCommandCredits = aCommandCredits; |
|
991 } |
|
992 } |
|
993 |
962 if (iCommandCredits > 0) |
994 if (iCommandCredits > 0) |
963 { |
995 { |
964 // We clear block flags when sending priority commands, so there may be some |
996 // We clear block flags when sending priority commands, so there may be some |
965 // commands blocked on insufficient credits, but the block flag not set |
997 // commands blocked on insufficient credits, but the block flag not set |
966 // anymore. Hence we want to schedule the callback irrespectably of the status |
998 // anymore. Hence we want to schedule the callback irrespectably of the status |
1715 LOG_FUNC |
1747 LOG_FUNC |
1716 |
1748 |
1717 // Ensure we are in a state that allows commands to be added. |
1749 // Ensure we are in a state that allows commands to be added. |
1718 if(!CanAddCommands()) |
1750 if(!CanAddCommands()) |
1719 { |
1751 { |
1720 delete &aQueItem; |
1752 CHCICommandQItem* pQueItem = &aQueItem; |
|
1753 DeleteCommand(pQueItem); |
1721 User::Leave(KErrHardwareNotAvailable); |
1754 User::Leave(KErrHardwareNotAvailable); |
1722 } |
1755 } |
1723 |
1756 |
1724 // Assign a unique CommandQId. |
1757 // Assign a unique CommandQId. |
1725 aQueItem.SetCommandQId(NextCommandQueueItemId()); |
1758 aQueItem.SetCommandQId(NextCommandQueueItemId()); |