examples/SFExamples/RockPaperScissorsGameSourceCode_S60/RPS/src/BluetoothServiceSearcher.cpp

00001 /*
00002 Copyright (c) 2002-2011 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 
00031 // INCLUDE FILES
00032 
00033 #include "BluetoothServiceSearcher.h"
00034 #include "common.hrh"
00035 /*
00036 ============================================================================
00037 CBluetoothServiceSearcher's constructor 
00038 ============================================================================
00039 */
00040 CBluetoothServiceSearcher::CBluetoothServiceSearcher(MBluetoothServiceSearcherObserver& aObs)
00041   : iObserver(aObs), iPort(KPort), iFoundRfcommProtocol(EFalse)
00042         {
00043         }
00044 
00045 /*
00046 ============================================================================
00047 CBluetoothServiceSearcher's destructor
00048 ============================================================================
00049 */
00050 CBluetoothServiceSearcher::~CBluetoothServiceSearcher()
00051         {
00052     delete iSdpSearchPattern;
00053   
00054         if (iAgent)
00055                 {
00056                 iAgent->Cancel();               
00057             delete iAgent;
00058                 }
00059         }
00060 
00061 /*
00062 ============================================================================
00063 Retrives from a remote device a SDP's service record.
00064 On completion calls NextRecordRequestComplete. 
00065 ============================================================================
00066 */
00067 void CBluetoothServiceSearcher::FindServiceByUUIDL(const TBTDevAddr& aTarget, const TUUID& aUUID)
00068         {
00069         /*
00070         ============================================================================
00071         Deletes any previous existing SDP agent and search pattern
00072         ============================================================================
00073         */
00074         delete iSdpSearchPattern;
00075         iSdpSearchPattern = NULL;
00076         delete iAgent;
00077         iAgent = NULL;
00078         /*
00079         ============================================================================
00080         Bluetooth's service class records are stored into the SDP database.
00081         In order to access/get SDP's records you need to use CSdpAgent.
00082         CSdpAgent can only been used if the address of a remote Bluetooth device has been identified.
00083         Also the class using CSdpAgent must implement the MSdpAgentNotifier interface in order
00084         to handle SDP's responses. See SDK for more details about CSdpAgent and MSdpAgentNotifier
00085         ============================================================================
00086         */
00087         iAgent=CSdpAgent::NewL(*this,aTarget);
00088         /*
00089         ============================================================================
00090         In order to retrive only the SDP record you are interested in, SDP provides the filter
00091         CSdpSearchPattern. CSdpSearchPattern is an array of TUUID (Bluetooth Universally Unique Identifier) 
00092         that uniquelly identifies a service class.
00093         Adding a service class to the filter is done by calling subsequentially CSdpSearchPattern::AddL().
00094         In our example we are interested only in seeing if the remote device provides the RPS service, but you could
00095         for example ask the SDP server to return all Bluetooth services that support the RFCOMM protocol.
00096         After adding all the TUUID you are interested in into CSdpSearchPattern you need to move it into
00097         CSdpAgent by calling CSdpAgent::SetRecordFilterL().
00098         ============================================================================
00099         */
00100         iSdpSearchPattern=CSdpSearchPattern::NewL();
00101         iSdpSearchPattern->AddL(aUUID);
00102         iAgent->SetRecordFilterL(*iSdpSearchPattern);
00103         /*
00104         ============================================================================
00105         We now need to get the handle of the record on the remote device that matches the service class we set previously in
00106         CSdpSearchPattern. You need to use CSdpAgent::NextRecordRequestL(). NextRecordRequestL() is  an asynchronous function
00107         and when completed it will call the callback NextRecordRequestComplete() from the MSdpAgentNotifier interface
00108         passed in the NewL. Note that as mention above CSdpSearchPattern could contain more then one service class TUUID and you can get 
00109         the next (if available) service record by calling subsequently NextRecordRequestL().
00110         ============================================================================
00111         */
00112         iAgent->NextRecordRequestL();
00113         }
00114 
00115 /*
00116 ============================================================================
00117 Called when a service record request (CSdpAgent::NextRecordRequestComplete()) operation is completed
00118 ============================================================================
00119 */
00120 void CBluetoothServiceSearcher::NextRecordRequestComplete(TInt aError,TSdpServRecordHandle aHandle,TInt aTotalRecordsCount)
00121         /*
00122         =================================================================================
00123         NextRecordRequestComplete is invoked each time a complete full SDP service record is retrieved from the remote Bluetooth target.
00124         NextRecordRequestComplete is the CSdpAgent::NextRecordRequestL's callback 
00125         If there is no error, we then invoke CSdpAgent::AttributeRequestL to browse the attributes of the SDP record.
00126         If there are no more records to browse then the error will be KErrEof.
00127         =================================================================================
00128         */
00129         {
00130         TBool terminated=EFalse;
00131                 
00132         if(aError == KErrNone)
00133                 {
00134                 if(aTotalRecordsCount==0)
00135                         {
00136                         /*
00137                         =================================================================================
00138                         This covers the case where CSdpAgent::NextRecordRequestL didn't find any SDP's records matching our RPS's service class
00139                         =================================================================================
00140                         */
00141                         iObserver.OnServiceSearchComplete(iPort, KErrNotFound);
00142                         }
00143                 else
00144                         {                               
00145                         iPort=KPort;
00146                         /*
00147                         =================================================================================
00148                         If there are SDP's records containing our class service, we need to browse the SDP record to retrive
00149                         the port of the service. The port is then used with the remote BT's address by the Master in order to connect to the slave.
00150                         CSdpAgent::AttributeRequestL is an asynchronous call. When the attributes have been retrived from the remote device then it
00151                         calls AttributeRequestResult from the MSdpAgentNotifier interface. AttributeRequestL takes two parameters: the first one
00152                         is the handle of the SDP's record that is a TUint32 (TSdpServRecordHandle) and the second parameter is one of the "Universal Attributes"
00153                         defined in btsdp.h; in our example we use KSdpAttrIdProtocolDescriptorList because we are only interested in SDP's record that
00154                         contains the RFCOMM protocol. Note that there is another overload AttributeRequestL where the search is done
00155                         with a range of attibutes instead of only one. You need to use AttributeRequestL(TSdpServRecordHandle aHandle, const CSdpAttrIdMatchList& aMatchList), 
00156                         where CSdpAttrIdMatchList is the list of attributes you want to filter. Also you can use your own builder class in order 
00157                         to browse the SDP's record attributes. In this case you need to use
00158                         AttributeRequestL(MSdpElementBuilder* aBuilder, TSdpServRecordHandle aHandle, TSdpAttributeID aAttrID) for a single attribute or
00159                         AttributeRequestL(MSdpElementBuilder* aBuilder,TSdpServRecordHandle aHandle,const CSdpAttrIdMatchList& aMatchList)
00160                         for a range of attributes. If you don't want to provide your own MSdpElementBuilder then you can use directly
00161                         CSdpAttrValue returned from AttributeRequestResult. See below.
00162                         =================================================================================
00163                         */
00164                         TRAPD(err, iAgent->AttributeRequestL(aHandle,KSdpAttrIdProtocolDescriptorList));
00165                         if(err != KErrNone)
00166                                 {
00167                                 iObserver.OnServiceSearchComplete(iPort, err);
00168                                 }
00169                         }
00170                 }
00171         else
00172                 {                       
00173                 /*
00174                 =================================================================================
00175                 This covers the case where there are no more SDP's records left to be read (KErrEof) or an SDP's error occurs.
00176                 =================================================================================
00177                 */
00178                 iObserver.OnServiceSearchComplete(iPort, aError);
00179                 terminated=ETrue;
00180                 }
00181         }
00182 
00183 /*
00184 ============================================================================
00185 Called when an attribute request (CSdpAgent::AttributeRequestL()) wants to pass up a result
00186 ============================================================================
00187 */
00188 void CBluetoothServiceSearcher::AttributeRequestResult(TSdpServRecordHandle /*aHandle*/, TSdpAttributeID /*aAttrID*/, CSdpAttrValue* aAttrValue)
00189         {
00190         /*
00191         =================================================================================
00192         AttributeRequestResult is invoked each time an attribute-value is retrieved from the SDP record. AttributeRequestResult is the CSdpAgent::AttributeRequestL's callback.
00193         We need to browse the attribute-value to decide whether we have a match with our initial requirements
00194         CSdpAttrValue::AcceptVisitorL passes the attribute value to the VisitAttributeValueL callback
00195         from MSdpAttributeValueVisitor
00196         =================================================================================
00197         */
00198         TRAPD(err,aAttrValue->AcceptVisitorL(*this));
00199         if(err != KErrNone)
00200                 {
00201             iObserver.OnServiceSearchComplete(iPort, err);                      
00202                 }
00203         }
00204 
00205 /*
00206 ============================================================================
00207 Called to pass an attribute value
00208 ============================================================================
00209 */
00210 void CBluetoothServiceSearcher::VisitAttributeValueL(CSdpAttrValue &aValue, TSdpElementType aType)
00211         {
00212         /*
00213         =================================================================================
00214         Here we browse the attributes to see if we have a match with our initial requirements.
00215         In our case we are interested only in RPS's services that used only the KRFCOMM protocol. If there is a match
00216         then we need to get the port of the RPS's service. VisitAttributeValueL is called for each
00217         attribute. When all the attributes have been browsed then AttributeRequestComplete callback below is called.
00218         =================================================================================
00219         */
00220         switch(aType)
00221                 {
00222         case ETypeUUID:
00223                 if(aValue.UUID() == TUUID(KRFCOMM))
00224                         {
00225                         iFoundRfcommProtocol = ETrue;   
00226                         }
00227         break;
00228         case ETypeUint:
00229         if(iFoundRfcommProtocol)
00230                 {
00231                 //get the RFCOMM's service port number
00232                 iPort=aValue.Uint();
00233                 iFoundRfcommProtocol = EFalse;
00234                 }
00235         break;
00236         default:
00237                 break;
00238                 }
00239         }
00240 
00241 /*
00242 =================================================================================
00243 Called when an attribute request (CSdpAgent::AttributeRequestL()) wants to  signal the completion of
00244 an attribute request.
00245 =================================================================================
00246 */
00247 void CBluetoothServiceSearcher::AttributeRequestComplete(TSdpServRecordHandle /*aHandle*/, TInt aError)
00248         {
00249         /*
00250         =================================================================================
00251         In our example we finish on the first match but you can use iAgent->NextRecordRequestL() to search for
00252         another record (if any).
00253         =================================================================================
00254         */
00255         iObserver.OnServiceSearchComplete(iPort, aError);
00256         }
00257 
00258 /*
00259 =================================================================================
00260 Indicates that subsequent elements added belong to a DES or DEA
00261 =================================================================================
00262 */
00263 void CBluetoothServiceSearcher::StartListL(CSdpAttrValueList& /*aList*/)
00264         {
00265         //From MSdpAttributeValueVisitor.
00266         //Not used
00267         }
00268 
00269 /*
00270 =================================================================================
00271 Indicates the end of a list started by StartListL().
00272 =================================================================================
00273 */
00274 void CBluetoothServiceSearcher::EndListL()
00275         {
00276         //From MSdpAttributeValueVisitor.
00277         //Not used
00278         }

Generated by  doxygen 1.6.2