bluetooth/btstack/linkmgr/AclDataQController.cpp
changeset 0 29b1cd4cb562
child 16 9f17f914e828
equal deleted inserted replaced
-1:000000000000 0:29b1cd4cb562
       
     1 // Copyright (c) 1999-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 // Link Command Q Controlling internal methods 
       
    15 // The command Q is used to store commands used by the stack
       
    16 // The HCI is at liberty to use its own command Q for any other HC signalling 
       
    17 // it requires.
       
    18 // The HCI in such cases would then signal the stack with not all credits etc.
       
    19 // 
       
    20 //
       
    21 
       
    22 #include <bluetooth/logger.h>
       
    23 #include "AclDataQController.h"
       
    24 #include "linkmgr.h"
       
    25 #include "AclDataQ.h"
       
    26 #include "hcifacade.h"
       
    27 
       
    28 #ifdef __FLOG_ACTIVE
       
    29 _LIT8(KLogComponent, LOG_COMPONENT_LINKMGR);
       
    30 #endif
       
    31 
       
    32 const TInt KACLDataQConnectionRecordGranularity = 2;
       
    33 
       
    34 /**
       
    35 	Factory function.
       
    36 
       
    37 	@return Ownership of a new CACLDataQController.
       
    38  */
       
    39 CACLDataQController* CACLDataQController::NewL(CLinkMgrProtocol& aProtocol,
       
    40 											   CLinkMuxer& aMuxer,
       
    41 											   TUint16 aBufSize,
       
    42 											   TUint16 aFrameOverhead,
       
    43 											   TUint aNumBufs)
       
    44 	{
       
    45 	LOG_STATIC_FUNC
       
    46 	LOG3(_L("CACLDataQController::NewL aBufSize = %d, aFramingOverhead = %d, aNumBufs = %d"),
       
    47 		aBufSize, aFrameOverhead, aNumBufs);
       
    48 
       
    49 	CACLDataQController* self = new(ELeave) CACLDataQController(aProtocol.HCIFacade(), aMuxer);
       
    50 	CleanupStack::PushL(self);
       
    51 	self->ConstructL(aProtocol, aBufSize, aFrameOverhead, aNumBufs);
       
    52 	CleanupStack::Pop(self);
       
    53 
       
    54 	LOG1(_L("CACLDataQController::NewL self = 0x%08x"), self);
       
    55 	return self;
       
    56 	}
       
    57 
       
    58 CACLDataQController::CACLDataQController(CHCIFacade& aHCIFacade,
       
    59 										 CLinkMuxer& aMuxer)
       
    60  :	iAclConns(KACLDataQConnectionRecordGranularity),
       
    61 	iLinkMuxer(aMuxer),
       
    62 	iHCIFacade(aHCIFacade)
       
    63 	{
       
    64 	LOG_FUNC
       
    65 	}
       
    66 
       
    67 CACLDataQController::~CACLDataQController()
       
    68 	{
       
    69 	LOG_FUNC
       
    70 
       
    71 	delete iDataQ;
       
    72 	iAclConns.Reset();
       
    73 	iAclConns.Close();
       
    74 	}
       
    75 
       
    76 void CACLDataQController::ConstructL(CLinkMgrProtocol& aProtocol,
       
    77 									 TUint16 aBufSize,
       
    78 									 TUint16 aFrameOverhead,
       
    79 									 TUint aNumBufs)
       
    80 	{
       
    81 	LOG_FUNC
       
    82 
       
    83 	iDataQ = CAclDataQ::NewL(aProtocol, aNumBufs, aBufSize, aFrameOverhead);
       
    84 
       
    85 #ifdef PROXY_COMMUNICATES
       
    86 	LOG(_L("\tPROXY_COMMUNICATES defined- reserving slots for broadcast channel"));
       
    87 
       
    88 	// Reserve BC one now
       
    89 	User::LeaveIfError(ACLLogicalLinkUp(KHCIBroadcastHandle, EFalse));
       
    90 #endif
       
    91 	}
       
    92 
       
    93 void CACLDataQController::InitialDataCredits(TUint16 aCredits)
       
    94 /**
       
    95 	Set the initial data credits to whatever number of buffers the HC has.
       
    96 */
       
    97 	{
       
    98 	LOG_FUNC
       
    99 	LOG1(_L("CACLDataQController::InitialDataCredits aCredits = %d"), aCredits);
       
   100 
       
   101 	iDataCredits = aCredits;
       
   102 	iNumControllerBufs = aCredits;
       
   103 	}
       
   104 
       
   105 CACLDataItem* CACLDataQController::GetFreeItem()
       
   106 /**
       
   107 	Returns ownership of a data item, or NULL if there are none free.
       
   108  */
       
   109 	{
       
   110 	LOG_FUNC
       
   111 
       
   112 	__ASSERT_DEBUG(iDataQ, Panic(EHCIBufferMgrBadState));
       
   113 	CACLDataItem* ret = iDataQ->RemoveFirstSpareItem();
       
   114 	
       
   115 	LOG1(_L("CACLDataQController::GetFreeItem ret = 0x%08x"), ret);
       
   116 	return ret;
       
   117 	}
       
   118 
       
   119 void CACLDataQController::AddItem(CACLDataItem& aAclItem)
       
   120 	{
       
   121 	LOG_FUNC
       
   122 	LOG1(_L("CACLDataQController::AddItem &aAclItem = 0x%08x"), &aAclItem);
       
   123 
       
   124 	// what Connection Handle is this frame for?
       
   125 	__ASSERT_DEBUG(aAclItem.Frame(), Panic(EHCIBufferMgrBadState));
       
   126 	THCIConnHandle connh = (*(aAclItem.Frame())).ConnectionHandle();
       
   127 	
       
   128 	// Get the connection record
       
   129 	const TInt index = FindConnection(connh);
       
   130 	__ASSERT_ALWAYS(index>=0, Panic(EHCIACLDataControllerConnectionListConnectionNotFound));
       
   131 
       
   132 	++(iAclConns[index].iPacketsQueued);
       
   133 	LOG3(_L("\tadded an item for connection handle %d: iPacketsQueued = %d, iPacketsPending = %d"), 
       
   134 		connh, iAclConns[index].iPacketsQueued, iAclConns[index].iPacketsPending);
       
   135 
       
   136 	__ASSERT_DEBUG(iDataQ, Panic(EHCIBufferMgrBadState));
       
   137 	iDataQ->AddItem(aAclItem);
       
   138 	iLinkMuxer.TryToSend();
       
   139 	}
       
   140 
       
   141 THCIConnHandle CACLDataQController::HighestPriority()
       
   142 /**
       
   143  Get the highest priority connection, starting to look from the connection 
       
   144  which sent last, and ignoring connections with no queued data to send.
       
   145  If there's no clear highest priority connection, the connection handle of the 
       
   146  0th connection in our array will be returned, whether it has anything to send 
       
   147  or not (i.e. you always get a valid connection handle). 
       
   148  Assumes that there is at least 1 connection handle in our array.
       
   149  */
       
   150 	{
       
   151 	LOG_FUNC
       
   152 	LOG1(_L("CACLDataQController::HighestPriority iIndexOfLastSendingConn = %d"), 
       
   153 		iIndexOfLastSendingConn);
       
   154 
       
   155 	const TUint count = iAclConns.Count();
       
   156 	LOG1(_L("\tcount = %d"), count);
       
   157 	// Should only be called if we have connections to judge the highest 
       
   158 	// priority of.
       
   159 	__ASSERT_DEBUG(count != 0, Panic(EHCIBufferMgrBadState));
       
   160 
       
   161 	// Deal with the most likely case first, for speed...
       
   162 	if ( count == 1 )
       
   163 		{
       
   164 		LOG1(_L("CACLDataQController::HighestPriority returning %d"), 
       
   165 			iAclConns[0].iConnH);
       
   166 		return iAclConns[0].iConnH;
       
   167 		}
       
   168 
       
   169 	// Now look through iAclConns from the one which sent last...
       
   170 	__ASSERT_DEBUG(iIndexOfLastSendingConn < count, Panic(EHCIBufferMgrBadState));
       
   171 	TInt highestpriority = -KMaxTInt;
       
   172 	// NB If no connections have anything to send, connection index 0 will be 
       
   173 	// indicated by the return value.
       
   174 	TInt highestindex = 0;
       
   175 	TUint index;
       
   176 	if ( iIndexOfLastSendingConn + 1 == count )
       
   177 		{
       
   178 		index = 0;
       
   179 		}
       
   180 	else
       
   181 		{
       
   182 		index = iIndexOfLastSendingConn + 1;
       
   183 		}
       
   184 
       
   185 	FOREVER
       
   186 		{
       
   187 		__ASSERT_DEBUG(index < static_cast<TUint>(iAclConns.Count()), Panic(EHCIBufferMgrBadState));
       
   188 
       
   189 		const TInt priority = -(iAclConns[index].iPacketsPending);
       
   190 		const TInt queued = iAclConns[index].iPacketsQueued;
       
   191 
       
   192 #ifdef __FLOG_ACTIVE
       
   193 		const THCIConnHandle connh = iAclConns[index].iConnH;
       
   194 		LOG3(_L("\tconnection handle %d: iPacketsQueued = %d, iPacketsPending = %d"), 
       
   195 			connh, queued, -priority);
       
   196 #endif
       
   197 
       
   198 		// Only consider connections with some data queued.
       
   199 		if ( queued > 0 && priority > highestpriority )
       
   200 			{
       
   201 			highestpriority = priority;
       
   202 			highestindex = index;
       
   203 			}
       
   204 
       
   205 		LOG3(_L("\tindex = %d, highestpriority = %d, highestindex = %d"),
       
   206 			index, highestpriority, highestindex);
       
   207 		
       
   208 		++index;
       
   209 		// Have we gone all the way round?
       
   210 		if ( index == iIndexOfLastSendingConn + 1 )
       
   211 			{
       
   212 			break;
       
   213 			}
       
   214 		// If we're at the end of the array, continue looking from the 
       
   215 		// beginning.
       
   216 		if ( index == count )
       
   217 			{
       
   218 			index = 0;
       
   219 			}
       
   220 		}
       
   221 
       
   222 	LOG1(_L("CACLDataQController::HighestPriority connection handle = %d"), 
       
   223 		iAclConns[highestindex].iConnH);
       
   224 	return iAclConns[highestindex].iConnH;
       
   225 	}
       
   226 
       
   227 TBool CACLDataQController::AnotherPacketAllowed(TDataQConnectionInfo& aRecord)
       
   228 /**	
       
   229 	A small strategy to see if another packet is allowed on a given connection 
       
   230 	handle.
       
   231 	Always try to keep some spare host controller buffers for another 
       
   232 	connection handle that might arise. This maxes out at 8.
       
   233 */
       
   234 	{
       
   235 	LOG_FUNC
       
   236 
       
   237 	TBool allowAnotherPacket;
       
   238 	
       
   239 	if ( aRecord.iParked && aRecord.iConnH != KHCIBroadcastHandle )
       
   240 		{
       
   241 		// not allowed to send on non-broadcast handle when parked
       
   242 		allowAnotherPacket = EFalse;
       
   243 		}
       
   244 	else
       
   245 		{
       
   246 		// the rest of the handles are in principle sendable, but need to 
       
   247 		// check for room in HC. NB The '- 1' here is to make sure that one 
       
   248 		// connection can't result in the whole device being locked up if the 
       
   249 		// remote device stops responding- there'll still be one slot left 
       
   250 		// over. 
       
   251 		allowAnotherPacket = aRecord.iPacketsPending < iNumControllerBufs - 1 ? ETrue : EFalse;
       
   252 		}
       
   253 
       
   254 	LOG1(_L("CACLDataQController::AnotherPacketAllowed allowAnotherPacket = %d"), 
       
   255 		allowAnotherPacket);
       
   256 	return allowAnotherPacket;
       
   257 	}
       
   258 
       
   259 /**
       
   260  Called by the link muxer to do an actual send.
       
   261  Get the link which is entitled to send (on the basis of priority (which is 
       
   262  simply (0-number of packets waiting to be sent)) and recent history (if it 
       
   263  was the last to send, we check all the other links first for a higher or 
       
   264  equal priority one).
       
   265  Finally, get a packet belonging to the winning link and attempt to send it. 
       
   266  
       
   267  @return EFalse if no send occurred, ETrue otherwise.
       
   268  */
       
   269 TBool CACLDataQController::IssueNextACLDataFragment()
       
   270 	{
       
   271 	LOG_FUNC
       
   272 	__ASSERT_DEBUG(iDataCredits>0,Panic(EHCIACLDataControllerDataCreditsZeroBeforeIssue));
       
   273 
       
   274 	if ( !iAclConns.Count() )
       
   275 		{
       
   276 		LOG(_L("CACLDataQController::IssueNextACLDataFragment returning EFalse"));
       
   277 		return EFalse;
       
   278 		}
       
   279 
       
   280 	THCIConnHandle connh = HighestPriority(); // find suggested connection handle to send on
       
   281 	//ask the DataQ for the first item on this connection handle
       
   282 	CACLDataItem* item = NULL;
       
   283 	__ASSERT_DEBUG(iDataQ, Panic(EHCIBufferMgrBadState));
       
   284 	item = iDataQ->FirstItemByConnectionHandle(iHCIFacade, connh);
       
   285 	//if still NULL then there is no longer stuff on that connH on the Q so get the head item
       
   286 	if ( !item )
       
   287 		{
       
   288 		item = iDataQ->FirstItem(iHCIFacade, connh); // connh will be set
       
   289 		}
       
   290 
       
   291 	TBool sent = EFalse;
       
   292 
       
   293 	const TInt index = FindConnection(connh);
       
   294 	LOG1(_L("\tFindConnection returned %d"), index);
       
   295 	if ( index == KErrNotFound )
       
   296 		{
       
   297 		// Connection not found, because it went down between the link muxer 
       
   298 		// realising it could try to send and it (asynchronously) actually 
       
   299 		// asking us to send.
       
   300 		LOG1(_L("CACLDataQController::IssueNextACLDataFragment sent = %d"), 
       
   301 			sent);
       
   302 		return sent;
       
   303 		}
       
   304 
       
   305 	if ( !AnotherPacketAllowed(iAclConns[index]) )
       
   306 		{
       
   307 		LOG1(_L("CACLDataQController::IssueNextACLDataFragment sent = %d"), 
       
   308 			sent);
       
   309 		return sent; // no more allowed, otherwise HC liable to clogging
       
   310 		}
       
   311 
       
   312 	__ASSERT_DEBUG(item, Panic(EHCIBufferMgrBadState));
       
   313 	sent = SendItem(*item);
       
   314 
       
   315 	// Regardless of whether the send succeeded, make a note that this 
       
   316 	// connection handle was the last to 'have a go'...
       
   317 	iIndexOfLastSendingConn = index;
       
   318 
       
   319 	if ( sent )
       
   320 		{
       
   321 		--iDataCredits;
       
   322 		--(iAclConns[index].iPacketsQueued);
       
   323 		++(iAclConns[index].iPacketsPending);
       
   324 		LOG3(_L("\tsent on connection handle %d: iPacketsQueued = %d, iPacketsPending = %d"),
       
   325 			connh, iAclConns[index].iPacketsQueued, iAclConns[index].iPacketsPending);
       
   326 		}
       
   327 	
       
   328 	LOG1(_L("CACLDataQController::IssueNextACLDataFragment sent = %d"), sent);
       
   329 	return sent;
       
   330 	}
       
   331 
       
   332 TBool CACLDataQController::SendItem(CACLDataItem& aItem) 
       
   333 /**
       
   334 	Actually do the send - return true if successful
       
   335 **/
       
   336 	{
       
   337 	LOG_FUNC
       
   338 
       
   339 	TBool ret = EFalse;
       
   340 	__ASSERT_DEBUG(aItem.Frame(), Panic(EHCIBufferMgrBadState));
       
   341 	if ( iHCIFacade.WriteACLData(*aItem.Frame()) == KErrNone )
       
   342 		{
       
   343 		__ASSERT_DEBUG(iDataQ, Panic(EHCIBufferMgrBadState));
       
   344 		iDataQ->PendingItem(aItem);
       
   345 		ret = ETrue;
       
   346 		}
       
   347 	
       
   348 	LOG1(_L("CACLDataQController::SendItem ret = %d"), ret);
       
   349 	return ret;
       
   350 	}
       
   351 
       
   352 void CACLDataQController::GetBufferInfo(TUint16& aBufSize, TUint& aNumBufs)
       
   353 /**
       
   354 	Retrieves information about what the capabilities of the Data Q are.
       
   355 	This information will be used in order to inform the HCI client about
       
   356 	our MTU and maximum buffers so flow control can be possible.
       
   357 */
       
   358 	{
       
   359 	LOG_FUNC
       
   360 	__ASSERT_DEBUG(iDataQ, Panic(EHCIBufferMgrBadState));
       
   361 	aBufSize = iDataQ->ItemSize();
       
   362 	aNumBufs = iDataQ->Ceiling();
       
   363 
       
   364 	LOG2(_L("CACLDataQController::GetBufferInfo aBufSize = %d, aNumBufs = %d"), 
       
   365 		aBufSize, aNumBufs);
       
   366 	}
       
   367 
       
   368 void CACLDataQController::GetDataQRecords(TUint& aQFillLevel, TUint16& aCredits)
       
   369 /**
       
   370 	Returns the number of things ready to send, and the number of credits we 
       
   371 	have to send
       
   372 **/
       
   373 	{
       
   374 	LOG_FUNC
       
   375 	__ASSERT_DEBUG(iDataQ, Panic(EHCIBufferMgrBadState));
       
   376 	aQFillLevel = iDataQ->FillLevel(); // items in the Q
       
   377 	aCredits = iDataCredits;
       
   378 	LOG2(_L("LL: CACLDataQController: Model: FillLevel %d, FillCeiling %d"),
       
   379 		aQFillLevel, iDataQ->Ceiling());
       
   380 
       
   381 	LOG2(_L("CACLDataQController::GetDataQRecords aQFillLevel = %d, aCredits = %d"), 
       
   382 		aQFillLevel, aCredits);
       
   383 	}
       
   384 
       
   385 void CACLDataQController::FlushOccurred(THCIConnHandle /*aConnH*/)
       
   386 	{
       
   387 	LOG_FUNC
       
   388 	// do nothing
       
   389 	// we will receive a num_completed_packets event
       
   390 	}
       
   391 
       
   392 TInt CACLDataQController::ACLLogicalLinkUp(THCIConnHandle aConnH, TBool aIsParked)
       
   393 /**
       
   394 	This object cares more about *ACL* links
       
   395 	Whether or not ACL comes up for free with physical channel, it
       
   396 	is worth drawing the distinction
       
   397 
       
   398 	If an error occurs we tell the caller - it's likely the ACL will need to 
       
   399 	be torn down
       
   400 **/
       
   401 	{
       
   402 	LOG_FUNC
       
   403 	LOG2(_L("CACLDataQController::ACLLogicalLinkUp aConnH = %d, aIsParked = %d"), 
       
   404 		aConnH, aIsParked);
       
   405 
       
   406 	TDataQConnectionInfo tmpConnRecord;
       
   407 	tmpConnRecord.iConnH = aConnH;
       
   408 	tmpConnRecord.iPacketsQueued = 0;
       
   409 	tmpConnRecord.iPacketsPending = 0;
       
   410 	tmpConnRecord.iParked = aIsParked;
       
   411 
       
   412 	TInt err = iAclConns.Append(tmpConnRecord);
       
   413 
       
   414 	// We don't need to update iIndexOfLastSendingConn because the new 
       
   415 	// connection will have been added 'after' its current position.
       
   416 
       
   417 	LOG1(_L("CACLDataQController::ACLLogicalLinkUp err = %d"), err);
       
   418 	return err;
       
   419 	}
       
   420 
       
   421 void CACLDataQController::ACLLogicalLinkDown(THCIConnHandle aConnH)
       
   422 /**
       
   423 	Updates the Q.
       
   424  */
       
   425 	{
       
   426 	LOG_FUNC
       
   427 	LOG1(_L("CACLDataQController::ACLLogicalLinkDown aConnH = %d"), 
       
   428 		aConnH);
       
   429 
       
   430 	TInt connection = FindConnection(aConnH);
       
   431 		
       
   432 	if ( connection == KErrNotFound )
       
   433 		{
       
   434 		LOG(_L("CACLDataQController::ACLLogicalLinkDown (Connection not found)."));
       
   435 		return;
       
   436 		}
       
   437 
       
   438 	const TUint index = static_cast<TUint>(connection);
       
   439 
       
   440 	const TUint16 dropped = iAclConns[index].iPacketsPending;
       
   441 	LOG1(_L("\treusing %d credits"), dropped);
       
   442 
       
   443 	// Increase iDataCredits by how many packets this link had on the air (we 
       
   444 	// won't receive a num_completed_packets event to do it the normal way)
       
   445 	iDataCredits = static_cast<TUint16>(iDataCredits + dropped);
       
   446 
       
   447 	__ASSERT_DEBUG(iDataQ, Panic(EHCIBufferMgrBadState));
       
   448 	iDataQ->InvalidateByConnH(aConnH, iHCIFacade);
       
   449 	iAclConns.Remove(index);
       
   450 
       
   451 	// The array of connections has changed- if the removed connection is 
       
   452 	// 'after' iIndexOfLastSendingConn, we don't need to bother changing it. 
       
   453 	// If the removed connection IS the connection that sent last, reset it to 
       
   454 	// zero. If the removed connection is before the one that sent last, just 
       
   455 	// decrement iIndexOfLastSendingConn. 
       
   456 	if ( index == iIndexOfLastSendingConn )
       
   457 		{
       
   458 		iIndexOfLastSendingConn = 0;
       
   459 		}
       
   460 	else if ( index < iIndexOfLastSendingConn )
       
   461 		{
       
   462 		--iIndexOfLastSendingConn;
       
   463 		}
       
   464 
       
   465 	__ASSERT_DEBUG(iDataCredits<=iNumControllerBufs, Panic(EHCIACLDataControllerMaxAllowedDataCreditsExceeded));
       
   466 	}
       
   467 
       
   468 void CACLDataQController::SetParked(THCIConnHandle aConnH, TBool aParked)
       
   469 	{
       
   470 	LOG_FUNC
       
   471 	LOG2(_L("CACLDataQController::SetParked aConnH = %d, aParked = %d"), 
       
   472 		aConnH, aParked);
       
   473 
       
   474 	// Check if there are any data connections.
       
   475 	if ( iAclConns.Count() > 1 )
       
   476 		{
       
   477 		const TInt index = FindConnection(aConnH);
       
   478 		if(index != KErrNotFound)
       
   479 			{
       
   480 			iAclConns[index].iParked = aParked;
       
   481 			}
       
   482 		else
       
   483 			{
       
   484 			LOG(_L("\tConnection handle not found."));
       
   485 			}
       
   486 		}
       
   487 	else
       
   488 		{
       
   489 		LOG(_L("\tcurrently no ACL connections"));
       
   490 		}
       
   491 
       
   492 	if ( aParked == EFalse )
       
   493 		{
       
   494 		// kick off draining of queue
       
   495 		iLinkMuxer.TryToSend();
       
   496 		}
       
   497 	}
       
   498 
       
   499 void CACLDataQController::CompletedPackets(THCIConnHandle aConnH, TUint16 aNo)
       
   500 /**
       
   501 	Called when some buffer slots become free in our HC (a 
       
   502 	NumberOfCompletedPackets event)- in other words, we can now send aNo more 
       
   503 	packets down if we wish.
       
   504  */
       
   505 	{
       
   506 	LOG_FUNC
       
   507 	LOG2(_L("CACLDataQController::CompletedPackets aConnH = %d, aNo = %d"), 
       
   508 		aConnH, aNo);
       
   509 
       
   510 	// Adjust the connection that's just had packets put on the air
       
   511 	const TInt index = FindConnection(aConnH);
       
   512 
       
   513 	//We have to check pending packets because it is possible this completed packets event comes 
       
   514 	//from a previous link and current link reuses the same connection handle
       
   515 	if (index!=KErrNotFound && iAclConns[index].iPacketsPending > 0)
       
   516 		{
       
   517 		iAclConns[index].iPacketsPending = static_cast<TUint16>(iAclConns[index].iPacketsPending - aNo);
       
   518 		
       
   519 		LOG4(_L("\t%d completed packets for connection handle %d: iPacketsQueued = %d, iPacketsPending = %d"),
       
   520 			aNo, aConnH, iAclConns[index].iPacketsQueued, iAclConns[index].iPacketsPending);
       
   521 
       
   522 		iDataCredits = static_cast<TUint16>(iDataCredits + aNo);
       
   523 		__ASSERT_DEBUG(iDataCredits<=iNumControllerBufs, Panic(EHCIACLDataControllerMaxAllowedDataCreditsExceeded));
       
   524 
       
   525 		LOG3(_L("LinkMgr: CACLDataQController: Got %d DataCredits on ConnH 0x%04x: total %d DataCredts"), 
       
   526 			aNo, aConnH, iDataCredits);
       
   527 		LOG2(_L("LL: CACLDataQController: Got %d DataCredits; total %d DataCredts"),
       
   528 			aNo,iDataCredits);
       
   529 			
       
   530 		// Notify sent items.
       
   531 		iDataQ->ItemsSent(aNo);
       
   532 		
       
   533 		// now we have credits - have a go at using them
       
   534 		iLinkMuxer.TryToSend();
       
   535 		}
       
   536 	else
       
   537 		{
       
   538 		LOG1(_L("LinkMgr: CACLDataQController: Got Completed Packets on lost ConnH(%d) [dropped?]"), aConnH);
       
   539 		//The Hardware has sent num_completed_packets for a ConnH which we don't know about,
       
   540 		//if this was a race with the connection being dropped we will already have reused the
       
   541 		//credits.
       
   542 		}
       
   543 	}
       
   544 
       
   545 #pragma warning (default:4244)// "conversion from 'int' to 'unsigned short', possible loss of data"
       
   546 
       
   547 TInt CACLDataQController::FindConnection(THCIConnHandle aConnH)
       
   548 /**
       
   549  Returns the index (in iAclConns) of the connection record with THCIConnHandle 
       
   550  aConnH, or error.
       
   551  */
       
   552 	{
       
   553 	LOG_FUNC
       
   554 	LOG2(_L("CACLDataQController::FindConnection aConnH = %d, iAclConns.Count() = %d"), 
       
   555 		aConnH, iAclConns.Count());
       
   556 
       
   557 	TDataQConnectionInfo tmpInfo;
       
   558 	tmpInfo.iConnH = aConnH;
       
   559 
       
   560 	TIdentityRelation<TDataQConnectionInfo> relation(LinkMatch);
       
   561 
       
   562 	const TInt position = iAclConns.Find(tmpInfo, relation);
       
   563 
       
   564 	LOG1(_L("CACLDataQController::FindConnection position = %d"), position);
       
   565 	return position;
       
   566 	}
       
   567 
       
   568 /*static*/ TBool CACLDataQController::LinkMatch(const TDataQConnectionInfo& aA,
       
   569 									 const TDataQConnectionInfo& aB)
       
   570 	{
       
   571 	LOG_STATIC_FUNC
       
   572 	return (aA.iConnH == aB.iConnH);
       
   573 	}
       
   574 
       
   575 void CACLDataQController::FlushComplete(TInt __DEBUG_ONLY(aErr), THCIConnHandle aConnH)
       
   576 	{
       
   577 	LOG_FUNC
       
   578 	__ASSERT_DEBUG(aErr == KErrNone || aErr == ECommandDisallowed, Panic(EHCIACLDataControllerFlushCompleteError));
       
   579 		 
       
   580 	TInt ix = FindConnection(aConnH);
       
   581 	__ASSERT_DEBUG(ix != KErrNotFound, Panic(EHCIACLDataControllerFlushCompleteError));
       
   582 	if(ix != KErrNotFound)
       
   583 		{
       
   584 		__ASSERT_DEBUG(iAclConns[ix].iFlushInProgress, Panic(EHCIACLDataControllerFlushCompleteError));
       
   585 		iAclConns[ix].iFlushInProgress = EFalse;
       
   586 
       
   587 		iLinkMuxer.TryToSend();
       
   588 		}
       
   589 	}
       
   590 	
       
   591 	
       
   592 TInt CACLDataQController::SetFlushInProgress(THCIConnHandle aConnH)
       
   593 	{
       
   594 	LOG_FUNC
       
   595 	// Check a flush is not currently outstanding against this
       
   596 	// Connection handle.
       
   597 	TInt rerr = KErrNone;
       
   598 	TInt ix = FindConnection(aConnH);
       
   599 	if(ix != KErrNotFound)
       
   600 		{
       
   601 		if(!iAclConns[ix].iFlushInProgress)
       
   602 			{
       
   603 			TRAP(rerr, iHCIFacade.FlushL(aConnH));
       
   604 			if(rerr == KErrNone)
       
   605 				{
       
   606 				iAclConns[ix].iFlushInProgress = ETrue;
       
   607 				}
       
   608 			}
       
   609 			
       
   610 		if(rerr == KErrNone)
       
   611 			{
       
   612 			iDataQ->ProcessFlush(iHCIFacade, aConnH);
       
   613 			}
       
   614 		}
       
   615 	else
       
   616 		{
       
   617 		rerr = ix;
       
   618 		}
       
   619 
       
   620 	return rerr;
       
   621 	}
       
   622 
       
   623 //
       
   624 // End of file