examples/ForumNokia/BluetoothPMPExample/src/ServiceDiscoverer.cpp

00001 /*
00002  * Copyright © 2009 Nokia Corporation.
00003  */
00004 
00005 // INCLUDE FILES
00006 #include <btsdp.h>
00007 #include "ServiceDiscoverer.h"
00008 
00009 CServiceDiscoverer* CServiceDiscoverer::NewL(MServiceDiscoObserver& aObserver)
00010     {
00011     CServiceDiscoverer* self = CServiceDiscoverer::NewLC(aObserver);
00012     CleanupStack::Pop(self);
00013     return self;
00014     }
00015 
00016 
00017 CServiceDiscoverer* CServiceDiscoverer::NewLC(MServiceDiscoObserver& aObserver)
00018     {
00019     CServiceDiscoverer* self = new (ELeave) CServiceDiscoverer(aObserver);
00020     CleanupStack::PushL(self);
00021     self->ConstructL();
00022     return self;
00023     }
00024 
00025 
00026 void CServiceDiscoverer::ConstructL()
00027     {
00028     iRunning = EFalse;
00029     }
00030 
00031 CServiceDiscoverer::CServiceDiscoverer(MServiceDiscoObserver& aObserver):
00032     iObserver(aObserver)
00033     {
00034     }
00035 
00036 CServiceDiscoverer::~CServiceDiscoverer()
00037     {
00038     FinishDiscovery();
00039     }
00040 
00041 
00042 // ----------------------------------------------------------------------------
00043 // CServiceDiscoverer::DiscoverServicesOnDeviceL(TDeviceData *aDevData)
00044 //
00045 // discover services on given device.  a service discovery agent will be
00046 // started to do the discovery of services on given remote device.
00047 // service discovery will be limited to search only for services with
00048 // our service id.
00049 // ----------------------------------------------------------------------------
00050 void CServiceDiscoverer::DiscoverServicesOnDeviceL(TDeviceData* aDevData)
00051     {
00052     FinishDiscovery();
00053     
00054     iDevDataChanged=EFalse;
00055     iDevData=aDevData;
00056 
00057     // init new service discovery agent
00058     iAgent = CSdpAgent::NewL( *this, iDevData->iDeviceAddr );
00059     // set search properties for agent
00060     iSpat = CSdpSearchPattern::NewL();
00061     // use our service id to filter the services discovered
00062     // -> will return only the services with matching service id(s)
00063     TUUID serviceUUID(KBT_serviceID);
00064     iSpat->AddL(serviceUUID);
00065     iAgent->SetRecordFilterL(*iSpat);
00066 
00067     // initiate search
00068     // this will result in call to NextRecordRequestComplete()
00069     iAgent->NextRecordRequestL();
00070     iRunning = ETrue;
00071     }
00072 
00073 
00074 // ----------------------------------------------------------------------------
00075 // CServiceDiscoverer::DiscoverServicesL(TDeviceDataList* aDevDataList)
00076 //
00077 // discover services of all devices on the given device data list.  this will
00078 // make the initial call to DiscoverServicesOnDeviceL(), the further calls
00079 // to DiscoverServicesOnDeviceL() will be made by NextRecordRequestComplete()
00080 // as the pending service discovery request completes.
00081 // ----------------------------------------------------------------------------
00082 void CServiceDiscoverer::DiscoverServicesL(TDeviceDataList* aDevDataList)
00083     {
00084     if ( aDevDataList->Count()> 0 )
00085         {
00086         iDeviceIdx=0;
00087         iDevDataList=aDevDataList;
00088         DiscoverServicesOnDeviceL((*iDevDataList)[iDeviceIdx]);
00089         }
00090     }
00091 
00092 
00093 // ----------------------------------------------------------------------------
00094 // CServiceDiscoverer::FinishDiscovery()
00095 //
00096 // stop discovering services, stop service discovery agent.
00097 // ----------------------------------------------------------------------------
00098 void CServiceDiscoverer::FinishDiscovery()
00099     {
00100     if(iAgent)
00101         iAgent->Cancel();
00102     delete iAgent;
00103     iAgent=NULL;
00104     if(iSpat)
00105         iSpat->Reset();
00106     delete iSpat;
00107     iSpat=NULL;
00108     }
00109 
00110 
00111 // ----------------------------------------------------------------------------
00112 // CServiceDiscoverer::NextRecordRequestComplete(
00113 //      TInt aError,
00114 //      TSdpServRecordHandle aHandle,
00115 //      TInt aTotalRecordsCount)
00116 //
00117 // called when the service discovery agent has completed discovering services
00118 // on device.  now the attributes of the found service records (if any) must
00119 // be evaluated.  if no service records were discovered, proceed doing
00120 // service discovery on next device.
00121 // ----------------------------------------------------------------------------
00122 void CServiceDiscoverer::NextRecordRequestComplete(
00123     TInt aError,
00124     TSdpServRecordHandle aHandle,
00125     TInt aTotalRecordsCount)
00126     {
00127     iRunning = EFalse;
00128     
00129     if ( aError==KErrNone && aTotalRecordsCount>0 )
00130         {
00131         // we got records, retrieve attributes for record
00132         // request protocol descriptor from remote device records,
00133         // we need this to retrieve remote port to connect to later on..
00134         TRAPD(err,iAgent->AttributeRequestL(aHandle, KSdpAttrIdProtocolDescriptorList) );
00135         if( err )
00136             TRAP(err,iObserver.ReportServiceDiscoveryErrorL(err));
00137         }
00138     else
00139         {
00140         // done with this device, store data if changed
00141         if ( iDevDataChanged )
00142             {
00143             iDevData->iDeviceServicePort=iPort;
00144             (*iDevDataList)[iDeviceIdx]=iDevData;
00145             }
00146 
00147         // discover services on next device, if any left
00148         iDeviceIdx++;
00149         if ( iDeviceIdx<iDevDataList->Count() )
00150             {
00151             // more devices to probe, proceed
00152             TRAPD(err,DiscoverServicesOnDeviceL((*iDevDataList)[iDeviceIdx]));
00153             if( err )
00154                 TRAP(err,iObserver.ReportServiceDiscoveryErrorL(err))
00155             }
00156         else
00157             {
00158             FinishDiscovery();
00159             // all devices done, notify
00160             TRAPD(err,iObserver.HandleServiceDiscoveryCompleteL());
00161             }
00162         }
00163     }
00164 
00165 
00166 // ----------------------------------------------------------------------------
00167 // CServiceDiscoverer::AttributeRequestResult(
00168 //      TSdpServRecordHandle /*aHandle*/,
00169 //      TSdpAttributeID /*aAttrID*/,
00170 //      CSdpAttrValue* aAttrValue)
00171 //
00172 // called when the service attributes for the service record have been
00173 // retrieved.
00174 // ----------------------------------------------------------------------------
00175 void CServiceDiscoverer::AttributeRequestResult(
00176     TSdpServRecordHandle /*aHandle*/,
00177     TSdpAttributeID /*aAttrID*/,
00178     CSdpAttrValue* aAttrValue)
00179     {
00180     // parse attributes, will result in call to VisitAttributeValue()
00181     TRAPD(err,aAttrValue->AcceptVisitorL(*this) );
00182     if( err )
00183         TRAP(err,iObserver.ReportServiceDiscoveryErrorL(err));
00184 
00185     delete aAttrValue;
00186     }
00187 
00188 
00189 // ----------------------------------------------------------------------------
00190 // CServiceDiscoverer::AttributeRequestComplete(
00191 //      TSdpServRecordHandle /*aHandle*/,
00192 //      TInt aError)
00193 //
00194 // called when the request to resolve the service attributes for the service
00195 // record completes.  if there are more service records, proceed resolving
00196 // the next service record.
00197 // ----------------------------------------------------------------------------
00198 void CServiceDiscoverer::AttributeRequestComplete(
00199     TSdpServRecordHandle /*aHandle*/,
00200     TInt aError)
00201     {
00202     if ( aError==KErrNone )
00203         {
00204         // done with attributes for this record, request next
00205         // service record
00206         TRAPD(err,iAgent->NextRecordRequestL());
00207         if( err )
00208             TRAP(err,iObserver.ReportServiceDiscoveryErrorL(err));
00209         }
00210     else
00211         {
00212         // error, should terminate discoverer?
00213         }
00214     }
00215 
00216 
00217 // ----------------------------------------------------------------------------
00218 // CServiceDiscoverer::VisitAttributeValueL(
00219 //      CSdpAttrValue &aValue,
00220 //      TSdpElementType aType)
00221 //
00222 // called for processing of each service attribute.  here we must look for
00223 // attributes of UUID type.  if the UUID is RFCOMM UUID, resolve the value
00224 // for this attribute, which will be channel number to be used for connection
00225 // to remote device.
00226 // ----------------------------------------------------------------------------
00227 void CServiceDiscoverer::VisitAttributeValueL(
00228     CSdpAttrValue &aValue,
00229     TSdpElementType aType)
00230     {
00231     switch (aType)
00232         {
00233         case ETypeUUID:
00234             {
00235             TPtrC8 uuid(aValue.UUID().ShortestForm());
00236             iLastUUID.SetL(uuid);
00237             break;
00238             }
00239 
00240         case ETypeUint:
00241             {
00242             if ( iLastUUID==KRFCOMM )
00243             {
00244                 // previous call to this method with rfcomm UUID, therefore
00245                 // this one will be the value, rfcomm service channel (port)
00246                 iPort=aValue.Uint();
00247                 // mark device data changed, so the device data record in
00248                 // device data list will be updated.
00249                 iDevDataChanged=ETrue;
00250             }
00251             break;
00252             }
00253 
00254         default:
00255             // rest don't really matter..
00256             break;
00257 
00258         }
00259     }
00260 
00261 
00262 void CServiceDiscoverer::StartListL(CSdpAttrValueList& /*aList*/)
00263     {
00264     // not needed
00265     }
00266 
00267 void CServiceDiscoverer::EndListL()
00268     {
00269     // not needed
00270     }
00271 
00272 
00273 // ----------------------------------------------------------------------------
00274 // CServiceDiscoverer::HasServices()
00275 //
00276 // returns true if any services matching our service id were found on any
00277 // remote device.
00278 // ----------------------------------------------------------------------------
00279 TBool CServiceDiscoverer::HasServices()
00280     {
00281     TBool exists = EFalse;
00282     if (iDevDataList)
00283         {
00284         if (iDevDataList->Count() > 0)
00285             {
00286             exists = ETrue;
00287             }
00288         }
00289     return exists;
00290     }
00291 
00292 

Generated by  doxygen 1.6.2