|
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 file implements the generic interface to a ESOCK PRT |
|
15 // for the Bluetooth PRT module |
|
16 // |
|
17 // |
|
18 |
|
19 // The Bluetooth protocol family also provides Control-plane facilities |
|
20 // thereby relieving the user-plane SAPs and muxers of these duties |
|
21 #include <bluetooth/logger.h> |
|
22 #include "Avctp.h" |
|
23 #include "bt.h" |
|
24 #include "linkmgr.h" |
|
25 #include "l2cap.h" |
|
26 #include "rfcomm.h" |
|
27 #include "sdp.h" |
|
28 #include "avdtp.h" |
|
29 |
|
30 #include "IncomingConnListener.h" |
|
31 |
|
32 #ifdef __FLOG_ACTIVE |
|
33 _LIT8(KLogComponent, LOG_COMPONENT_BT_PRT); |
|
34 #endif |
|
35 |
|
36 #ifdef _DEBUG |
|
37 PANICCATEGORY("btprt"); |
|
38 #endif |
|
39 |
|
40 _LIT(KBTPrtPanic, "BluetoothPRT Panic"); |
|
41 |
|
42 |
|
43 void Panic(TBluetoothFamilyPanic aPanic) |
|
44 { |
|
45 LOG_STATIC_FUNC |
|
46 User::Panic(KBTPrtPanic, aPanic); |
|
47 } |
|
48 |
|
49 extern "C" |
|
50 { |
|
51 IMPORT_C CProtocolFamilyBase* InstallBTProtocolFamily(); // Force export |
|
52 } |
|
53 |
|
54 EXPORT_C CProtocolFamilyBase* InstallBTProtocolFamily() |
|
55 // Create a new protocol family |
|
56 { |
|
57 LOG_STATIC_FUNC |
|
58 //Return NULL if CBTProtocolFamily::NewL() leaves |
|
59 CProtocolFamilyBase* result=NULL; |
|
60 TRAP_IGNORE(result=CBTProtocolFamily::NewL()); |
|
61 return result; |
|
62 } |
|
63 |
|
64 CBTProtocolFamily* CBTProtocolFamily::NewL() |
|
65 { |
|
66 #ifdef __FLOG_ACTIVE |
|
67 CONNECT_LOGGER |
|
68 #endif |
|
69 LOG_STATIC_FUNC |
|
70 // Flogging can start after the installation of the Blogger |
|
71 // and the instantiation of the HCI |
|
72 // LOG(_L("+CBTProtocolFamily::NewL")); |
|
73 CBTProtocolFamily* pf= new (ELeave) CBTProtocolFamily(); |
|
74 CleanupStack::PushL(pf); |
|
75 pf->ConstructL(); |
|
76 CleanupStack::Pop(); |
|
77 return pf; |
|
78 } |
|
79 |
|
80 CBTProtocolFamily::CBTProtocolFamily() |
|
81 : CProtocolFamilyBase(), |
|
82 iBTRefCount(0) |
|
83 { |
|
84 LOG_FUNC |
|
85 } |
|
86 |
|
87 void CBTProtocolFamily::ConstructL() |
|
88 { |
|
89 LOG_FUNC |
|
90 // install TLS |
|
91 Dll::SetTls(&iBTTls); |
|
92 |
|
93 LOG(_L("+CBTProtocolFamily::ConstructL")); |
|
94 iCallback = new (ELeave) CAsyncCallBack(EPriorityHigh); |
|
95 } |
|
96 |
|
97 CBTProtocolFamily::~CBTProtocolFamily() |
|
98 { |
|
99 LOG_FUNC |
|
100 LOG(_L("+CBTProtocolFamily::~CBTProtocolFamily")); |
|
101 BTSocketTimer::Close(); |
|
102 delete iSecurityMgr; |
|
103 delete iCallback; |
|
104 delete iCodServiceMan; |
|
105 iControlPlane.Close(); |
|
106 Dll::FreeTls(); |
|
107 #ifdef __FLOG_ACTIVE |
|
108 CLOSE_LOGGER |
|
109 #endif |
|
110 } |
|
111 |
|
112 |
|
113 TInt CBTProtocolFamily::Install() |
|
114 { |
|
115 LOG_FUNC |
|
116 |
|
117 TRAPD(err, BTSocketTimer::InitL()); |
|
118 return err; |
|
119 } |
|
120 |
|
121 TInt CBTProtocolFamily::Remove() |
|
122 { |
|
123 LOG_FUNC |
|
124 // set the asynccallback to delete us cleanly |
|
125 return KErrNone; |
|
126 } |
|
127 |
|
128 TUint CBTProtocolFamily::ProtocolList(TServerProtocolDesc*& aProtocolPointer) |
|
129 { |
|
130 LOG_FUNC |
|
131 // This is cleaned up by ESOCK |
|
132 aProtocolPointer = new TServerProtocolDesc[6]; |
|
133 |
|
134 if (!aProtocolPointer) |
|
135 return 0; |
|
136 |
|
137 // Note it helps if the protocols are defined here in the same order |
|
138 // as in the .esk file or Esock's tags will get mis-assigned. |
|
139 |
|
140 CLinkMgrProtocol::ProtocolIdentity(&aProtocolPointer[0]); |
|
141 CL2CAPProtocol::ProtocolIdentity (&aProtocolPointer[1]); |
|
142 #ifdef TCI |
|
143 return 2; |
|
144 #else // !TCI |
|
145 CRfcommProtocol::ProtocolIdentity (&aProtocolPointer[2]); |
|
146 CSdpProtocol::ProtocolIdentity (&aProtocolPointer[3]); |
|
147 #ifndef BLUETOOTH_NO_AV |
|
148 CAvctpProtocol::ProtocolIdentity (&aProtocolPointer[4]); |
|
149 CAvdtpProtocol::ProtocolIdentity (&aProtocolPointer[5]); |
|
150 return 6; |
|
151 #else |
|
152 #pragma message("Note: Bluetooth stack will not contain AVCTP or AVDTP"); |
|
153 return 4; |
|
154 #endif // BLUETOOTH_NO_AV |
|
155 #endif // TCI |
|
156 }; |
|
157 |
|
158 CProtocolBase* CBTProtocolFamily::NewProtocolL(TUint /*aSockType*/,TUint aProtocol) |
|
159 /** |
|
160 Called by the socket server to create an instance of a new |
|
161 Protocol (layer) of the specified name - must be a subclass of |
|
162 CProtocolBase. |
|
163 **/ |
|
164 { |
|
165 LOG_FUNC |
|
166 |
|
167 // Create the Security mgr |
|
168 if (!iSecurityMgr) |
|
169 { |
|
170 iSecurityMgr = CBTSecMan::NewL(); |
|
171 } |
|
172 |
|
173 // We create our one instance of our protocols |
|
174 CBluetoothProtocolBase* p = NULL; |
|
175 |
|
176 // Create the Cod Service manager with reference to linkmgr |
|
177 if (!iCodServiceMan) |
|
178 { |
|
179 iCodServiceMan = CBTCodServiceMan::NewL(/*reinterpret_cast<CLinkMgrProtocol&>(p)*/); |
|
180 } |
|
181 |
|
182 |
|
183 switch (aProtocol) |
|
184 { |
|
185 case KBTLinkManager: |
|
186 LOG(_L("CBTProtocolFamily::NewProtocolL - BTLinkMgr")); |
|
187 p = CLinkMgrProtocol::NewL(*iSecurityMgr, iControlPlane, *iCodServiceMan); |
|
188 |
|
189 iCodServiceMan->iLinkMgr = reinterpret_cast<CLinkMgrProtocol*>(p); |
|
190 |
|
191 break; |
|
192 |
|
193 #ifdef TCI |
|
194 case KTCIL2CAP: |
|
195 #endif |
|
196 case KL2CAP: |
|
197 LOG(_L("CBTProtocolFamily::NewProtocolL - L2CAP")); |
|
198 p = CL2CAPProtocol::NewL(*iSecurityMgr, iControlPlane, *iCodServiceMan); |
|
199 break; |
|
200 |
|
201 #ifndef TCI |
|
202 case KRFCOMM: |
|
203 LOG(_L("CBTProtocolFamily::NewProtocolL - RFCOMM")); |
|
204 p = CRfcommProtocol::NewL(*iSecurityMgr, iControlPlane, *iCodServiceMan ); |
|
205 break; |
|
206 |
|
207 case KSDP: |
|
208 LOG(_L("CBTProtocolFamily::NewProtocolL - SDP")); |
|
209 p = CSdpProtocol::NewL(*iSecurityMgr, iControlPlane, *iCodServiceMan); |
|
210 break; |
|
211 case KAVCTP: |
|
212 #ifndef BLUETOOTH_NO_AV |
|
213 LOG(_L("CBTProtocolFamily::NewProtocolL - AVCTP")); |
|
214 p = CAvctpProtocol::NewL(*iSecurityMgr, iControlPlane, *iCodServiceMan); |
|
215 #else |
|
216 LOG(_L("CBTProtocolFamily::NewProtocolL - AVCTP: NOT SUPPORTED, Leaving")); |
|
217 User::Leave(KErrNotSupported); |
|
218 #endif //BLUETOOTH_NO_AV |
|
219 break; |
|
220 |
|
221 case KAVDTP: |
|
222 #ifndef BLUETOOTH_NO_AV |
|
223 LOG(_L("CBTProtocolFamily::NewProtocolL - AVDTP")); |
|
224 p = CAvdtpProtocol::NewL(*iSecurityMgr, iControlPlane, *iCodServiceMan); |
|
225 #else |
|
226 LOG(_L("CBTProtocolFamily::NewProtocolL - AVDTP: NOT SUPPORTED, Leaving")); |
|
227 User::Leave(KErrNotSupported); |
|
228 #endif //BLUETOOTH_NO_AV |
|
229 break; |
|
230 |
|
231 #endif //TCI |
|
232 |
|
233 default: |
|
234 User::Leave(KErrArgument); |
|
235 } |
|
236 CleanupStack::PushL(p); |
|
237 iControlPlane.AttachProtocolL(aProtocol, *p); |
|
238 CleanupStack::Pop(p); |
|
239 return p; |
|
240 } |
|
241 |
|
242 void CBTProtocolFamily::Open() |
|
243 { |
|
244 LOG_FUNC |
|
245 // we don't use the reference-counting of the base-class. We prefer to async close |
|
246 // so we override Open amd implement our own ref counting. |
|
247 iBTRefCount++; |
|
248 } |
|
249 |
|
250 void CBTProtocolFamily::Close() |
|
251 { |
|
252 LOG_FUNC |
|
253 if(--iBTRefCount <= 0) |
|
254 { |
|
255 iBTRefCount = 0; |
|
256 iCallback->Cancel(); |
|
257 // defer calling d'tor |
|
258 TCallBack cb(Destruct, this); |
|
259 iCallback->Set(cb); |
|
260 iCallback->CallBack(); |
|
261 } |
|
262 } |
|
263 |
|
264 /*static*/ TInt CBTProtocolFamily::Destruct(TAny* aProtocolFamily) |
|
265 { |
|
266 LOG_STATIC_FUNC |
|
267 // self-destruct |
|
268 CProtocolFamilyBase* p = reinterpret_cast<CProtocolFamilyBase*>(aProtocolFamily); |
|
269 delete p; |
|
270 |
|
271 return EFalse; |
|
272 } |
|
273 |
|
274 CBluetoothProtocolBase::CBluetoothProtocolBase(CBTSecMan& aSecMan, RBTControlPlane& aControlPlane, CBTCodServiceMan& aCodMan) |
|
275 : iSecMan(aSecMan), iControlPlane(aControlPlane), iCodMan(aCodMan) |
|
276 { |
|
277 LOG_FUNC |
|
278 } |
|
279 |
|
280 CBluetoothProtocolBase::~CBluetoothProtocolBase() |
|
281 { |
|
282 LOG_FUNC |
|
283 // detach from control plane |
|
284 ControlPlane().DetachProtocol(*this); |
|
285 delete iListener; |
|
286 } |
|
287 |
|
288 |
|
289 TInt CBluetoothProtocolBase::IncrementListeners() |
|
290 /** |
|
291 A protocol object (typically a SAP) has declared that it is listening |
|
292 |
|
293 This may mean that the protocol has to provide a bearer-listener |
|
294 **/ |
|
295 { |
|
296 LOG_FUNC |
|
297 TInt retVal = KErrNone; |
|
298 |
|
299 if (!iListeningEntities++) |
|
300 { |
|
301 // need our own listener to bring up lower layers if required for this protocol-level listening SAPs |
|
302 retVal = StartProtocolListening(); |
|
303 } |
|
304 return retVal; |
|
305 } |
|
306 |
|
307 void CBluetoothProtocolBase::DecrementListeners() |
|
308 /** |
|
309 A protocol object (typically a SAP) has declared that it is not listening |
|
310 |
|
311 This may mean that the protocol can cleanup the bearer-listener |
|
312 **/ |
|
313 { |
|
314 LOG_FUNC |
|
315 --iListeningEntities; |
|
316 ASSERT_DEBUG(iListeningEntities>=0); |
|
317 if (!iListeningEntities) |
|
318 { |
|
319 // stop protocol listening |
|
320 StopProtocolListening(); |
|
321 } |
|
322 } |
|
323 |
|
324 |
|
325 TInt CBluetoothProtocolBase::StartListening(TUint aPort, TUint aSockType, TUint aQueSize, TUid aUid) |
|
326 { |
|
327 LOG_FUNC |
|
328 TRAPD(err, DoStartListeningL(aPort, aSockType, aQueSize, aUid)); |
|
329 return err; |
|
330 } |
|
331 |
|
332 TInt CBluetoothProtocolBase::StartProtocolListening() |
|
333 { |
|
334 LOG_FUNC |
|
335 // protocol doesnt support listening |
|
336 Panic(EBTPrtProtocolCannotListen); |
|
337 return KErrNotSupported; |
|
338 } |
|
339 |
|
340 // default implementation for stopping a protocol listening |
|
341 void CBluetoothProtocolBase::StopProtocolListening() |
|
342 { |
|
343 LOG_FUNC |
|
344 delete iListener; |
|
345 iListener = NULL; |
|
346 } |
|
347 |
|
348 |
|
349 void CBluetoothProtocolBase::DoStartListeningL(TUint aPort, TUint aSockType, TUint aQueSize, TUid aUid) |
|
350 { |
|
351 LOG_FUNC |
|
352 CServProviderBase* sap =iLowerProtocol->NewSAPL(aSockType); |
|
353 iListener=CIncomingConnectionListener::NewL(*this, sap, aPort, aQueSize, aUid); |
|
354 } |
|
355 |
|
356 TInt CBluetoothProtocolBase::ControlPlaneMessage(TBTControlPlaneMessage /*aMessage*/, TAny* /*aParam*/) |
|
357 { |
|
358 LOG_FUNC |
|
359 __DEBUGGER(); // a C-plane message was targetted for a protocol that didnt implement C-plane stuff |
|
360 return KErrNotSupported; |
|
361 } |
|
362 void CBluetoothProtocolBase::Error(TInt /*aError*/,CProtocolBase* /*aSourceProtocol=NULL*/) |
|
363 { |
|
364 LOG_FUNC |
|
365 //Don't do anything, overrides CProtocolBase::Error which causes a Panic |
|
366 } |
|
367 void RBTControlPlane::AttachProtocolL(TInt aProtocolNum, CBluetoothProtocolBase& aProtocol) |
|
368 /** |
|
369 Called when a protocol is instantiated - allows the Control plane to |
|
370 be aware of it |
|
371 **/ |
|
372 { |
|
373 LOG_FUNC |
|
374 if (Protocol(aProtocolNum)) |
|
375 { |
|
376 User::Leave(KErrAlreadyExists); |
|
377 } |
|
378 |
|
379 TBTProtocol protocol; |
|
380 protocol.iProtocolNum = aProtocolNum; |
|
381 protocol.iProtocol = &aProtocol; |
|
382 |
|
383 User::LeaveIfError(iProtocols.Append(protocol)); |
|
384 } |
|
385 |
|
386 void RBTControlPlane::DetachProtocol(CBluetoothProtocolBase& aProtocol) |
|
387 { |
|
388 LOG_FUNC |
|
389 for (TInt i=0; i<iProtocols.Count();i++) |
|
390 { |
|
391 if (iProtocols[i].iProtocol == &aProtocol) |
|
392 { |
|
393 iProtocols.Remove(i); |
|
394 break; |
|
395 } |
|
396 } |
|
397 } |
|
398 |
|
399 void RBTControlPlane::Close() |
|
400 { |
|
401 LOG_FUNC |
|
402 iProtocols.Close(); |
|
403 } |
|
404 |
|
405 |
|
406 CBluetoothProtocolBase* RBTControlPlane::Protocol(TInt aProtocolNum) const |
|
407 { |
|
408 LOG_FUNC |
|
409 CBluetoothProtocolBase* p= NULL; |
|
410 for (TInt i=0; i<iProtocols.Count(); i++) |
|
411 { |
|
412 if (iProtocols[i].iProtocolNum == aProtocolNum) |
|
413 p = iProtocols[i].iProtocol; |
|
414 } |
|
415 return p; // does not pass ownership |
|
416 } |
|
417 |
|
418 /* |
|
419 a C-plane message to send a signal to the (possible) SAP handling the physical link |
|
420 to the address aAddr |
|
421 */ |
|
422 TInt RBTControlPlane::ModifyPhysicalLink(TBTControlPlaneMessage aMessage, const TBTDevAddr& aAddr) const |
|
423 { |
|
424 LOG_FUNC |
|
425 // link mgr must be there! |
|
426 CBluetoothProtocolBase* linkmgr = Protocol(KBTLinkManager); |
|
427 ASSERT_DEBUG(linkmgr); |
|
428 return linkmgr->ControlPlaneMessage(aMessage, const_cast<TAny*>(reinterpret_cast<const TAny*>(&aAddr))); |
|
429 } |
|
430 |
|
431 void RBTControlPlane::TryToAndThenPreventHostEncryptionKeyRefresh(const TBTDevAddr& aAddr, MBluetoothControlPlaneToken*& aOutToken) |
|
432 { |
|
433 LOG_FUNC |
|
434 CBluetoothProtocolBase* linkmgr = Protocol(KBTLinkManager); |
|
435 ASSERT_DEBUG(linkmgr); |
|
436 const TBTDevAddr* addrPtr = &aAddr; |
|
437 TAny* ptr = reinterpret_cast<TAny*>(&addrPtr); |
|
438 TInt err = linkmgr->ControlPlaneMessage(ETryToAndThenPreventHostEncryptionKeyRefresh, ptr); |
|
439 if (err == KErrNone) |
|
440 { |
|
441 aOutToken = *reinterpret_cast<MBluetoothControlPlaneToken**>(ptr); |
|
442 } |
|
443 else |
|
444 { |
|
445 aOutToken = NULL; |
|
446 } |
|
447 } |
|
448 |
|
449 /* |
|
450 a C-plane message to send a message to a target protocol telling them not to authorise a device |
|
451 used for multiple protocols taking part in a single use-case that requires only |
|
452 one authorisation - eg AVCTP and AVDTP doing A2DP + AVRCP stereo headset |
|
453 */ |
|
454 TInt RBTControlPlane::Preauthorise(TInt aTargetProtocolNum, |
|
455 const TOverrideAuthorise& aSetPreauthorisation) |
|
456 { |
|
457 LOG_FUNC |
|
458 // either protocol may not be running |
|
459 CBluetoothProtocolBase* target = Protocol(aTargetProtocolNum); |
|
460 if (target) |
|
461 { |
|
462 return target->ControlPlaneMessage(EPreauthoriseDevice, const_cast<TAny*>(reinterpret_cast<const TAny*>(&aSetPreauthorisation))); |
|
463 } |
|
464 else |
|
465 { |
|
466 return KErrNotFound; |
|
467 } |
|
468 } |
|
469 |
|
470 TPhysicalLinkPresent RBTControlPlane::PhysicalLinkPresent(const TBTDevAddr& aAddr) const |
|
471 { |
|
472 LOG_FUNC |
|
473 // need to stick down a control plane message to ascertain whether a physical channel is in place |
|
474 // linkmgr must be there |
|
475 CBluetoothProtocolBase* linkmgr = Protocol(KBTLinkManager); |
|
476 ASSERT_DEBUG(linkmgr); |
|
477 |
|
478 return static_cast<TPhysicalLinkPresent>( |
|
479 linkmgr->ControlPlaneMessage(EPresent, |
|
480 const_cast<TAny*>(reinterpret_cast<const TAny*>(&aAddr)))); |
|
481 } |
|
482 |
|
483 /* |
|
484 a C-plane message to send a signal to the (possible) SAP handling the Physical Link(aAddr) |
|
485 to add aObserver to its list of subscribers. |
|
486 */ |
|
487 TInt RBTControlPlane::SubscribePhysicalLink(MPhysicalLinkObserver& aObserver, TBTDevAddr aAddr) const |
|
488 { |
|
489 LOG_FUNC |
|
490 // link mgr must be there! |
|
491 CBluetoothProtocolBase* linkmgr = Protocol(KBTLinkManager); |
|
492 ASSERT_DEBUG(linkmgr); |
|
493 |
|
494 TPhysicalLinkSubscriptionInfo subscriptionInfo(aObserver,aAddr); |
|
495 |
|
496 return linkmgr->ControlPlaneMessage(ESubscribePhysicalLink, const_cast<TAny*>(reinterpret_cast<const TAny*>(&subscriptionInfo))); |
|
497 } |
|
498 |
|
499 /* |
|
500 a C-plane message to send a signal to the (possible) SAP handling the Physical Link(aAddr) |
|
501 to remove aObserver its list of subscribers. |
|
502 */ |
|
503 TInt RBTControlPlane::UnsubscribePhysicalLink(MPhysicalLinkObserver& aObserver, TBTDevAddr aAddr) const |
|
504 { |
|
505 LOG_FUNC |
|
506 // link mgr must be there! |
|
507 CBluetoothProtocolBase* linkmgr = Protocol(KBTLinkManager); |
|
508 ASSERT_DEBUG(linkmgr); |
|
509 |
|
510 TPhysicalLinkSubscriptionInfo subscriptionInfo(aObserver,aAddr); |
|
511 |
|
512 return linkmgr->ControlPlaneMessage(EUnsubscribePhysicalLink, const_cast<TAny*>(reinterpret_cast<const TAny*>(&subscriptionInfo))); |
|
513 } |
|
514 |
|
515 void MBluetoothControlPlaneToken::Release(MBluetoothControlPlaneToken*& aToken) |
|
516 { |
|
517 if(aToken) |
|
518 { |
|
519 aToken->Release(); |
|
520 aToken = NULL; |
|
521 } |
|
522 } |
|
523 |
|
524 |