First submission to Symbian Foundation staging server.
// btincoming.cpp
//
// Copyright (c) 2008 - 2010 Accenture. All rights reserved.
// This component and the accompanying materials are made available
// under the terms of the "Eclipse Public License v1.0"
// which accompanies this distribution, and is available
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
//
// Initial Contributors:
// Accenture - Initial contribution
//
#include <e32base.h>
#include "btincomingserial.h"
#include "btservice.h"
#include "btdebug.h"
_LIT(KBtSerialPanic, "BTSerial");
void Panic(TBtSerialPanic aReason)
{
TRACE2("BtIncoming panic %d", aReason);
User::Panic(KBtSerialPanic, aReason);
};
NONSHARABLE_CLASS(CBtRegQuery) : public CActive
{
public:
CBtRegQuery(CBluetoothIncomingSerialConnection& aOwner);
void Start(CBTRegistryResponse& aResponse);
private:
virtual void RunL();
virtual void DoCancel();
private:
CBluetoothIncomingSerialConnection& iOwner;
CBTRegistryResponse* iResponse;
};
EXPORT_C CBluetoothIncomingSerialConnection* CBluetoothIncomingSerialConnection::NewL(MBtIncomingConnectionObserver& aObserver)
{
TRACE1("CBluetoothIncomingSerialConnection::NewL");
CBluetoothIncomingSerialConnection* self = new(ELeave)CBluetoothIncomingSerialConnection(aObserver);
CleanupStack::PushL(self);
self->ConstructL();
CleanupStack::Pop(self);
return self;
}
EXPORT_C CBluetoothIncomingSerialConnection::~CBluetoothIncomingSerialConnection()
{
TRACE1("CBluetoothIncomingSerialConnection::~CBluetoothIncomingSerialConnection");
delete iService;
delete iSocket;
iSockServ.Close();
iSdpSession.Close();
}
CBluetoothIncomingSerialConnection::CBluetoothIncomingSerialConnection(MBtIncomingConnectionObserver& aObserver)
: iObserver(aObserver)
{
}
void CBluetoothIncomingSerialConnection::ConstructL()
{
TRACE1("+CBluetoothIncomingSerialConnection::ConstructL");
User::LeaveIfError(iSdpSession.Connect());
User::LeaveIfError(iSockServ.Connect());
TUUID serialPortUUID = TUUID(0x1101);
iService = CBtService::NewL(serialPortUUID, iSdpSession, iSockServ, *this, KRFCOMM);
// create a blank socket for the incoming connection
iSocket = CBluetoothSocket::NewL(*this, iSockServ);
TRACE1("-CBluetoothIncomingSerialConnection::ConstructL");
}
EXPORT_C void CBluetoothIncomingSerialConnection::WaitForConnection()
{
TRACE1("CBluetoothIncomingSerialConnection::WaitForConnection");
iService->AcceptConnection(*iSocket);
}
EXPORT_C TBool CBluetoothIncomingSerialConnection::Connected()
{
TRACE2("CBluetoothIncomingSerialConnection::Connected %d", iSocketReady);
return iSocketReady;
}
EXPORT_C TBTDevAddr CBluetoothIncomingSerialConnection::ConnectedDeviceAddrL()
{
if (!iSocketReady) User::Leave(KErrNotReady);
TBTSockAddr remote;
iSocket->RemoteName(remote);
return remote.BTAddr();
}
EXPORT_C void CBluetoothIncomingSerialConnection::GetConnectedDeviceNameL()
{
if (iConnectedDevice) return;
if (!iSocketReady) User::Leave(KErrNotReady);
// lazy construction....
if (!iRegQuery) iRegQuery = new(ELeave)CBtRegQuery(*this);
if (iRegQuery->IsActive())
{
return;
}
if (reinterpret_cast<RHandleBase&>(iBtRegServ).Handle() == KNullHandle)
{
User::LeaveIfError(iBtRegServ.Connect());
}
if (iBtReg.SubSessionHandle() == KNullHandle)
{
User::LeaveIfError(iBtReg.Open(iBtRegServ));
}
if (!iRegReponse) iRegReponse = CBTRegistryResponse::NewL(iBtReg);
TBTSockAddr remote;
iSocket->RemoteName(remote);
TBTRegistrySearch findConnected;
findConnected.FindAddress(remote.BTAddr());
TRequestStatus stat;
iBtReg.CreateView(findConnected, stat);
User::WaitForRequest(stat);
User::LeaveIfError(stat.Int());
iRegQuery->Start(*iRegReponse);
}
void CBluetoothIncomingSerialConnection::QueryComplete(TInt aError)
{
iBtReg.CloseView();
if (aError == KErrNone)
{
RBTDeviceArray& results = iRegReponse->Results();
if (results.Count() != 1)
// we queried by BD address, so should get 1 (or 0) results
{
aError = KErrNotFound;
}
if (aError == KErrNone)
{
TRAP(aError, iConnectedDevice = results[0]->CopyL());
}
if (aError == KErrNone)
{
if (iConnectedDevice->IsValidFriendlyName())
{
aError = iDeviceName.Create(iConnectedDevice->FriendlyName());
}
else
{
aError = iDeviceName.Create(iConnectedDevice->DeviceName().Length());
if (aError == KErrNone)
{
iDeviceName.Copy(iConnectedDevice->DeviceName());
}
}
if (aError!=KErrNone)
{
delete iConnectedDevice;
iConnectedDevice = NULL;
}
}
}
iObserver.BtNameReceived(aError, iDeviceName);
}
EXPORT_C void CBluetoothIncomingSerialConnection::Write(const TDesC8& aData)
{
TRACE1("CBluetoothIncomingSerialConnection::Write");
__ASSERT_ALWAYS(iSocketReady, Panic(EBtSerialNotConnected));
__ASSERT_ALWAYS(!iSending, Panic(EBtSerialWritePending));
TInt err = iSocket->Send(aData, 0);
if (err==KErrNone)
{
iSending = ETrue;
}
else
{
iObserver.BtWriteComplete(err);
}
}
EXPORT_C void CBluetoothIncomingSerialConnection::CancelWrite()
{
TRACE1("CBluetoothIncomingSerialConnection::CancelWrite");
iSocket->CancelSend();
iSending = EFalse;
}
EXPORT_C void CBluetoothIncomingSerialConnection::Read(TDes8& aData)
{
TRACE1("CBluetoothIncomingSerialConnection::Read");
__ASSERT_ALWAYS(iSocketReady, Panic(EBtSerialNotConnected));
__ASSERT_ALWAYS(!iReceiving, Panic(EBtSerialReadPending));
aData.Zero();
TInt err = iSocket->RecvOneOrMore(aData, 0, iXferLen);
if (err==KErrNone)
{
iReceiving = ETrue;
}
else
{
iObserver.BtReadComplete(err);
}
}
EXPORT_C void CBluetoothIncomingSerialConnection::CancelRead()
{
TRACE1("CBluetoothIncomingSerialConnection::CancelRead");
iSocket->CancelRead();
iReceiving = EFalse;
}
EXPORT_C void CBluetoothIncomingSerialConnection::ShutDown()
{
iSocket->Shutdown(RSocket::EImmediate);
}
void CBluetoothIncomingSerialConnection::HandleConnectCompleteL(TInt _BTDEB(aErr))
{
TRACE2("CBluetoothIncomingSerialConnection::HandleConnectCompleteL(%d)", aErr);
}
void CBluetoothIncomingSerialConnection::HandleAcceptCompleteL(TInt _BTDEB(aErr))
{
TRACE2("CBluetoothIncomingSerialConnection::HandleAcceptCompleteL(%d)", aErr);
}
void CBluetoothIncomingSerialConnection::HandleShutdownCompleteL(TInt aErr)
{
TRACE2("CBluetoothIncomingSerialConnection::HandleShutdownCompleteL(%d)", aErr);
iObserver.BtShutdownComplete(aErr);
}
void CBluetoothIncomingSerialConnection::HandleSendCompleteL(TInt aErr)
{
TRACE1("CBluetoothIncomingSerialConnection::HandleSendCompleteL");
__ASSERT_ALWAYS(iSending, PANIC());
iSending = EFalse;
iObserver.BtWriteComplete(aErr);
}
void CBluetoothIncomingSerialConnection::HandleReceiveCompleteL(TInt aErr)
{
TRACE1("CBluetoothIncomingSerialConnection::HandleReceiveCompleteL");
__ASSERT_ALWAYS(iReceiving, PANIC());
iReceiving = EFalse;
iObserver.BtReadComplete(aErr);
}
void CBluetoothIncomingSerialConnection::HandleIoctlCompleteL(TInt _BTDEB(aErr))
{
TRACE2("CBluetoothIncomingSerialConnection::HandleIoctlCompleteL(%d)", aErr);
}
void CBluetoothIncomingSerialConnection::HandleActivateBasebandEventNotifierCompleteL(TInt _BTDEB(aErr), TBTBasebandEventNotification& /*aEventNotification*/)
{
TRACE2("CBluetoothIncomingSerialConnection::HandleActivateBasebandEventNotifierCompleteL(%d)", aErr);
}
void CBluetoothIncomingSerialConnection::HandleNewConnection(CBluetoothSocket* aConnectedSocket)
{
TRACE1("CBluetoothIncomingSerialConnection::HandleNewConnection");
__ASSERT_ALWAYS(iSocket == aConnectedSocket, PANIC());
iSocketReady = ETrue;
iObserver.BtSerialConnected();
}
void CBluetoothIncomingSerialConnection::HandleConnectFailed(TInt aError)
{
TRACE2("CBluetoothIncomingSerialConnection::HandleConnectFailed", aError);
iSocketReady = EFalse;
iObserver.BtSerialError(aError);
}
CBtRegQuery::CBtRegQuery(CBluetoothIncomingSerialConnection& aOwner)
: CActive(CActive::EPriorityStandard), iOwner(aOwner)
{
CActiveScheduler::Add(this);
}
void CBtRegQuery::Start(CBTRegistryResponse& aBtResponse)
{
iResponse = &aBtResponse;
iResponse->Start(iStatus);
SetActive();
}
void CBtRegQuery::RunL()
{
iOwner.QueryComplete(iStatus.Int());
}
void CBtRegQuery::DoCancel()
{
iResponse->Cancel();
// nasty race condition inside CBTRegistryResponse which means the cancal call may not
// request out TRequestStatus (if DoCancel doesn't need to be called)
if (iStatus == KRequestPending)
{
TRequestStatus* stat = &iStatus;
User::RequestComplete(stat, KErrCancel);
}
}