|
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 // This implements the CL2CAPProtocol object that is the contact point from |
|
15 // BT PRT to the L2cap stack |
|
16 // |
|
17 // |
|
18 |
|
19 #include <bluetooth/logger.h> |
|
20 #include <bt_sock.h> |
|
21 #include <bluetooth/aclsockaddr.h> |
|
22 |
|
23 #include "l2cap.h" |
|
24 |
|
25 #include "l2sapstates.h" |
|
26 #include "l2util.h" |
|
27 #include "linkmgr.h" |
|
28 #include "l2capSAPSignalHandler.h" |
|
29 #include "l2sap.h" |
|
30 |
|
31 |
|
32 #ifdef _DEBUG |
|
33 #include "L2CapDebugControlInterface.h" |
|
34 #endif |
|
35 |
|
36 #ifdef __FLOG_ACTIVE |
|
37 _LIT8(KLogComponent, LOG_COMPONENT_L2CAP); |
|
38 #endif |
|
39 |
|
40 // Construction & Initialisation |
|
41 |
|
42 CL2CAPProtocol::CL2CAPProtocol(CBTSecMan& aSecMan, RBTControlPlane& aControlPlane, CBTCodServiceMan& aCodMan) |
|
43 : CBluetoothProtocolBase(aSecMan, aControlPlane, aCodMan) |
|
44 { |
|
45 LOG_FUNC |
|
46 TCallBack cb(TryToClose, this); |
|
47 iIdleTimerEntry.Set(cb); |
|
48 } |
|
49 |
|
50 CL2CAPProtocol::~CL2CAPProtocol() |
|
51 { |
|
52 LOG_FUNC |
|
53 RemoveIdleTimerEntry(); |
|
54 |
|
55 delete iStateFactory; |
|
56 delete iSigStateFactory; |
|
57 |
|
58 if(LowerProtocol()) |
|
59 { |
|
60 LowerProtocol()->Close(); |
|
61 } |
|
62 |
|
63 // Delete the Mux controller. |
|
64 delete iMuxController; |
|
65 |
|
66 #ifdef _DEBUG |
|
67 SBtTls* tls = static_cast<SBtTls*>(Dll::Tls()); |
|
68 CDebugControlInterface* ptr = tls->iDebugCtrlIF; |
|
69 delete ptr; |
|
70 tls->iDebugCtrlIF = NULL; |
|
71 #endif |
|
72 |
|
73 #ifdef __FLOG_ACTIVE |
|
74 CLOSE_LOGGER |
|
75 #endif |
|
76 } |
|
77 |
|
78 CL2CAPProtocol* CL2CAPProtocol::NewL(CBTSecMan& aSecMan, RBTControlPlane& aControlPlane, CBTCodServiceMan& aCodMan) |
|
79 { |
|
80 #ifdef __FLOG_ACTIVE |
|
81 CONNECT_LOGGER |
|
82 #endif |
|
83 LOG_STATIC_FUNC |
|
84 CL2CAPProtocol* prot = new (ELeave) CL2CAPProtocol(aSecMan, aControlPlane, aCodMan); |
|
85 CleanupStack::PushL(prot); |
|
86 prot->ConstructL(); |
|
87 CleanupStack::Pop(); |
|
88 return prot; |
|
89 } |
|
90 |
|
91 void CL2CAPProtocol::ConstructL() |
|
92 { |
|
93 LOG_FUNC |
|
94 iMuxController = new (ELeave) CL2CAPMuxController(*this); |
|
95 } |
|
96 |
|
97 void CL2CAPProtocol::InitL(TDesC& /*aTag*/) |
|
98 /** |
|
99 Pre-binding initialise. |
|
100 Allocate any objects we need here. |
|
101 The socket ensures that this function will only be called once per |
|
102 object of this class, regardless of how long it hangs around. |
|
103 **/ |
|
104 { |
|
105 LOG_FUNC |
|
106 // Init |
|
107 __ASSERT_DEBUG(!iClosePending, Panic(EL2CAPProtocolOpenedAfterClose)); |
|
108 __ASSERT_DEBUG(!iIdleEntryQueued, Panic(EL2CAPProtocolOpenedAfterClose)); |
|
109 __ASSERT_DEBUG(!iStateFactory, Panic(EL2CAPProtocolOpenedAfterClose)); |
|
110 __ASSERT_DEBUG(!iSigStateFactory, Panic(EL2CAPProtocolOpenedAfterClose)); |
|
111 |
|
112 // Create all the things we need now |
|
113 LOG(_L("L2CAP : Initialising states")); |
|
114 iStateFactory=CL2CAPSAPStateFactory::NewL(); |
|
115 iSigStateFactory=CL2CAPSignalStateFactory::NewL(); |
|
116 LOG(_L("L2CAP : Initialising complete")); |
|
117 |
|
118 #ifdef _DEBUG |
|
119 SBtTls* tls = static_cast<SBtTls*>(Dll::Tls()); |
|
120 tls->iDebugCtrlIF = CDebugControlInterface::NewL(); |
|
121 #endif |
|
122 } |
|
123 |
|
124 |
|
125 void CL2CAPProtocol::StartL() |
|
126 /** |
|
127 Binding complete. |
|
128 Startup call from socket. Do nothing |
|
129 **/ |
|
130 { |
|
131 LOG_FUNC |
|
132 } |
|
133 |
|
134 // From higher protocol |
|
135 void CL2CAPProtocol::BindL(CProtocolBase* /*aProtocol*/, TUint /*aId*/) |
|
136 { |
|
137 // Could register the protocol that's bound to us |
|
138 LOG_FUNC |
|
139 } |
|
140 |
|
141 void CL2CAPProtocol::BindToL(CProtocolBase* aProtocol) |
|
142 { |
|
143 LOG_FUNC |
|
144 #ifdef _DEBUG |
|
145 TServerProtocolDesc prtDesc; |
|
146 aProtocol->Identify(&prtDesc); |
|
147 |
|
148 if(prtDesc.iAddrFamily!=KBTAddrFamily || |
|
149 prtDesc.iProtocol!=KBTLinkManager) |
|
150 { |
|
151 LEAVEL(KErrBtEskError); |
|
152 } |
|
153 #endif |
|
154 aProtocol->BindL(this, 0); |
|
155 aProtocol->Open(); |
|
156 iLowerProtocol = static_cast<CBluetoothProtocolBase*>(aProtocol); |
|
157 } |
|
158 |
|
159 // Factory functions |
|
160 CServProviderBase* CL2CAPProtocol::NewSAPL(TUint aSockType) |
|
161 /** |
|
162 Create a new SAP. |
|
163 The SAP returned is owned by the caller -- this protocol will not clean it up. |
|
164 The socket uses this function to create a new SAP, and the socket will delete when it |
|
165 is finished with it. |
|
166 **/ |
|
167 { |
|
168 LOG_FUNC |
|
169 |
|
170 CL2CAPConnectionSAP* lsap = NULL; |
|
171 |
|
172 switch(aSockType) |
|
173 { |
|
174 case KSockSeqPacket: // packet interface |
|
175 lsap=CL2CAPConnectionSAP::NewL(*this); |
|
176 break; |
|
177 default: |
|
178 LEAVEL(KErrNotSupported); |
|
179 break; |
|
180 } |
|
181 |
|
182 return lsap; |
|
183 } |
|
184 |
|
185 // Query functions |
|
186 |
|
187 void CL2CAPProtocol::Identify(TServerProtocolDesc *aDesc)const |
|
188 // |
|
189 // Identify request from SOCKET server |
|
190 // |
|
191 { |
|
192 LOG_FUNC |
|
193 CL2CAPProtocol::ProtocolIdentity(aDesc); |
|
194 } |
|
195 |
|
196 void CL2CAPProtocol::ProtocolIdentity(TServerProtocolDesc* aDesc) |
|
197 { |
|
198 LOG_STATIC_FUNC |
|
199 _LIT(name,"L2CAP"); |
|
200 aDesc->iProtocol=KL2CAP; |
|
201 aDesc->iName=name; |
|
202 aDesc->iAddrFamily=KBTAddrFamily; |
|
203 aDesc->iSockType=KSockSeqPacket; |
|
204 |
|
205 aDesc->iVersion=TVersion(KBTMajor,KBTMinor,KBTBuild); |
|
206 aDesc->iByteOrder=ELittleEndian; |
|
207 aDesc->iServiceInfo=KL2CAPSeqPacketServiceInfo; |
|
208 aDesc->iNamingServices=0; |
|
209 aDesc->iSecurity=KSocketNoSecurity; |
|
210 aDesc->iMessageSize=KSocketMessageSizeNoLimit; //This is the MAX packet size. |
|
211 aDesc->iServiceTypeInfo=ESocketSupport|ETransport|EPreferMBufChains|ENeedMBufs|EUseCanSend; |
|
212 aDesc->iNumSockets=KL2CAPSockets; |
|
213 } |
|
214 |
|
215 void CL2CAPProtocol::CloseNow() |
|
216 /** |
|
217 Close command from base class. |
|
218 Called when ref count reaches 0. |
|
219 We don't actually have to close now, but when we finally |
|
220 do, we must call CanClose (done within TryToClose). That will |
|
221 actually delete us. In the mean time, if a new client tries |
|
222 to connect to L2CAP, the socket will use this existing one and just |
|
223 call Open on it. |
|
224 What we do here, is queue an idle timer entry. It's expiry will |
|
225 call TryToClose, which will actually do the close. |
|
226 **/ |
|
227 { |
|
228 LOG_FUNC |
|
229 iClosePending = ETrue; |
|
230 QueIdleTimerEntry(); |
|
231 } |
|
232 |
|
233 void CL2CAPProtocol::Open() |
|
234 /** |
|
235 Open L2CAP protocol. |
|
236 Called every time a new client (of L2CAP) wants to use it. |
|
237 **/ |
|
238 { |
|
239 LOG_FUNC |
|
240 iClosePending = EFalse; |
|
241 RemoveIdleTimerEntry(); |
|
242 CProtocolBase::Open(); |
|
243 } |
|
244 |
|
245 void CL2CAPProtocol::Close() |
|
246 { |
|
247 LOG_FUNC |
|
248 CProtocolBase::Close(); |
|
249 } |
|
250 |
|
251 void CL2CAPProtocol::QueIdleTimerEntry() |
|
252 /** |
|
253 Queue idle timer entry. |
|
254 When this timer expires, it'll call TryToClose, which actually |
|
255 causes the thing to finally close down. |
|
256 **/ |
|
257 { |
|
258 LOG_FUNC |
|
259 RemoveIdleTimerEntry(); |
|
260 iIdleEntryQueued = ETrue; |
|
261 BTSocketTimer::Queue(KL2ProtocolIdleTimeout*KL2ProtocolSecondTimerMultiplier, iIdleTimerEntry); |
|
262 } |
|
263 |
|
264 void CL2CAPProtocol::RemoveIdleTimerEntry() |
|
265 /** |
|
266 Called whenever we're opened. |
|
267 Checks there are no idle timer entries queued. |
|
268 **/ |
|
269 { |
|
270 LOG_FUNC |
|
271 if (!iIdleEntryQueued) |
|
272 return; |
|
273 BTSocketTimer::Remove(iIdleTimerEntry); |
|
274 iIdleEntryQueued = EFalse; |
|
275 } |
|
276 |
|
277 void CL2CAPProtocol::TryToClose() |
|
278 { |
|
279 LOG_FUNC |
|
280 if (!iIdleEntryQueued && iClosePending && MuxController().CanProtocolClose()) |
|
281 { |
|
282 CanClose(); |
|
283 } |
|
284 } |
|
285 |
|
286 TInt CL2CAPProtocol::TryToClose(TAny* aProtocol) |
|
287 /* |
|
288 Actually try to close the protocol. |
|
289 Called after the idle timeout period by the BTSocketTimer. If |
|
290 we're all set to close down, the thing is closed. |
|
291 */ |
|
292 { |
|
293 LOG_STATIC_FUNC |
|
294 CL2CAPProtocol* p=static_cast<CL2CAPProtocol*>(aProtocol); |
|
295 p->iIdleEntryQueued = EFalse; |
|
296 p->TryToClose(); |
|
297 return EFalse; |
|
298 } |
|
299 |
|
300 CL2CAPSAPStateFactory& CL2CAPProtocol::StateFactory() const |
|
301 { |
|
302 LOG_FUNC |
|
303 return *iStateFactory; |
|
304 } |
|
305 |
|
306 CL2CAPSignalStateFactory& CL2CAPProtocol::SigStateFactory() const |
|
307 { |
|
308 LOG_FUNC |
|
309 return *iSigStateFactory; |
|
310 } |
|
311 |
|
312 TInt CL2CAPProtocol::BearerConnectComplete(const TBTDevAddr& aAddr, CServProviderBase* aSAP) |
|
313 { |
|
314 LOG_FUNC |
|
315 return iMuxController->BearerConnectComplete(aAddr, aSAP); |
|
316 } |
|
317 |
|
318 const TBTDevAddr& CL2CAPProtocol::LocalBTAddr() const |
|
319 { |
|
320 LOG_FUNC |
|
321 return static_cast<CLinkMgrProtocol*>(iLowerProtocol)->LocalBTAddress(); |
|
322 } |
|
323 |
|
324 TInt CL2CAPProtocol::StartProtocolListening() |
|
325 // forward L2CAPs listening requirements to listener |
|
326 { |
|
327 LOG_FUNC |
|
328 return CBluetoothProtocolBase::StartListening(EACLPortL2CAP, |
|
329 KSockBluetoothTypeACL, |
|
330 KL2CAPIncomingConnQueueSize, |
|
331 KUidServiceL2CAP); |
|
332 } |
|
333 |
|
334 |