www.pudn.com > Bluetooth_PMP_Example_v1_0.zip > ServiceDiscoverer.cpp


/* 
* ============================================================================ 
*  Name     : CServiceDiscoverer from ServiceDiscoverer.h 
*  Part of  : BluetoothPMPExample 
*  Created  : 14.01.2004 by Forum Nokia 
*  Implementation notes: 
*     Initial content was generated by Series 60 AppWizard. 
*  Version  : 
*  Copyright: Nokia Corporation 
* ============================================================================ 
*/ 
 
// INCLUDE FILES 
#include  
#include "ServiceDiscoverer.h" 
 
 
CServiceDiscoverer* CServiceDiscoverer::NewL(MServiceDiscoObserver *aObserver) 
	{ 
	CServiceDiscoverer* self = CServiceDiscoverer::NewLC(aObserver); 
    CleanupStack::Pop(self); 
	return self; 
	} 
 
 
CServiceDiscoverer* CServiceDiscoverer::NewLC(MServiceDiscoObserver *aObserver) 
	{ 
	CServiceDiscoverer* self = new (ELeave) CServiceDiscoverer(aObserver); 
	CleanupStack::PushL(self); 
	self->ConstructL(); 
	return self; 
	} 
 
 
void CServiceDiscoverer::ConstructL() 
	{ 
	} 
 
 
// ---------------------------------------------------------------------------- 
// CServiceDiscoverer::CServiceDiscoverer(MServiceDiscoObserver *aObserver) 
// 
// constructor 
// ---------------------------------------------------------------------------- 
CServiceDiscoverer::CServiceDiscoverer(MServiceDiscoObserver *aObserver): 
	iObserver(aObserver), 
	iAgent(NULL), 
	iSpat(NULL), 
	iDiscoveredServiceCount(0) 
	{ 
	} 
 
 
// ---------------------------------------------------------------------------- 
// CServiceDiscoverer::~CServiceDiscoverer() 
// 
// destructor 
// ---------------------------------------------------------------------------- 
CServiceDiscoverer::~CServiceDiscoverer() 
	{  
	iDiscoveredServiceCount=0; 
	FinishDiscovery(); 
	} 
 
 
// ---------------------------------------------------------------------------- 
// CServiceDiscoverer::DiscoverServicesOnDeviceL(TDeviceData *aDevData) 
// 
// discover services on given device.  a service discovery agent will be 
// started to do the discovery of services on given remote device. 
// service discovery will be limited to search only for services with 
// our service id. 
// ---------------------------------------------------------------------------- 
void CServiceDiscoverer::DiscoverServicesOnDeviceL(TDeviceData *aDevData) 
	{ 
	if(iSpat) 
		iSpat->Reset(); 
	delete iSpat; 
	iSpat=NULL; 
 
	if(iAgent) 
		iAgent->Cancel(); 
 
	delete iAgent; 
	iAgent=NULL; 
 
	iDevDataChanged=EFalse; 
	iDevData=aDevData; 
 
	// init new service discovery agent 
	iAgent = CSdpAgent::NewL( *this, iDevData->iDeviceAddr ); 
	// set search properties for agent 
	iSpat = CSdpSearchPattern::NewL(); 
	// use our service id to filter the services discovered 
	// -> will return only the services with matching service id(s) 
	TUUID serviceUUID(KBT_serviceID); 
	iSpat->AddL(serviceUUID); 
	iAgent->SetRecordFilterL(*iSpat); 
 
	// initiate search 
	// this will result in call to NextRecordRequestComplete() 
	iAgent->NextRecordRequestL(); 
	} 
 
 
// ---------------------------------------------------------------------------- 
// CServiceDiscoverer::DiscoverServicesL(TDeviceDataList *aDevDataList) 
// 
// discover services of all devices on the given device data list.  this will 
// make the initial call to DiscoverServicesOnDeviceL(), the further calls 
// to DiscoverServicesOnDeviceL() will be made by NextRecordRequestComplete() 
// as the pending service discovery request completes. 
// ---------------------------------------------------------------------------- 
void CServiceDiscoverer::DiscoverServicesL(TDeviceDataList *aDevDataList) 
	{ 
 
	if ( aDevDataList->Count()> 0 ) 
		{ 
		iDeviceIdx=0; 
		iDevDataList=aDevDataList; 
		DiscoverServicesOnDeviceL((*iDevDataList)[iDeviceIdx]); 
		} 
	} 
 
 
// ---------------------------------------------------------------------------- 
// CServiceDiscoverer::FinishDiscovery() 
// 
// stop discovering services, stop service discovery agent. 
// ---------------------------------------------------------------------------- 
void CServiceDiscoverer::FinishDiscovery() 
	{ 
	if(iAgent) 
		iAgent->Cancel(); 
	delete iAgent; 
	iAgent=NULL; 
	if(iSpat) 
		iSpat->Reset(); 
	delete iSpat; 
	iSpat=NULL; 
 
	} 
 
 
