⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bluetooth1.cpp

📁 《UIQ 3 The Complete Guide》书的源代码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
// Start the acceptance of a connection from a remote BT entity
// In all cases we exit from here will an event source outstanding.
	{
	__ASSERT_DEBUG(iState==EListenerStateIdle,Panic(2));
	TInt ret=iSocket.Open(iSocketServer);
	if (ret==KErrNone)
		{
		SetAvailability(0xFF);		// publish our service as available now fully set up + listening
		iListener.Accept(iSocket,iStatus);
		}
	else
		RequestComplete(ret); // defer dealing with errors until the RunL()
	SetActive();
	iState=EListenerStateConnecting;

	_LIT(KListening,"Listening");
	iObserver->LogInfo(KListening);
	}

TBool CBtConnectionListener::SendData(const TDesC8& aData)
// We use the iWriteChannel for writing - so simply route to that. Our AO is used
// for read completions.
	{
	if (iState!=EListenerStateConnected)
		return(EFalse); // block writes cos were connecting/shutting down at this precise moment
	return(iWriteChannel->SendData(aData));
	}

void CBtConnectionListener::DoCancel()
// Cancel any outstanding activity, maybe called from destructor - if so the listbox has disappeared by
// here so cant log any messages.
	{
	switch (iState)
		{
	case EListenerStateConnecting:	// we were attempting to accept the connection
		iListener.CancelAccept();
		break;
	case EListenerStateConnected:
		iSocket.CancelRead();
		break;
	default:
		Panic(3); // what AO is running ?
		break;
		}
	iState=EListenerStateIdle;
	}

void CBtConnectionListener::RunL()
// A socket event has occured. 
	{
	switch (iState)
		{
	case EListenerStateConnected:	// data arrived for us to process
		if (iReadingState==EReadingHeader)
			{
			TInt error=iStatus.Int();
			if (error==KErrNone)
				{ // weve got the hdr, ensure its correct content, if so get main body
				TPtr8 q((TUint8*)iFrameHdr.Ptr(),5,5);
				if (q==KBluetoothHeaderText)
					{
					ReadContent(); // get the frame proper
					break;
					}

				// header is broken, were out of sync or communicating with the wrong thing...
				// shut down and re-start
				error=KErrCorrupt;
				}
			iObserver->StatusInfo(EBtsDisconnected,error);
			iState=EListenerStateIdle;
			iSocket.Close();
			StartListening();	// re-try connection
			}
		else
			{ // process whole frame
			if (iStatus.Int()==KErrNone)
				{
				iData.SetLength(iDataPtr.Length());
				iObserver->DataReceived(iData);
				Read(); // get next frame header, DataReceived() sorts out errors b4 here
				}
			else
				{
				iObserver->StatusInfo(EBtsDisconnected,iStatus.Int());
				iState=EListenerStateIdle;
				iSocket.Close();
				StartListening();	// re-try connection
				}
			}
		break;
	case EListenerStateConnecting:	// weve finished connect request
		SetAvailability(0x00); // no more connections at this time
		if (iStatus.Int()==KErrNone)
			{
			iState=EListenerStateConnected;
			Read();
			iObserver->StatusInfo(EBtsConnectionEstablished,KErrNone);
			}
		else
			{ // shutdown and start again
			_LIT(KListenError,"Listen Error");
			iObserver->LogInfo(KListenError);
			iState=EListenerStateIdle;
			iSocket.Close();
			StartListening();	// re-try connection
			}
		break;
	default:
		Panic(4); // what AO is running ?
		break;
		}
	}

TInt CBtConnectionListener::IsConnected() const
// Report if the connection creator is connected
	{
	return(iState==EListenerStateConnected);
	}

/////////////////////////////////////////////////////////////////////////////////////////////////
// This part of the engine creates BT connections.

enum TAttributeAction
	{
    EAttrItemCheckType,
    EAttrItemCheckTypeAndValue,  
    EAttrItemCheckEnd,      
    EAttrItemReadValue,    
    EAttrItemFinished
	};

typedef struct {
	TAttributeAction iAction;			// what to do when encountering this item
    TSdpElementType iElementType;		// what were expecting the item to be
    TInt iValue;						// what val is associated with the ElementType
    } SSdpAttributeItem;

