📄 bluetoothservicesearcher.cpp.svn-base
字号:
/*
============================================================================================
Name : BluetoothServiceSearcher.cpp
Author : BluetoothAPI is a initiative of Embedded LAB - http://www.embedded.ufcg.edu.br/
OpenC/SymbianC++ - http://efforts.embedded.ufcg.edu.br/symbiancpp
Version :
Copyright : This file is part of BluetoothAPI.
BluetoothAPI is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
BluetoothAPI is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with BluetoothAPI. If not, see <http://www.gnu.org/licenses/>.
Description : BluetoothServiceSearcher.cpp implementation
===========================================================================================
*/
#include "BluetoothServiceSearcher.h"
const TInt KPort = -1;
/*
============================================================================
CBluetoothServiceSearcher's constructor
============================================================================
*/
CBluetoothServiceSearcher::CBluetoothServiceSearcher(MBluetoothServiceSearcherObserver* aObs)
: iObserver(aObs), iPort(KPort), iFoundRfcommProtocol(EFalse)
{
}
/*
============================================================================
CBluetoothServiceSearcher's destructor
============================================================================
*/
CBluetoothServiceSearcher::~CBluetoothServiceSearcher()
{
delete iSdpSearchPattern;
if (iAgent)
{
iAgent->Cancel();
delete iAgent;
}
}
/*
============================================================================
Retrives from a remote device a SDP's service record.
On completion calls NextRecordRequestComplete.
============================================================================
*/
void CBluetoothServiceSearcher::FindServiceByUUIDL(const TBTDevAddr& aTarget, const TUUID& aUUID)
{
/*
============================================================================
Deletes any previous existing SDP agent and search pattern
============================================================================
*/
delete iSdpSearchPattern;
iSdpSearchPattern = NULL;
delete iAgent;
iAgent = NULL;
/*
============================================================================
Bluetooth's service class records are stored into the SDP database.
In order to access/get SDP's records you need to use CSdpAgent.
CSdpAgent can only been used if the address of a remote Bluetooth device has been identified.
Also the class using CSdpAgent must implement the MSdpAgentNotifier interface in order
to handle SDP's responses. See SDK for more details about CSdpAgent and MSdpAgentNotifier
============================================================================
*/
iAgent=CSdpAgent::NewL(*this,aTarget);
/*
============================================================================
In order to retrive only the SDP record you are interested in, SDP provides the filter
CSdpSearchPattern. CSdpSearchPattern is an array of TUUID (Bluetooth Universally Unique Identifier)
that uniquelly identifies a service class.
Adding a service class to the filter is done by calling subsequentially CSdpSearchPattern::AddL().
In our example we are interested only in seeing if the remote device provides the RPS service, but you could
for example ask the SDP server to return all Bluetooth services that support the RFCOMM protocol.
After adding all the TUUID you are interested in into CSdpSearchPattern you need to move it into
CSdpAgent by calling CSdpAgent::SetRecordFilterL().
============================================================================
*/
iSdpSearchPattern=CSdpSearchPattern::NewL();
iSdpSearchPattern->AddL(aUUID);
iAgent->SetRecordFilterL(*iSdpSearchPattern);
/*
============================================================================
We now need to get the handle of the record on the remote device that matches the service class we set previously in
CSdpSearchPattern. You need to use CSdpAgent::NextRecordRequestL(). NextRecordRequestL() is an asynchronous function
and when completed it will call the callback NextRecordRequestComplete() from the MSdpAgentNotifier interface
passed in the NewL. Note that as mention above CSdpSearchPattern could contain more then one service class TUUID and you can get
the next (if available) service record by calling subsequently NextRecordRequestL().
============================================================================
*/
iAgent->NextRecordRequestL();
}
/*
============================================================================
Called when a service record request (CSdpAgent::NextRecordRequestComplete()) operation is completed
============================================================================
*/
void CBluetoothServiceSearcher::NextRecordRequestComplete(TInt aError, TSdpServRecordHandle aHandle, TInt aTotalRecordsCount)
/*
=================================================================================
NextRecordRequestComplete is invoked each time a complete full SDP service record is retrieved from the remote Bluetooth target.
NextRecordRequestComplete is the CSdpAgent::NextRecordRequestL's callback
If there is no error, we then invoke CSdpAgent::AttributeRequestL to browse the attributes of the SDP record.
If there are no more records to browse then the error will be KErrEof.
=================================================================================
*/
{
TBool terminated=EFalse;
if(aError == KErrNone)
{
if(aTotalRecordsCount==0)
{
/*
=================================================================================
This covers the case where CSdpAgent::NextRecordRequestL didn't find any SDP's records matching our RPS's service class
=================================================================================
*/
iObserver->OnServiceSearchComplete(iPort, KErrNotFound);
}
else
{
iPort=KPort;
/*
=================================================================================
If there are SDP's records containing our class service, we need to browse the SDP record to retrive
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.
CSdpAgent::AttributeRequestL is an asynchronous call. When the attributes have been retrived from the remote device then it
calls AttributeRequestResult from the MSdpAgentNotifier interface. AttributeRequestL takes two parameters: the first one
is the handle of the SDP's record that is a TUint32 (TSdpServRecordHandle) and the second parameter is one of the "Universal Attributes"
defined in btsdp.h; in our example we use KSdpAttrIdProtocolDescriptorList because we are only interested in SDP's record that
contains the RFCOMM protocol. Note that there is another overload AttributeRequestL where the search is done
with a range of attibutes instead of only one. You need to use AttributeRequestL(TSdpServRecordHandle aHandle, const CSdpAttrIdMatchList& aMatchList),
where CSdpAttrIdMatchList is the list of attributes you want to filter. Also you can use your own builder class in order
to browse the SDP's record attributes. In this case you need to use
AttributeRequestL(MSdpElementBuilder* aBuilder, TSdpServRecordHandle aHandle, TSdpAttributeID aAttrID) for a single attribute or
AttributeRequestL(MSdpElementBuilder* aBuilder,TSdpServRecordHandle aHandle,const CSdpAttrIdMatchList& aMatchList)
for a range of attributes. If you don't want to provide your own MSdpElementBuilder then you can use directly
CSdpAttrValue returned from AttributeRequestResult. See below.
=================================================================================
*/
TRAPD(err, iAgent->AttributeRequestL(aHandle,KSdpAttrIdProtocolDescriptorList));
if(err != KErrNone)
{
iObserver->OnServiceSearchComplete(iPort, err);
}
}
}
else
{
/*
=================================================================================
This covers the case where there are no more SDP's records left to be read (KErrEof) or an SDP's error occurs.
=================================================================================
*/
iObserver->OnServiceSearchComplete(iPort, aError);
terminated=ETrue;
}
}
/*
============================================================================
Called when an attribute request (CSdpAgent::AttributeRequestL()) wants to pass up a result
============================================================================
*/
void CBluetoothServiceSearcher::AttributeRequestResult(TSdpServRecordHandle /*aHandle*/, TSdpAttributeID /*aAttrID*/, CSdpAttrValue* aAttrValue)
{
/*
=================================================================================
AttributeRequestResult is invoked each time an attribute-value is retrieved from the SDP record. AttributeRequestResult is the CSdpAgent::AttributeRequestL's callback.
We need to browse the attribute-value to decide whether we have a match with our initial requirements
CSdpAttrValue::AcceptVisitorL passes the attribute value to the VisitAttributeValueL callback
from MSdpAttributeValueVisitor
=================================================================================
*/
TRAPD(err,aAttrValue->AcceptVisitorL(*this));
if(err != KErrNone)
{
iObserver->OnServiceSearchComplete(iPort, err);
}
}
/*
============================================================================
Called to pass an attribute value
============================================================================
*/
void CBluetoothServiceSearcher::VisitAttributeValueL(CSdpAttrValue &aValue, TSdpElementType aType)
{
/*
=================================================================================
Here we browse the attributes to see if we have a match with our initial requirements.
In our case we are interested only in RPS's services that used only the KRFCOMM protocol. If there is a match
then we need to get the port of the RPS's service. VisitAttributeValueL is called for each
attribute. When all the attributes have been browsed then AttributeRequestComplete callback below is called.
=================================================================================
*/
switch(aType)
{
case ETypeUUID:
if(aValue.UUID() == TUUID(KRFCOMM))
{
iFoundRfcommProtocol = ETrue;
}
break;
case ETypeUint:
if(iFoundRfcommProtocol)
{
//get the RFCOMM's service port number
iPort=aValue.Uint();
iFoundRfcommProtocol = EFalse;
}
break;
default:
break;
}
}
/*
=================================================================================
Called when an attribute request (CSdpAgent::AttributeRequestL()) wants to signal the completion of
an attribute request.
=================================================================================
*/
void CBluetoothServiceSearcher::AttributeRequestComplete(TSdpServRecordHandle /*aHandle*/, TInt aError)
{
/*
=================================================================================
In our example we finish on the first match but you can use iAgent->NextRecordRequestL() to search for
another record (if any).
=================================================================================
*/
iObserver->OnServiceSearchComplete(iPort, aError);
}
/*
=================================================================================
Indicates that subsequent elements added belong to a DES or DEA
=================================================================================
*/
void CBluetoothServiceSearcher::StartListL(CSdpAttrValueList& /*aList*/)
{
//From MSdpAttributeValueVisitor.
//Not used
}
/*
=================================================================================
Indicates the end of a list started by StartListL().
=================================================================================
*/
void CBluetoothServiceSearcher::EndListL()
{
//From MSdpAttributeValueVisitor.
//Not used
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -