|
1 /* |
|
2 * Copyright (c) 2006 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: Helper class for BTEng server to manage and interface with |
|
15 * the profile plug-ins the profile plug-ins. |
|
16 * |
|
17 */ |
|
18 |
|
19 |
|
20 |
|
21 #include <ecom/ecom.h> |
|
22 #include <btsdp.h> |
|
23 #include <centralrepository.h> |
|
24 #include <featmgr.h> |
|
25 |
|
26 #include "btengsrvpluginmgr.h" |
|
27 #include "btengserver.h" |
|
28 #include "btengsrvsession.h" |
|
29 #include "btengsrvbbconnectionmgr.h" |
|
30 #include "btengprivatecrkeys.h" |
|
31 #include "debug.h" |
|
32 #include <btfeaturescfg.h> |
|
33 |
|
34 /** UID for BTEng plug-ins */ |
|
35 const TUid KBTEngPluginUid = { 0x2000277B }; |
|
36 /** ECOM registration info for BTSAP plugin */ |
|
37 _LIT8( KEComBTSapPlugin, "112D" ); |
|
38 /** The message argument which holds the Bluetooth address. */ |
|
39 const TInt KBTEngAddrSlot = 0; |
|
40 /** The message argument which holds the connection status parameter. */ |
|
41 const TInt KBTEngParamSlot = 1; |
|
42 |
|
43 // ======== MEMBER FUNCTIONS ======== |
|
44 |
|
45 // --------------------------------------------------------------------------- |
|
46 // C++ default constructor |
|
47 // --------------------------------------------------------------------------- |
|
48 // |
|
49 CBTEngSrvPluginMgr::CBTEngSrvPluginMgr( CBTEngServer* aServer ) |
|
50 : iServer( aServer ) |
|
51 { |
|
52 } |
|
53 |
|
54 |
|
55 // --------------------------------------------------------------------------- |
|
56 // Symbian 2nd-phase constructor |
|
57 // --------------------------------------------------------------------------- |
|
58 // |
|
59 void CBTEngSrvPluginMgr::ConstructL() |
|
60 { |
|
61 } |
|
62 |
|
63 |
|
64 // --------------------------------------------------------------------------- |
|
65 // NewL |
|
66 // --------------------------------------------------------------------------- |
|
67 // |
|
68 CBTEngSrvPluginMgr* CBTEngSrvPluginMgr::NewL( CBTEngServer* aServer ) |
|
69 { |
|
70 CBTEngSrvPluginMgr* self = new( ELeave ) CBTEngSrvPluginMgr( aServer ); |
|
71 CleanupStack::PushL( self ); |
|
72 self->ConstructL(); |
|
73 CleanupStack::Pop( self ); |
|
74 return self; |
|
75 } |
|
76 |
|
77 |
|
78 // --------------------------------------------------------------------------- |
|
79 // Destructor |
|
80 // --------------------------------------------------------------------------- |
|
81 // |
|
82 CBTEngSrvPluginMgr::~CBTEngSrvPluginMgr() |
|
83 { |
|
84 iPluginInfoArray.Close(); |
|
85 iPluginArray.ResetAndDestroy(); |
|
86 } |
|
87 |
|
88 |
|
89 // --------------------------------------------------------------------------- |
|
90 // ?implementation_description |
|
91 // --------------------------------------------------------------------------- |
|
92 // |
|
93 void CBTEngSrvPluginMgr::ProcessCommandL( const RMessage2& aMessage ) |
|
94 { |
|
95 TRACE_FUNC_ENTRY |
|
96 TInt opcode = aMessage.Function(); |
|
97 TInt err = KErrNone; |
|
98 TBTDevAddrPckgBuf addr; |
|
99 switch( opcode ) |
|
100 { |
|
101 case EBTEngConnectDevice: |
|
102 { |
|
103 aMessage.ReadL( KBTEngAddrSlot, addr ); |
|
104 TBTEngDevClassPkg cod; |
|
105 aMessage.ReadL( KBTEngParamSlot, cod ); |
|
106 err = Connect( addr(), TBTDeviceClass( cod() ) ); |
|
107 } |
|
108 break; |
|
109 case EBTEngCancelConnectDevice: |
|
110 { |
|
111 aMessage.ReadL( KBTEngAddrSlot, addr ); |
|
112 err = CancelConnect( addr() ); |
|
113 } |
|
114 break; |
|
115 case EBTEngDisconnectDevice: |
|
116 { |
|
117 aMessage.ReadL( KBTEngAddrSlot, addr ); |
|
118 TPckgBuf<TUint> discType; |
|
119 aMessage.ReadL( KBTEngParamSlot, discType ); |
|
120 err = Disconnect( addr(), (TBTDisconnectType) discType() ); |
|
121 } |
|
122 break; |
|
123 case EBTEngIsDeviceConnected: |
|
124 { |
|
125 aMessage.ReadL( KBTEngAddrSlot, addr ); |
|
126 TBTEngConnectionStatus connectStatus = EBTEngNotConnected; |
|
127 connectStatus = IsDeviceConnected( addr() ); |
|
128 TBTEngParamPkg statusPkg( connectStatus ); |
|
129 aMessage.WriteL( KBTEngParamSlot, statusPkg ); |
|
130 } |
|
131 break; |
|
132 case EBTEngIsDeviceConnectable: |
|
133 { |
|
134 aMessage.ReadL( KBTEngAddrSlot, addr ); |
|
135 TBTEngDevClassPkg cod; |
|
136 aMessage.ReadL( KBTEngParamSlot, cod ); |
|
137 TBool connectable = ( GetConnectablePluginIndex(cod(), addr() ) != KErrNotFound ) ; |
|
138 TPckgBuf<TBool> connPkg( connectable ); |
|
139 aMessage.WriteL( 2, connPkg ); |
|
140 } |
|
141 break; |
|
142 case EBTEngGetConnectedAddresses: |
|
143 { |
|
144 TPckgBuf<TBTProfile> profile; |
|
145 aMessage.ReadL( KBTEngParamSlot, profile ); |
|
146 RBTDevAddrArray addrArray; |
|
147 if( profile() == EBTProfileUndefined ) |
|
148 { |
|
149 // Get all baseband connections |
|
150 iServer->iBBConnMgr->GetConnectedAddressesL( addrArray ); |
|
151 } |
|
152 else |
|
153 { |
|
154 err = GetConnectedAddresses( addrArray, profile() ); |
|
155 } |
|
156 HBufC8* buf = HBufC8::NewLC( aMessage.GetDesMaxLengthL( KBTEngAddrSlot ) ); |
|
157 TPtr8 ptr = buf->Des(); |
|
158 aMessage.ReadL( KBTEngAddrSlot, ptr ); |
|
159 ptr.Zero(); |
|
160 for( TInt i = 0; i < addrArray.Count(); i++ ) |
|
161 { |
|
162 addr = addrArray[ i ]; |
|
163 ptr.Append( addr ); |
|
164 } |
|
165 aMessage.WriteL( KBTEngAddrSlot, ptr ); |
|
166 CleanupStack::PopAndDestroy( buf ); |
|
167 } |
|
168 break; |
|
169 default: |
|
170 { |
|
171 TRACE_INFO( ( _L( "ProcessCommandL: bad request (%d)" ), |
|
172 aMessage.Function() ) ) |
|
173 err = KErrArgument; |
|
174 } |
|
175 break; |
|
176 } |
|
177 User::LeaveIfError( err ); |
|
178 TRACE_FUNC_EXIT |
|
179 } |
|
180 |
|
181 |
|
182 // --------------------------------------------------------------------------- |
|
183 // ?implementation_description |
|
184 // --------------------------------------------------------------------------- |
|
185 // |
|
186 void CBTEngSrvPluginMgr::DisconnectAllPlugins() |
|
187 { |
|
188 TRACE_FUNC_ENTRY |
|
189 TBTDevAddr nullAddr; |
|
190 for( TInt i = 0; i < iPluginArray.Count(); i++ ) |
|
191 { |
|
192 (void) iPluginArray[ i ]->Disconnect( nullAddr, EBTDiscImmediate ); |
|
193 } |
|
194 } |
|
195 |
|
196 |
|
197 // --------------------------------------------------------------------------- |
|
198 // ?implementation_description |
|
199 // --------------------------------------------------------------------------- |
|
200 // |
|
201 void CBTEngSrvPluginMgr::LoadProfilePluginsL( const TEComResolverParams aParams ) |
|
202 { |
|
203 TRACE_FUNC_ENTRY |
|
204 if( aParams.DataType().Length() ) |
|
205 { |
|
206 // This is a request to enable a specific service, e.g. BT SAP. |
|
207 REComSession::ListImplementationsL( KBTEngPluginUid, aParams, |
|
208 iPluginInfoArray ); |
|
209 } |
|
210 else |
|
211 { |
|
212 if( iPluginArray.Count() > 0 || iPluginInfoArray.Count() > 0 ) |
|
213 { |
|
214 // Could be the case if we received a command to turn BT on |
|
215 // halfway through a power down sequence. Just ignore. |
|
216 return; |
|
217 } |
|
218 iPluginInfoArray.Reset(); |
|
219 iPluginArray.Reset(); |
|
220 REComSession::ListImplementationsL( KBTEngPluginUid, iPluginInfoArray ); |
|
221 } |
|
222 // Ignore the number of plug-ins left to load; the server state machine |
|
223 // will handle this at a later stage. |
|
224 (void) LoadPluginL(); |
|
225 TRACE_FUNC_EXIT |
|
226 } |
|
227 |
|
228 TBool CBTEngSrvPluginMgr::FilterByEnterpriseDisablementModeL(TUid aUid) const |
|
229 { |
|
230 TRACE_FUNC_ENTRY |
|
231 TBool want = EFalse; |
|
232 switch ( iServer->EnterpriseEnablementMode() ) |
|
233 { |
|
234 case BluetoothFeatures::EDisabled: |
|
235 // In Disabled mode all plugins are filtered out. |
|
236 break; |
|
237 case BluetoothFeatures::EDataProfilesDisabled: |
|
238 // In 'privileged profiles only' mode we only allow the following. |
|
239 if ( aUid == TUid::Uid(0x1020897B) // audio (i.e. allow HSP, HFP and A2DP) |
|
240 || aUid == TUid::Uid(0x10208979) // remote control (i.e. allow AVRCP) ) |
|
241 || aUid == TUid::Uid(0x2001E309) // HID |
|
242 ) |
|
243 { |
|
244 want = ETrue; |
|
245 } |
|
246 break; |
|
247 case BluetoothFeatures::EEnabled: |
|
248 // In Enabled mode we do not filter plugins. |
|
249 want = ETrue; |
|
250 break; |
|
251 default: |
|
252 __ASSERT_DEBUG( NULL, PanicServer( EBTEngPanicCorruptSettings ) ); |
|
253 break; |
|
254 } |
|
255 TRACE_INFO( ( _L( "[BTENG]\t returning want = %d" ), want ) ) |
|
256 TRACE_FUNC_EXIT |
|
257 return want; |
|
258 } |
|
259 |
|
260 // --------------------------------------------------------------------------- |
|
261 // ?implementation_description |
|
262 // --------------------------------------------------------------------------- |
|
263 // |
|
264 TInt CBTEngSrvPluginMgr::LoadPluginL() |
|
265 { |
|
266 TRACE_FUNC_ENTRY |
|
267 if( !iPluginInfoArray.Count() ) |
|
268 { |
|
269 // All plug-ins have been loaded. |
|
270 return KErrNotFound; |
|
271 } |
|
272 |
|
273 // Simply pop the first info object, process it, and delete it. |
|
274 // There is no need to keep it after the plug-in has been constructed. |
|
275 CImplementationInformation* implInfo = iPluginInfoArray[ 0 ]; |
|
276 iPluginInfoArray.Remove( 0 ); |
|
277 CleanupStack::PushL( implInfo ); |
|
278 TLex8 lex( implInfo->DataType() ); |
|
279 TUint profile = (TInt) EBTProfileUndefined; |
|
280 TInt err = lex.Val( profile, EHex ); |
|
281 // Check if the feature is allowed to be loaded |
|
282 if( !err && CheckFeatureEnabledL( profile ) && FilterByEnterpriseDisablementModeL(implInfo->ImplementationUid()) ) |
|
283 { |
|
284 TRACE_INFO( ( _L( "[BTENG]\t loading profile 0x%04x" ), profile ) ) |
|
285 TUid implUid = implInfo->ImplementationUid(); |
|
286 CBTEngPlugin* plugin = CBTEngPlugin::NewL( implUid ); |
|
287 CleanupStack::PushL( plugin ); |
|
288 plugin->SetObserver( ( MBTEngPluginObserver* ) this ); |
|
289 User::LeaveIfError( iPluginArray.Append( plugin ) ); |
|
290 CleanupStack::Pop( plugin ); |
|
291 } |
|
292 CleanupStack::PopAndDestroy( implInfo ); |
|
293 TRACE_FUNC_RES( ( _L( "%d plug-ins left to load" ), iPluginInfoArray.Count() ) ) |
|
294 return iPluginInfoArray.Count(); |
|
295 } |
|
296 |
|
297 |
|
298 // --------------------------------------------------------------------------- |
|
299 // ?implementation_description |
|
300 // --------------------------------------------------------------------------- |
|
301 // |
|
302 void CBTEngSrvPluginMgr::UnloadProfilePlugins() |
|
303 { |
|
304 TRACE_FUNC_ARG( ( _L( "[BTENG]\t unloading %d plug-ins" ), iPluginArray.Count() ) ) |
|
305 |
|
306 // All plug-ins need to be unloaded at once. Otherwise it gets too |
|
307 // difficult to keep track in case of a power-on command during a |
|
308 // power-off sequence. |
|
309 iPluginArray.ResetAndDestroy(); |
|
310 |
|
311 REComSession::FinalClose(); |
|
312 TRACE_FUNC_EXIT |
|
313 } |
|
314 |
|
315 |
|
316 // --------------------------------------------------------------------------- |
|
317 // ?implementation_description |
|
318 // --------------------------------------------------------------------------- |
|
319 // |
|
320 void CBTEngSrvPluginMgr::LoadBTSapPluginL() |
|
321 { |
|
322 TRACE_FUNC_ENTRY |
|
323 |
|
324 // SAP is supported in neither Data Profiles Disabled nor Disabled mode. |
|
325 if ( iServer->EnterpriseEnablementMode() != BluetoothFeatures::EEnabled ) |
|
326 { |
|
327 TRACE_INFO( ( _L( "\tno we're not... Bluetooth is enterprise-IT-disabled" ) ) ) |
|
328 User::Leave(KErrNotSupported); |
|
329 } |
|
330 |
|
331 if( CheckFeatureEnabledL( EBTProfileSAP ) ) |
|
332 { |
|
333 TEComResolverParams params; |
|
334 TPtrC8 ptr( KEComBTSapPlugin ); |
|
335 params.SetDataType( ptr ); |
|
336 LoadProfilePluginsL( params ); |
|
337 } |
|
338 TRACE_FUNC_EXIT |
|
339 } |
|
340 |
|
341 |
|
342 // --------------------------------------------------------------------------- |
|
343 // ?implementation_description |
|
344 // --------------------------------------------------------------------------- |
|
345 // |
|
346 void CBTEngSrvPluginMgr::UnloadBTSapPlugin() |
|
347 { |
|
348 TRACE_FUNC_ENTRY |
|
349 TInt ret = GetFirstPluginOfProfileSupported( EBTProfileSAP ); |
|
350 if( ret != KErrNotFound ) |
|
351 { |
|
352 CBTEngPlugin* plugin = iPluginArray[ ret ]; |
|
353 iPluginArray.Remove( ret ); |
|
354 delete plugin; |
|
355 } |
|
356 |
|
357 TRACE_FUNC_EXIT |
|
358 } |
|
359 |
|
360 // --------------------------------------------------------------------------- |
|
361 // ?implementation_description |
|
362 // --------------------------------------------------------------------------- |
|
363 // |
|
364 void CBTEngSrvPluginMgr::DisconnectProfile( TBTProfile aProfile ) |
|
365 { |
|
366 TRACE_FUNC_ENTRY |
|
367 RBTDevAddrArray addrArray; |
|
368 TInt count = iPluginArray.Count(); |
|
369 while( count ) |
|
370 { |
|
371 count--; |
|
372 if( iPluginArray[ count ]->IsProfileSupported( aProfile ) ) |
|
373 { |
|
374 iPluginArray[ count ]->GetConnections( addrArray, aProfile ); |
|
375 for ( TInt i = 0; i < addrArray.Count(); i++ ) |
|
376 { |
|
377 iPluginArray[ count ]->Disconnect( addrArray[i], EBTDiscImmediate ); |
|
378 } |
|
379 break; |
|
380 } |
|
381 } |
|
382 TRACE_FUNC_EXIT |
|
383 } |
|
384 |
|
385 |
|
386 // --------------------------------------------------------------------------- |
|
387 // From class MBTEngPluginObserver. |
|
388 // ?implementation_description |
|
389 // --------------------------------------------------------------------------- |
|
390 // |
|
391 void CBTEngSrvPluginMgr::ConnectComplete( const TBTDevAddr& aAddr, |
|
392 TBTProfile aProfile, TInt aErr, RBTDevAddrArray* aConflicts ) |
|
393 { |
|
394 TRACE_FUNC_ENTRY |
|
395 // Inform listeners of this event. |
|
396 (void) aProfile; |
|
397 iServer->iSessionIter.SetToFirst(); |
|
398 CBTEngSrvSession* session = (CBTEngSrvSession*) iServer->iSessionIter++; |
|
399 while( session ) |
|
400 { |
|
401 TRACE_INFO( ( _L( "[BTEng]\t Notifying session %d" ), (TInt) session ) ) |
|
402 session->NotifyConnectionEvent( aAddr, EBTEngConnected, aConflicts, aErr ); |
|
403 session = (CBTEngSrvSession*) iServer->iSessionIter++; |
|
404 } |
|
405 TRACE_FUNC_EXIT |
|
406 } |
|
407 |
|
408 |
|
409 // --------------------------------------------------------------------------- |
|
410 // From class MBTEngPluginObserver. |
|
411 // ?implementation_description |
|
412 // --------------------------------------------------------------------------- |
|
413 // |
|
414 void CBTEngSrvPluginMgr::DisconnectComplete( const TBTDevAddr& aAddr, |
|
415 TBTProfile aProfile, TInt aErr ) |
|
416 { |
|
417 TRACE_FUNC_ENTRY |
|
418 // Inform listeners of this event. |
|
419 (void) aProfile; |
|
420 iServer->iSessionIter.SetToFirst(); |
|
421 CBTEngSrvSession* session = (CBTEngSrvSession*) iServer->iSessionIter++; |
|
422 while( session ) |
|
423 { |
|
424 TRACE_INFO( ( _L( "[BTEng]\t Notifying session %d" ), (TInt) session ) ) |
|
425 session->NotifyConnectionEvent( aAddr, EBTEngNotConnected, NULL, aErr ); |
|
426 session = (CBTEngSrvSession*) iServer->iSessionIter++; |
|
427 } |
|
428 TRACE_FUNC_EXIT |
|
429 } |
|
430 |
|
431 // --------------------------------------------------------------------------- |
|
432 // ?implementation_description |
|
433 // --------------------------------------------------------------------------- |
|
434 // |
|
435 TInt CBTEngSrvPluginMgr::Connect( const TBTDevAddr& aAddr, |
|
436 const TBTDeviceClass& aDeviceClass ) |
|
437 { |
|
438 TRACE_FUNC_ENTRY |
|
439 TRACE_BDADDR ( aAddr ) |
|
440 TInt pindex = GetConnectablePluginIndex( aDeviceClass ); |
|
441 TRACE_INFO( ( _L( "[BTEng]\t The %dth of plugin in plugarray to connect" ), pindex ) ) |
|
442 TInt err (KErrNotFound); |
|
443 if( pindex != KErrNotFound && iPluginArray.Count()) |
|
444 { |
|
445 err = iPluginArray[ pindex ]->Connect( aAddr ); |
|
446 } |
|
447 TRACE_FUNC_RES( ( _L( "result: %d" ), err ) ) |
|
448 return err; |
|
449 } |
|
450 |
|
451 |
|
452 // --------------------------------------------------------------------------- |
|
453 // ?implementation_description |
|
454 // --------------------------------------------------------------------------- |
|
455 // |
|
456 TInt CBTEngSrvPluginMgr::CancelConnect( const TBTDevAddr& aAddr ) |
|
457 { |
|
458 TRACE_FUNC_ENTRY |
|
459 TInt err = KErrNotFound; |
|
460 TRACE_BDADDR(aAddr); |
|
461 for( TInt i = 0; i < iPluginArray.Count(); i++ ) |
|
462 { |
|
463 TBTEngConnectionStatus status = iPluginArray[ i ]->IsConnected( aAddr ); |
|
464 if( status == EBTEngConnecting || status == EBTEngConnected ) |
|
465 { |
|
466 (void) iPluginArray[ i ]->CancelConnect( aAddr ); |
|
467 err = KErrNone; |
|
468 break; |
|
469 } |
|
470 } |
|
471 TRACE_FUNC_RES( ( _L( "result: %d" ), err ) ) |
|
472 return err; |
|
473 } |
|
474 |
|
475 |
|
476 // --------------------------------------------------------------------------- |
|
477 // ?implementation_description |
|
478 // --------------------------------------------------------------------------- |
|
479 // |
|
480 TInt CBTEngSrvPluginMgr::Disconnect( const TBTDevAddr& aAddr, |
|
481 TBTDisconnectType aDiscType ) |
|
482 { |
|
483 TRACE_FUNC_ENTRY |
|
484 TRACE_BDADDR(aAddr); |
|
485 TInt err = KErrNotFound; |
|
486 for( TInt i = 0; i < iPluginArray.Count(); i++ ) |
|
487 { |
|
488 // Should be ignored if the plug-in does not have |
|
489 // a connection to the address. |
|
490 err = iPluginArray[ i ]->Disconnect( aAddr, aDiscType ); |
|
491 } |
|
492 TRACE_FUNC_RES( ( _L( "result: %d" ), err ) ) |
|
493 return err; |
|
494 } |
|
495 |
|
496 |
|
497 // --------------------------------------------------------------------------- |
|
498 // ?implementation_description |
|
499 // --------------------------------------------------------------------------- |
|
500 // |
|
501 TBTEngConnectionStatus CBTEngSrvPluginMgr::IsDeviceConnected( const TBTDevAddr& aAddr ) |
|
502 { |
|
503 TRACE_FUNC_ENTRY |
|
504 TRACE_BDADDR(aAddr); |
|
505 TBTEngConnectionStatus status = EBTEngNotConnected; |
|
506 for( TInt i = 0; i < iPluginArray.Count(); i++ ) |
|
507 { |
|
508 status = iPluginArray[ i ]->IsConnected( aAddr ); |
|
509 if( status == EBTEngConnecting || status == EBTEngConnected ) |
|
510 { |
|
511 break; // Just exit the loop here, we have a connection status. |
|
512 } |
|
513 } |
|
514 TRACE_FUNC_RES( ( _L( "result: %d" ), (TInt) status ) ) |
|
515 return status; |
|
516 } |
|
517 |
|
518 |
|
519 // --------------------------------------------------------------------------- |
|
520 // ?implementation_description |
|
521 // --------------------------------------------------------------------------- |
|
522 // |
|
523 TInt CBTEngSrvPluginMgr::GetConnectablePluginIndex( const TBTDeviceClass& aDeviceClass, const TBTDevAddr& aAddr ) |
|
524 { |
|
525 TRACE_FUNC_ENTRY |
|
526 TInt plugindex( KErrNotFound ); |
|
527 TRACE_BDADDR(aAddr); |
|
528 TRACE_INFO ( (_L("[BTENG] cod %b"), aDeviceClass.DeviceClass())) |
|
529 if( aAddr != TBTDevAddr() ) |
|
530 { |
|
531 DoGetEirData( aAddr ); |
|
532 } |
|
533 |
|
534 if( iUuidContainter.UUIDs().Count() > 0) |
|
535 { |
|
536 plugindex = GetConnectablePluginIndexByEir(); |
|
537 } |
|
538 |
|
539 if ( plugindex == KErrNotFound ) |
|
540 { |
|
541 TBTProfile profile = MapDeviceClassToProfile( aDeviceClass ); |
|
542 if( profile == EBTProfileUndefined ) |
|
543 { |
|
544 return plugindex; |
|
545 } |
|
546 |
|
547 plugindex = GetFirstPluginOfProfileSupported( profile ); |
|
548 |
|
549 if ( !iPluginArray.Count() ) |
|
550 { |
|
551 // In case BT is off and plugins are not loaded |
|
552 if ( profile == EBTProfileHFP || profile == EBTProfileA2DP ) |
|
553 { |
|
554 plugindex = KErrNone; |
|
555 } |
|
556 } |
|
557 } |
|
558 |
|
559 TRACE_FUNC_RES( ( _L( "result: %d" ), plugindex ) ) |
|
560 return plugindex; |
|
561 } |
|
562 |
|
563 // --------------------------------------------------------------------------- |
|
564 // ?implementation_description |
|
565 // --------------------------------------------------------------------------- |
|
566 // |
|
567 TInt CBTEngSrvPluginMgr::GetConnectedAddresses( RBTDevAddrArray& aAddrArray, |
|
568 TBTProfile aProfile ) |
|
569 { |
|
570 TRACE_FUNC_ENTRY |
|
571 TInt ret = GetFirstPluginOfProfileSupported( aProfile ); |
|
572 if( ret != KErrNotFound ) |
|
573 { |
|
574 iPluginArray[ ret ]->GetConnections( aAddrArray, aProfile ); |
|
575 ret = KErrNone; |
|
576 } |
|
577 TRACE_FUNC_RES( ( _L( "result: %d" ), ret ) ) |
|
578 return ret; |
|
579 } |
|
580 |
|
581 // --------------------------------------------------------------------------- |
|
582 // ?implementation_description |
|
583 // --------------------------------------------------------------------------- |
|
584 // |
|
585 TBool CBTEngSrvPluginMgr::CheckFeatureEnabledL( TInt aProfile ) |
|
586 { |
|
587 TRACE_FUNC_ARG( ( _L( "requested feature: 0x%04x" ), aProfile ) ) |
|
588 // By default, a feature is supported. This allowd features that do not |
|
589 // have a related feature flag to be loaded too. |
|
590 TBool supported = ETrue; |
|
591 if( aProfile == EBTProfileSAP ) |
|
592 { |
|
593 // First check from central repository. |
|
594 CRepository* cenrep = CRepository::NewL( KCRUidBTEngPrivateSettings ); |
|
595 TInt enabled = 0; |
|
596 TInt err = cenrep->Get( KBTSapEnabled, enabled ); |
|
597 delete cenrep; |
|
598 if( err || !enabled ) |
|
599 { |
|
600 return EFalse; |
|
601 } |
|
602 } |
|
603 |
|
604 TInt feature = MapProfileToFeature( aProfile ); |
|
605 if( feature ) |
|
606 { |
|
607 // Check from feature manager if this phone enables this feature. |
|
608 FeatureManager::InitializeLibL(); |
|
609 supported = FeatureManager::FeatureSupported( feature ); |
|
610 FeatureManager::UnInitializeLib(); |
|
611 } |
|
612 TRACE_FUNC_RES( ( _L ( "result: %d" ), supported ) ) |
|
613 return supported; |
|
614 } |
|
615 |
|
616 |
|
617 // --------------------------------------------------------------------------- |
|
618 // ?implementation_description |
|
619 // --------------------------------------------------------------------------- |
|
620 // |
|
621 TBTProfile CBTEngSrvPluginMgr::MapDeviceClassToProfile( |
|
622 const TBTDeviceClass& aDeviceClass ) |
|
623 { |
|
624 TRACE_FUNC_ARG( ( _L( "Mapping CoD %b ..." ), aDeviceClass.DeviceClass() ) ) |
|
625 // Could (should?) be done more dynamically or with some header file definition. |
|
626 // Right now these are the only known/possible ECOM plug-ins. |
|
627 TBTProfile profile = EBTProfileUndefined; |
|
628 if( aDeviceClass.MajorServiceClass() & EMajorServiceAudio ) |
|
629 { |
|
630 profile = EBTProfileHFP; |
|
631 } |
|
632 else if( aDeviceClass.MajorServiceClass() & EMajorServiceRendering && |
|
633 ( aDeviceClass.MajorDeviceClass() != EMajorDeviceImaging ) ) |
|
634 // Printer or camera or other imaging device may set EMajorServiceRendering bit |
|
635 // as well as stereo audio device, so check EMajorDeviceImaging too. |
|
636 { |
|
637 profile = EBTProfileA2DP; |
|
638 } |
|
639 else if( aDeviceClass.MajorDeviceClass() == EMajorDevicePeripheral && |
|
640 ( (aDeviceClass.MinorDeviceClass() & EMinorDevicePeripheralKeyboard) || |
|
641 (aDeviceClass.MinorDeviceClass() & EMinorDevicePeripheralPointer) ) ) |
|
642 { |
|
643 profile = EBTProfileHID; |
|
644 } |
|
645 else if( aDeviceClass.MajorDeviceClass() == EMajorDeviceLanAccessPoint ) |
|
646 { |
|
647 // Mainly for testing now; PAN profile is a personal favorite. |
|
648 profile = EBTProfilePANU; |
|
649 } |
|
650 |
|
651 TRACE_FUNC_RES( ( _L( "... to profile 0x%04x." ), profile ) ) |
|
652 return profile; |
|
653 } |
|
654 |
|
655 |
|
656 // --------------------------------------------------------------------------- |
|
657 // Maps a profile UUID to any Bluetooth-related pflatfom feature flag. |
|
658 // --------------------------------------------------------------------------- |
|
659 // |
|
660 TInt CBTEngSrvPluginMgr::MapProfileToFeature( TInt aProfile ) |
|
661 { |
|
662 TInt feature = 0; |
|
663 switch( aProfile ) |
|
664 { |
|
665 case EBTProfileHSP: |
|
666 case EBTProfileHFP: |
|
667 { |
|
668 feature = KFeatureIdBtAudio; |
|
669 } |
|
670 break; |
|
671 case EBTProfileA2DP: |
|
672 { |
|
673 feature = KFeatureIdBtStereoAudio; |
|
674 } |
|
675 break; |
|
676 case EBTProfileSAP: |
|
677 { |
|
678 feature = KFeatureIdBtSap; |
|
679 } |
|
680 break; |
|
681 case EBTProfileDUN: |
|
682 { |
|
683 feature = KFeatureIdDialupNetworking; |
|
684 } |
|
685 break; |
|
686 case EBTProfileFAX: |
|
687 { |
|
688 feature = KFeatureIdBtFaxProfile; |
|
689 } |
|
690 break; |
|
691 case EBTProfilePANU: |
|
692 case EBTProfileNAP: |
|
693 case EBTProfileGN: |
|
694 { |
|
695 //feature = KFeatureIdBtPanProfile; |
|
696 feature = 0;// Testin' |
|
697 } |
|
698 break; |
|
699 case EBTProfileBIP: |
|
700 { |
|
701 feature = KFeatureIdBtImagingProfile; |
|
702 } |
|
703 break; |
|
704 case EBTProfileBPP: |
|
705 { |
|
706 feature = KFeatureIdBtPrintingProfile; |
|
707 } |
|
708 break; |
|
709 default: |
|
710 break; |
|
711 } |
|
712 TRACE_FUNC_RES( ( _L( "selected feature %d" ), feature ) ) |
|
713 return feature; |
|
714 } |
|
715 |
|
716 // --------------------------------------------------------------------------- |
|
717 // Get Eir Data by hostResolver in Cache |
|
718 // --------------------------------------------------------------------------- |
|
719 // |
|
720 TInt CBTEngSrvPluginMgr::DoGetEirData( const TBTDevAddr& aAddr ) |
|
721 { |
|
722 TRACE_FUNC_ENTRY |
|
723 TInt err = KErrNone; |
|
724 iUuidContainter.Close(); |
|
725 |
|
726 if( !iServer->iSocketServ.Handle() ) |
|
727 { |
|
728 err = iServer->iSocketServ.Connect(); |
|
729 } |
|
730 |
|
731 TProtocolDesc pInfo; |
|
732 if(err == KErrNone) |
|
733 { |
|
734 _LIT(KBTLinkManagerProtocol, "BTLinkManager"); |
|
735 err = iServer->iSocketServ.FindProtocol( KBTLinkManagerProtocol(), pInfo ); |
|
736 } |
|
737 if (err == KErrNone) |
|
738 { |
|
739 err = iHostResolver.Open(iServer->iSocketServ, pInfo.iAddrFamily, pInfo.iProtocol); |
|
740 } |
|
741 if(err == KErrNone) |
|
742 { |
|
743 iInquirySockAddr = TInquirySockAddr(); |
|
744 iInquirySockAddr.SetBTAddr(aAddr); |
|
745 iInquirySockAddr.SetAction(KHostResCache | KHostResEir); |
|
746 |
|
747 TRequestStatus status; |
|
748 iHostResolver.GetByAddress(iInquirySockAddr, iNameEntry, status); |
|
749 User::WaitForRequest(status); |
|
750 err = status.Int(); |
|
751 TRACE_FUNC_RES(( _L( "HostResolver GetByAddress status: %d" ), err)) |
|
752 iHostResolver.Close(); |
|
753 } |
|
754 if(err == KErrNone) |
|
755 { |
|
756 TBluetoothNameRecordWrapper eirWrapper( iNameEntry() ); |
|
757 err = eirWrapper.GetServiceClassUuids( iUuidContainter ); |
|
758 } |
|
759 |
|
760 TRACE_FUNC_EXIT |
|
761 return err; |
|
762 } |
|
763 |
|
764 // --------------------------------------------------------------------------- |
|
765 // Check if Service UUID is supported by some plugin. |
|
766 // --------------------------------------------------------------------------- |
|
767 // |
|
768 TInt CBTEngSrvPluginMgr::GetConnectablePluginIndexByEir() |
|
769 { |
|
770 CBTEngPlugin::RProfileArray profiles; |
|
771 TInt count = iUuidContainter.UUIDs().Count(); |
|
772 |
|
773 for( TInt u = 0; u < count; u++) |
|
774 { |
|
775 for( TInt i = 0; i < iPluginArray.Count(); i++ ) |
|
776 { |
|
777 profiles.Reset(); |
|
778 iPluginArray[ i ]->GetSupportedProfiles( profiles ); |
|
779 for (TInt x = 0; x < profiles.Count(); x++) |
|
780 { |
|
781 if (iUuidContainter.UUIDs().At(u) == TUUID(profiles[x])) |
|
782 { |
|
783 profiles.Close(); |
|
784 TRACE_INFO( ( _L( "connectable plugin index %d" ), i ) ) |
|
785 return i; |
|
786 } |
|
787 } |
|
788 } |
|
789 } |
|
790 profiles.Close(); |
|
791 return KErrNotFound; |
|
792 } |
|
793 |
|
794 // --------------------------------------------------------------------------- |
|
795 // Internal utility function |
|
796 // --------------------------------------------------------------------------- |
|
797 // |
|
798 TInt CBTEngSrvPluginMgr::GetFirstPluginOfProfileSupported(TBTProfile aProfile ) |
|
799 { |
|
800 TRACE_FUNC_ENTRY |
|
801 for( TInt i = 0; i < iPluginArray.Count(); i++ ) |
|
802 { |
|
803 if( iPluginArray[ i ]->IsProfileSupported( aProfile ) ) |
|
804 { |
|
805 return i; |
|
806 } |
|
807 } |
|
808 return KErrNotFound; |
|
809 } |
|
810 |
|
811 // --------------------------------------------------------------------------- |
|
812 // Check if any audio connection exists. |
|
813 // --------------------------------------------------------------------------- |
|
814 // |
|
815 |
|
816 TBool CBTEngSrvPluginMgr::CheckAudioConnectionsL() |
|
817 { |
|
818 TRACE_FUNC_ENTRY |
|
819 TBool result = EFalse; |
|
820 RArray <TBTProfile> profiles; |
|
821 CleanupClosePushL( profiles ); |
|
822 profiles.AppendL( EBTProfileHSP ); |
|
823 profiles.AppendL( EBTProfileHFP ); |
|
824 profiles.AppendL( EBTProfileA2DP ); |
|
825 profiles.AppendL( EBTProfileAVRCP ); |
|
826 |
|
827 RBTDevAddrArray addrArray; |
|
828 for ( TInt i = 0; i < profiles.Count(); i++ ) |
|
829 { |
|
830 GetConnectedAddresses( addrArray, profiles[i] ); |
|
831 if ( addrArray.Count() > 0 ) |
|
832 { |
|
833 result = ETrue; |
|
834 break; |
|
835 } |
|
836 addrArray.Reset(); |
|
837 } |
|
838 addrArray.Close(); |
|
839 |
|
840 CleanupStack::PopAndDestroy( &profiles ); |
|
841 TRACE_FUNC_RES( ( _L( "result: %d" ), result ) ) |
|
842 return result; |
|
843 } |