static const SSdpAttributeItem lSerialPortAttributeList[] = 
    {
    {EAttrItemCheckType,ETypeDES,0},		// validate we see a ETypeDES

		{EAttrItemCheckType,ETypeDES,0},	// validate we see a ETypeDES
			{EAttrItemCheckTypeAndValue,ETypeUUID,KL2CAP}, // ensure its a UUID for KL2CAP
        {EAttrItemCheckEnd,ETypeNil,0},		// ensure thats all the attrs at that node

        {EAttrItemCheckType,ETypeDES,0},	// validate we see a ETypeDES
            {EAttrItemCheckTypeAndValue,ETypeUUID,KRFCOMM}, // ensure its a UUID for KL2CAP
            {EAttrItemReadValue,ETypeUint,1},	// 1 == field Key for 'the port', the Uint will be that actual port
        {EAttrItemCheckEnd,ETypeNil,0},		// ensure thats all the attrs at that node

    {EAttrItemCheckEnd,ETypeNil,0},			// ensure thats all the attrs at that node
    {EAttrItemFinished,ETypeNil,0}			// ensure weve finished reading that attribute set
    };

class CBtConnectionCreator : public CBtConnection, public MSdpAgentNotifier, public MSdpAttributeValueVisitor
	{
protected:
	enum TBtCreatorStates
		{
		ECreatorStateIdle,			// not doing much (val = 0 == default construct val)
		ECreatorStateFindService,
		ECreatorStateConnecting,	// attempting socket level connection
		ECreatorStateConnected,		// connected + able to transfer data
		};

	// from CActive
	void DoCancel();
	void RunL();

	// from MSdpAttributeValueVisitor
    void VisitAttributeValueL(CSdpAttrValue &aValue,TSdpElementType aType);
    void StartListL(CSdpAttrValueList &aList);
    void EndListL();

	// from MSdpAgentNotifier
	void NextRecordRequestComplete(TInt aError,TSdpServRecordHandle aHandle,TInt aTotalRecordsCount);
	void AttributeRequestResult(TSdpServRecordHandle aHandle,TSdpAttributeID aAttrID,CSdpAttrValue* aAttrValue);
	void AttributeRequestComplete(TSdpServRecordHandle,TInt aError);

	// new methods
	void Connect();
	void NextNodeL();

public:
	// from CBtConnection
	TBool SendData(const TDesC8& aData);

	// new methods
	~CBtConnectionCreator();
	CBtConnectionCreator(RSocketServ& aServ,MBtEngineObserver* aOwner);
	void ConstructL();
	void StartDiscoveryL();
	TInt IsConnected() const;

protected:
	CBtWriter* iWriteChannel;			// who writes data on our behalf
	TInt iRemotePort;					// the remote port we need to connect on

    CSdpAgent* iSdpAgent;					// connection to remte SDP database
    CSdpSearchPattern* iSdpSearchPattern;	// what can search remote SDP database records
	TInt iNodeIndex;						// which node weve reached in parsing a remote SDP record
	TInt iExtractedValue;					// extracted whilst parsing the SDP record

	TBTDevAddr iRemoteDevAddr;
	TBTDeviceName iRemoteDevName;
	TBTDeviceClass iRemoteDevClass;

	TBtCreatorStates iState;			// our state machine status
	};

CBtConnectionCreator::CBtConnectionCreator(RSocketServ& aServ,MBtEngineObserver* aOwner) :
	CBtConnection(aServ,aOwner)
	{}

CBtConnectionCreator::~CBtConnectionCreator()
	{
	// cancel any outstanding connect/read requests
	Cancel();

	// before we close the socket - cancel any outstanding write request
	delete(iWriteChannel); 

	// now all async requests been cancelled we can sensibly close the socket we xfer data over.
	iSocket.Close();
	}

void CBtConnectionCreator::ConstructL()
// Construct the Bt connection creator entities
	{
    User::LeaveIfError(iSocket.Open(iSocketServer,KRFCOMMDesC));
	iWriteChannel=new(ELeave)CBtWriter(iSocket,iObserver);
	}

