bluetoothengine/bteng/btengdiscovery/src/btengdevicesearch.cpp
author hgs
Fri, 03 Sep 2010 16:17:59 +0300
changeset 57 5ebadcda06cb
parent 28 7e2761e776bd
child 56 9386f31cc85b
permissions -rw-r--r--
201035_7

/*
* Copyright (c) 2006 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:  Helper class implementation for performing device discovery.
*
*/


#include "btengdevicesearch.h"
#include "btengdiscovery.h"
#include "debug.h"

/**
 * the request ID for device search using RNotifer.
 */
const TInt KDevSearchAoReqId = 40;

/*
 * the request ID for EIR service uuids using host resolver
 */
const TInt KDevEirServiceListAoReqId = 41;

// ======== MEMBER FUNCTIONS ========

// ---------------------------------------------------------------------------
// C++ default constructor
// ---------------------------------------------------------------------------
//
CBTEngDeviceSearch::CBTEngDeviceSearch()
    {
    }


// ---------------------------------------------------------------------------
// Symbian 2nd-phase constructor
// ---------------------------------------------------------------------------
//
void CBTEngDeviceSearch::ConstructL()
    {
    User::LeaveIfError( iNotifier.Connect() );
    iActive = CBTEngActive::NewL( *this, KDevSearchAoReqId, 
                                   CActive::EPriorityStandard );
    }


// ---------------------------------------------------------------------------
// NewL
// ---------------------------------------------------------------------------
//
CBTEngDeviceSearch* CBTEngDeviceSearch::NewL()
    {
    CBTEngDeviceSearch* self = new( ELeave ) CBTEngDeviceSearch();
    CleanupStack::PushL( self );
    self->ConstructL();
    CleanupStack::Pop( self );
    return self;
    }

// ---------------------------------------------------------------------------
// Destructor
// ---------------------------------------------------------------------------
//
CBTEngDeviceSearch::~CBTEngDeviceSearch()
    {
    delete iActive;
    iNotifier.Close();
    iHostResolver.Close();
    iSocketServer.Close();
    }

// ---------------------------------------------------------------------------
// Start the device discovery notifier.
// ---------------------------------------------------------------------------
//
TInt CBTEngDeviceSearch::StartSearch( CBTDevice* aDevice, TNameEntry* aNameEntry,
    const TBTDeviceClass& aDeviceClass, MBTEngSdpResultReceiver* aNotifier )
    {
    TRACE_FUNC_ENTRY
    TInt err ( KErrNone );
    if( iActive->IsActive() )
        {
        err = KErrInUse;
        }
    if( !err && !iNotifier.Handle() )
        {
        err = iNotifier.Connect();
        }
    if( !err )
        {
        iClientReq = EDeviceSearch;
        iResultNotifier = aNotifier;
        iNameEntry = aNameEntry;
        iDevice = aDevice;
            // Selection parameters
        TBTDeviceSelectionParams params;
        params.SetDeviceClass( aDeviceClass );
        iSelectionPckg = TBTDeviceSelectionParamsPckg( params );
            // Response parameters
        TBTDeviceResponseParams result;
        iResponsePckg = TBTDeviceResponseParamsPckg( result );
        iActive->SetRequestId( KDevSearchAoReqId );
        iNotifier.StartNotifierAndGetResponse( iActive->RequestStatus(), 
                                                KDeviceSelectionNotifierUid, 
                                                iSelectionPckg, iResponsePckg );
        iActive->GoActive();
        }
    TRACE_FUNC_EXIT
    return err;
    }

// ---------------------------------------------------------------------------
// Cancel an ongoing device discovery.
// ---------------------------------------------------------------------------
//
void CBTEngDeviceSearch::CancelSearch()
    {
    TRACE_FUNC_ENTRY
    if( iActive->IsActive() && iClientReq == EDeviceSearch)
        {
        iActive->Cancel();
        if (iActive->RequestId() == KDevSearchAoReqId)
            {
            iNotifier.Close();
            NotifyClient(KErrAbort);
            }
        else if (iActive->RequestId() == KDevEirServiceListAoReqId)
            {
            iHostResolver.Close();
            }
        }
    TRACE_FUNC_EXIT
    }

// ---------------------------------------------------------------------------
// Get cached EIR data from host resolver and extract service uuids
// ---------------------------------------------------------------------------
//
TInt CBTEngDeviceSearch::GetEirServiceUUIDs( const TBTDevAddr& aAddr, 
        TNameEntry* aNameEntry, MBTEngSdpResultReceiver* aNotifier)
    {
    TRACE_FUNC_ENTRY
    TInt err = KErrNone;
    if( iActive->IsActive() )
        {
        err = KErrInUse;
        }
    if (!err)
        {
        iClientReq = EGetDeviceEir;
        iResultNotifier = aNotifier;
        iNameEntry = aNameEntry;
        err = DoGetDeviceEir(aAddr);
        }
    TRACE_FUNC_EXIT
    return err;
    }

// ---------------------------------------------------------------------------
// Cancel an ongoing EIR services retieval.
// ---------------------------------------------------------------------------
//
void CBTEngDeviceSearch::CancelGetEirServiceUUIDs()
    {
    TRACE_FUNC_ENTRY
    if( iActive->IsActive() && iClientReq == EGetDeviceEir)
        {
        iActive->Cancel();
        iHostResolver.Close();
        }
    TRACE_FUNC_EXIT
    }

