|
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 |