|
1 // Copyright (c) 2004-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 // Implements the handling of l2cap signal packets (both inbound and outbound) from SAP interface |
|
15 // |
|
16 // |
|
17 |
|
18 #include <bt_sock.h> |
|
19 #include <bluetooth/logger.h> |
|
20 |
|
21 |
|
22 #include "l2capSAPSignalHandler.h" |
|
23 #include "l2capSigStates.h" |
|
24 #include "l2capSigPacketConnection.h" |
|
25 #include "l2capSigPacketConfigure.h" |
|
26 #include "l2capSigPacketDisconnection.h" |
|
27 #include "l2capSigPacketEcho.h" |
|
28 #include "l2capSigPacketCommandReject.h" |
|
29 #include "l2util.h" |
|
30 #include "l2sap.h" |
|
31 #include "l2cap.h" |
|
32 |
|
33 #include "l2capEntityConfig.h" |
|
34 #include "l2signalmgr.h" |
|
35 |
|
36 #ifdef __FLOG_ACTIVE |
|
37 _LIT8(KLogComponent, LOG_COMPONENT_L2CAP); |
|
38 #endif |
|
39 |
|
40 /*static*/ CL2CapSAPSignalHandler* CL2CapSAPSignalHandler::NewL(CL2CAPConnectionSAP& aSAP) |
|
41 { |
|
42 LOG_STATIC_FUNC |
|
43 CL2CapSAPSignalHandler* self = new(ELeave) CL2CapSAPSignalHandler(aSAP); |
|
44 CleanupStack::PushL(self); |
|
45 self->ConstructL(); |
|
46 CleanupStack::Pop(); |
|
47 return self; |
|
48 } |
|
49 |
|
50 // Disable warning WINS 4355: 'this' : used in base member initializer list |
|
51 // This will not cause any problems in this usage and is preferable to the use of a |
|
52 // non-owned pointer. |
|
53 #pragma warning (disable: 4355) |
|
54 CL2CapSAPSignalHandler::CL2CapSAPSignalHandler(CL2CAPConnectionSAP& aSAP) |
|
55 : CL2CapSignalHandler(), |
|
56 iSAP(&aSAP), |
|
57 iLocalBTAddress(TBTDevAddr(0)), |
|
58 iDefaultRTXTimerDuration(HL2CapCommand::KDefaultRTXTimerDuration), |
|
59 iERTXTimerDuration(HL2CapCommand::KDefaultERTXTimerDuration), |
|
60 iSigState(&aSAP.Protocol().SigStateFactory().GetState(CL2CAPSignalStateFactory::EClosed)), |
|
61 iSAPSignalHandlerTimerState(ETimerIdle) |
|
62 { |
|
63 LOG_FUNC |
|
64 } |
|
65 #pragma warning (default: 4355) |
|
66 |
|
67 void CL2CapSAPSignalHandler::ConstructL() |
|
68 { |
|
69 LOG_FUNC |
|
70 iChannelConfig = CL2CapChannelConfig::NewL(*this); |
|
71 LOG2(_L("CL2CapSAPSignalHandler.iChannelConfig = %X.%X"), (TAny*)this, (TAny*)iChannelConfig) |
|
72 } |
|
73 |
|
74 CL2CapSAPSignalHandler::~CL2CapSAPSignalHandler() |
|
75 { |
|
76 LOG_FUNC |
|
77 DetachFromMux(); |
|
78 delete iChannelConfig; |
|
79 |
|
80 __ASSERT_DEBUG(iMuxer == NULL, Panic(EL2CAPSigHandlerDeletedWithResources)); |
|
81 // If our ConstructL leaves we will be deleted with iSAP non-NULL. This is ok as |
|
82 // the SAP will also be deleted as part of the cleanup process. Because it's useful |
|
83 // to keep this assert for the normal case we test iChannelConfig (which may never be |
|
84 // NULL after ConstructL) to detect the case where ConstructL has left and iSAP may |
|
85 // validly be non-NULL |
|
86 __ASSERT_DEBUG((iSAP == NULL) || (iChannelConfig == NULL), Panic(EL2CAPSigHandlerDeletedWithResources)); |
|
87 } |
|
88 |
|
89 TInt CL2CapSAPSignalHandler::ConstructConnectionResponse(TUint8 aId, TConnectResponseResult aResult, TConnectResponseStatus aStatus/*= EConnectPendNoFurtherInfo*/) |
|
90 { |
|
91 LOG_FUNC |
|
92 TInt rerr = KErrNone; |
|
93 |
|
94 HL2CapCommand* command = HConnectionResponse::New(aId, iLocalPort, iRemotePort, aResult, aStatus); |
|
95 if(command) |
|
96 { |
|
97 AddToOutgoingQueue(command); |
|
98 } |
|
99 else |
|
100 { |
|
101 rerr = KErrNoMemory; |
|
102 } |
|
103 return rerr; |
|
104 } |
|
105 |
|
106 TInt CL2CapSAPSignalHandler::ConstructConnectionRequest() |
|
107 { |
|
108 LOG_FUNC |
|
109 TInt rerr = KErrNone; |
|
110 |
|
111 HL2CapCommand* command = HConnectionRequest::New(iLocalPort, iRemotePort, CurrentRTXTimerDuration(iDefaultRTXTimerDuration), iERTXTimerDuration); |
|
112 if(command) |
|
113 { |
|
114 AddToOutgoingQueue(command); |
|
115 } |
|
116 else |
|
117 { |
|
118 rerr = KErrNoMemory; |
|
119 } |
|
120 return rerr; |
|
121 } |
|
122 |
|
123 |
|
124 TInt CL2CapSAPSignalHandler::ConstructConfigRequest() |
|
125 { |
|
126 LOG_FUNC |
|
127 TInt rerr = KErrNone; |
|
128 |
|
129 HL2CapCommand* command = HConfigureRequest::New(RemotePort(), *iChannelConfig, CurrentRTXTimerDuration(iDefaultRTXTimerDuration), iERTXTimerDuration); |
|
130 if(command) |
|
131 { |
|
132 AddToOutgoingQueue(command); |
|
133 } |
|
134 else |
|
135 { |
|
136 rerr = KErrNoMemory; |
|
137 } |
|
138 return rerr; |
|
139 } |
|
140 |
|
141 /** |
|
142 Used for constructing a configuration response for unknown parameters |
|
143 @internalComponent |
|
144 **/ |
|
145 TInt CL2CapSAPSignalHandler::ConstructConfigResponse(TUint8 aId, TConfigFlags aFlags, TConfigResponseResult aResult, RMBufChain& aUnknownParameters) |
|
146 { |
|
147 LOG_FUNC |
|
148 TInt rerr = KErrNone; |
|
149 |
|
150 HConfigureResponse* command = HConfigureResponse::New(aId, RemotePort(), aFlags, aResult); |
|
151 if(command) |
|
152 { |
|
153 command->AddUnknownOptionsToCommand(aUnknownParameters); |
|
154 AddToOutgoingQueue(command); |
|
155 } |
|
156 else |
|
157 { |
|
158 rerr = KErrNoMemory; |
|
159 } |
|
160 return rerr; |
|
161 } |
|
162 |
|
163 |
|
164 TInt CL2CapSAPSignalHandler::ConstructConfigResponse(TUint8 aId, TConfigFlags aFlags, TConfigResponseResult aResult) |
|
165 { |
|
166 LOG_FUNC |
|
167 TInt rerr = KErrNone; |
|
168 |
|
169 HConfigureResponse* command = HConfigureResponse::New(aId, RemotePort(), aFlags, aResult); |
|
170 if(command) |
|
171 { |
|
172 // Only add options if this is not a response to a Config Request |
|
173 // with the C-flag set. |
|
174 if(aFlags & KConfigOptionContinuationMask) |
|
175 { |
|
176 command->WriteDataLength(); |
|
177 } |
|
178 else if (aResult == EConfigSuccess || aResult == EConfigUnacceptableParams) |
|
179 { |
|
180 // Add the options |
|
181 rerr = command->AddOptionsToCommand(*iChannelConfig, aResult); |
|
182 if(rerr != KErrNone) |
|
183 { |
|
184 delete command; |
|
185 command = NULL; |
|
186 } |
|
187 } |
|
188 |
|
189 if(command) |
|
190 { |
|
191 AddToOutgoingQueue(command); |
|
192 } |
|
193 } |
|
194 else |
|
195 { |
|
196 rerr = KErrNoMemory; |
|
197 } |
|
198 return rerr; |
|
199 } |
|
200 |
|
201 TInt CL2CapSAPSignalHandler::ConstructDisconnectRequest() |
|
202 { |
|
203 LOG_FUNC |
|
204 TInt rerr = KErrNone; |
|
205 |
|
206 HL2CapCommand* command = HDisconnectRequest::New(iLocalPort, iRemotePort, CurrentRTXTimerDuration(iDefaultRTXTimerDuration), iERTXTimerDuration); |
|
207 if(command) |
|
208 { |
|
209 AddToOutgoingQueue(command); |
|
210 } |
|
211 else |
|
212 { |
|
213 rerr = KErrNoMemory; |
|
214 } |
|
215 return rerr; |
|
216 } |
|
217 |
|
218 TInt CL2CapSAPSignalHandler::ConstructDisconnectResponse(TUint8 aId) |
|
219 { |
|
220 LOG_FUNC |
|
221 TInt rerr = KErrNone; |
|
222 |
|
223 HL2CapCommand* command = HDisconnectResponse::New(aId, iLocalPort, iRemotePort); |
|
224 if(command) |
|
225 { |
|
226 AddToOutgoingQueue(command); |
|
227 } |
|
228 else |
|
229 { |
|
230 rerr = KErrNoMemory; |
|
231 } |
|
232 return rerr; |
|
233 } |
|
234 |
|
235 |
|
236 TBool CL2CapSAPSignalHandler::HandleConnectionResponse(HConnectionResponse* aConnectionResponse) |
|
237 { |
|
238 LOG_FUNC |
|
239 TBool rcode = EFalse; |
|
240 |
|
241 // Check the response is for this CID. |
|
242 if(aConnectionResponse->SourceCID() == iLocalPort) |
|
243 { |
|
244 // Check that the Connection Response has been requested. |
|
245 HL2CapCommand* requestCommand = FindMatchingOutstandingRequest(EConnectionRequest, aConnectionResponse->ID()); |
|
246 if(requestCommand) |
|
247 { |
|
248 // If this has a pending result. Re-start the the Extended RTX timer |
|
249 // on the Request. |
|
250 if(aConnectionResponse->Result() == EConnectPending) |
|
251 { |
|
252 requestCommand->StartRTXTimer(HL2CapCommand::EERTXTimer, *this); |
|
253 } |
|
254 else |
|
255 { |
|
256 // Delete the request. |
|
257 delete requestCommand; |
|
258 } |
|
259 |
|
260 iSigState->ConnectResponse(*this, aConnectionResponse); // the state m/c will update the Destination CID |
|
261 } |
|
262 else |
|
263 { |
|
264 LOG(_L("CL2CapSAPSignalHandler::HandleConnectionResponse, no matching req")); |
|
265 } |
|
266 |
|
267 // NOTE: If there was no Connection Request outstanding |
|
268 // (i.e., requestCommand == NULL) but the command IS for this |
|
269 // CID this could be a duplicate response, one that has arrived in |
|
270 // the window between RTX expiry and retransmission, or just bogus. |
|
271 // Silently discard the packet. |
|
272 rcode = ETrue; |
|
273 } |
|
274 |
|
275 return rcode; |
|
276 } |
|
277 |
|
278 |
|
279 TBool CL2CapSAPSignalHandler::HandleConfigureRequest(HConfigureRequest* aConfigRequest) |
|
280 { |
|
281 LOG_FUNC |
|
282 TBool rcode = EFalse; |
|
283 |
|
284 // Check the response is for this CID. |
|
285 if(aConfigRequest->DestinationCID() == iLocalPort) |
|
286 { |
|
287 iSigState->ConfigRequest(*this, aConfigRequest); |
|
288 rcode = ETrue; |
|
289 } |
|
290 |
|
291 return rcode; |
|
292 } |
|
293 |
|
294 |
|
295 TBool CL2CapSAPSignalHandler::HandleConfigureResponse(HConfigureResponse* aConfigResponse) |
|
296 { |
|
297 LOG_FUNC |
|
298 TBool rcode = EFalse; |
|
299 |
|
300 // Check the response is for this CID. |
|
301 if(aConfigResponse->SourceCID() == iLocalPort) |
|
302 { |
|
303 // Check that the Config Response has been requested. |
|
304 HL2CapCommand* requestCommand = FindMatchingOutstandingRequest(EConfigureRequest, aConfigResponse->ID()); |
|
305 if(requestCommand) |
|
306 { |
|
307 // Delete the corresponding request. |
|
308 delete requestCommand; |
|
309 |
|
310 iSigState->ConfigResponse(*this, aConfigResponse); |
|
311 } |
|
312 // NOTE: If there was no Configure Request outstanding |
|
313 // (i.e., requestCommand == NULL) this could be a duplicate |
|
314 // response, or just bogus. Silently discard the packet. |
|
315 rcode = ETrue; |
|
316 } |
|
317 |
|
318 return rcode; |
|
319 } |
|
320 |
|
321 TBool CL2CapSAPSignalHandler::HandleDisconnectRequest(HDisconnectRequest* aDisconnectRequest) |
|
322 { |
|
323 LOG_FUNC |
|
324 TBool rcode = EFalse; |
|
325 |
|
326 // Check the response is for this CID. |
|
327 if(aDisconnectRequest->DestinationCID() == iLocalPort && |
|
328 aDisconnectRequest->SourceCID() == iRemotePort) |
|
329 { |
|
330 iSigState->DisconnectRequest(*this, aDisconnectRequest->ID()); |
|
331 rcode = ETrue; |
|
332 } |
|
333 |
|
334 return rcode; |
|
335 } |
|
336 |
|
337 TBool CL2CapSAPSignalHandler::HandleDisconnectResponse(HDisconnectResponse* aDisconnectResponse) |
|
338 { |
|
339 LOG_FUNC |
|
340 TBool rcode = EFalse; |
|
341 |
|
342 // Check the response is for this CID. |
|
343 if(aDisconnectResponse->DestinationCID() == iRemotePort && |
|
344 aDisconnectResponse->SourceCID() == iLocalPort) |
|
345 { |
|
346 // Check that the Disconnect Response has been requested. |
|
347 HL2CapCommand* requestCommand = FindMatchingOutstandingRequest(EDisconnectionRequest, aDisconnectResponse->ID()); |
|
348 if(requestCommand) |
|
349 { |
|
350 // Delete the corresponding request. |
|
351 delete requestCommand; |
|
352 |
|
353 iSigState->DisconnectResponse(*this); |
|
354 } |
|
355 // NOTE: If there was no Disconnect Request outstanding |
|
356 // (i.e., requestCommand == NULL) this could be a duplicate |
|
357 // response, or just bogus. Silently discard the packet. |
|
358 rcode = ETrue; |
|
359 } |
|
360 |
|
361 return rcode; |
|
362 } |
|
363 |
|
364 |
|
365 TBool CL2CapSAPSignalHandler::HandleCommandReject(HCommandReject* aCommandReject) |
|
366 { |
|
367 LOG_FUNC |
|
368 TBool rcode = EFalse; |
|
369 |
|
370 // Process the incoming command reject data |
|
371 TL2CAPCommandRejectData rejectData; |
|
372 |
|
373 if (aCommandReject->RejectData(rejectData) != KErrNone) return rcode; |
|
374 |
|
375 switch(rejectData.iReason) |
|
376 { |
|
377 case EInvalidCID: |
|
378 { |
|
379 TBool forThisChannel = EFalse; |
|
380 |
|
381 // To be considered as 'for this channel', either both pairs should match |
|
382 // OR only one of the endpoints should be present and match. |
|
383 if(rejectData.iLocalEndpoint != 0 && |
|
384 rejectData.iLocalEndpoint == iRemotePort) |
|
385 { |
|
386 forThisChannel = ETrue; |
|
387 } |
|
388 |
|
389 if(rejectData.iRemoteEndpoint != 0) |
|
390 { |
|
391 if(rejectData.iRemoteEndpoint == iLocalPort) |
|
392 { |
|
393 forThisChannel = ETrue; |
|
394 } |
|
395 else |
|
396 { |
|
397 forThisChannel = EFalse; |
|
398 } |
|
399 } |
|
400 |
|
401 if(forThisChannel) |
|
402 { |
|
403 LOG1(_L("CL2CapSAPSignalHandler::HandleCommandReject(): forThisChannel = ETrue for commandID = 0x%04x"),aCommandReject->ID()) |
|
404 LOG2(_L("rejectData.iLocalEndpoint = 0x%04x, iRemotePort = 0x%04x"),rejectData.iLocalEndpoint,iRemotePort) |
|
405 LOG2(_L("rejectData.iRemoteEndpoint = 0x%04x, iLocalPort = 0x%04x"),rejectData.iRemoteEndpoint,iLocalPort) |
|
406 |
|
407 // If there is no matching command then this rejection is not for this handler |
|
408 if (FindMatchingOutstandingRequest(EMatchAnyL2CAPRequest,aCommandReject->ID())) |
|
409 { |
|
410 // The channel has been disconnected or is not |
|
411 // recognised by the peer. Error the channel. |
|
412 iSigState->Error(*this, KErrL2PeerRejectedCommand, MSocketNotify::EErrorAllOperations); |
|
413 rcode = ETrue; |
|
414 } |
|
415 else |
|
416 { |
|
417 LOG(_L("CL2CapSAPSignalHandler::HandleCommandReject(): No matching command is found, skipping it")) |
|
418 } |
|
419 } |
|
420 break; |
|
421 } |
|
422 default: |
|
423 break; |
|
424 }; |
|
425 |
|
426 return rcode; |
|
427 } |
|
428 |
|
429 void CL2CapSAPSignalHandler::CloneChannelConfig(CL2CapChannelConfig& aL2CAPChannelConfig) |
|
430 { |
|
431 LOG_FUNC |
|
432 iChannelConfig->CloneChannelConfig(aL2CAPChannelConfig); |
|
433 } |
|
434 |
|
435 |
|
436 TInt CL2CapSAPSignalHandler::UpdateChannelConfig(const TL2CapConfig& aAPIConfig) |
|
437 { |
|
438 LOG_FUNC |
|
439 return iSigState->UpdateChannelConfig(*this, aAPIConfig); |
|
440 } |
|
441 |
|
442 void CL2CapSAPSignalHandler::SetState(TL2CAPSigState& aState) |
|
443 { |
|
444 LOG_FUNC |
|
445 LOG2(_L("CL2CapSAPSignalHandler::SetState 0x%08x -> 0x%.8x"), iSigState, &aState); |
|
446 |
|
447 iSigState->Exit(*this); |
|
448 iSigState = &aState; |
|
449 iSigState->Enter(*this); |
|
450 } |
|
451 |
|
452 void CL2CapSAPSignalHandler::SetLocalPort(TL2CAPPort aPort) |
|
453 { |
|
454 LOG_FUNC |
|
455 LOG1(_L("Setting local port to %d"), aPort); |
|
456 iLocalPort = aPort; |
|
457 } |
|
458 |
|
459 void CL2CapSAPSignalHandler::SetRemotePort(TL2CAPPort aPort) |
|
460 { |
|
461 LOG_FUNC |
|
462 LOG1(_L("Setting remote port to %d"), aPort); |
|
463 iRemotePort = aPort; |
|
464 } |
|
465 |
|
466 void CL2CapSAPSignalHandler::SetRemName(TL2CAPSockAddr& aAddr) |
|
467 { |
|
468 LOG_FUNC |
|
469 SetRemotePort(aAddr.Port()); |
|
470 } |
|
471 |
|
472 void CL2CapSAPSignalHandler::GetRemName(TL2CAPSockAddr& aAddr) const |
|
473 { |
|
474 LOG_FUNC |
|
475 aAddr.SetBTAddr(RemoteBTAddress()); |
|
476 aAddr.SetPort(iRemotePort); |
|
477 } |
|
478 |
|
479 void CL2CapSAPSignalHandler::SetLocalParameters(TL2CAPSockAddr& aAddr) |
|
480 { |
|
481 LOG_FUNC |
|
482 iLocalBTAddress = aAddr.BTAddr(); |
|
483 LOGBTDEVADDR(iLocalBTAddress); |
|
484 SetLocalPort(aAddr.Port()); |
|
485 } |
|
486 |
|
487 void CL2CapSAPSignalHandler::GetLocalParameters(TL2CAPSockAddr& aAddr) const |
|
488 { |
|
489 LOG_FUNC |
|
490 aAddr.SetBTAddr(iLocalBTAddress); |
|
491 aAddr.SetPort(iLocalPort); |
|
492 } |
|
493 |
|
494 TInt CL2CapSAPSignalHandler::SetOption(TUint aLevel, TUint aName, const TDesC8& aOption) |
|
495 { |
|
496 LOG_FUNC |
|
497 // iMuxer may be NULL |
|
498 if (iMuxer != NULL) |
|
499 { |
|
500 return iMuxer->SetOption(aLevel, aName, aOption); |
|
501 } |
|
502 else |
|
503 { |
|
504 return KErrNotReady; |
|
505 } |
|
506 } |
|
507 |
|
508 |
|
509 TInt CL2CapSAPSignalHandler::GetOption(TUint aLevel, TUint aName, TDes8& aOption) const |
|
510 { |
|
511 LOG_FUNC |
|
512 // iMuxer may be NULL |
|
513 if (iMuxer != NULL) |
|
514 { |
|
515 return iMuxer->GetOption(aLevel, aName, aOption); |
|
516 } |
|
517 else |
|
518 { |
|
519 return KErrNotReady; |
|
520 } |
|
521 } |
|
522 |
|
523 void CL2CapSAPSignalHandler::SAPSignalHandlerRegistered(CL2CAPMux& aMuxer, TL2CAPEntityConfig& aEntityConfig) |
|
524 { |
|
525 LOG_FUNC |
|
526 __ASSERT_DEBUG(iMuxer == NULL, Panic(EL2CAPSAPSignalHandlerRegisteredTwice)); |
|
527 iMuxer = &aMuxer; |
|
528 iSAP->SetRemoteDev(iMuxer->RemoteBTAddr()); |
|
529 iChannelConfig->RegisterL2CapEntityConfig(aEntityConfig); |
|
530 } |
|
531 |
|
532 |
|
533 // Indicates that the baseband is up and going and that all the objects are tied together ok. |
|
534 void CL2CapSAPSignalHandler::LinkUp() |
|
535 { |
|
536 LOG_FUNC |
|
537 iSAP->LinkUp(); |
|
538 } |
|
539 |
|
540 void CL2CapSAPSignalHandler::Error(TInt aErrorCode, MSocketNotify::TOperationBitmasks aErrorAction) |
|
541 { |
|
542 LOG_FUNC |
|
543 iSigState->Error(*this, aErrorCode, aErrorAction); |
|
544 } |
|
545 |
|
546 //Called by the state machine when we go into channel reconfiguration |
|
547 void CL2CapSAPSignalHandler::ReconfiguringChannel() |
|
548 { |
|
549 LOG_FUNC |
|
550 iSAP->ReconfiguringChannel(); |
|
551 } |
|
552 |
|
553 void CL2CapSAPSignalHandler::SignalHandlerDisconnectedCanClose() |
|
554 { |
|
555 LOG_FUNC |
|
556 // If the SAP exists signal the disconnect. Otherwise delete this |
|
557 // signal handler. |
|
558 if(iSAP) |
|
559 { |
|
560 iSAP->ChannelClosed(); |
|
561 } |
|
562 else |
|
563 { |
|
564 delete this; |
|
565 } |
|
566 } |
|
567 |
|
568 void CL2CapSAPSignalHandler::SignalHandlerErrorD(TInt aErrorCode, MSocketNotify::TOperationBitmasks aErrorAction) |
|
569 { |
|
570 LOG_FUNC |
|
571 // If the SAP exists signal the error. Otherwise delete this |
|
572 // signal handler. |
|
573 if(iSAP) |
|
574 { |
|
575 iSAP->SignalHandlerError(aErrorCode, aErrorAction); |
|
576 } |
|
577 else |
|
578 { |
|
579 delete this; |
|
580 } |
|
581 } |
|
582 |
|
583 //Called by the link signal handler |
|
584 TInt CL2CapSAPSignalHandler::PassiveConnectionRequest(const TBTDevAddr& aAddr,HConnectionRequest* aConnectionRequest) |
|
585 { |
|
586 LOG_FUNC |
|
587 TInt rerr = KErrNone; |
|
588 CL2CAPConnectionSAP *clonedSAP = NULL; |
|
589 |
|
590 TUint8 id = aConnectionRequest->ID(); |
|
591 TL2CAPPort scid = aConnectionRequest->SourceCID(); |
|
592 |
|
593 // Check if the SAP is ready to accept a connection. |
|
594 // Note. If the SAP is not in the listening state this |
|
595 // will return with the not ready error code. |
|
596 if(!iSAP->CanAcceptConnection()) |
|
597 { |
|
598 rerr = KErrNotReady; |
|
599 } |
|
600 else |
|
601 { |
|
602 if((clonedSAP = iSAP->CloneListeningSAP(aAddr)) == NULL) |
|
603 { |
|
604 rerr = KErrNoMemory; |
|
605 } |
|
606 else |
|
607 { |
|
608 CL2CapSAPSignalHandler& clonedSH = clonedSAP->SignalHandler(); |
|
609 |
|
610 clonedSH.iRemotePort = scid; |
|
611 clonedSH.iOutstandingRequestID = id; |
|
612 |
|
613 clonedSH.CloneChannelConfig(*iChannelConfig); |
|
614 rerr = iSAP->Protocol().MuxController().AttachPassiveSignalHandler(clonedSH, aAddr); |
|
615 } |
|
616 } |
|
617 return rerr; |
|
618 } |
|
619 |
|
620 void CL2CapSAPSignalHandler::ActiveConnectionRequest() |
|
621 { |
|
622 LOG_FUNC |
|
623 iMuxer->CompleteACLConnect(NULL); |
|
624 } |
|
625 |
|
626 void CL2CapSAPSignalHandler::L2CapEntityConfigUpdated() |
|
627 { |
|
628 LOG_FUNC |
|
629 if (iOpenChannelRequestAwaitingPeerEntityConfig) |
|
630 { |
|
631 // SAP state machine requested that we open the channel before we could do it. |
|
632 // We can do it now. |
|
633 iOpenChannelRequestAwaitingPeerEntityConfig = EFalse; |
|
634 iSigState->OpenChannelRequest(*this); |
|
635 } |
|
636 } |
|
637 |
|
638 TBool CL2CapSAPSignalHandler::DelayConfigRequest() |
|
639 { |
|
640 LOG_FUNC |
|
641 iAwaitingConfigRequestDelayTimer = iSAPSignalHandlerTimerState==EConfigRequestDelayTimer; |
|
642 |
|
643 return iAwaitingConfigRequestDelayTimer; //true if we are delaying |
|
644 } |
|
645 |
|
646 void CL2CapSAPSignalHandler::ConfigRequestDelayTimerExpiry() |
|
647 { |
|
648 LOG_FUNC |
|
649 if(iAwaitingConfigRequestDelayTimer) |
|
650 { |
|
651 iAwaitingConfigRequestDelayTimer = EFalse; |
|
652 ConfigureChannelRequest(); |
|
653 } |
|
654 } |
|
655 |
|
656 void CL2CapSAPSignalHandler::CloseChannelRequest() |
|
657 { |
|
658 LOG_FUNC |
|
659 iSigState->CloseChannelRequest(*this); |
|
660 } |
|
661 |
|
662 void CL2CapSAPSignalHandler::OpenChannelRequest() |
|
663 { |
|
664 LOG_FUNC |
|
665 __ASSERT_DEBUG(!iOpenChannelRequestAwaitingPeerEntityConfig, |
|
666 Panic(EL2CAPOpenChannelRequestCalledTwice)); |
|
667 |
|
668 if (IsPeerInfoDefined()) |
|
669 { |
|
670 iSigState->OpenChannelRequest(*this); |
|
671 } |
|
672 else |
|
673 { |
|
674 iOpenChannelRequestAwaitingPeerEntityConfig = ETrue; |
|
675 // We'll realize the OpenChannelRequest as soon as we receive |
|
676 // the Information Response. |
|
677 } |
|
678 } |
|
679 |
|
680 void CL2CapSAPSignalHandler::ConnectRequestReceived() |
|
681 { |
|
682 LOG_FUNC |
|
683 iSigState->ConnectRequestReceived(*this); |
|
684 } |
|
685 |
|
686 void CL2CapSAPSignalHandler::ConfigureChannelRequest() |
|
687 { |
|
688 LOG_FUNC |
|
689 iSigState->ConfigureChannelRequest(*this); |
|
690 } |
|
691 |
|
692 void CL2CapSAPSignalHandler::PendingCommandsDrained() |
|
693 { |
|
694 LOG_FUNC |
|
695 iSigState->PendingCommandsDrained(*this); |
|
696 } |
|
697 |
|
698 // SAP signal handler timer methods. |
|
699 /*static*/ TInt CL2CapSAPSignalHandler::TimerExpired(TAny* aSAPSignalHandler) |
|
700 { |
|
701 LOG_STATIC_FUNC |
|
702 CL2CapSAPSignalHandler* sh = reinterpret_cast<CL2CapSAPSignalHandler*>(aSAPSignalHandler); |
|
703 sh->HandleTimerExpired(); |
|
704 return EFalse; |
|
705 } |
|
706 |
|
707 void CL2CapSAPSignalHandler::StartConfigurationTimer() |
|
708 { |
|
709 LOG_FUNC |
|
710 switch(iSAPSignalHandlerTimerState) |
|
711 { |
|
712 case EConfigurationTimer: |
|
713 case EConfigRequestDelayTimer: |
|
714 // The timer is already running. Cancel it and start it again. |
|
715 BTSocketTimer::Remove(iSAPSignalHandlerTimerEntry); |
|
716 iSAPSignalHandlerTimerState = ETimerIdle; |
|
717 break; |
|
718 |
|
719 case ETimerIdle: |
|
720 default: |
|
721 // No timer running, nothing needs to be done. |
|
722 break; |
|
723 }; |
|
724 |
|
725 if(iSAPSignalHandlerTimerState == ETimerIdle) |
|
726 { |
|
727 TCallBack cb(TimerExpired, this); |
|
728 iSAPSignalHandlerTimerEntry.Set(cb); |
|
729 BTSocketTimer::Queue(KL2ConfigRequestDelayTimout, |
|
730 iSAPSignalHandlerTimerEntry); |
|
731 iSAPSignalHandlerTimerState = EConfigRequestDelayTimer; |
|
732 } |
|
733 } |
|
734 |
|
735 void CL2CapSAPSignalHandler::CancelTimer() |
|
736 { |
|
737 |
|
738 LOG_FUNC |
|
739 if(iSAPSignalHandlerTimerState != ETimerIdle) |
|
740 { |
|
741 BTSocketTimer::Remove(iSAPSignalHandlerTimerEntry); |
|
742 iSAPSignalHandlerTimerState = ETimerIdle; |
|
743 } |
|
744 } |
|
745 |
|
746 void CL2CapSAPSignalHandler::HandleTimerExpired() |
|
747 { |
|
748 LOG_FUNC |
|
749 switch(iSAPSignalHandlerTimerState) |
|
750 { |
|
751 case ETimerIdle: |
|
752 Panic(EL2CAPSSHTimerExpiredWhileInIdleState); |
|
753 break; |
|
754 |
|
755 case EConfigRequestDelayTimer: |
|
756 { |
|
757 TCallBack cb(TimerExpired, this); |
|
758 iSAPSignalHandlerTimerEntry.Set(cb); |
|
759 BTSocketTimer::Queue(KL2ConfigWatchdogTimeout * KL2ProtocolSecondTimerMultiplier, |
|
760 iSAPSignalHandlerTimerEntry); |
|
761 iSAPSignalHandlerTimerState = EConfigurationTimer; |
|
762 ConfigRequestDelayTimerExpiry(); |
|
763 } |
|
764 break; |
|
765 |
|
766 case EConfigurationTimer: |
|
767 iSAPSignalHandlerTimerState = ETimerIdle; |
|
768 iSigState->ConfigurationTimerExpiry(*this); |
|
769 break; |
|
770 |
|
771 default: |
|
772 Panic(EL2CAPInvalidSAPSHTimerState); |
|
773 break; |
|
774 }; |
|
775 } |
|
776 |
|
777 void CL2CapSAPSignalHandler::DetachFromMux() |
|
778 { |
|
779 LOG_FUNC |
|
780 __ASSERT_DEBUG(iPendingCommands.IsEmpty(), Panic(EL2CAPSigHandlerDeletedWithResources)); |
|
781 __ASSERT_DEBUG(iCommandsAwaitingResponse.IsEmpty(), Panic(EL2CAPSigHandlerDeletedWithResources)); |
|
782 |
|
783 // If this is a listening Socket then it will not have |
|
784 // an associated muxer to detach. |
|
785 if(iMuxer) |
|
786 { |
|
787 iLink.Deque(); |
|
788 |
|
789 iMuxer->DetachFromMux(*this); |
|
790 |
|
791 // Check to see if the stack needs to be brought down |
|
792 iMuxer->MuxController().Protocol().TryToClose(); |
|
793 |
|
794 iMuxer = NULL; |
|
795 |
|
796 // If the SAP's Config object has registered with the Entity |
|
797 // Config object then remove this association. |
|
798 iChannelConfig->DetachChannelConfig(); |
|
799 } |
|
800 } |
|
801 |
|
802 void CL2CapSAPSignalHandler::SAPClosed() |
|
803 { |
|
804 LOG_FUNC |
|
805 // The SAP is about to be detached from this signal handler. |
|
806 // Ensure no park overrides are active. |
|
807 UndoOverrideParkMode(); |
|
808 |
|
809 // Check if this SH has any unsent commands |
|
810 // outstanding. |
|
811 iSAP = NULL; |
|
812 if(iMuxer == NULL) |
|
813 { |
|
814 delete this; |
|
815 } |
|
816 } |
|
817 |
|
818 void CL2CapSAPSignalHandler::CommandResponseFailure(HL2CapCommand* aCommand) |
|
819 { |
|
820 LOG_FUNC |
|
821 // Pass on this error to the state and delete the command. |
|
822 iSigState->Error(*this, KErrL2CAPRequestTimeout, MSocketNotify::EErrorAllOperations); |
|
823 delete aCommand; |
|
824 } |
|
825 |
|
826 TInt CL2CapSAPSignalHandler::SendEchoRequest(const TDes8* aData) |
|
827 { |
|
828 LOG_FUNC |
|
829 TInt rerr = KErrNone; |
|
830 if(iMuxer) |
|
831 { |
|
832 // Check to ensure that the echo payload isn't too big to send |
|
833 if ((!aData) || (aData->Size() <= iMuxer->SigMTU() - HEchoRequest::KEchoRequestEmptyLength)) |
|
834 { |
|
835 rerr = iMuxer->SendEchoRequest(aData, *this); |
|
836 } |
|
837 else |
|
838 { |
|
839 rerr = KErrTooBig; |
|
840 } |
|
841 } |
|
842 else |
|
843 { |
|
844 rerr = KErrDisconnected; |
|
845 } |
|
846 return rerr; |
|
847 } |
|
848 |
|
849 void CL2CapSAPSignalHandler::EchoResponseReceived(const TDesC8* aData) |
|
850 { |
|
851 LOG_FUNC |
|
852 if(iSAP) |
|
853 { |
|
854 iSAP->EchoResponseReceived(aData); |
|
855 } |
|
856 } |
|
857 |
|
858 TInt CL2CapSAPSignalHandler::SetRTXTimerDuration(TUint8 aDuration) |
|
859 { |
|
860 LOG_FUNC |
|
861 TInt rerr = KErrNone; |
|
862 if(aDuration > 0 && aDuration < HL2CapCommand::KMaxRTXTimerDuration) |
|
863 { |
|
864 iDefaultRTXTimerDuration = aDuration; |
|
865 } |
|
866 else |
|
867 { |
|
868 rerr = KErrArgument; |
|
869 } |
|
870 return rerr; |
|
871 } |
|
872 |
|
873 TInt CL2CapSAPSignalHandler::SetERTXTimerDuration(TUint16 aDuration) |
|
874 { |
|
875 LOG_FUNC |
|
876 TInt rerr = KErrNone; |
|
877 if(aDuration > 0 && aDuration < HL2CapCommand::KMaxERTXTimerDuration) |
|
878 { |
|
879 iERTXTimerDuration = aDuration; |
|
880 } |
|
881 else |
|
882 { |
|
883 rerr = KErrArgument; |
|
884 } |
|
885 return rerr; |
|
886 } |
|
887 |
|
888 void CL2CapSAPSignalHandler::OverrideParkMode() |
|
889 { |
|
890 LOG_FUNC |
|
891 // Override Park mode. A reference to the SAP is required |
|
892 // to get the remote device address. |
|
893 if(iSAP) |
|
894 { |
|
895 iSAP->Protocol().ControlPlane().ModifyPhysicalLink(EOverridePark, iSAP->RemoteDev()); |
|
896 } |
|
897 } |
|
898 |
|
899 void CL2CapSAPSignalHandler::UndoOverrideParkMode() |
|
900 { |
|
901 LOG_FUNC |
|
902 // Remove Park mode override. A reference to the SAP is required |
|
903 // to get the remote device address. |
|
904 if(iSAP) |
|
905 { |
|
906 iSAP->Protocol().ControlPlane().ModifyPhysicalLink(EUndoOverridePark, iSAP->RemoteDev()); |
|
907 } |
|
908 } |
|
909 |
|
910 void CL2CapSAPSignalHandler::OverrideLPMWithTimeout() |
|
911 { |
|
912 LOG_FUNC |
|
913 // Temporarily override all low power modes. A reference to the SAP is required |
|
914 // to get the remote device address. |
|
915 if(iSAP) |
|
916 { |
|
917 iSAP->Protocol().ControlPlane().ModifyPhysicalLink(EOverrideLPMWithTimeout, iSAP->RemoteDev()); |
|
918 } |
|
919 } |
|
920 |