bluetoothengine/btnotif/btnotifsrv/src/btnotifsecuritymanager.cpp
changeset 57 5ebadcda06cb
parent 47 9e2a905b887f
child 70 f5508c13dfe0
equal deleted inserted replaced
51:625f43ae9362 57:5ebadcda06cb
    67 // Symbian 2nd-phase constructor
    67 // Symbian 2nd-phase constructor
    68 // ---------------------------------------------------------------------------
    68 // ---------------------------------------------------------------------------
    69 //
    69 //
    70 void CBTNotifSecurityManager::ConstructL()
    70 void CBTNotifSecurityManager::ConstructL()
    71     {
    71     {
       
    72     BOstraceFunctionEntry0( DUMMY_DEVLIST );
    72     // Connect to pairing server for authentication & simple pairing 
    73     // Connect to pairing server for authentication & simple pairing 
    73     // results directly from the BT stack.
    74     // results directly from the BT stack.
    74     // Pairing server doesn't exist if we run BT 2.0 stack:
    75     // Pairing server doesn't exist if we run BT 2.0 stack:
    75     iPairingServ = new (ELeave) RBluetoothPairingServer;
    76     iPairingServ = new (ELeave) RBluetoothPairingServer;
    76     TInt err = iPairingServ->Connect();
    77     TInt err = iPairingServ->Connect();
    96     iLocalAddrActive = CBtSimpleActive::NewL( *this, ERegistryGetLocalAddress );
    97     iLocalAddrActive = CBtSimpleActive::NewL( *this, ERegistryGetLocalAddress );
    97     SubscribeLocalAddress();
    98     SubscribeLocalAddress();
    98     iPairNotifier = CBTNotifPairNotifier::NewL( *this );
    99     iPairNotifier = CBTNotifPairNotifier::NewL( *this );
    99     iDevRepository.AddObserverL( this );
   100     iDevRepository.AddObserverL( this );
   100     iServiceAuthorizer = CBTNotifServiceAuthorizer::NewL(*this);
   101     iServiceAuthorizer = CBTNotifServiceAuthorizer::NewL(*this);
       
   102     BOstraceFunctionExit0( DUMMY_DEVLIST);
   101     }
   103     }
   102 
   104 
   103 // ---------------------------------------------------------------------------
   105 // ---------------------------------------------------------------------------
   104 // NewL
   106 // NewL
   105 // ---------------------------------------------------------------------------
   107 // ---------------------------------------------------------------------------
   120 // Destructor
   122 // Destructor
   121 // ---------------------------------------------------------------------------
   123 // ---------------------------------------------------------------------------
   122 //
   124 //
   123 CBTNotifSecurityManager::~CBTNotifSecurityManager()
   125 CBTNotifSecurityManager::~CBTNotifSecurityManager()
   124     {
   126     {
       
   127     BOstraceFunctionEntry0( DUMMY_DEVLIST );
   125     delete iSSPResultActive;
   128     delete iSSPResultActive;
   126     delete iAuthenResultActive;
   129     delete iAuthenResultActive;
   127     delete iPairNotifier;
   130     delete iPairNotifier;
   128     delete iPairingHandler;
   131     delete iPairingHandler;
   129     iPairedDevices.Close();
   132     iPairedDevices.Close();
   140     if ( !iMessage.IsNull() )
   143     if ( !iMessage.IsNull() )
   141         {
   144         {
   142         iMessage.Complete( KErrCancel );
   145         iMessage.Complete( KErrCancel );
   143         }
   146         }
   144     delete iServiceAuthorizer;
   147     delete iServiceAuthorizer;
       
   148     BOstraceFunctionExit0( DUMMY_DEVLIST);
   145     }
   149     }
   146 
   150 
   147 // ---------------------------------------------------------------------------
   151 // ---------------------------------------------------------------------------
   148 // Initialises the paired devices list.
   152 // Initialises the paired devices list.
   149 // If the local address is not available from the P&S key 
   153 // If the local address is not available from the P&S key 
   153 // new devices for new pairings.
   157 // new devices for new pairings.
   154 // ---------------------------------------------------------------------------
   158 // ---------------------------------------------------------------------------
   155 //
   159 //
   156 void CBTNotifSecurityManager::SubscribeLocalAddress()
   160 void CBTNotifSecurityManager::SubscribeLocalAddress()
   157     {
   161     {
       
   162     BOstraceFunctionEntry0( DUMMY_DEVLIST );
   158     // Check that we have the Bluetooth local address. If we don't then initialise anyway, but subscribe for an update.
   163     // Check that we have the Bluetooth local address. If we don't then initialise anyway, but subscribe for an update.
   159     // This allows us to refresh our paired devices list to include updates made to the remote devices table of the 
   164     // This allows us to refresh our paired devices list to include updates made to the remote devices table of the 
   160     // Bluetooth registry from a restore operation. We need to include these devices without mistaking them for new 
   165     // Bluetooth registry from a restore operation. We need to include these devices without mistaking them for new 
   161     // pairings. We look solely at the P&S key for the address to avoid the condition whereby the address has been
   166     // pairings. We look solely at the P&S key for the address to avoid the condition whereby the address has been
   162     // entered into the reigstry but the Bluetooth Manager server has not begun the restore process yet. The signalling
   167     // entered into the reigstry but the Bluetooth Manager server has not begun the restore process yet. The signalling
   165 
   170 
   166     // Subscribe to local address property in case we need an update.
   171     // Subscribe to local address property in case we need an update.
   167     iPropertyLocalAddr.Subscribe( iLocalAddrActive->iStatus );
   172     iPropertyLocalAddr.Subscribe( iLocalAddrActive->iStatus );
   168     iLocalAddrActive->SetRequestId( ERegistryGetLocalAddress );
   173     iLocalAddrActive->SetRequestId( ERegistryGetLocalAddress );
   169     iLocalAddrActive->GoActive();
   174     iLocalAddrActive->GoActive();
       
   175     BOstraceFunctionExit0( DUMMY_DEVLIST);
   170     }
   176     }
   171 
   177 
   172 // ---------------------------------------------------------------------------
   178 // ---------------------------------------------------------------------------
   173 // Tells whether the local address is available from the P&S key 
   179 // Tells whether the local address is available from the P&S key 
   174 // KPropertyKeyBluetoothGetLocalDeviceAddress.
   180 // KPropertyKeyBluetoothGetLocalDeviceAddress.
   200 // Handles pairing related requests from BTNotif clients.
   206 // Handles pairing related requests from BTNotif clients.
   201 // ---------------------------------------------------------------------------
   207 // ---------------------------------------------------------------------------
   202 //
   208 //
   203 void CBTNotifSecurityManager::HandleBondingRequestL( const RMessage2& aMessage )
   209 void CBTNotifSecurityManager::HandleBondingRequestL( const RMessage2& aMessage )
   204     {
   210     {
       
   211     BOstraceFunctionEntry0( DUMMY_DEVLIST );
   205     TInt opcode = aMessage.Function();
   212     TInt opcode = aMessage.Function();
   206     TBTDevAddrPckgBuf addrPkg;
       
   207     switch( opcode )
   213     switch( opcode )
   208         {
   214         {
   209         case EBTNotifPairDevice:
   215         case EBTNotifPairDevice:
   210             {
   216             {
   211             if ( !iMessage.IsNull() )
   217             if ( !iMessage.IsNull() )
   234         default:
   240         default:
   235             {
   241             {
   236             User::Leave( KErrArgument );
   242             User::Leave( KErrArgument );
   237             }
   243             }
   238         }
   244         }
       
   245     BOstraceFunctionExit0( DUMMY_DEVLIST);
   239     }
   246     }
   240 
   247 
   241 // ---------------------------------------------------------------------------
   248 // ---------------------------------------------------------------------------
   242 // Process a client message related to notifiers.
   249 // Process a client message related to notifiers.
   243 // ---------------------------------------------------------------------------
   250 // ---------------------------------------------------------------------------
   244 //
   251 //
   245 void CBTNotifSecurityManager::HandleNotifierRequestL( const RMessage2& aMessage )
   252 void CBTNotifSecurityManager::HandleNotifierRequestL( const RMessage2& aMessage )
   246     {
   253     {
       
   254     BOstraceFunctionEntry0( DUMMY_DEVLIST );
   247     if(aMessage.Int0() == KBTManAuthNotifierUid.iUid)
   255     if(aMessage.Int0() == KBTManAuthNotifierUid.iUid)
   248         {
   256         {
   249         iServiceAuthorizer->StartNotifierL( aMessage );
   257         iServiceAuthorizer->StartNotifierL( aMessage );
   250         }
   258         }
   251     else
   259     else
   298 // ---------------------------------------------------------------------------
   306 // ---------------------------------------------------------------------------
   299 //
   307 //
   300 void CBTNotifSecurityManager::RenewPairingHandler( 
   308 void CBTNotifSecurityManager::RenewPairingHandler( 
   301         CBTNotifBasePairingHandler* aPairingHandler )
   309         CBTNotifBasePairingHandler* aPairingHandler )
   302     {
   310     {
       
   311     BOstraceFunctionEntry0( DUMMY_DEVLIST );
   303     delete iPairingHandler;
   312     delete iPairingHandler;
   304     iPairingHandler = aPairingHandler;
   313     iPairingHandler = aPairingHandler;
       
   314     BOstraceFunctionExit0( DUMMY_DEVLIST);
   305     }
   315     }
   306 
   316 
   307 // ---------------------------------------------------------------------------
   317 // ---------------------------------------------------------------------------
   308 // Find the session who requested this and completes its request.
   318 // Find the session who requested this and completes its request.
   309 // ---------------------------------------------------------------------------
   319 // ---------------------------------------------------------------------------
   310 //
   320 //
   311 void CBTNotifSecurityManager::OutgoingPairCompleted( TInt aErr )
   321 void CBTNotifSecurityManager::OutgoingPairCompleted( TInt aErr )
   312     {
   322     {
       
   323     BOstraceFunctionEntry0( DUMMY_DEVLIST );
   313     // the meaning of KHCIErrorBase equals KErrNone. Hide this specific BT stack
   324     // the meaning of KHCIErrorBase equals KErrNone. Hide this specific BT stack
   314 	// detail from clients:
   325 	// detail from clients:
   315     if ( !iMessage.IsNull()  )
   326     if ( !iMessage.IsNull()  )
   316         {
   327         {
   317         iMessage.Complete( (aErr == KHCIErrorBase) ? KErrNone : aErr );
   328         iMessage.Complete( (aErr == KHCIErrorBase) ? KErrNone : aErr );
   318         }
   329         }
       
   330     BOstraceFunctionExit0( DUMMY_DEVLIST);
   319     }
   331     }
   320 
   332 
   321 // ---------------------------------------------------------------------------
   333 // ---------------------------------------------------------------------------
   322 // A session will be ended, completes the pending request for this session.
   334 // A session will be ended, completes the pending request for this session.
   323 // ---------------------------------------------------------------------------
   335 // ---------------------------------------------------------------------------
   324 //
   336 //
   325 void CBTNotifSecurityManager::SessionClosed( CSession2* aSession )
   337 void CBTNotifSecurityManager::SessionClosed( CSession2* aSession )
   326     {
   338     {
       
   339     BOstraceFunctionEntry0( DUMMY_DEVLIST );
   327     BOstrace1(TRACE_DEBUG,DUMMY_DEVLIST," session %x", aSession);
   340     BOstrace1(TRACE_DEBUG,DUMMY_DEVLIST," session %x", aSession);
   328     if ( !iMessage.IsNull() && iMessage.Session() == aSession )
   341     if ( !iMessage.IsNull() && iMessage.Session() == aSession )
   329         {
   342         {
   330         iMessage.Complete( KErrCancel );
   343         iMessage.Complete( KErrCancel );
   331         }
   344         }
       
   345     BOstraceFunctionExit0( DUMMY_DEVLIST);
   332     }
   346     }
   333 
   347 
   334 // ---------------------------------------------------------------------------
   348 // ---------------------------------------------------------------------------
   335 // Unpair the device from registry
   349 // Unpair the device from registry
   336 // ---------------------------------------------------------------------------
   350 // ---------------------------------------------------------------------------
   337 //
   351 //
   338 void CBTNotifSecurityManager::UnpairDevice( const TBTDevAddr& aAddr )
   352 void CBTNotifSecurityManager::UnpairDevice( const TBTDevAddr& aAddr )
   339     {
   353     {
       
   354     BOstraceFunctionEntry0( DUMMY_DEVLIST );
   340     TIdentityRelation<TBTNamelessDevice> addrComp( CompareDeviceByAddress );
   355     TIdentityRelation<TBTNamelessDevice> addrComp( CompareDeviceByAddress );
   341     TBTNamelessDevice dev;
   356     TBTNamelessDevice dev;
   342     dev.SetAddress( aAddr );
   357     dev.SetAddress( aAddr );
   343     // only do unpairing if the we have a link key with it.
   358     // only do unpairing if the we have a link key with it.
   344     TInt index = iPairedDevices.Find( dev, addrComp );
   359     TInt index = iPairedDevices.Find( dev, addrComp );
   370             // status.Int() could be -1 if the device is not in registry 
   385             // status.Int() could be -1 if the device is not in registry 
   371             // which is totally fine for us.
   386             // which is totally fine for us.
   372             (void) UpdateRegDevice( dev );
   387             (void) UpdateRegDevice( dev );
   373             }
   388             }
   374         }
   389         }
       
   390     BOstraceFunctionExit0( DUMMY_DEVLIST);
   375     }
   391     }
   376 
   392 
   377 void CBTNotifSecurityManager::BlockDevice( const TBTDevAddr& aAddr , TBool aBanned)
   393 void CBTNotifSecurityManager::BlockDevice( const TBTDevAddr& aAddr , TBool aBanned)
   378     {
   394     {
       
   395     BOstraceFunctionEntry0( DUMMY_DEVLIST );
   379     TIdentityRelation<TBTNamelessDevice> addrComp( CompareDeviceByAddress );
   396     TIdentityRelation<TBTNamelessDevice> addrComp( CompareDeviceByAddress );
   380     TBTNamelessDevice dev;
   397     TBTNamelessDevice dev;
   381     dev.SetAddress( aAddr );
   398     dev.SetAddress( aAddr );
   382     TRequestStatus status( KRequestPending );
   399     TRequestStatus status( KRequestPending );
   383     // Unpair the device in registry (synchronously)
   400     // Unpair the device in registry (synchronously)
   392             security.SetNoAuthorise(EFalse);
   409             security.SetNoAuthorise(EFalse);
   393             }
   410             }
   394         dev.SetGlobalSecurity(security);
   411         dev.SetGlobalSecurity(security);
   395         (void)UpdateRegDevice(dev);
   412         (void)UpdateRegDevice(dev);
   396         }
   413         }
       
   414     BOstraceFunctionExit0( DUMMY_DEVLIST);
   397     }
   415     }
   398 
   416 
   399 TInt CBTNotifSecurityManager::AddUiCookieJustWorksPaired( const TBTNamelessDevice& aDev )
   417 TInt CBTNotifSecurityManager::AddUiCookieJustWorksPaired( const TBTNamelessDevice& aDev )
   400     {
   418     {
       
   419     BOstraceFunctionEntry0( DUMMY_DEVLIST );
   401     TInt err( KErrNone );
   420     TInt err( KErrNone );
   402     // There might be UI cookies used by other applications,
   421     // There might be UI cookies used by other applications,
   403     // we should not overwrite them. 
   422     // we should not overwrite them. 
   404     TInt32 cookie = aDev.IsValidUiCookie() ? aDev.UiCookie() : EBTUiCookieUndefined;
   423     TInt32 cookie = aDev.IsValidUiCookie() ? aDev.UiCookie() : EBTUiCookieUndefined;
   405     if ( !( cookie & EBTUiCookieJustWorksPaired ) )
   424     if ( !( cookie & EBTUiCookieJustWorksPaired ) )
   410         cookie |= EBTUiCookieJustWorksPaired;
   429         cookie |= EBTUiCookieJustWorksPaired;
   411         dev.SetUiCookie( cookie );
   430         dev.SetUiCookie( cookie );
   412         err = UpdateRegDevice( dev );
   431         err = UpdateRegDevice( dev );
   413         BOstrace1(TRACE_DEBUG,DUMMY_DEVLIST,"Outgoing Pairing write Ui cookie ret %d", err );
   432         BOstrace1(TRACE_DEBUG,DUMMY_DEVLIST,"Outgoing Pairing write Ui cookie ret %d", err );
   414         }
   433         }
       
   434     BOstraceFunctionExit0( DUMMY_DEVLIST);
   415     return err;
   435     return err;
   416     }
   436     }
   417 
   437 
   418 // ---------------------------------------------------------------------------
   438 // ---------------------------------------------------------------------------
   419 // update a nameless device in registry
   439 // update a nameless device in registry
   420 // ---------------------------------------------------------------------------
   440 // ---------------------------------------------------------------------------
   421 //
   441 //
   422 TInt CBTNotifSecurityManager::UpdateRegDevice( const TBTNamelessDevice& aDev )
   442 TInt CBTNotifSecurityManager::UpdateRegDevice( const TBTNamelessDevice& aDev )
   423     {
   443     {
       
   444     BOstraceFunctionEntry0( DUMMY_DEVLIST );
   424     TRequestStatus status( KRequestPending );
   445     TRequestStatus status( KRequestPending );
   425     // update the device in registry synchronously
   446     // update the device in registry synchronously
   426     iRegistry.ModifyDevice( aDev, status );
   447     iRegistry.ModifyDevice( aDev, status );
   427     User::WaitForRequest( status );
   448     User::WaitForRequest( status );
   428     BOstrace1(TRACE_DEBUG,DUMMY_DEVLIST,"UpdateRegDevice, ret %d", status.Int());
   449     BOstrace1(TRACE_DEBUG,DUMMY_DEVLIST,"UpdateRegDevice, ret %d", status.Int());
       
   450     BOstraceFunctionExit0( DUMMY_DEVLIST);
   429     return status.Int();
   451     return status.Int();
   430     }
   452     }
   431 
   453 
   432 // ---------------------------------------------------------------------------
   454 // ---------------------------------------------------------------------------
   433 // 0000 for outgoing pairing with a headset.
   455 // 0000 for outgoing pairing with a headset.
   435 // ---------------------------------------------------------------------------
   457 // ---------------------------------------------------------------------------
   436 //
   458 //
   437 void CBTNotifSecurityManager::GetPinCode(
   459 void CBTNotifSecurityManager::GetPinCode(
   438         TBTPinCode& aPin, const TBTDevAddr& aAddr, TInt aMinPinLength )
   460         TBTPinCode& aPin, const TBTDevAddr& aAddr, TInt aMinPinLength )
   439     {
   461     {
       
   462     BOstraceFunctionEntry0( DUMMY_DEVLIST );
   440     if ( iPairingHandler )
   463     if ( iPairingHandler )
   441         {
   464         {
   442         iPairingHandler->GetPinCode( aPin, aAddr, aMinPinLength );
   465         iPairingHandler->GetPinCode( aPin, aAddr, aMinPinLength );
   443         }
   466         }
   444     else
   467     else
   445         {
   468         {
   446         // make sure not to leave any text as PIN.
   469         // make sure not to leave any text as PIN.
   447         aPin.Zero();
   470         aPin.Zero();
   448         aPin().iLength = 0;
   471         aPin().iLength = 0;
   449         }
   472         }
       
   473     BOstraceFunctionExit0( DUMMY_DEVLIST);
   450     }
   474     }
   451 
   475 
   452 // ---------------------------------------------------------------------------
   476 // ---------------------------------------------------------------------------
   453 // Ask server class the connection status of the specified device
   477 // Ask server class the connection status of the specified device
   454 // ---------------------------------------------------------------------------
   478 // ---------------------------------------------------------------------------
   455 //
   479 //
   456 TBTEngConnectionStatus CBTNotifSecurityManager::ConnectStatus( const TBTDevAddr& aAddr )
   480 TBTEngConnectionStatus CBTNotifSecurityManager::ConnectStatus( const TBTDevAddr& aAddr )
   457     {
   481     {
       
   482     BOstraceFunctionEntry0( DUMMY_DEVLIST );
   458     const CBtDevExtension* devExt = iDevRepository.Device(aAddr);
   483     const CBtDevExtension* devExt = iDevRepository.Device(aAddr);
   459     TBTEngConnectionStatus status = EBTEngNotConnected;
   484     TBTEngConnectionStatus status = EBTEngNotConnected;
   460     if ( devExt ) 
   485     if ( devExt ) 
   461         {
   486         {
   462         status = devExt->ServiceConnectionStatus();
   487         status = devExt->ServiceConnectionStatus();
   463         }
   488         }
       
   489     BOstraceFunctionExit0( DUMMY_DEVLIST);
   464     return status;
   490     return status;
   465     }
   491     }
   466 
   492 
   467 // ---------------------------------------------------------------------------
   493 // ---------------------------------------------------------------------------
   468 // From class MBTNotifPairingAOObserver.
   494 // From class MBTNotifPairingAOObserver.
   469 // Checks if there is an authentication result.
   495 // Checks if there is an authentication result.
   470 // ---------------------------------------------------------------------------
   496 // ---------------------------------------------------------------------------
   471 //
   497 //
   472 void CBTNotifSecurityManager::RequestCompletedL( CBtSimpleActive* aActive, TInt aStatus )
   498 void CBTNotifSecurityManager::RequestCompletedL( CBtSimpleActive* aActive, TInt aStatus )
   473     {
   499     {
       
   500     BOstraceFunctionEntry0( DUMMY_DEVLIST );
   474     BOstraceExt2(TRACE_DEBUG,DUMMY_DEVLIST,"aId: %d, aStatus: %d", aActive->RequestId(), aStatus);
   501     BOstraceExt2(TRACE_DEBUG,DUMMY_DEVLIST,"aId: %d, aStatus: %d", aActive->RequestId(), aStatus);
   475     // Check which request is completed.
   502     // Check which request is completed.
   476     switch( aActive->RequestId() )
   503     switch( aActive->RequestId() )
   477         {
   504         {
   478         case ESimplePairingResult:
   505         case ESimplePairingResult:
   508             }
   535             }
   509         default:
   536         default:
   510             // Should not be possible, but no need for handling.
   537             // Should not be possible, but no need for handling.
   511             break;
   538             break;
   512         }
   539         }
       
   540     BOstraceFunctionExit0( DUMMY_DEVLIST);
   513     }
   541     }
   514 
   542 
   515 // ---------------------------------------------------------------------------
   543 // ---------------------------------------------------------------------------
   516 // From class MBTEngActiveObserver.
   544 // From class MBTEngActiveObserver.
   517 // cancels an outstanding request according to the given id.
   545 // cancels an outstanding request according to the given id.
   518 // ---------------------------------------------------------------------------
   546 // ---------------------------------------------------------------------------
   519 //
   547 //
   520 void CBTNotifSecurityManager::CancelRequest( TInt aRequestId )
   548 void CBTNotifSecurityManager::CancelRequest( TInt aRequestId )
   521     {
   549     {
       
   550     BOstraceFunctionEntry0( DUMMY_DEVLIST );
   522     switch ( aRequestId )
   551     switch ( aRequestId )
   523         {
   552         {
   524         case ESimplePairingResult:
   553         case ESimplePairingResult:
   525             {
   554             {
   526             // Cancel listening Simple pairing result
   555             // Cancel listening Simple pairing result
   538             // cancel listening local address status change
   567             // cancel listening local address status change
   539             iPropertyLocalAddr.Cancel();
   568             iPropertyLocalAddr.Cancel();
   540             break;
   569             break;
   541             }
   570             }
   542         }
   571         }
       
   572     BOstraceFunctionExit0( DUMMY_DEVLIST);
   543     }
   573     }
   544 
   574 
   545 // ---------------------------------------------------------------------------
   575 // ---------------------------------------------------------------------------
   546 // From class MBtSimpleActiveObserver.
   576 // From class MBtSimpleActiveObserver.
   547 // ---------------------------------------------------------------------------
   577 // ---------------------------------------------------------------------------
   548 //
   578 //
   549 void CBTNotifSecurityManager::HandleError( CBtSimpleActive* aActive, TInt aError )
   579 void CBTNotifSecurityManager::HandleError( CBtSimpleActive* aActive, TInt aError )
   550     {
   580     {
       
   581     BOstraceFunctionEntry0( DUMMY_DEVLIST );
   551     BOstraceExt2(TRACE_DEBUG,DUMMY_DEVLIST,"request id: %d, error: %d", aActive->RequestId(), aError);
   582     BOstraceExt2(TRACE_DEBUG,DUMMY_DEVLIST,"request id: %d, error: %d", aActive->RequestId(), aError);
   552     (void) aActive;
   583     (void) aActive;
   553     (void) aError;
   584     (void) aError;
       
   585     BOstraceFunctionExit0( DUMMY_DEVLIST);
   554     }
   586     }
   555 
   587 
   556 // ---------------------------------------------------------------------------
   588 // ---------------------------------------------------------------------------
   557 // From class MBtDevRepositoryObserver.
   589 // From class MBtDevRepositoryObserver.
   558 // ---------------------------------------------------------------------------
   590 // ---------------------------------------------------------------------------
   559 //
   591 //
   560 void CBTNotifSecurityManager::RepositoryInitialized()
   592 void CBTNotifSecurityManager::RepositoryInitialized()
   561     {
   593     {
       
   594     BOstraceFunctionEntry0( DUMMY_DEVLIST );
   562     TRAPD(err, UpdatePairedDeviceListL() );
   595     TRAPD(err, UpdatePairedDeviceListL() );
   563     if ( !err && iPairingHandler )
   596     if ( !err && iPairingHandler )
   564         {
   597         {
   565         // non-null pairing handler means we are involved in a
   598         // non-null pairing handler means we are involved in a
   566         // pairing operation already.
   599         // pairing operation already.
   567         // todo: is some handling for above case needed?
   600         // todo: is some handling for above case needed?
   568         }
   601         }
       
   602     BOstraceFunctionExit0( DUMMY_DEVLIST);
   569     }
   603     }
   570 
   604 
   571 // ---------------------------------------------------------------------------
   605 // ---------------------------------------------------------------------------
   572 // From class MBtDevRepositoryObserver.
   606 // From class MBtDevRepositoryObserver.
   573 // ---------------------------------------------------------------------------
   607 // ---------------------------------------------------------------------------
   574 //
   608 //
   575 void CBTNotifSecurityManager::DeletedFromRegistry( const TBTDevAddr& aAddr )
   609 void CBTNotifSecurityManager::DeletedFromRegistry( const TBTDevAddr& aAddr )
   576     {
   610     {
       
   611     BOstraceFunctionEntry0( DUMMY_DEVLIST );
   577     // We are only interested in the removal of a paired device.
   612     // We are only interested in the removal of a paired device.
   578     // thus check whether it is in our local paired list:
   613     // thus check whether it is in our local paired list:
   579     TInt i = iPairedDevices.Find( aAddr, MatchDeviceAddress);
   614     TInt i = iPairedDevices.Find( aAddr, MatchDeviceAddress);
   580     if ( i > KErrNotFound )
   615     if ( i > KErrNotFound )
   581         {
   616         {
   582         iPairedDevices.Remove( i );
   617         iPairedDevices.Remove( i );
   583         }
   618         }
       
   619     BOstraceFunctionExit0( DUMMY_DEVLIST);
   584     }
   620     }
   585 
   621 
   586 // ---------------------------------------------------------------------------
   622 // ---------------------------------------------------------------------------
   587 // From class MBtDevRepositoryObserver.
   623 // From class MBtDevRepositoryObserver.
   588 // ---------------------------------------------------------------------------
   624 // ---------------------------------------------------------------------------
   589 //
   625 //
   590 void CBTNotifSecurityManager::AddedToRegistry( const CBtDevExtension& aDevice )
   626 void CBTNotifSecurityManager::AddedToRegistry( const CBtDevExtension& aDevice )
   591     {
   627     {
       
   628     BOstraceFunctionEntry0( DUMMY_DEVLIST );
   592     // We are only interested in paired device.
   629     // We are only interested in paired device.
   593     if ( CBtDevExtension::IsBonded( aDevice.Device().AsNamelessDevice() ) )
   630     if ( CBtDevExtension::IsBonded( aDevice.Device().AsNamelessDevice() ) )
   594         {
   631         {
   595         TRAP_IGNORE( 
   632         TRAP_IGNORE( 
   596                 HandleRegistryBondingL( aDevice.Device().AsNamelessDevice() ) );
   633                 HandleRegistryBondingL( aDevice.Device().AsNamelessDevice() ) );
   597         }
   634         }
       
   635     BOstraceFunctionExit0( DUMMY_DEVLIST);
   598     }
   636     }
   599 
   637 
   600 
   638 
   601 // ---------------------------------------------------------------------------
   639 // ---------------------------------------------------------------------------
   602 // From class MBtDevRepositoryObserver.
   640 // From class MBtDevRepositoryObserver.
   603 // ---------------------------------------------------------------------------
   641 // ---------------------------------------------------------------------------
   604 //
   642 //
   605 void CBTNotifSecurityManager::ChangedInRegistry(
   643 void CBTNotifSecurityManager::ChangedInRegistry(
   606         const CBtDevExtension& aDevice, TUint aSimilarity )
   644         const CBtDevExtension& aDevice, TUint aSimilarity )
   607     {
   645     {
       
   646     BOstraceFunctionEntry0( DUMMY_DEVLIST );
   608     // We are only interested in paired device.
   647     // We are only interested in paired device.
   609     // thus check whether it is in our local paired list:
   648     // thus check whether it is in our local paired list:
   610     TInt i = iPairedDevices.Find( aDevice.Addr(), MatchDeviceAddress);
   649     TInt i = iPairedDevices.Find( aDevice.Addr(), MatchDeviceAddress);
   611     TBool bonded = CBtDevExtension::IsBonded( aDevice.Device().AsNamelessDevice() );
   650     TBool bonded = CBtDevExtension::IsBonded( aDevice.Device().AsNamelessDevice() );
   612     if ( i == KErrNotFound )
   651     if ( i == KErrNotFound )
   613         {
   652         {
       
   653         BOstrace0(TRACE_DEBUG,DUMMY_DEVLIST,"Not found");
   614         if ( bonded ) 
   654         if ( bonded ) 
   615             {
   655             {
       
   656             BOstrace0(TRACE_DEBUG,DUMMY_DEVLIST,"Not found but bonded");
   616             TRAP_IGNORE(
   657             TRAP_IGNORE(
   617                     HandleRegistryBondingL( 
   658                     HandleRegistryBondingL( 
   618                             aDevice.Device().AsNamelessDevice() ) );                
   659                             aDevice.Device().AsNamelessDevice() ) );                
   619             }
   660             }
       
   661         BOstraceFunctionExit0( DUMMY_DEVLIST);
   620         return;
   662         return;
   621         }
   663         }
   622     // Device was inregistry before, but we need to evaluate its bonding
   664     // Device was inregistry before, but we need to evaluate its bonding
   623     // status.
   665     // status.
   624     // The given similarity will tell if the linkkey and paired is changed
   666     // The given similarity will tell if the linkkey and paired is changed
   628     if ( ( pairingProperty & aSimilarity) == pairingProperty )
   670     if ( ( pairingProperty & aSimilarity) == pairingProperty )
   629         {
   671         {
   630         // no pairing or linkkey change. Nothing to do for pairing handling.
   672         // no pairing or linkkey change. Nothing to do for pairing handling.
   631         // but we'd better update local copy just in case other data
   673         // but we'd better update local copy just in case other data
   632         // of this device is needed by someone:
   674         // of this device is needed by someone:
       
   675         BOstrace0(TRACE_DEBUG,DUMMY_DEVLIST,"No pairing or link key change");
   633         iPairedDevices[i] = aDevice.Device().AsNamelessDevice();
   676         iPairedDevices[i] = aDevice.Device().AsNamelessDevice();
       
   677         BOstraceFunctionExit0( DUMMY_DEVLIST);
   634         return;
   678         return;
   635         }
   679         }
   636     if ( !CBtDevExtension::IsBonded( aDevice.Device().AsNamelessDevice() ) )
   680     if ( !bonded )
   637         {
   681         {
   638         // device is not user-bonded.
   682         // device is not user-bonded.
       
   683         UnTrustDevice(iPairedDevices[i].Address());
   639         iPairedDevices.Remove( i );
   684         iPairedDevices.Remove( i );
       
   685         BOstraceFunctionExit0( DUMMY_DEVLIST);
   640         return;
   686         return;
   641         }
   687         }
   642     // it is a new paired device if its link-key has been upgraded
   688     // it is a new paired device if its link-key has been upgraded
   643     if ( aDevice.Device().LinkKeyType() != ELinkKeyUnauthenticatedUpgradable )
   689     if ( aDevice.Device().LinkKeyType() != ELinkKeyUnauthenticatedUpgradable )
   644         {
   690         {
   645         iPairedDevices.Remove( i );
   691         iPairedDevices.Remove( i );
   646         TRAP_IGNORE(
   692         TRAP_IGNORE(
   647                 HandleRegistryBondingL( 
   693                 HandleRegistryBondingL( 
   648                         aDevice.Device().AsNamelessDevice() ) );                
   694                         aDevice.Device().AsNamelessDevice() ) );                
   649         }
   695         }
       
   696     BOstraceFunctionExit0( DUMMY_DEVLIST);
   650     }
   697     }
   651 
   698 
   652 // ---------------------------------------------------------------------------
   699 // ---------------------------------------------------------------------------
   653 // From class MBtDevRepositoryObserver.
   700 // From class MBtDevRepositoryObserver.
   654 // This class is not interested in such events.
   701 // This class is not interested in such events.
   655 // ---------------------------------------------------------------------------
   702 // ---------------------------------------------------------------------------
   656 //
   703 //
   657 void CBTNotifSecurityManager::ServiceConnectionChanged(
   704 void CBTNotifSecurityManager::ServiceConnectionChanged(
   658         const CBtDevExtension& aDevice, TBool aConnected )
   705         const CBtDevExtension& aDevice, TBool aConnected )
   659     {
   706     {
       
   707     BOstraceFunctionEntry0( DUMMY_DEVLIST );
   660     (void) aDevice;
   708     (void) aDevice;
   661     (void) aConnected;
   709     (void) aConnected;
       
   710     BOstraceFunctionExit0( DUMMY_DEVLIST);
   662     }
   711     }
   663 
   712 
   664 // ---------------------------------------------------------------------------
   713 // ---------------------------------------------------------------------------
   665 // Activate or deactivate a pairing handler
   714 // Activate or deactivate a pairing handler
   666 // ---------------------------------------------------------------------------
   715 // ---------------------------------------------------------------------------
   667 //
   716 //
   668 TInt CBTNotifSecurityManager::SetPairObserver(const TBTDevAddr& aAddr, TBool aActivate)
   717 TInt CBTNotifSecurityManager::SetPairObserver(const TBTDevAddr& aAddr, TBool aActivate)
   669     {
   718     {
       
   719     BOstraceFunctionEntry0( DUMMY_DEVLIST );
   670     BOstrace1(TRACE_DEBUG,DUMMY_DEVLIST,"%d", aActivate);
   720     BOstrace1(TRACE_DEBUG,DUMMY_DEVLIST,"%d", aActivate);
   671     BtTraceBtAddr0(TRACE_DEBUG,DUMMY_DEVLIST, aAddr );
   721     BtTraceBtAddr0(TRACE_DEBUG,DUMMY_DEVLIST, aAddr );
   672     TInt err( KErrNone );
   722     TInt err( KErrNone );
   673     if ( !aActivate )
   723     if ( !aActivate )
   674         {
   724         {
   675         if ( iPairingHandler )
   725         if ( iPairingHandler )
   676             {
   726             {
   677             iPairingHandler->StopPairHandling( aAddr );
   727             iPairingHandler->StopPairHandling( aAddr );
   678             }
   728             }
       
   729         BOstraceFunctionExit0( DUMMY_DEVLIST);
   679         return err;
   730         return err;
   680         }
   731         }
   681     
   732     
   682     if ( !iPairingHandler)
   733     if ( !iPairingHandler)
   683         {
   734         {
   689     if ( iPairingHandler)
   740     if ( iPairingHandler)
   690         {
   741         {
   691         // let the handler decide what to do:
   742         // let the handler decide what to do:
   692         err = iPairingHandler->ObserveIncomingPair( aAddr );
   743         err = iPairingHandler->ObserveIncomingPair( aAddr );
   693         }
   744         }
       
   745     BOstraceFunctionExit0( DUMMY_DEVLIST);
   694     return err;
   746     return err;
   695     }
   747     }
   696 
   748 
   697 // ---------------------------------------------------------------------------
   749 // ---------------------------------------------------------------------------
   698 // Delegates the request to current pair handler
   750 // Delegates the request to current pair handler
   699 // ---------------------------------------------------------------------------
   751 // ---------------------------------------------------------------------------
   700 //
   752 //
   701 void CBTNotifSecurityManager::PairDeviceL( const TBTDevAddr& aAddr, TUint32 aCod )
   753 void CBTNotifSecurityManager::PairDeviceL( const TBTDevAddr& aAddr, TUint32 aCod )
   702     {
   754     {
       
   755     BOstraceFunctionEntry0( DUMMY_DEVLIST );
   703     if ( !iPairingHandler)
   756     if ( !iPairingHandler)
   704         {
   757         {
   705         // no existing pair handling, create one:
   758         // no existing pair handling, create one:
   706         iPairingHandler = CBTNotifOutgoingPairingHandler::NewL( *this, aAddr );
   759         iPairingHandler = CBTNotifOutgoingPairingHandler::NewL( *this, aAddr );
   707         }
   760         }
   708     // let pair handler decide what to do:
   761     // let pair handler decide what to do:
   709     iPairingHandler->HandleOutgoingPairL( aAddr, aCod );
   762     iPairingHandler->HandleOutgoingPairL( aAddr, aCod );
       
   763     BOstraceFunctionExit0( DUMMY_DEVLIST);
   710     }
   764     }
   711 
   765 
   712 // ---------------------------------------------------------------------------
   766 // ---------------------------------------------------------------------------
   713 // cancel Subscribings to simple pairing result and authentication result from
   767 // cancel Subscribings to simple pairing result and authentication result from
   714 // Pairing Server
   768 // Pairing Server
   715 // ---------------------------------------------------------------------------
   769 // ---------------------------------------------------------------------------
   716 //
   770 //
   717 void CBTNotifSecurityManager::CancelSubscribePairingAuthenticate()
   771 void CBTNotifSecurityManager::CancelSubscribePairingAuthenticate()
   718     {
   772     {
       
   773     BOstraceFunctionEntry0( DUMMY_DEVLIST );
   719     if( iSSPResultActive )
   774     if( iSSPResultActive )
   720         {
   775         {
   721         // Cancel listening Simple pairing result
   776         // Cancel listening Simple pairing result
   722         iSSPResultActive->Cancel();
   777         iSSPResultActive->Cancel();
   723         }
   778         }
   724     if( iAuthenResultActive )
   779     if( iAuthenResultActive )
   725         {
   780         {
   726         iAuthenResultActive->Cancel();
   781         iAuthenResultActive->Cancel();
   727         }
   782         }
       
   783     BOstraceFunctionExit0( DUMMY_DEVLIST);
   728     }
   784     }
   729 
   785 
   730 // ---------------------------------------------------------------------------
   786 // ---------------------------------------------------------------------------
   731 // Subscribes to simple pairing result from Pairing Server (if not already 
   787 // Subscribes to simple pairing result from Pairing Server (if not already 
   732 // subscribed).
   788 // subscribed).
   733 // ---------------------------------------------------------------------------
   789 // ---------------------------------------------------------------------------
   734 //
   790 //
   735 void CBTNotifSecurityManager::SubscribeSspPairingResult()
   791 void CBTNotifSecurityManager::SubscribeSspPairingResult()
   736     {
   792     {
       
   793     BOstraceFunctionEntry0( DUMMY_DEVLIST );
   737     if ( !iSSPResultActive->IsActive() )
   794     if ( !iSSPResultActive->IsActive() )
   738         {
   795         {
   739         iPairingResult.SimplePairingResult( iSimplePairingRemote, iSSPResultActive->RequestStatus() );
   796         iPairingResult.SimplePairingResult( iSimplePairingRemote, iSSPResultActive->RequestStatus() );
   740         iSSPResultActive->GoActive();
   797         iSSPResultActive->GoActive();
   741         }
   798         }
       
   799     BOstraceFunctionExit0( DUMMY_DEVLIST);
   742     }
   800     }
   743 
   801 
   744 // ---------------------------------------------------------------------------
   802 // ---------------------------------------------------------------------------
   745 // Subscribes to authentication result from Pairing Server (if not already
   803 // Subscribes to authentication result from Pairing Server (if not already
   746 // subscribed).
   804 // subscribed).
   747 // ---------------------------------------------------------------------------
   805 // ---------------------------------------------------------------------------
   748 //
   806 //
   749 void CBTNotifSecurityManager::SubscribeAuthenticateResult()
   807 void CBTNotifSecurityManager::SubscribeAuthenticateResult()
   750     {
   808     {
       
   809     BOstraceFunctionEntry0( DUMMY_DEVLIST );
   751     if ( !iAuthenResultActive->IsActive() )
   810     if ( !iAuthenResultActive->IsActive() )
   752         {
   811         {
   753         // Subscribe authentication result (which requires pairing for unpaired devices)
   812         // Subscribe authentication result (which requires pairing for unpaired devices)
   754         iAuthenResult.AuthenticationResult( iAuthenticateRemote, iAuthenResultActive->RequestStatus() );
   813         iAuthenResult.AuthenticationResult( iAuthenticateRemote, iAuthenResultActive->RequestStatus() );
   755         iAuthenResultActive->GoActive();
   814         iAuthenResultActive->GoActive();
   756         }
   815         }
       
   816     BOstraceFunctionExit0( DUMMY_DEVLIST);
   757     }
   817     }
   758 
   818 
   759 // ---------------------------------------------------------------------------
   819 // ---------------------------------------------------------------------------
   760 // Handle a pairing result from the pairing server.
   820 // Handle a pairing result from the pairing server.
   761 // ---------------------------------------------------------------------------
   821 // ---------------------------------------------------------------------------
   762 //
   822 //
   763 void CBTNotifSecurityManager::HandlePairingResultL( const TBTDevAddr& aAddr, TInt aResult )
   823 void CBTNotifSecurityManager::HandlePairingResultL( const TBTDevAddr& aAddr, TInt aResult )
   764     {
   824     {
       
   825     BOstraceFunctionEntry0( DUMMY_DEVLIST );
   765     BOstrace1(TRACE_DEBUG,DUMMY_DEVLIST,"result %d", aResult);
   826     BOstrace1(TRACE_DEBUG,DUMMY_DEVLIST,"result %d", aResult);
   766     BtTraceBtAddr0(TRACE_DEBUG,DUMMY_DEVLIST, aAddr );
   827     BtTraceBtAddr0(TRACE_DEBUG,DUMMY_DEVLIST, aAddr );
   767  
   828  
   768     if ( !iPairingHandler && ( aResult == KErrNone || aResult == KHCIErrorBase ) )
   829     if ( !iPairingHandler && ( aResult == KErrNone || aResult == KHCIErrorBase ) )
   769         {
   830         {
   784             {
   845             {
   785             // No handler yet, create incoming pairing handler:
   846             // No handler yet, create incoming pairing handler:
   786             iPairingHandler = CBTNotifIncomingPairingHandler::NewL( *this, aAddr );
   847             iPairingHandler = CBTNotifIncomingPairingHandler::NewL( *this, aAddr );
   787             }
   848             }
   788         }
   849         }
       
   850 
   789     if ( iPairingHandler )
   851     if ( iPairingHandler )
   790         {
   852         {
   791         iPairingHandler->HandlePairServerResult( aAddr, aResult );
   853         iPairingHandler->HandlePairServerResult( aAddr, aResult );
   792         }
   854         }
       
   855     BOstraceFunctionExit0( DUMMY_DEVLIST);
   793     }
   856     }
   794 
   857 
   795 // ---------------------------------------------------------------------------
   858 // ---------------------------------------------------------------------------
   796 // copy the nameless devices to local array
   859 // copy the nameless devices to local array
   797 // ---------------------------------------------------------------------------
   860 // ---------------------------------------------------------------------------
   798 //
   861 //
   799 void CBTNotifSecurityManager::UpdatePairedDeviceListL()
   862 void CBTNotifSecurityManager::UpdatePairedDeviceListL()
   800     {
   863     {
       
   864     BOstraceFunctionEntry0( DUMMY_DEVLIST );
   801     iPairedDevices.Reset();
   865     iPairedDevices.Reset();
   802     const RDevExtensionArray& alldevs = iDevRepository.AllDevices();
   866     const RDevExtensionArray& alldevs = iDevRepository.AllDevices();
   803     for ( TInt i = 0; i < alldevs.Count(); i++ )
   867     for ( TInt i = 0; i < alldevs.Count(); i++ )
   804         {
   868         {
   805         if ( CBtDevExtension::IsBonded( alldevs[i]->Device().AsNamelessDevice() ) )
   869         if ( CBtDevExtension::IsBonded( alldevs[i]->Device().AsNamelessDevice() ) )
   806             {
   870             {
   807             iPairedDevices.AppendL( alldevs[i]->Device().AsNamelessDevice() );
   871             iPairedDevices.AppendL( alldevs[i]->Device().AsNamelessDevice() );
   808             }
   872             }
   809         }
   873         }
       
   874     BOstraceFunctionExit0( DUMMY_DEVLIST);
   810     }
   875     }
   811 
   876 
   812 // ---------------------------------------------------------------------------
   877 // ---------------------------------------------------------------------------
   813 // Create incoming pairing handler if no one exists yet.
   878 // Create incoming pairing handler if no one exists yet.
   814 // ---------------------------------------------------------------------------
   879 // ---------------------------------------------------------------------------
   815 //
   880 //
   816 void CBTNotifSecurityManager::HandleRegistryBondingL(
   881 void CBTNotifSecurityManager::HandleRegistryBondingL(
   817         const TBTNamelessDevice& aNameless)
   882         const TBTNamelessDevice& aNameless)
   818     {
   883     {
       
   884     BOstraceFunctionEntry0( DUMMY_DEVLIST );
   819     TInt err = iPairedDevices.Append( aNameless );
   885     TInt err = iPairedDevices.Append( aNameless );
   820     if ( !err && !iPairingHandler)
   886     if ( !err && !iPairingHandler)
   821         {
   887         {
   822         // New paired device, but no pairing handler yet.
   888         // New paired device, but no pairing handler yet.
   823         // this means an incoming pairing has occured:
   889         // this means an incoming pairing has occured:
   835         {
   901         {
   836         // error could occur due to no memory, 
   902         // error could occur due to no memory, 
   837         // let us try aborting pairing handling
   903         // let us try aborting pairing handling
   838         iPairingHandler->StopPairHandling( aNameless.Address() );
   904         iPairingHandler->StopPairHandling( aNameless.Address() );
   839         }
   905         }
       
   906     BOstraceFunctionExit0( DUMMY_DEVLIST);
   840     }
   907     }
   841 
   908 
   842 void CBTNotifSecurityManager::TrustDevice( const TBTDevAddr& aAddr )
   909 void CBTNotifSecurityManager::TrustDevice( const TBTDevAddr& aAddr )
   843     {
   910     {
       
   911     BOstraceFunctionEntry0( DUMMY_DEVLIST );
   844     TIdentityRelation<TBTNamelessDevice> addrComp( CompareDeviceByAddress );
   912     TIdentityRelation<TBTNamelessDevice> addrComp( CompareDeviceByAddress );
   845     TBTNamelessDevice dev;
   913     TBTNamelessDevice dev;
   846     dev.SetAddress( aAddr );
   914     dev.SetAddress( aAddr );
   847     TRequestStatus status( KRequestPending );
   915     TRequestStatus status( KRequestPending );
   848     
   916     
   854         security.SetNoAuthorise(ETrue);
   922         security.SetNoAuthorise(ETrue);
   855         security.SetBanned(EFalse);
   923         security.SetBanned(EFalse);
   856         dev.SetGlobalSecurity(security);
   924         dev.SetGlobalSecurity(security);
   857         (void)UpdateRegDevice(dev);
   925         (void)UpdateRegDevice(dev);
   858         }
   926         }
   859     }
   927     BOstraceFunctionExit0( DUMMY_DEVLIST);
   860 
   928     }
       
   929 
       
   930 void CBTNotifSecurityManager::UnTrustDevice( const TBTDevAddr& aAddr )
       
   931     {
       
   932     BOstraceFunctionEntry0( DUMMY_DEVLIST );
       
   933     TIdentityRelation<TBTNamelessDevice> addrComp( CompareDeviceByAddress );
       
   934     TBTNamelessDevice dev;
       
   935     dev.SetAddress( aAddr );
       
   936     TRequestStatus status( KRequestPending );
       
   937     
       
   938     iRegistry.GetDevice(dev,status);
       
   939     User::WaitForRequest( status ); 
       
   940     if(status == KErrNone)
       
   941         {
       
   942         TBTDeviceSecurity security = dev.GlobalSecurity();
       
   943         security.SetNoAuthorise(EFalse);
       
   944         dev.SetGlobalSecurity(security);
       
   945         (void)UpdateRegDevice(dev);
       
   946         }
       
   947     BOstraceFunctionExit0( DUMMY_DEVLIST);
       
   948     }
       
   949 
       
   950 CBTNotifBasePairingHandler* CBTNotifSecurityManager::PairingHandler()
       
   951     {
       
   952     return iPairingHandler;
       
   953     }
       
   954 
       
   955