examples/ForumNokia/BluetoothPMPExample/src/ServiceDiscoverer.cpp

00001 /*
00002  * Copyright (c) 2009-2010 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
00003  *    
00004  * Redistribution and use in source and binary forms, with or without
00005  * modification, are permitted provided that the following conditions are met:
00006  *    
00007  *  * Redistributions of source code must retain the above copyright notice, this
00008  *    list of conditions and the following disclaimer.
00009  *  * Redistributions in binary form must reproduce the above copyright notice,
00010  *    this list of conditions and the following disclaimer in the documentation
00011  *    and/or other materials provided with the distribution.
00012  *  * Neither the name of Nokia Corporation nor the names of its contributors
00013  *    may be used to endorse or promote products derived from this software
00014  *    without specific prior written permission.
00015  *    
00016  *    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00017  *    AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00018  *    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00019  *    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
00020  *    FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00021  *    DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
00022  *    SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00023  *    CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00024  *    OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00025  *    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00026  *    
00027  *    Description:  
00028  */
00029 
00030 // INCLUDE FILES
00031 #include <btsdp.h>
00032 #include "ServiceDiscoverer.h"
00033 
00034 CServiceDiscoverer* CServiceDiscoverer::NewL(MServiceDiscoObserver& aObserver)
00035     {
00036     CServiceDiscoverer* self = CServiceDiscoverer::NewLC(aObserver);
00037     CleanupStack::Pop(self);
00038     return self;
00039     }
00040 
00041 
00042 CServiceDiscoverer* CServiceDiscoverer::NewLC(MServiceDiscoObserver& aObserver)
00043     {
00044     CServiceDiscoverer* self = new (ELeave) CServiceDiscoverer(aObserver);
00045     CleanupStack::PushL(self);
00046     self->ConstructL();
00047     return self;
00048     }
00049 
00050 
00051 void CServiceDiscoverer::ConstructL()
00052     {
00053     iRunning = EFalse;
00054     }
00055 
00056 CServiceDiscoverer::CServiceDiscoverer(MServiceDiscoObserver& aObserver):
00057     iObserver(aObserver)
00058     {
00059     }
00060 
00061 CServiceDiscoverer::~CServiceDiscoverer()
00062     {
00063     FinishDiscovery();
00064     }
00065 
00066 
00067 // ----------------------------------------------------------------------------
00068 // CServiceDiscoverer::DiscoverServicesOnDeviceL(TDeviceData *aDevData)
00069 //
00070 // discover services on given device.  a service discovery agent will be
00071 // started to do the discovery of services on given remote device.
00072 // service discovery will be limited to search only for services with
00073 // our service id.
00074 // ----------------------------------------------------------------------------
00075 void CServiceDiscoverer::DiscoverServicesOnDeviceL(TDeviceData* aDevData)
00076     {
00077     FinishDiscovery();
00078     
00079     iDevDataChanged=EFalse;
00080     iDevData=aDevData;
00081 
00082     // init new service discovery agent
00083     iAgent = CSdpAgent::NewL( *this, iDevData->iDeviceAddr );
00084     // set search properties for agent
00085     iSpat = CSdpSearchPattern::NewL();
00086     // use our service id to filter the services discovered
00087     // -> will return only the services with matching service id(s)
00088     TUUID serviceUUID(KBT_serviceID);
00089     iSpat->AddL(serviceUUID);
00090     iAgent->SetRecordFilterL(*iSpat);
00091 
00092     // initiate search
00093     // this will result in call to NextRecordRequestComplete()
00094     iAgent->NextRecordRequestL();
00095     iRunning = ETrue;
00096     }
00097 
00098 
00099 // ----------------------------------------------------------------------------
00100 // CServiceDiscoverer::DiscoverServicesL(TDeviceDataList* aDevDataList)
00101 //
00102 // discover services of all devices on the given device data list.  this will
00103 // make the initial call to DiscoverServicesOnDeviceL(), the further calls
00104 // to DiscoverServicesOnDeviceL() will be made by NextRecordRequestComplete()
00105 // as the pending service discovery request completes.
00106 // ----------------------------------------------------------------------------
00107 void CServiceDiscoverer::DiscoverServicesL(TDeviceDataList* aDevDataList)
00108     {
00109     if ( aDevDataList->Count()> 0 )
00110         {
00111         iDeviceIdx=0;
00112         iDevDataList=aDevDataList;
00113         DiscoverServicesOnDeviceL((*iDevDataList)[iDeviceIdx]);
00114         }
00115     }
00116 
00117 
00118 // ----------------------------------------------------------------------------
00119 // CServiceDiscoverer::FinishDiscovery()
00120 //
00121 // stop discovering services, stop service discovery agent.
00122 // ----------------------------------------------------------------------------
00123 void CServiceDiscoverer::FinishDiscovery()
00124     {
00125     if(iAgent)
00126         iAgent->Cancel();
00127     delete iAgent;
00128     iAgent=NULL;
00129     if(iSpat)
00130         iSpat->Reset();
00131     delete iSpat;
00132     iSpat=NULL;
00133     }
00134 
00135 
00136 // ----------------------------------------------------------------------------
00137 // CServiceDiscoverer::NextRecordRequestComplete(
00138 //      TInt aError,
00139 //      TSdpServRecordHandle aHandle,
00140 //      TInt aTotalRecordsCount)
00141 //
00142 // called when the service discovery agent has completed discovering services
00143 // on device.  now the attributes of the found service records (if any) must
00144 // be evaluated.  if no service records were discovered, proceed doing
00145 // service discovery on next device.
00146 // ----------------------------------------------------------------------------
00147 void CServiceDiscoverer::NextRecordRequestComplete(
00148     TInt aError,
00149     TSdpServRecordHandle aHandle,
00150     TInt aTotalRecordsCount)
00151     {
00152     iRunning = EFalse;
00153     
00154     if ( aError==KErrNone && aTotalRecordsCount>0 )
00155         {
00156         // we got records, retrieve attributes for record
00157         // request protocol descriptor from remote device records,
00158         // we need this to retrieve remote port to connect to later on..
00159         TRAPD(err,iAgent->AttributeRequestL(aHandle, KSdpAttrIdProtocolDescriptorList) );
00160         if( err )
00161             TRAP(err,iObserver.ReportServiceDiscoveryErrorL(err));
00162         }
00163     else
00164         {
00165         // done with this device, store data if changed
00166         if ( iDevDataChanged )
00167             {
00168             iDevData->iDeviceServicePort=iPort;
00169             (*iDevDataList)[iDeviceIdx]=iDevData;
00170             }
00171 
00172         // discover services on next device, if any left
00173         iDeviceIdx++;
00174         if ( iDeviceIdx<iDevDataList->Count() )
00175             {
00176             // more devices to probe, proceed
00177             TRAPD(err,DiscoverServicesOnDeviceL((*iDevDataList)[iDeviceIdx]));
00178             if( err )
00179                 TRAP(err,iObserver.ReportServiceDiscoveryErrorL(err))
00180             }
00181         else
00182             {
00183             FinishDiscovery();
00184             // all devices done, notify
00185             TRAPD(err,iObserver.HandleServiceDiscoveryCompleteL());
00186             }
00187         }
00188     }
00189 
00190 
00191 // ----------------------------------------------------------------------------
00192 // CServiceDiscoverer::AttributeRequestResult(
00193 //      TSdpServRecordHandle /*aHandle*/,
00194 //      TSdpAttributeID /*aAttrID*/,
00195 //      CSdpAttrValue* aAttrValue)
00196 //
00197 // called when the service attributes for the service record have been
00198 // retrieved.
00199 // ----------------------------------------------------------------------------
00200 void CServiceDiscoverer::AttributeRequestResult(
00201     TSdpServRecordHandle /*aHandle*/,
00202     TSdpAttributeID /*aAttrID*/,
00203     CSdpAttrValue* aAttrValue)
00204     {
00205     // parse attributes, will result in call to VisitAttributeValue()
00206     TRAPD(err,aAttrValue->AcceptVisitorL(*this) );
00207     if( err )
00208         TRAP(err,iObserver.ReportServiceDiscoveryErrorL(err));
00209 
00210     delete aAttrValue;
00211     }
00212 
00213 
00214 // ----------------------------------------------------------------------------
00215 // CServiceDiscoverer::AttributeRequestComplete(
00216 //      TSdpServRecordHandle /*aHandle*/,
00217 //      TInt aError)
00218 //
00219 // called when the request to resolve the service attributes for the service
00220 // record completes.  if there are more service records, proceed resolving
00221 // the next service record.
00222 // ----------------------------------------------------------------------------
00223 void CServiceDiscoverer::AttributeRequestComplete(
00224     TSdpServRecordHandle /*aHandle*/,
00225     TInt aError)
00226     {
00227     if ( aError==KErrNone )
00228         {
00229         // done with attributes for this record, request next
00230         // service record
00231         TRAPD(err,iAgent->NextRecordRequestL());
00232         if( err )
00233             TRAP(err,iObserver.ReportServiceDiscoveryErrorL(err));
00234         }
00235     else
00236         {
00237         // error, should terminate discoverer?
00238         }
00239     }
00240 
00241 
00242 // ----------------------------------------------------------------------------
00243 // CServiceDiscoverer::VisitAttributeValueL(
00244 //      CSdpAttrValue &aValue,
00245 //      TSdpElementType aType)
00246 //
00247 // called for processing of each service attribute.  here we must look for
00248 // attributes of UUID type.  if the UUID is RFCOMM UUID, resolve the value
00249 // for this attribute, which will be channel number to be used for connection
00250 // to remote device.
00251 // ----------------------------------------------------------------------------
00252 void CServiceDiscoverer::VisitAttributeValueL(
00253     CSdpAttrValue &aValue,
00254     TSdpElementType aType)
00255     {
00256     switch (aType)
00257         {
00258         case ETypeUUID:
00259             {
00260             TPtrC8 uuid(aValue.UUID().ShortestForm());
00261             iLastUUID.SetL(uuid);
00262             break;
00263             }
00264 
00265         case ETypeUint:
00266             {
00267             if ( iLastUUID==KRFCOMM )
00268             {
00269                 // previous call to this method with rfcomm UUID, therefore
00270                 // this one will be the value, rfcomm service channel (port)
00271                 iPort=aValue.Uint();
00272                 // mark device data changed, so the device data record in
00273                 // device data list will be updated.
00274                 iDevDataChanged=ETrue;
00275             }
00276             break;
00277             }
00278 
00279         default:
00280             // rest don't really matter..
00281             break;
00282 
00283         }
00284     }
00285 
00286 
00287 void CServiceDiscoverer::StartListL(CSdpAttrValueList& /*aList*/)
00288     {
00289     // not needed
00290     }
00291 
00292 void CServiceDiscoverer::EndListL()
00293     {
00294     // not needed
00295     }
00296 
00297 
00298 // ----------------------------------------------------------------------------
00299 // CServiceDiscoverer::HasServices()
00300 //
00301 // returns true if any services matching our service id were found on any
00302 // remote device.
00303 // ----------------------------------------------------------------------------
00304 TBool CServiceDiscoverer::HasServices()
00305     {
00306     TBool exists = EFalse;
00307     if (iDevDataList)
00308         {
00309         if (iDevDataList->Count() > 0)
00310             {
00311             exists = ETrue;
00312             }
00313         }
00314     return exists;
00315     }
00316 
00317 

Generated by  doxygen 1.6.2