bluetoothengine/btserviceutil/src/basicdevdiscoverer.cpp
branchRCL_3
changeset 56 9386f31cc85b
parent 55 613943a21004
child 61 269724087bed
equal deleted inserted replaced
55:613943a21004 56:9386f31cc85b
     1 /*
       
     2 * Copyright (c) 2010 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:  class for searching BT devices
       
    15 *
       
    16 */
       
    17 #include "basicdevdiscoverer.h"
       
    18 #include <btservices/devdiscoveryobserver.h>
       
    19 #include "btserviceutilconsts.h"
       
    20 
       
    21 // ----------------------------------------------------------
       
    22 // CBasicDevDiscoverer::CBasicDevDiscoverer
       
    23 // ----------------------------------------------------------
       
    24 //
       
    25 CBasicDevDiscoverer::CBasicDevDiscoverer( MDevDiscoveryObserver& aObserver )
       
    26     : iObserver( aObserver )
       
    27     {
       
    28     }
       
    29 
       
    30 // ----------------------------------------------------------
       
    31 // CBasicDevDiscoverer::ConstructL
       
    32 // ----------------------------------------------------------
       
    33 //
       
    34 void CBasicDevDiscoverer::ConstructL()
       
    35     {
       
    36     User::LeaveIfError( iSocketServer.Connect() );
       
    37     iActive = CBtSimpleActive::NewL( *this, BtServiceUtil::EBluetoothInquiry );
       
    38     }
       
    39 
       
    40 // ----------------------------------------------------------
       
    41 // CBasicDevDiscoverer::NewL
       
    42 // ----------------------------------------------------------
       
    43 //
       
    44 CBasicDevDiscoverer* CBasicDevDiscoverer::NewL( MDevDiscoveryObserver& aObserver )
       
    45     {
       
    46     CBasicDevDiscoverer* self = new (ELeave) 
       
    47             CBasicDevDiscoverer( aObserver );
       
    48     CleanupStack::PushL( self );
       
    49     self->ConstructL();
       
    50     CleanupStack::Pop( self );
       
    51     return self;
       
    52     }
       
    53 
       
    54 // ----------------------------------------------------------
       
    55 // CBasicDevDiscoverer::
       
    56 // ----------------------------------------------------------
       
    57 //
       
    58 CBasicDevDiscoverer::~CBasicDevDiscoverer()
       
    59     {
       
    60     delete iActive;
       
    61     Reset();
       
    62     iSocketServer.Close();
       
    63     iDevices.Close();
       
    64     }
       
    65 
       
    66 // ----------------------------------------------------------
       
    67 // CBasicDevDiscoverer::SetObserver
       
    68 // ----------------------------------------------------------
       
    69 //
       
    70 void CBasicDevDiscoverer::SetObserver( MDevDiscoveryObserver& aObserver )
       
    71     {
       
    72     iObserver = aObserver;
       
    73     }
       
    74 
       
    75 // ----------------------------------------------------------
       
    76 // CBasicDevDiscoverer::
       
    77 // ----------------------------------------------------------
       
    78 //
       
    79 void CBasicDevDiscoverer::Cancel()
       
    80     {
       
    81     iActive->Cancel();
       
    82     iHostResolver.Close();
       
    83     iDevices.ResetAndDestroy();
       
    84     }
       
    85 
       
    86 // ----------------------------------------------------------
       
    87 // CBasicDevDiscoverer::
       
    88 // ----------------------------------------------------------
       
    89 //
       
    90 void CBasicDevDiscoverer::DiscoverDeviceL(TBTMajorDeviceClass aDeviceClass )
       
    91     {
       
    92     // This class supports only one request at the time:
       
    93     if ( iActive->IsActive() )
       
    94         {
       
    95         User::Leave( KErrInUse );
       
    96         }
       
    97     Reset();
       
    98     iMajorDeviceClassFilter = aDeviceClass;
       
    99     _LIT( KLinkMgrDes, "BTLinkManager" );
       
   100     // Associate with bluetooth Link Manager.
       
   101     TProtocolName protocol( KLinkMgrDes );
       
   102     TProtocolDesc pInfo;
       
   103     User::LeaveIfError( iSocketServer.FindProtocol( protocol, pInfo));
       
   104     User::LeaveIfError( iHostResolver.Open(iSocketServer, 
       
   105             pInfo.iAddrFamily, pInfo.iProtocol));
       
   106     iActive->SetRequestId( BtServiceUtil::EBluetoothInquiry );
       
   107     iInquirySockAddr.SetAction( KHostResInquiry + KHostResEir + KHostResIgnoreCache );
       
   108     // We always do Generic Inquiry.
       
   109     // Limited Inquiry could be added here in future on business need.
       
   110     iInquirySockAddr.SetIAC(KGIAC);
       
   111     iHostResolver.GetByAddress( iInquirySockAddr, iEntry, iActive->RequestStatus() );
       
   112     iActive->GoActive();
       
   113     }
       
   114 
       
   115 // ----------------------------------------------------------
       
   116 // CBasicDevDiscoverer::RequestCompletedL
       
   117 // Inform caller for received device and issue next EIR/Name request
       
   118 // if the request was successful.
       
   119 // ----------------------------------------------------------
       
   120 //
       
   121 void CBasicDevDiscoverer::RequestCompletedL( CBtSimpleActive* aActive, TInt aStatus )
       
   122     {
       
   123     TInt errToObserver( aStatus );
       
   124     // position in array iDevices: the device item the observer will be notified of.
       
   125     TInt devToNotify ( KErrNotFound ); 
       
   126     
       
   127     if ( aActive->RequestId() == BtServiceUtil::EBluetoothInquiry )
       
   128         {
       
   129         if ( aStatus == KErrNone )
       
   130             {
       
   131             TInt pos = HandleInquiryResultL();
       
   132             // continue to inquiry for more devices in range
       
   133             iHostResolver.Next( iEntry, iActive->RequestStatus() );
       
   134             iActive->GoActive();
       
   135             if ( pos > KErrNotFound && iDevices[pos]->iName.Length() > 0 )
       
   136                 {
       
   137                 devToNotify = pos;
       
   138                 }
       
   139             }
       
   140         else if( iDevices.Count() > 0 )
       
   141             {
       
   142             // an error from inquiry operation. 
       
   143             // we move to next step to get device names if some devices have been
       
   144             // found but without a name.
       
   145             iPagingNamePos = iDevices.Count() - 1;
       
   146             aActive->SetRequestId( BtServiceUtil::EBluetoothPageDeviceName );
       
   147             PageNextDeviceName();
       
   148             }
       
   149         }
       
   150     else if ( aActive->RequestId() ==  BtServiceUtil::EBluetoothPageDeviceName )
       
   151         {
       
   152         errToObserver = KErrNone;
       
   153         devToNotify = iPagingNamePos;
       
   154         // the name in iEntry was reset before paging operation, so we
       
   155         // can rely on this length() at this time:
       
   156         if ( aStatus == KErrNone && iEntry().iName.Length() > 0 )
       
   157             {
       
   158             iDevices[iPagingNamePos]->iName = iEntry().iName;
       
   159             }
       
   160             // the return error is not checked here. We continue to page the rest
       
   161             // device names.
       
   162             --iPagingNamePos;
       
   163             PageNextDeviceName();
       
   164         }
       
   165     // request ID is BtServiceUtil::EAsyncNotifyDeviceSearchCompleted
       
   166     else 
       
   167         {
       
   168         iObserver.HandleDiscoveryCompleted( errToObserver );
       
   169         return;
       
   170         }
       
   171     
       
   172     // AO not active means that this is neither inquiring nor paging name.
       
   173     // Schedule an operation completion callback:
       
   174     if ( !iActive->IsActive() && 
       
   175             aActive->RequestId() != BtServiceUtil::EAsyncNotifyDeviceSearchCompleted )
       
   176         {
       
   177         // We inform the client of operation completion asynchronously, so that
       
   178         // we will not end up with problems, e.g., invalid memory,
       
   179         // if the client issues more request in the callback context.
       
   180         aActive->SetRequestId( BtServiceUtil::EAsyncNotifyDeviceSearchCompleted );
       
   181         aActive->RequestStatus() = KRequestPending;
       
   182         TRequestStatus* sta = &aActive->RequestStatus();
       
   183         User::RequestComplete( sta, errToObserver );
       
   184         aActive->GoActive();
       
   185         }
       
   186     
       
   187     // This could be possible in both inquiry and paging operations.
       
   188     if ( devToNotify > KErrNotFound )
       
   189         {
       
   190         // This device record is not used any more after we have informed client.
       
   191         // Extract it and push to cleanup for detroy.
       
   192         // This is to prevent peak memory usage in case of a great number of 
       
   193         // devices being in range.
       
   194         CDeviceSearchRecord* rec = iDevices[devToNotify];
       
   195         iDevices.Remove( devToNotify );
       
   196         CleanupStack::PushL( rec );
       
   197         iObserver.HandleNextDiscoveryResultL( rec->iAddr, rec->iName );
       
   198         CleanupStack::PopAndDestroy( rec );
       
   199         }
       
   200     }
       
   201 
       
   202 // ----------------------------------------------------------
       
   203 // CBasicDevDiscoverer::DoCancelRequest
       
   204 // ----------------------------------------------------------
       
   205 //
       
   206 void CBasicDevDiscoverer::CancelRequest( TInt aId )
       
   207     {
       
   208     // host resolver needs to be cancelled.
       
   209     // For request BtServiceUtil::EAsyncNotifyDeviceSearchCompleted, we 
       
   210     // are doing self-completing. Thus, nothing is needed now.
       
   211     if ( aId == BtServiceUtil::EBluetoothInquiry || 
       
   212          aId == BtServiceUtil::EBluetoothPageDeviceName )
       
   213         {
       
   214         iHostResolver.Cancel();
       
   215         }
       
   216     }
       
   217 
       
   218 // ----------------------------------------------------------
       
   219 // CBasicDevDiscoverer::HandleError
       
   220 // Inform UI from error occured.
       
   221 // ----------------------------------------------------------
       
   222 //
       
   223 void CBasicDevDiscoverer::HandleError( CBtSimpleActive* aActive, TInt aError )
       
   224     {
       
   225     // We might have issued an request to Host Resolver in RequestCompleted().
       
   226     // Cancel AO just in case:
       
   227     aActive->Cancel();
       
   228     Reset();
       
   229     // We cannot proceed more. Inform client:
       
   230     iObserver.HandleDiscoveryCompleted( aError );
       
   231     }
       
   232 
       
   233 // ----------------------------------------------------------
       
   234 // CBasicDevDiscoverer::
       
   235 // ----------------------------------------------------------
       
   236 //
       
   237 void CBasicDevDiscoverer::PageNextDeviceName()
       
   238     {
       
   239     // reset the name in entry so that previous result will
       
   240     // not propogate if the next paging operation fails.
       
   241     iEntry().iName.Zero();
       
   242     for (; iPagingNamePos > -1; --iPagingNamePos )
       
   243         {
       
   244         // Get the next in-range device that has no device name yet 
       
   245         // This is practically meaning that the device would be
       
   246         // < v2.1
       
   247         if( iDevices[iPagingNamePos]->iName.Length() == 0 )
       
   248             {
       
   249             iInquirySockAddr.SetAction( KHostResName + KHostResIgnoreCache );
       
   250             TBTDevAddr btaddr = iDevices[iPagingNamePos]->iAddr.BTAddr();
       
   251             iInquirySockAddr.SetBTAddr( iDevices[iPagingNamePos]->iAddr.BTAddr() );
       
   252             iInquirySockAddr.SetIAC(KGIAC);
       
   253             iHostResolver.GetByAddress( iInquirySockAddr, iEntry, iActive->RequestStatus() );
       
   254             iActive->GoActive();
       
   255             break;
       
   256             }
       
   257         }
       
   258     }
       
   259 
       
   260 // ----------------------------------------------------------
       
   261 // CBasicDevDiscoverer::HandleInquiryResultL
       
   262 // Inform of properties of the found BTdevice,   
       
   263 // which passes the search filter. Its name would be retrived 
       
   264 // later if not contained by the first round of inquiry.   
       
   265 // ----------------------------------------------------------
       
   266 //
       
   267 TInt CBasicDevDiscoverer::HandleInquiryResultL()
       
   268     {
       
   269     TInquirySockAddr& sa = TInquirySockAddr::Cast( iEntry().iAddr );
       
   270     // parse the inquiry result if this device passes the filters:
       
   271     if ( iMajorDeviceClassFilter == EMajorDeviceMisc 
       
   272          || sa.MajorClassOfDevice() == iMajorDeviceClassFilter )
       
   273         {
       
   274         CDeviceSearchRecord* record = NewInstanceL( sa );
       
   275         CleanupStack::PushL( record );
       
   276         iDevices.InsertL(record, 0 );
       
   277         CleanupStack::Pop( record );
       
   278         
       
   279         TBTDeviceName devName;
       
   280         TBluetoothNameRecordWrapper eir( iEntry() );
       
   281         TInt length = eir.GetDeviceNameLength();
       
   282         TBool isComplete( EFalse );
       
   283         if( length > 0 )
       
   284             {
       
   285             User::LeaveIfError( eir.GetDeviceName( record->iName, isComplete) );
       
   286             }
       
   287         return 0;
       
   288         }
       
   289     return KErrNotFound;
       
   290     }
       
   291 
       
   292 // ----------------------------------------------------------
       
   293 // CBasicDevDiscoverer::CompleteDiscovery
       
   294 // ----------------------------------------------------------
       
   295 //
       
   296 CDeviceSearchRecord* CBasicDevDiscoverer::NewInstanceL( 
       
   297         const TInquirySockAddr& aAddr, const TDesC& aName )
       
   298     {
       
   299     CDeviceSearchRecord* record = new (ELeave) CDeviceSearchRecord();
       
   300     record->iAddr = aAddr;
       
   301     record->iName = aName;
       
   302     return record;
       
   303     }
       
   304 
       
   305 // ----------------------------------------------------------
       
   306 // CBasicDevDiscoverer::Reset
       
   307 // ----------------------------------------------------------
       
   308 //
       
   309 void CBasicDevDiscoverer::Reset()
       
   310     {
       
   311     // Free the cache of host Resolver.
       
   312     iHostResolver.Close();
       
   313     // Clean previous in-range devices whose proximity status
       
   314     // may have been changed.
       
   315     iDevices.ResetAndDestroy();
       
   316     }
       
   317 
       
   318 // End of File