void CBtConnectionCreator::Connect()
// Issue the connect request now we have the remote device address and port.
	{
	// setup the security settings for this app
    TBTServiceSecurity serviceSecurity;
    serviceSecurity.SetAuthentication(EFalse);    
    serviceSecurity.SetEncryption(EFalse); 
    serviceSecurity.SetAuthorisation(ETrue);
    serviceSecurity.SetDenied(EFalse);

	// setup which device ID and port to connect to
	TBTSockAddr addr;
	addr.SetBTAddr(iRemoteDevAddr);
	addr.SetPort(iRemotePort);		// as fetched from remote
	addr.SetSecurity(serviceSecurity);

	// and start the connection request
	iSocket.Connect(addr,iStatus);
	SetActive();
	iState=ECreatorStateConnecting;
	}

TBool CBtConnectionCreator::SendData(const TDesC8& aData)
// We use the iWriteChannel channel for writing - so simply route to that. Our AO is used
// for reading/connecting.
	{
	if (iState!=ECreatorStateConnected)
		return(EFalse); // were not connected enough to allow writing of data
	return(iWriteChannel->SendData(aData));
	}

void CBtConnectionCreator::NextNodeL()
// Attempt to move to the next node. If weve already reached the end report this
    {
    if (lSerialPortAttributeList[iNodeIndex].iAction==EAttrItemFinished)
        User::Leave(KErrEof);
    iNodeIndex++;
    }

void CBtConnectionCreator::VisitAttributeValueL(CSdpAttrValue &aValue,TSdpElementType aType)
// Called back by the CSdpAttrValue obj to allow us to parse + validate the contents
// are those we are searching for.
	{
	TBuf<32>bb;
	_LIT(KVisitAttributeValueL,"VisitAttributeValueL %d");
	bb.Format(KVisitAttributeValueL,iNodeIndex);
	iObserver->LogInfo(bb);

    switch (lSerialPortAttributeList[iNodeIndex].iAction)
        {
	case EAttrItemCheckType:	// just check the type is as expected
		if (lSerialPortAttributeList[iNodeIndex].iElementType!=aType)
	        User::Leave(KErrGeneral);
        break;
    case EAttrItemCheckTypeAndValue: // check type and values are as expected
		if (lSerialPortAttributeList[iNodeIndex].iElementType!=aType)
	        User::Leave(KErrGeneral);
		// check value is as expected
		switch (aValue.Type())
			{
        case ETypeUint:
            if (aValue.Uint()!=(TUint)lSerialPortAttributeList[iNodeIndex].iValue)
                User::Leave(KErrArgument);
            break;
        case ETypeInt:
            if (aValue.Int()!=lSerialPortAttributeList[iNodeIndex].iValue)
                User::Leave(KErrArgument);
            break;
        case ETypeBoolean:
            if (aValue.Bool()!=lSerialPortAttributeList[iNodeIndex].iValue)
                User::Leave(KErrArgument);
            break;
        case ETypeUUID:
            if (aValue.UUID()!=TUUID(lSerialPortAttributeList[iNodeIndex].iValue))
                User::Leave(KErrArgument);
            break;
        default: // either not supported or bad
            break;
			}
        break;
    case EAttrItemCheckEnd:
	case EAttrItemFinished: // too many items in list
        User::Leave(KErrGeneral);
        break;
    case EAttrItemReadValue: // check type is as expected and read remote value
		if (lSerialPortAttributeList[iNodeIndex].iElementType!=aType)
	        User::Leave(KErrGeneral);
		iExtractedValue=aValue.Uint();	// possibly found the remote port info

		// report some info
		_LIT(KEAttrItemReadValue,"EAttrItemReadValue: %d");
		bb.Format(KEAttrItemReadValue,iExtractedValue);
		iObserver->LogInfo(bb);
        break;
    default:
        break;
        }
    NextNodeL();
	}

void CBtConnectionCreator::StartListL(CSdpAttrValueList& aList)
	{
	}

void CBtConnectionCreator::EndListL()
	{
    if (lSerialPortAttributeList[iNodeIndex].iAction!=EAttrItemCheckEnd)
        User::Leave(KErrGeneral);
    NextNodeL();
	}

