For some Bluetooth profiles, a device needs to allow remote devices to connect in. Examples are the Audio Gateway role in HSP, the Gateway in DUNP, or one end of a chat application. Like outgoing connections, incoming requests to connect from other Bluetooth devices are handled through EPOC's generic sockets API. To receive an incoming connection, a service must open a listening socket on which it can then accept connections. The steps are given below:
Connect to the Sockets Server and select the protocol to be used
Open a socket for that protocol
Create a Bluetooth socket address object (TBTSockAddr
) and set its port to the PSM or server channel (for L2CAP or RFCOMM respectively) and bind the socket to this address. Note you do not have to set the local Bluetooth device address in the address.
Tell the socket to listen for incoming connections using RSocket::Listen()
.
Create a blank socket and pass it to the listening socket through RSocket::Accept()
. When this call completes, the socket passed in a parameter is now fully connected and can be used to send and receive data. The listening socket remains in place, ready for another socket to be passed in when the program can handle another connection.
When the receiver wishes to shutdown, it must ensure that it closes the listening socket as well as any connected ones.
Before accepting incoming connections, you may need to set the security requirements for incoming connections to the service, as described in Using Bluetooth Security Manager, and advertise the service's availability, explained in Using Bluetooth Service Discovery Database.
// 1. Connect to the socket server
RSocketServ socketServ;
socketServ.Connect();
TProtocolDesc pInfo;
_LIT(KL2Cap, "L2CAP"); // or RFCOMM as appropriate
// 2. Open a socket
RSocket listen;
listen.Open(ss,KL2Cap);
// 3. Set up address object
TBTSockAddr addr;
addr.SetPort(KListeningPSM);
User::LeaveIfError(listen.Bind(addr));
// 4. Begin to listen
User::LeaveIfError(listen.Listen(2));
// 5. Wait for connection
RSocket accept;
TRequestStatus status;
User::LeaveIfError(accept.Open(socketServ));
listen.Accept(accept,status);
User::WaitForRequest(status);
// if status == KErrNone, accept is now fully connected
If the channel is already in use, as indicated if Bind()
returns an error, you can find a free channel using the KRFCOMMGetAvailableServerChannel
ioctl.