Contents |
This wiki page show you how to add bluetooth serial port service to sdp database and listen for connection.
The code in this example was cut and edit from Bluetooth Point to Multipoint example.
/*
* Copyright ฉ 2008 Nokia Corporation.
*/
#ifndef COMMON_H
#define COMMON_H
#include <e32base.h>
#include <es_sock.h>
#include <bttypes.h>
// structure that will hold the info about the remote device
struct TDeviceData
{
THostName iDeviceName;
TBTDevAddr iDeviceAddr;
TUint iDeviceServicePort;
};
// for ease of use and clarity, the type definition for device data list
typedef RPointerArray<TDeviceData> TDeviceDataList;
// the service id that identifies our service. this id will be
// used when advertising the service and discovering the service.
#define KBT_serviceID 0x1101
// passed to RSocket::Listen, the size of listen queue
const TInt KSizeOfListenQueue = 5;
_LIT(KRfComm,"RFCOMM");
#endif
/*
* Copyright ฉ 2008 Nokia Corporation.
*/
#ifndef LISTENER_H
#define LISTENER_H
// INCLUDES
#include <e32base.h>
#include <es_sock.h>
#include <btdevice.h>
#include <bt_sock.h>
#include <btmanclient.h>
#include "Common.h"
const TInt KReceivedBufferSize = 40;
class MListenerObserver
{
public:
/*!
* HandleListenerDataReceivedL()
*
* discussion Observer interface for handling listener data reception event.
*/
virtual void HandleListenerDataReceivedL(const TDesC& aData)=0;
/*!
* HandleListenerConnectedL()
*
* discussion Observer interface for handling listener connection event.
*/
virtual void HandleListenerConnectedL()=0;
/*!
* HandleListenerDisconnectedL()
*
* discussion Observer interface for handling disconnection event.
*/
virtual void HandleListenerDisconnectedL()=0;
};
class CListener : public CActive
{
public:
/*!
* NewL()
*
* discussion Create new CListener object
* return a pointer to the created instance of CListener
*/
static CListener* NewL(MListenerObserver& aObserver,
RSocketServ& aSocketServ);
/*!
* NewLC()
*
*/
static CListener* NewLC(MListenerObserver& aObserver,
RSocketServ& aSocketServ);
/*!
* ~CConnector()
*
* discussion Destroy the object and release all memory objects
*/
~CListener();
/*!
* StartListenerL()
*
* discussion Starts the listener. listener will open a listening socket and
* listen on incoming connections.
*
* param aChannel the communication channel (port) the listener listens to.
*/
void StartListenerL(TInt& aChannel);
/*!
* StopListener()
*
* discussion Stops the listener, closes the listening socket.
*/
void StopListener();
/*!
* SendData()
*
* discussion Sends data to master. user will be prompted to enter the
* message to send.
*
* param aData the message to be send.
*/
void SendData(const TDesC8& aData);
/*!
* IsConnected()
*
* discussion check if listener is connected to.
*
* return true if listener has a connection from master.
*/
TBool IsConnected();
protected:
/*!
* RunL()
*
* discussion Handle the active objects request completion.
*/
void RunL();
/*!
* DoCancel()
*
* discussion Cancels the outstanding request on active object.
*/
void DoCancel();
TInt RunError(TInt aError);
private:
/*!
* CListener()
*
* discussion Perform the first phase of two phase construction
*
* param aObserver reference to observer handling the listener events
* param aSocketServ reference to socket server
*/
CListener(MListenerObserver& aObserver, RSocketServ& aSocketServ);
/*!
* ConstructL()
*
*/
void ConstructL();
/*!
* ReceiveData()
*
* discussion Receive data from listening socket.
*/
void ReceiveData();
/*!
* SetSecurityL()
*
* discussion Sets the security of the bluetooth comm channel.
*/
void SetSecurityL(TInt /*aChannel*/);
/*!
* HandleListenerDataReceivedL()
*
* discussion Handles the data received from a master. the handling request
* will be passed onto handling observer.
*
* param aData the data received.
*/
void HandleListenerDataReceivedL(const TDesC& aData);
/*!
* HandleListenerConnectedL()
*
* discussion Handles the event of slave connection (slave was connected to
* by master). the handling request will be passed onto handling observer.
*/
void HandleListenerConnectedL();
/*!
* HandleListenerDisconnectedL()
*
* discussion Handles the event of slave disconnection, the master connection
* to slave was terminated. the handling request will be passed onto handling
* observer.
*/
void HandleListenerDisconnectedL();
public: // data
// listening socket
RSocket iListenSock;
// accepted socket
RSocket iSock;
// length of received data
TSockXfrLength iLen;
// buffer holding received data
TBuf8<KReceivedBufferSize> iBuffer;
// observer reference
MListenerObserver& iObserver;
// socket server handle
RSocketServ& iSocketServ;
// listener connection status
TBool iIsConnected;
// the state of the listener
enum TState
{
ENone = 1,
EConnecting,
EWaiting,
ESending
};
TState iState;
};
#endif
/*
* Copyright © 2008 Nokia Corporation.
*/
// INCLUDE FILES
#include "Listener.h"
CListener* CListener::NewL(MListenerObserver& aObserver,
RSocketServ& aSocketServ)
{
CListener* self = CListener::NewLC(aObserver, aSocketServ);
CleanupStack::Pop(self);
return self;
}
CListener* CListener::NewLC(MListenerObserver& aObserver,
RSocketServ& aSocketServ)
{
CListener* self = new (ELeave) CListener(aObserver, aSocketServ);
CleanupStack::PushL(self);
self->ConstructL();
return self;
}
void CListener::ConstructL()
{
}
// ----------------------------------------------------------------------------
// CListener::CListener(MListernetObserver* aObserver,
// RSocketServ *aSocketServ)
//
// constructor
// ----------------------------------------------------------------------------
CListener::CListener(MListenerObserver& aObserver,
RSocketServ& aSocketServ):
CActive(CActive::EPriorityStandard),
iObserver(aObserver),
iSocketServ(aSocketServ),
iIsConnected(EFalse),
iState(ENone)
{
CActiveScheduler::Add(this);
}
// ----------------------------------------------------------------------------
// CListener::~CListener()
//
// destructor
// ----------------------------------------------------------------------------
CListener::~CListener()
{
// cancel active object
Cancel();
// close sockets
StopListener();
}
// ----------------------------------------------------------------------------
// CListener::StartListenerL()
//
// start listener. listener will open a listening socket on a channel (port)
// gotten from GetOpt() call.
// ----------------------------------------------------------------------------
void CListener::StartListenerL(TInt& aChannel)
{
// get out if we're already running..
if ( iState!=ENone )
{
User::Leave(KErrInUse);
}
// set this active object to connecting state
iState=EConnecting;
// load protocol, RFCOMM
TProtocolDesc pdesc;
User::LeaveIfError(iSocketServ.FindProtocol(KRfComm(), pdesc));
// open a socket
User::LeaveIfError(
iListenSock.Open(iSocketServ,
pdesc.iAddrFamily,pdesc.iSockType,KRFCOMM)
);
// get listening channel
User::LeaveIfError(iListenSock.GetOpt(KRFCOMMGetAvailableServerChannel,
KSolBtRFCOMM, aChannel));
// bluetooth socket address object
TBTSockAddr btsockaddr;
btsockaddr.SetPort(aChannel);
// bind socket
User::LeaveIfError(iListenSock.Bind(btsockaddr));
// listen on port
iListenSock.Listen(KSizeOfListenQueue);
//now set security
//old way to set security is in Listener.cpp
//CListener::SetSecurityL(TInt aChannel)
TBTServiceSecurity secSettings;
TUid settingsUID;
settingsUID.iUid = KBT_serviceID;
secSettings.SetUid(settingsUID);
//the old way involved the following two steps:
//secSettings.SetChannelID(aChannel);
//secSettings.SetProtocolID(KSolBtRFCOMM);
secSettings.SetAuthentication(EFalse);
secSettings.SetAuthorisation(EFalse);
secSettings.SetEncryption(EFalse);
// attach the security settings.
btsockaddr.SetSecurity(secSettings);
// close old accepted socket if open
iSock.Close();
// open blank socket and pass it to accept to be assigned a proper
// socket upon completion of Accept()
User::LeaveIfError(iSock.Open(iSocketServ));
// set to accept incoming connections, active object will handle
iListenSock.Accept(iSock,iStatus);
SetActive();
}
// ----------------------------------------------------------------------------
// CListener::SetSecurityL(TInt aChannel)
//
// sets the security of given bluetooth channel. these settings will turn
// off authentication, authorisation and encryption on given channel.
//
// Not supported in 2nd ed. FP2 and newer versions.
// Left here just for comparing.
// ----------------------------------------------------------------------------
void CListener::SetSecurityL(TInt /*aChannel*/)
{
//this is not supported in 2nd ed. FP2 and above:
//setup channel security:
//TRequestStatus status;
//RBTMan secManager;
//RBTSecuritySettings secDatabase;
//TBTServiceSecurity secSettings;
// connect to security manager
//User::LeaveIfError(secManager.Connect());
//CleanupClosePushL(secManager);
//User::LeaveIfError(secDatabase.Open(secManager));
//CleanupClosePushL(secDatabase);
// setup security
//TUid settingsUID;
//settingsUID.iUid = KBT_serviceID;
//secSettings.SetUid(settingsUID);
//secSettings.SetChannelID(aChannel);
//secSettings.SetProtocolID(KSolBtRFCOMM);
//secSettings.SetAuthentication(EFalse);
//secSettings.SetAuthorisation(EFalse);
//secSettings.SetEncryption(EFalse);
// register settings with security
//secDatabase.RegisterService(secSettings, status);
//User::WaitForRequest(status);
//CleanupStack::PopAndDestroy(2,&secManager);//SecDatabase, secManager
}
// ----------------------------------------------------------------------------
// CListener::StopListener()
//
// stops the listener by closing the listening socket
// ----------------------------------------------------------------------------
void CListener::StopListener()
{
// kill sockets
if ( iState!=ENone )
{
iSock.Close();
iListenSock.Close();
iState=ENone;
}
}
// ----------------------------------------------------------------------------
// CListener::ReceiveData()
//
// receive more data from listening socket, asynchronously.
// ----------------------------------------------------------------------------
void CListener::ReceiveData()
{
// set state to waiting - for RunL()
iState = EWaiting;
// make async request
iSock.RecvOneOrMore(iBuffer, 0, iStatus, iLen);
// set as active to get the async req response (iState) in RunL()
SetActive();
}
// ----------------------------------------------------------------------------
// CListener::SendData(const TDesC8& aData)
//
// send data to remote device, write data to socket.
// ----------------------------------------------------------------------------
void CListener::SendData(const TDesC8& aData)
{
if ( iState!=EWaiting )
return;
// cancel any read requests on socket
Cancel();
// try to send message by writing to socket
// - set the state of this active object to "sending"
iState=ESending;
// - make async socket write request
iSock.Write(aData, iStatus);
// - start waiting async req response (iState) from active scheduler
SetActive();
}
void CListener::RunL()
{
if ( iStatus!=KErrNone )
{
StopListener();
HandleListenerDisconnectedL();
return;
}
switch (iState)
{
case EConnecting:
{
// connected listening socket!
HandleListenerConnectedL();
ReceiveData();
break;
}
case EWaiting:
{
// returned from receiving data
if(iState!=KErrNone)
{
// add the error handling / re-reading code here..
// not needed in this example
}
HBufC* text = HBufC::NewLC(iBuffer.Length());
text->Des().Copy(iBuffer);
// observer will handle data
HandleListenerDataReceivedL(*text);
CleanupStack::PopAndDestroy(text);
// start expecting next data to be read
ReceiveData();
break;
}
case ESending:
{
// returned from sending the date, check the state
if(iState!=KErrNone)
{
// add the error handling / re-sending code here..
// not needed in this example
}
// start expecting next data to be read
ReceiveData();
break;
}
default:
break;
}
}
TInt CListener::RunError(TInt /*aError*/)
{
// add the error handling
return KErrNone;
}
void CListener::DoCancel()
{
// cancel all pending socket operations
iSock.CancelAll();
iListenSock.CancelAll();
}
// ----------------------------------------------------------------------------
// CListener::IsConnected()
//
// returns true if listener has been connected to
// ----------------------------------------------------------------------------
TBool CListener::IsConnected()
{
return iIsConnected;
}
// ----------------------------------------------------------------------------
// CListener::HandleListenerDataReceivedL(TDesC& aData)
//
// a callback to observer indicating that listener has received data
// ----------------------------------------------------------------------------
void CListener::HandleListenerDataReceivedL(const TDesC& aData)
{
iObserver.HandleListenerDataReceivedL(aData);
}
// ----------------------------------------------------------------------------
// CListener::HandleListenerConnectedL()
//
// a callback to observer indicating that listener has been connected to
// ----------------------------------------------------------------------------
void CListener::HandleListenerConnectedL()
{
iIsConnected=ETrue;
iObserver.HandleListenerConnectedL();
}
// ----------------------------------------------------------------------------
// CListener::HandleListenerDisconnectedL()
//
// a callback to observer indicating that listener has been disconnected
// ----------------------------------------------------------------------------
void CListener::HandleListenerDisconnectedL()
{
iIsConnected=EFalse;
iObserver.HandleListenerDisconnectedL();
}
/*
* Copyright ฉ 2008 Nokia Corporation.
*/
#ifndef SERVICEADVERTISER_H
#define SERVICEADVERTISER_H
// INCLUDES
#include <e32base.h>
#include <coecntrl.h>
#include <es_sock.h>
#include <btdevice.h>
#include <bt_sock.h>
#include <btsdp.h>
#include <btmanclient.h>
#include "Common.h"
class CServiceAdvertiser : public CBase
{
public:
/*!
* NewL()
*
* discussion Create new CServiceAdvertiser object
* return a pointer to the created instance of CServiceAdvertiser
*/
static CServiceAdvertiser* NewL();
/*!
* NewLC()
*
*/
static CServiceAdvertiser* NewLC();
/*!
* ~CDeviceDiscoverer()
*
* discussion Destroy the object and release all memory objects
*/
~CServiceAdvertiser();
/*!
* StartAdvertiserL()
*
* discussion Starts the service advertiser.
*
* param aChannel the communication channel (port) the service will be
* advertised on. an entry for our advertisement will be added to service
* discovery database.
*/
void StartAdvertiserL(TInt /*aChannel*/);
/*!
* StopAdvertiserL()
*
* discussion Stops the service advertiser. our entry from service
* discovery database will be removed.
*/
void StopAdvertiserL();
/*!
* UpdateAvailabilityL()
*
* discussion Updates the availability of advertised service. the service
* record in service discovery database will be updated accordingly.
*
* param aAvailable true if the service should be set as available,
* false if unavailable.
*/
void UpdateAvailabilityL(TBool /*aAvailable*/);
private:
/*!
* CServiceAdvertiser()
*
* discussion Perform the first phase of two phase construction
*/
CServiceAdvertiser();
/*!
* ConstructL()
*
*/
void ConstructL();
private: // data
// service discovery protocol session
RSdp iSdp;
// service discovery database (sdp)
RSdpDatabase iSdpDB;
// service record
TSdpServRecordHandle iRecord;
// service record state
TInt iRecordState;
};
#endif
/*
* Copyright ฉ 2008 Nokia Corporation.
*/
// INCLUDE FILES
#include <btmanclient.h>
#include "ServiceAdvertiser.h"
// see https://www.bluetooth.org/foundry/assignnumb/document/service_discovery
// service name and description for our service
_LIT(KBTServiceName, "Bluetooth Serial Example");
_LIT(KBTServiceDesc, "Bluetooth Serial Example");
CServiceAdvertiser* CServiceAdvertiser::NewL()
{
CServiceAdvertiser* self = CServiceAdvertiser::NewLC();
CleanupStack::Pop(self);
return self;
}
CServiceAdvertiser* CServiceAdvertiser::NewLC()
{
CServiceAdvertiser* self = new (ELeave) CServiceAdvertiser();
CleanupStack::PushL(self);
self->ConstructL();
return self;
}
void CServiceAdvertiser::ConstructL()
{
}
// ----------------------------------------------------------------------------
// CServiceAdvertiser::CServiceAdvertiser()
//
// constructor
// ----------------------------------------------------------------------------
CServiceAdvertiser::CServiceAdvertiser()
{
}
// ----------------------------------------------------------------------------
// CServiceAdvertiser::~CServiceAdvertiser()
//
// destructor
// ----------------------------------------------------------------------------
CServiceAdvertiser::~CServiceAdvertiser()
{
TRAPD(err, StopAdvertiserL());
}
// ----------------------------------------------------------------------------
// CServiceAdvertiser::StartAdvertiserL(TInt aChannel)
//
// start service advertiser on given channel. an entry to service discovery
// database will be entered describing our advertised service.
// ----------------------------------------------------------------------------
void CServiceAdvertiser::StartAdvertiserL(TInt aChannel)
{
// open sdp session
User::LeaveIfError(iSdp.Connect());
// open sdp database session
User::LeaveIfError(iSdpDB.Open(iSdp));
// create a record of the correct service class
TUUID serviceUUID(KBT_serviceID);
iSdpDB.CreateServiceRecordL(serviceUUID, iRecord);
// add a protocol to the record
CSdpAttrValueDES* protocolDescriptorList = CSdpAttrValueDES::NewDESL(NULL);
CleanupStack::PushL(protocolDescriptorList);
TBuf8<1> channel;
channel.Append((TChar)aChannel);
// create protocol list for our service
protocolDescriptorList
->StartListL() // list of protocols required for this method
->BuildDESL()
->StartListL()
->BuildUUIDL(KL2CAP)
->EndListL()
->BuildDESL()
->StartListL()
->BuildUUIDL(KRFCOMM)
->BuildUintL(channel)
->EndListL()
->EndListL();
// set protocol list to the record
iSdpDB.UpdateAttributeL(iRecord, KSdpAttrIdProtocolDescriptorList,
*protocolDescriptorList);
CleanupStack::PopAndDestroy(protocolDescriptorList);
// add a name to the record
iSdpDB.UpdateAttributeL(iRecord,
KSdpAttrIdBasePrimaryLanguage +
KSdpAttrIdOffsetServiceName,
KBTServiceName);
// add a description to the record
iSdpDB.UpdateAttributeL(iRecord,
KSdpAttrIdBasePrimaryLanguage +
KSdpAttrIdOffsetServiceDescription,
KBTServiceDesc);
// set service available
UpdateAvailabilityL(ETrue);
}
// ----------------------------------------------------------------------------
// CServiceAdvertiser::StopAdvertiserL()
//
// stop service advertiser. delete service record from service discovery
// database to stop advertising.
// ----------------------------------------------------------------------------
void CServiceAdvertiser::StopAdvertiserL()
{
if ( iRecord!=0 )
{
// delete out record from service discovery database
iSdpDB.DeleteRecordL(iRecord);
// close sdp and sdp db sessions
iSdpDB.Close();
iSdp.Close();
iRecord=0;
}
}
// ----------------------------------------------------------------------------
// CServiceAdvertiser::UpdateAvailability(TBool aAvailable)
//
// set availability of our advertised service. the service record on the
// service discovery database will be updated accordingly.
// ----------------------------------------------------------------------------
void CServiceAdvertiser::UpdateAvailabilityL(TBool aAvailable)
{
TInt state = aAvailable ? 0xFF : 0x00;
// set availability
iSdpDB.UpdateAttributeL(iRecord, KSdpAttrIdServiceAvailability, state);
// mark record changed
iSdpDB.UpdateAttributeL(iRecord, KSdpAttrIdServiceRecordState,
++iRecordState);
}
iSocketServ.Connect();
TInt tChannel = 1;
iListener = CListener::NewL(*this, iSocketServ);
TRAPD(err, iListener->StartListenerL(tChannel));
iServiceAdvertiser = CServiceAdvertiser::NewL();
iServiceAdvertiser->StartAdvertiserL(tChannel);
if (iListener)
{
delete iListener;
iListener = NULL;
}
if (iServiceAdvertiser)
{
delete iServiceAdvertiser;
iServiceAdvertiser = NULL;
}
iSocketServ.Close();
LIBRARY bluetooth.lib sdpdatabase.lib esock.lib
ReadUserData LocalServices NetworkServices
Open application and try to discovery for all available services on Phone. If you're lucky enough, you will see Bluetooth Serial Example service.
File:Listen for Bluetooth Serial Port service in Symbian.zip
User:Neois Bold text
No related wiki articles found