void CBtConnectionCreator::NextRecordRequestComplete(
// Called back by the iSdpAgent as its found a next record
    TInt aError, 
    TSdpServRecordHandle aHandle, 
    TInt aTotalRecordsCount)
    {
    if (aError==KErrEof) // scanned all records - see if found the data were looking for
		{
		TBuf<32>bb;
		_LIT(KErrEof,"KErrEof %d");
		bb.Format(KErrEof,iRemotePort);
		iObserver->LogInfo(bb);

		RequestComplete(iRemotePort==(-1)?KErrNotFound:KErrNone);
		}
	else if (aTotalRecordsCount==0)
		RequestComplete(KErrNotFound);
	else if (aError!=KErrNone)
		RequestComplete(aError);
	else
		{ // we want attributes of the record
		TRAPD(err,iSdpAgent->AttributeRequestL(aHandle,KSdpAttrIdProtocolDescriptorList));
		if (err!=KErrNone)
			RequestComplete(err);
		}
    }

void CBtConnectionCreator::AttributeRequestResult(
// Called back by the iSdpAgent as its found answer to the AttributeRequestL()
    TSdpServRecordHandle aHandle, 
    TSdpAttributeID aAttrID, 
    CSdpAttrValue* aAttrValue)
    {
	iNodeIndex=0; // scan that set of attribute/values from the start
	TRAPD(err,aAttrValue->AcceptVisitorL(*this));
	if (err!=KErrNone)
		RequestComplete(err); // couldnt run AcceptVisitorL()
	else if (lSerialPortAttributeList[iNodeIndex].iAction==EAttrItemFinished)
		{
        iRemotePort=iExtractedValue; // reached end of struct + all as expected - so this is the port

		TBuf<32>bb;
		_LIT(KPortIndex,"Port %d, Index %d");
		bb.Format(KPortIndex,iRemotePort,iNodeIndex);
		iObserver->LogInfo(bb);
		}
    }

void CBtConnectionCreator::AttributeRequestComplete(TSdpServRecordHandle aHandle,TInt aError)
// Called back by the iSdpAgent when weve finished processing the SDP record in AttributeRequestResult()
    {
	if (aError==KErrNone)
		{
		TRAP(aError,iSdpAgent->NextRecordRequestL()); // get next SDP record + see if its got our info
		}

	// deal with errors via 'completion' of the outstanding request
	if (aError!=KErrNone)
		RequestComplete(aError);
    }

void CBtConnectionCreator::RunL()
// Something has happened, see what state were in + thus whats happened
	{
	switch (iState)
		{
	case ECreatorStateFindService:
		// weve finished with these components
		delete(iSdpAgent);
		iSdpAgent=NULL;
		delete(iSdpSearchPattern);
		iSdpSearchPattern=NULL;

		if (iStatus.Int()==KErrNone)
			{	// weve sucessfully discovered the remote port
			__ASSERT_DEBUG(iRemotePort!=(-1),Panic(0));
			Connect();
			}
		else
			{ // report we failed to connect
			iObserver->StatusInfo(EBtsConnectionEstablished,iStatus.Int());
			iState=ECreatorStateIdle;
			}
		break;

	case ECreatorStateConnecting:
		if (iStatus.Int()==KErrNone)
			{ // sucessfully connected to remote, can now send/recv data
			iState=ECreatorStateConnected;
			Read(); // get any data thats sent to us
			iObserver->StatusInfo(EBtsConnectionEstablished,KErrNone);
			}
		else
			{ // failed to connect
			iObserver->StatusInfo(EBtsConnectionEstablished,iStatus.Int());
			iState=ECreatorStateIdle;
			}
		break;

	case ECreatorStateConnected:	// data arrived for us to process
		if (iReadingState==EReadingHeader)
			{
			TInt error=iStatus.Int();
			if (error==KErrNone)
				{ // weve got the hdr, ensure its correct content, if so get main body
				TPtr8 q((TUint8*)iFrameHdr.Ptr(),5,5);
				if (q==KBluetoothHeaderText)
					{
					ReadContent(); // get the frame proper
					break;
					}
				error=KErrCorrupt;
				}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -