/** Standard 2nd phase constructor, perform initialisation which could leave */ void CBtService::ConstructL(const TUUID& aServiceUUID, RSdp& aSdpSession, const TBTServiceSecurity* aSecurity) { LOG_FN_TRACE((_L("+CBtService::ConstructL"))); //open handle so it is certain to be valid in the destructor iServiceRecord.Open(aSdpSession); //First, create a listening socket if(iProtocol == KL2CAP) { iAcceptorSocket = CBluetoothSocket::NewL(*this, iSocketServer, KSockSeqPacket, KL2CAP); //bind the socket to a port TL2CAPSockAddr addr; addr.SetPort(KL2CAPPassiveAutoBind); //allow the stack to choose a free port automatically if(aSecurity) { addr.SetSecurity(*aSecurity); //set security requirements, if present } User::LeaveIfError(iAcceptorSocket->Bind(addr)); } else if(iProtocol == KRFCOMM) { iAcceptorSocket = CBluetoothSocket::NewL(*this, iSocketServer, KSockStream, KRFCOMM); //bind the socket to a port TRfcommSockAddr addr; addr.SetPort(KRfcommPassiveAutoBind); //allow the stack to choose a free port automatically if(aSecurity) { addr.SetSecurity(*aSecurity); //set security requirements, if present } User::LeaveIfError(iAcceptorSocket->Bind(addr)); } User::LeaveIfError(iAcceptorSocket->Listen(1)); //Now, register in the SDP database TUint port = iAcceptorSocket->LocalPort(); //get the port chosen by the stack LOG_INFO((_L("Listening for connections on port %d"), port)); iServiceRecord.CreateServiceRecordL(aServiceUUID, iServiceRecordHandle); // Set attr 4 (protocol list) to L2CAP, and RFCOMM CSdpAttrValueDES *attrValDES; //This following code is doing these steps //1. create a DES (data element set) attribute //2. within that list, create a DES for each protocol, L2CAP and optionally RFCOMM //3. each protocol is a list of elements, the UUID of the protocol, and the port to connect to. //4. the service record is updated to include the new attribute //5. discard the attribute we built, as it has been copied to the SDP server attrValDES = CSdpAttrValueDES::NewDESL(NULL); CleanupStack::PushL(attrValDES); if(iProtocol == KL2CAP) { LOG_INFO((_L("Registering SDP PDL for L2CAP"))); //This code will register an L2CAP (datagram) service attrValDES ->StartListL() ->BuildDESL() ->StartListL() ->BuildUUIDL(TUUID(TUint16(KL2CAP))) // L2CAP ->BuildUintL(TSdpIntBuf<TUint16>(TUint16(port))) // The Protocol Service Multiplexor (port) for our service ->EndListL() ->EndListL(); } else if(iProtocol == KRFCOMM) { LOG_INFO((_L("Registering SDP PDL for RFCOMM"))); //This code will register an RFCOMM (stream) service attrValDES ->StartListL() ->BuildDESL() ->StartListL() ->BuildUUIDL(TUUID(TUint16(KL2CAP))) // L2CAP ->EndListL() ->BuildDESL() ->StartListL() ->BuildUUIDL(TUUID(TUint16(KRFCOMM))) // RFCOMM ->BuildUintL(TSdpIntBuf<TUint8>(TUint8(port))) ->EndListL() ->EndListL(); } iServiceRecord.UpdateAttributeL(iServiceRecordHandle, KSdpAttrIdProtocolDescriptorList, *attrValDES); CleanupStack::PopAndDestroy(attrValDES); attrValDES = NULL; LOG_FN_TRACE((_L("-CBtService::ConstructL"))); }
TInt CStatTransportBT::StartSocketL() { TUint error; //make sure we are in the correct state asserte( iBTTransportStatus == EConnectingRegisterMgr ); // connect to the socket server (as we are the receiver and not the initiator), create a socket, bind, listen, accept User::LeaveIfError( iSocketServ.Connect() ); //now select the protocol to use (RFCOMM (serial emulation - boo. Problems with demultiplexing if 1 generic serial port is used for multiple BT connections) or L2CAP) TProtocolDesc pInfo; User::LeaveIfError( iSocketServ.FindProtocol(_L("RFCOMM"),pInfo ) ); //open the listener socket User::LeaveIfError( iListenSocket.Open(iSocketServ, pInfo.iAddrFamily, pInfo.iSockType, pInfo.iProtocol) ); // RFComm Socket TRfcommSockAddr addr; // Get First available server channel addr.SetPort(KRfcommPassiveAutoBind); // Set the service security //Set user defined EPOC TUid to internally represent the service iServiceSecurity.SetUid( TUid::Uid( 0x1234 ) ); //Define security requirements iServiceSecurity.SetAuthentication( EFalse ); iServiceSecurity.SetEncryption( EFalse ); iServiceSecurity.SetAuthorisation( EFalse ); addr.SetSecurity(iServiceSecurity); //bind User::LeaveIfError( iListenSocket.Bind( addr ) ); // Get the assigned port iPort=iListenSocket.LocalPort(); // register with the SDP database error = RegWithSDPDatabaseL(); if( error != KSTErrSuccess ) { iTransport->HandleError( error, (void*)iStatus.Int() ); return KSTErrGeneralFailure; } //listen User::LeaveIfError( iListenSocket.Listen( KLittleStatBTListenQueue ) ); // create a blank socket which is used as the data socket User::LeaveIfError( iDataSocket.Open(iSocketServ) ); // everything should now be set up, we just wait for a stat connection asserte( !IsActive() ); iListenSocket.Accept( iDataSocket, iStatus ); SetActive(); return KSTErrSuccess; }