// ---------------------------------------------------------------------------
// From class MBTEngActiveObserver.
// Callback to notify that an outstanding request has completed.
// ---------------------------------------------------------------------------
//
void CBTEngDeviceSearch::RequestCompletedL( CBTEngActive* aActive, 
    TInt aStatus )
    {
    TRACE_FUNC_ARG( ( _L( "status: %d") , aStatus ) )
    (void) aActive;
    if ( aActive->RequestId() == KDevSearchAoReqId )
        {
        HandleDeviceSelectionResultL(aStatus);
        }
    else if ( aActive->RequestId() == KDevEirServiceListAoReqId )
        {
        HandleDeviceEirDataResult( aStatus );
        }
    TRACE_FUNC_EXIT
    }

// ---------------------------------------------------------------------------
// From class MBTEngActiveObserver.
// Handles cancelation of an outstanding request
// ---------------------------------------------------------------------------
//
void CBTEngDeviceSearch::CancelRequest( TInt aRequestId )
    {
    TRACE_FUNC_ARG( ( _L( "reqID %d" ), aRequestId ) )
    if ( aRequestId == KDevSearchAoReqId )
        {
        iNotifier.CancelNotifier( KDeviceSelectionNotifierUid );
        }
    else if ( aRequestId == KDevEirServiceListAoReqId )
        {
        iHostResolver.Cancel();
        }
    TRACE_FUNC_EXIT 
    }

// ---------------------------------------------------------------------------
// From class MBTEngActiveObserver.
// Callback to notify that an error has occurred in RunL.
// ---------------------------------------------------------------------------
//
void CBTEngDeviceSearch::HandleError( CBTEngActive* aActive, 
    TInt aError )
    {
    TRACE_FUNC_ARG( ( _L( "error: %d") , aError ) )
    (void) aActive;
    iNotifier.Close();
    iHostResolver.Close();
    NotifyClient(aError);
    }

// ---------------------------------------------------------------------------
// get device eir from cache
// ---------------------------------------------------------------------------
//
TInt CBTEngDeviceSearch::DoGetDeviceEir(const TBTDevAddr& aAddr)
    {
    TRACE_FUNC_ENTRY
    TInt err (KErrNone);
    if (!iSocketServer.Handle())
        {
        err = iSocketServer.Connect();
        }
    
    TProtocolDesc pInfo;
    if (!err)
        {
        _LIT(KBTLinkManagerProtocol, "BTLinkManager");
        err =  iSocketServer.FindProtocol( KBTLinkManagerProtocol(), pInfo );
        }
    if (!err)
        {
        err = iHostResolver.Open(iSocketServer, pInfo.iAddrFamily, pInfo.iProtocol);
        }
    if( !err )
        {
        iInquirySockAddr = TInquirySockAddr();
        iInquirySockAddr.SetBTAddr(aAddr );
        iInquirySockAddr.SetAction( KHostResCache );
        iActive->SetRequestId( KDevEirServiceListAoReqId );
        iHostResolver.GetByAddress( iInquirySockAddr, *iNameEntry, iActive->RequestStatus() );
        iActive->GoActive();
        }
    TRACE_FUNC_EXIT
    return err;
    }

void CBTEngDeviceSearch::HandleDeviceSelectionResultL(TInt aErr)
    {
    TRACE_FUNC_ENTRY
    TInt err (aErr);
    iNotifier.Close();
    if (!err)
        {
        // Copy information to returned device
        iDevice->SetDeviceAddress( iResponsePckg().BDAddr() );
        iDevice->SetDeviceNameL( BTDeviceNameConverter::ToUTF8L( 
                                                iResponsePckg().DeviceName() ) );
        iDevice->SetDeviceClass( iResponsePckg().DeviceClass() );  
        }
    if (!err && iNameEntry)
        {
        err = DoGetDeviceEir(iResponsePckg().BDAddr());
        }
    // if an error happens, or the caller doesn't need the EIR part, complete
    // the request. Otherwise the client will be called after getting EIR 
    // completes.
    if (err || !iNameEntry)
        {
        NotifyClient(err);
        }
    TRACE_FUNC_EXIT
    }

// ---------------------------------------------------------------------------
// extracting service uuids from the device EIR data returned by host resolver
// ---------------------------------------------------------------------------
//
void CBTEngDeviceSearch::HandleDeviceEirDataResult(TInt aErr)
    {
    TRACE_FUNC_ENTRY
    iHostResolver.Close();
    
    if ( iClientReq == EDeviceSearch)
        {
        // Device search has already completed correctly, so 
        // we don't pass GetEir error 
        NotifyClient( KErrNone );
        }
    else
        {
        NotifyClient( aErr );
        }
    TRACE_FUNC_EXIT
    }

// ---------------------------------------------------------------------------
// Callback to notify that the caller's request has completed.
// ---------------------------------------------------------------------------
//
void CBTEngDeviceSearch::NotifyClient(TInt aErr)
    {
    TRACE_FUNC_ENTRY
    if( iResultNotifier && iClientReq == EDeviceSearch)
        {
        if (iNameEntry)
            {
            iResultNotifier->DeviceSearchComplete( iDevice, iNameEntry, aErr );
            }
        else
            {
            iResultNotifier->DeviceSearchComplete( iDevice, aErr );
            }
        }
    if (iResultNotifier && iClientReq == EGetDeviceEir)
        {
        iResultNotifier->GetEirServiceUUIDsComplete(iNameEntry, aErr);
        }
    TRACE_FUNC_EXIT
    }