// ---------------------------------------------------------------------------- 
// CServiceDiscoverer::NextRecordRequestComplete( 
//		TInt aError, 
//		TSdpServRecordHandle aHandle, 
//		TInt aTotalRecordsCount) 
// 
// called when the service discovery agent has completed discovering services 
// on device.  now the attributes of the found service records (if any) must 
// be evaluated.  if no service records were discovered, proceed doing  
// service discovery on next device. 
// ---------------------------------------------------------------------------- 
void CServiceDiscoverer::NextRecordRequestComplete( 
	TInt aError, 
	TSdpServRecordHandle aHandle, 
	TInt aTotalRecordsCount) 
	{ 
	if ( aError==KErrNone && aTotalRecordsCount>0 )	 
		{ 
		// we got records, retrieve attributes for record 
		// request protocol descriptor from remote device records, 
		// we need this to retrieve remote port to connect to later on.. 
		iAgent->AttributeRequestL(aHandle, KSdpAttrIdProtocolDescriptorList); 
		} 
	else  
		{ 
		// done with this device, store data if changed 
		if ( iDevDataChanged ) 
			{ 
			iDevData->iDeviceServicePort=iPort; 
			(*iDevDataList)[iDeviceIdx]=iDevData; 
			iDiscoveredServiceCount++; 
			} 
		 
		// discover services on next device, if any left 
		iDeviceIdx++; 
		if ( iDeviceIdxCount() ) 
			{ 
			// more devices to probe, proceed 
			DiscoverServicesOnDeviceL((*iDevDataList)[iDeviceIdx]); 
			} 
		else 
			{ 
			FinishDiscovery(); 
			// all devices done, notify  
			iObserver->HandleServiceDiscoveryCompleteL(); 
			} 
		} 
	} 
 
 
// ---------------------------------------------------------------------------- 
// CServiceDiscoverer::AttributeRequestResult( 
//		TSdpServRecordHandle /*aHandle*/, 
//		TSdpAttributeID /*aAttrID*/, 
//		CSdpAttrValue* aAttrValue) 
// 
// called when the service attributes for the service record have been  
// retrieved. 
// ---------------------------------------------------------------------------- 
void CServiceDiscoverer::AttributeRequestResult( 
	TSdpServRecordHandle /*aHandle*/, 
	TSdpAttributeID /*aAttrID*/, 
	CSdpAttrValue* aAttrValue) 
	{ 
	// parse attributes, will result in call to VisitAttributeValue() 
	aAttrValue->AcceptVisitorL(*this); 
	} 
 
 
// ---------------------------------------------------------------------------- 
// CServiceDiscoverer::AttributeRequestComplete( 
//		TSdpServRecordHandle /*aHandle*/,  
//		TInt aError) 
// 
// called when the request to resolve the service attributes for the service 
// record completes.  if there are more service records, proceed resolving  
// the next service record. 
// ---------------------------------------------------------------------------- 
void CServiceDiscoverer::AttributeRequestComplete( 
	TSdpServRecordHandle /*aHandle*/,  
	TInt aError) 
	{ 
	if ( aError==KErrNone ) 
		{ 
		// done with attributes for this record, request next 
		// service record 
		iAgent->NextRecordRequestL(); 
		} 
	else 
		{ 
		// error, should terminate discoverer? 
		} 
	} 
 
 
// ---------------------------------------------------------------------------- 
// CServiceDiscoverer::VisitAttributeValueL( 
//		CSdpAttrValue &aValue, 
//		TSdpElementType aType) 
// 
// called for processing of each service attribute.  here we must look for  
// attributes of UUID type.  if the UUID is RFCOMM UUID, resolve the value 
// for this attribute, which will be channel number to be used for connection 
// to remote device. 
// ---------------------------------------------------------------------------- 
void CServiceDiscoverer::VisitAttributeValueL( 
	CSdpAttrValue &aValue, 
	TSdpElementType aType) 
	{ 
	switch (aType)	 
		{ 
		case ETypeUUID: 
			{ 
			TPtrC8 uuid(aValue.UUID().ShortestForm()); 
			iLastUUID.SetL(uuid); 
			break; 
			} 
 
		case ETypeUint: 
			{ 
			if ( iLastUUID==KRFCOMM ) 
			{ 
				// previous call to this method with rfcomm UUID, therefore 
				// this one will be the value, rfcomm service channel (port) 
				iPort=aValue.Uint(); 
				// mark device data changed, so the device data record in  
				// device data list will be updated. 
				iDevDataChanged=ETrue; 
			} 
			break; 
			} 
 
		default: 
			// rest don't really matter.. 
			break; 
 
		} 
	} 
 
 
void CServiceDiscoverer::StartListL(CSdpAttrValueList& /*aList*/) 
	{ 
	// not needed 
	} 
 
void CServiceDiscoverer::EndListL() 
	{ 
	// not needed 
	} 
 
 
// ---------------------------------------------------------------------------- 
// CServiceDiscoverer::HasServices() 
// 
// returns true if any services matching our service id were found on any  
// remote device. 
// ---------------------------------------------------------------------------- 
TBool CServiceDiscoverer::HasServices() 
	{ 
	return ( iDiscoveredServiceCount>0 ); 
	}