00001 /* 00002 * Copyright (c) 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