commands/btservices/btservices.cpp
changeset 0 7f656887cf89
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commands/btservices/btservices.cpp	Wed Jun 23 15:52:26 2010 +0100
@@ -0,0 +1,646 @@
+// btservices.cpp
+// 
+// Copyright (c) 2009 - 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 <e32std.h>
+#include <BTExtNotifiers.h>
+
+#include <fshell/common.mmh>
+#include <fshell/ioutils.h>
+using namespace IoUtils;
+
+#include "BtServicesEng.h"
+#include "BtServiceView.h"
+
+class CBTEngSettings;
+
+#if FSHELL_PLATFORM_S60 >= 5
+// This is an S60-only API
+#define SUPPORT_ONOFF
+#endif
+
+#ifdef SUPPORT_ONOFF
+#include <btengsettings.h>
+#endif
+
+CBtServiceView::CBtServiceView()
+	{
+	}
+
+CBtServiceView::~CBtServiceView()
+	{
+	}
+
+void CBtServiceView::PrintTextMsg(TInt /*aVerboseLevel*/, const TDesC& /*aMsg*/)
+	{
+	}
+
+void CBtServiceView::AsyncCompleted()
+	{
+	}
+
+class CCmdBtsvc : public CCommandBase, public CBtServiceView 
+	{
+public:
+	static CCommandBase* NewLC();
+	~CCmdBtsvc();
+private:
+	CCmdBtsvc();
+	void DoScanDeviceL();
+	void DoListServiceL();
+	void DoAttributeL();
+	void DoLocalL();
+	void DoListUuidFilterL();
+	void SelectBTDeviceL(TBTDeviceName& aName, TBTDevAddr& aBDAddr, TBTDeviceClass& aDevClass);
+	TBool GetBTDevClassFromRegistryL(TBTDevAddr& aBDAddr, TBTDeviceClass& aDevClass);
+
+#ifdef SUPPORT_ONOFF
+	void SetEnabledL(TBool aEnable);
+	void ShowStatusL();
+	TBool GetPowerStateL();
+#endif
+
+private: // From CCommandBase.
+	virtual const TDesC& Name() const;
+	virtual void DoRunL();
+	virtual void ArgumentsL(RCommandArgumentList& aArguments);
+	virtual void OptionsL(RCommandOptionList& aOptions);
+	
+private:
+	virtual void PrintTextMsg(TInt aVerboseLevel, const TDesC& aMsg);
+	virtual void AsyncCompleted();
+
+private:
+	CBtServicesEng* iEngine; 
+	CActiveSchedulerWait* iActiveWait;
+	RArray<TBool> iVerbose;
+	
+	HBufC* iOptBTAddr;
+	HBufC* iOptSvcHandle;	//service handle
+	HBufC* iOptUuidFilter;	//uuid filter
+	
+	enum TBtSvcCmd
+		{
+		ECmdDevice,
+		ECmdService,
+		ECmdAttribute,
+		ECmdLocal,
+		ECmdUuid,
+		ECmdStatus,
+		ECmdEnable,
+		ECmdDisable,
+		};
+	
+	TBtSvcCmd iCommand;
+
+	CBTEngSettings* iSettings;
+	};
+
+CCommandBase* CCmdBtsvc::NewLC()
+	{
+	CCmdBtsvc* self = new(ELeave) CCmdBtsvc();
+	CleanupStack::PushL(self);
+	self->BaseConstructL();
+	return self;
+	}
+
+CCmdBtsvc::CCmdBtsvc()
+	{
+	iActiveWait = new (ELeave) CActiveSchedulerWait;
+	}
+
+
+CCmdBtsvc::~CCmdBtsvc()
+	{
+#ifdef SUPPORT_ONOFF
+	delete iSettings;
+#endif
+
+	delete iOptBTAddr;
+	delete iOptSvcHandle;
+	delete iOptUuidFilter;
+	delete iActiveWait;
+	delete iEngine;
+	iVerbose.Close();
+	}
+
+void CCmdBtsvc::PrintTextMsg(TInt aVerboseLevel, const TDesC& aMsg)
+	{
+	TInt VerboseLevel = iVerbose.Count();
+	if (aVerboseLevel <= VerboseLevel)
+		Printf(aMsg);
+	}
+
+void CCmdBtsvc::AsyncCompleted()
+	{
+	if (iActiveWait->IsStarted())
+		{
+		iActiveWait->AsyncStop();
+		}
+	}
+
+const TDesC& CCmdBtsvc::Name() const
+	{
+	_LIT(KName, "btservices");
+	return KName;
+	}
+
+void CCmdBtsvc::ArgumentsL(RCommandArgumentList& aArguments)
+	{
+	_LIT(KArgCommand, "command");
+	aArguments.AppendEnumL((TInt&)iCommand, KArgCommand);
+	}
+
+void CCmdBtsvc::OptionsL(RCommandOptionList& aOptions)
+	{		
+	aOptions.AppendStringL(iOptBTAddr, _L("address"));
+	aOptions.AppendStringL(iOptSvcHandle, _L("record"));
+	aOptions.AppendStringL(iOptUuidFilter, _L("uuid"));		
+	aOptions.AppendBoolL(iVerbose, _L("verbose"));
+	}
+
+void CCmdBtsvc::DoRunL()
+	{
+	switch (iCommand)
+		{
+		case ECmdDevice:
+			DoScanDeviceL();
+			break;
+		case ECmdService:
+			DoListServiceL();
+			break;
+		case ECmdAttribute:
+			DoAttributeL();
+			break;
+		case ECmdLocal:
+			DoLocalL();
+			break;
+		case ECmdUuid:
+			DoListUuidFilterL();
+			break;
+#ifdef SUPPORT_ONOFF
+		case ECmdStatus:
+			ShowStatusL();
+			break;
+		case ECmdEnable:
+			SetEnabledL(ETrue);
+			break;
+		case ECmdDisable:
+			SetEnabledL(EFalse);
+			break;
+#endif
+		default:	
+			LeaveIfErr(KErrArgument, _L("Invalid command"));
+		}
+	}
+
+void CCmdBtsvc::DoAttributeL()
+	{
+	TInt err;
+		
+	//if want to query full attribute set of one particular service,
+	//call CBtServicesEng::GetAttributesL()
+	if (iOptSvcHandle && iOptSvcHandle->Length())
+		{
+		iEngine = CBtServicesEng::NewL();
+		iEngine->SetView(this);
+		
+		iEngine->CancelSdpAgent();
+		iEngine->DeleteSdpAgent();
+		
+		err = iEngine->BluetoothReady();
+		LeaveIfErr(err, _L("Bluetooth not ready"));
+				
+		TBTDeviceName Name; 
+		TBTDevAddr BDAddr;
+		TBTDeviceClass DevClass;
+			
+		//iOptSvcHandle should begin with "0x" (hex)
+		if ((iOptSvcHandle->Left(2))==_L("0x"))
+			{
+			TSdpServRecordHandle Handle;
+			TLex lex(*iOptSvcHandle);
+			lex.SkipAndMark(2);
+			err = lex.Val(Handle, EHex);
+			LeaveIfErr(err, _L("Service Handle:\"%S\" is not in valid format"), iOptSvcHandle);
+		
+			SelectBTDeviceL(Name, BDAddr, DevClass);
+			Printf(_L("==============================================\r\n"));
+			
+			iEngine->GetDeviceAttributesL(BDAddr, Name, Handle);
+			
+			//wait for results
+			iActiveWait->Start();
+									
+			}
+		else
+			LeaveIfErr(KErrArgument, _L("Service Handle:\"%S\" is not in valid format"), iOptSvcHandle);		
+		}
+	else
+		LeaveIfErr(KErrArgument, _L("use -r to specify a service record handle"));
+	}
+
+
+//do a BT device scan with RHostResolver,
+//and make a list of BT addresses, device name, and device class
+//
+void CCmdBtsvc::DoScanDeviceL()
+	{
+	TInt err;
+	TInt ItemsFound = 0;
+	TBTDevAddr BDAddr;
+	TBTDeviceName Name;
+	TBTDeviceClass DevClass;
+	
+	Printf(_L("Scanning for BT devices ...\r\n"));
+		
+	RSocketServ SktSrv;
+	CleanupClosePushL(SktSrv);
+	
+	err = SktSrv.Connect();
+	LeaveIfErr(err, _L("Could not connect to socket server"));
+	
+	RHostResolver Host;
+	CleanupClosePushL(Host);
+	RHostResolver HostForName;
+	CleanupClosePushL(HostForName);
+	
+	TProtocolDesc ProtocolInfo;
+	err = SktSrv.FindProtocol(_L("BTLinkManager"), ProtocolInfo);
+	User::LeaveIfError(err);
+	
+	err = Host.Open(SktSrv, ProtocolInfo.iAddrFamily , ProtocolInfo.iProtocol);
+	LeaveIfErr(err, _L("Could not open host resolver"));
+	err = HostForName.Open(SktSrv, ProtocolInfo.iAddrFamily , ProtocolInfo.iProtocol);
+	LeaveIfErr(err, _L("Could not open host resolver"));
+	
+	TInquirySockAddr Inq;	
+	Inq.SetIAC(KGIAC);
+	Inq.SetAction(KHostResInquiry/*|KHostResIgnoreCache*/);
+	
+	
+	TNameEntry Result;
+	err = Host.GetByAddress(Inq, Result);
+	
+	//this is for querying name
+	TInquirySockAddr InqName;	
+	InqName.SetAction(KHostResName);
+	TNameEntry ResultName;
+	
+	Printf(_L("========================================================\r\n"));
+	Printf(_L("BTAddr         | DeviceClass| Name\r\n"));
+	Printf(_L("========================================================\r\n"));
+	
+	while(1)
+		{
+		if (err == KErrNone)
+			{
+			ItemsFound++;
+			TInquirySockAddr& sa = TInquirySockAddr::Cast(Result().iAddr);
+			const TBTDevAddr& bdaddr = sa.BTAddr();
+			BDAddr = bdaddr;
+			Name = Result().iName;
+			
+			TUint16 MajorServiceClass = sa.MajorServiceClass(); 
+			DevClass = TBTDeviceClass(
+					MajorServiceClass, sa.MajorClassOfDevice(), sa.MinorClassOfDevice() );
+			
+			TBuf<128> BTReadAddress;
+			BDAddr.GetReadable(BTReadAddress);
+			
+			//query its name
+			InqName.SetBTAddr(bdaddr);
+			err = HostForName.GetByAddress(InqName, ResultName);			
+			if (err==KErrNone)
+				Name = ResultName().iName;
+			else
+				Name.Format(_L("Unable to get the name, err=%d"), err);
+			
+			Printf(_L("0x%S | 0x%08x | \"%S\" \r\n"), 
+					&BTReadAddress, DevClass.DeviceClass(), &Name);
+								
+			err = Host.Next(Result);
+			}
+		else if (err == KErrEof)
+			{
+			break;
+			}
+		else
+			LeaveIfErr(err, _L("Resolving address failed"));
+		}
+	CleanupStack::PopAndDestroy();
+	CleanupStack::PopAndDestroy();
+	CleanupStack::PopAndDestroy();
+	
+	Printf(_L("%d devices found\r\n"),ItemsFound);
+	}
+
+//NOT TESTED YET, do not use
+//aBDAddr:[in]
+//aDevClass:[out]	
+TBool CCmdBtsvc::GetBTDevClassFromRegistryL(TBTDevAddr& aBDAddr, TBTDeviceClass& aDevClass)
+	{
+	TInt err;
+	
+	TBuf<128> buf;
+	aBDAddr.GetReadable(buf);
+	Printf(_L("Query DeviceClass for BTAddr:0x%S\r\n"), &buf);
+	
+	RBTRegServ Srv;
+	CleanupClosePushL(Srv);
+	err = Srv.Connect();
+	User::LeaveIfError(err);
+	
+	RBTRegistry Reg;
+	CleanupClosePushL(Reg);
+	err = Reg.Open(Srv);
+	User::LeaveIfError(err);
+
+	TBTNamelessDevice Dev;
+	Dev.SetAddress(aBDAddr);
+	
+	TRequestStatus status;
+	Reg.GetDevice(Dev, status);
+	User::WaitForRequest(status);
+	
+	err = status.Int();
+	User::LeaveIfError(err);
+	
+	if (err == KErrNone )
+		{
+		aDevClass = Dev.DeviceClass();		
+		}
+	
+	CleanupStack::PopAndDestroy();	
+	CleanupStack::PopAndDestroy();	
+	
+	return ETrue;
+	}
+
+//select a BT device either from RNotifier, 
+//or using BT address string if it is specified
+//aName: [out]
+//aBDAddr: [out]
+//aDevClass: [out]
+void CCmdBtsvc::SelectBTDeviceL(TBTDeviceName& aName, TBTDevAddr& aBDAddr, TBTDeviceClass& aDevClass)
+	{
+	TInt err;
+	if (iOptBTAddr && iOptBTAddr->Length()>0)
+		//use RHostResolver to get name and device class
+		{
+		Printf(_L("Querying name for \"%S\"...\r\n"), iOptBTAddr);
+			
+		RSocketServ SktSrv;
+		CleanupClosePushL(SktSrv);
+		
+		err = SktSrv.Connect();
+		LeaveIfErr(err, _L("Could not connect to socket server"));
+		
+		RHostResolver Host;
+		CleanupClosePushL(Host);
+		
+		TProtocolDesc ProtocolInfo;
+		err = SktSrv.FindProtocol(_L("BTLinkManager"), ProtocolInfo);
+		User::LeaveIfError(err);
+		
+		err = Host.Open(SktSrv, ProtocolInfo.iAddrFamily , ProtocolInfo.iProtocol);
+		LeaveIfErr(err, _L("Could not open host resolver"));
+		
+		TBTDevAddr Addr;
+		err = Addr.SetReadable(*iOptBTAddr);
+		LeaveIfErr(err, _L("User-input BT address invalid"));
+				
+		TInquirySockAddr Inq;	
+		Inq.SetAction(KHostResName);
+		Inq.SetBTAddr(Addr);	
+		
+		TNameEntry Result;
+		err = Host.GetByAddress(Inq, Result);
+		if (err == KErrNone)
+			{
+			TInquirySockAddr& sa = TInquirySockAddr::Cast(Result().iAddr);
+			const TBTDevAddr& bdaddr = sa.BTAddr();
+			aBDAddr = bdaddr;
+			aName = Result().iName;
+						
+			TUint16 MajorServiceClass = sa.MajorServiceClass(); 
+			aDevClass = TBTDeviceClass(
+					MajorServiceClass, sa.MajorClassOfDevice(), sa.MinorClassOfDevice() );			
+			}
+		else
+			LeaveIfErr(err, _L("Resolving address failed"));		
+		
+		CleanupStack::PopAndDestroy();
+		CleanupStack::PopAndDestroy();
+		
+		TBuf<128> AddressStr;
+		aBDAddr.GetReadable(AddressStr);
+		Printf(_L("Device \"%S\" BTAddr:0x%S\r\n"), 
+				&aName, &AddressStr);		
+		}
+	else
+		//use RNotifier to select a BT device
+		{
+		//about the search device, prompting user about curret status
+		Printf(_L("Searching Bluetooth device through RNotifier,\r\nplease go to main UI screen to select a device...\r\n"));
+		
+		////////////////////////////////////////////
+		RNotifier noti;
+		User::LeaveIfError(noti.Connect());
+
+		// 2. Start the device selection plug-in
+		TBTDeviceSelectionParams selectionFilter;
+		//TUUID targetServiceClass(0x2345);
+		//selectionFilter.SetUUID(targetServiceClass);
+		TBTDeviceSelectionParamsPckg pckg(selectionFilter);
+		TBTDeviceResponseParams result;
+		TBTDeviceResponseParamsPckg resultPckg(result);
+		TRequestStatus status;
+		noti.StartNotifierAndGetResponse(status, KDeviceSelectionNotifierUid, pckg, resultPckg);
+		User::After(2000000);
+
+		// 3. Extract device name if it was returned
+		User::WaitForRequest(status);
+
+		if (status.Int() == KErrNone)
+		    {
+		    if (resultPckg().IsValidDeviceName() &&
+		    	resultPckg().IsValidBDAddr() &&
+		    	resultPckg().IsValidDeviceClass()
+		    	)
+		        {
+		        aName = (resultPckg().DeviceName());	        
+		        aBDAddr = resultPckg().BDAddr();
+		        aDevClass = resultPckg().DeviceClass();
+		        
+		        }
+		    }
+		    
+		    
+		// 4. Clean up
+		noti.CancelNotifier(KDeviceSelectionNotifierUid);
+		noti.Close();		
+		
+		TBuf<128> AddressStr;
+		aBDAddr.GetReadable(AddressStr);
+		Printf(_L("Device \"%S\" BTAddr:0x%S DeviceClass:0x%08X\r\n"), 
+				&aName, &AddressStr, aDevClass.DeviceClass());		
+		
+		}	
+	}
+
+
+//search and make a list of results
+void CCmdBtsvc::DoListServiceL()
+	{
+	TInt VerboseLevel = iVerbose.Count();
+	
+	if (VerboseLevel >= 2)
+		Printf(_L("calling CBtServicesEng::NewL() ...\r\n"));
+	
+	iEngine = CBtServicesEng::NewL();
+	
+	
+	if (VerboseLevel >= 2)
+		Printf(_L("calling CBtServicesEng::SetView()... iEngine=0x%08x\r\n"), 
+				iEngine);
+	
+	iEngine->SetView(this);
+	
+	if (VerboseLevel >= 2)
+		Printf(_L("calling CBtServicesEng::CancelSdpAgent()...\r\n"));
+	iEngine->CancelSdpAgent();
+
+	if (VerboseLevel >= 2)
+		Printf(_L("calling CBtServicesEng::DeleteSdpAgent()...\r\n"));	
+	iEngine->DeleteSdpAgent();
+	
+	TInt err = iEngine->BluetoothReady();
+	LeaveIfErr(err, _L("Bluetooth not ready"));
+
+	TBTDeviceName Name; 
+	TBTDevAddr BDAddr;
+	TBTDeviceClass DevClass;
+	
+	SelectBTDeviceL(Name, BDAddr, DevClass);
+	
+	//see if user has specified a UUID filter
+	if (iOptUuidFilter && iOptUuidFilter->Length())
+		{
+		TUint32 uuid;
+		if ((iOptUuidFilter->Left(2))==_L("0x"))
+			{
+			TLex lex(*iOptUuidFilter);
+			lex.SkipAndMark(2);
+			err = lex.Val(uuid, EHex);
+			if (err==KErrNone)
+				{
+				iEngine->SetUUIDFilterL(uuid);
+				goto QueryService;
+				}
+			}
+		
+			//the UUID could be in string form.
+			TBool Match = iEngine->StringToUUID(*iOptUuidFilter, uuid);
+			if (Match==EFalse)
+				{
+				Printf(_L("UUID filter not recognised. Ignored\r\n"));
+				}
+		}
+		
+QueryService:	
+	iEngine->NewDeviceSelectedL(BDAddr, Name);		
+	iActiveWait->Start();
+	
+	iEngine->MakeTextServiceList();	
+	
+	//test code: just to test if attributes query is OK	
+	//iEngine->GetAttributesL(0);
+	//iActiveWait->Start();
+	
+	}
+
+void CCmdBtsvc::DoLocalL()
+	{
+	TInt err;
+	iEngine = CBtServicesEng::NewL();
+	iEngine->SetView(this);
+	
+	iEngine->CancelSdpAgent();
+	iEngine->DeleteSdpAgent();
+	
+	err = iEngine->BluetoothReady();
+	LeaveIfErr(err, _L("Bluetooth not ready"));
+	
+	iEngine->DisplayLocalInfoL();
+	
+	}
+
+
+//make a list of UUID filters, values and strings  
+void CCmdBtsvc::DoListUuidFilterL()
+	{
+	TInt err;
+	iEngine = CBtServicesEng::NewL();
+	iEngine->SetView(this);
+	
+	iEngine->CancelSdpAgent();
+	iEngine->DeleteSdpAgent();
+	
+	err = iEngine->BluetoothReady();
+	LeaveIfErr(err, _L("Bluetooth not ready"));
+	
+	
+	iEngine->MakeTextUUIDList();
+	}
+
+	
+EXE_BOILER_PLATE(CCmdBtsvc)
+
+#ifdef SUPPORT_ONOFF
+
+TBool CCmdBtsvc::GetPowerStateL()
+	{
+	if (!iSettings)
+		{
+		TRAPL(iSettings = CBTEngSettings::NewL(NULL), _L("Couldn't construct CBTEngSettings"));
+		}
+	TBTPowerStateValue state;
+	LeaveIfErr(iSettings->GetPowerState(state), _L("Couldn't read BT power state"));
+	return state == EBTPowerOn;
+	}
+
+void CCmdBtsvc::ShowStatusL()
+	{
+	if (GetPowerStateL())
+		{
+		Printf(_L("Bluetooth is enabled.\r\n"));
+		}
+	else
+		{
+		Printf(_L("Bluetooth is disabled.\r\n"));
+		}
+	}
+
+void CCmdBtsvc::SetEnabledL(TBool aEnable)
+	{
+	TBool on = GetPowerStateL();
+	if (on && !aEnable)
+		{
+		LeaveIfErr(iSettings->SetPowerState(EBTPowerOff), _L("Couldn't set power state"));
+		}
+	else if (!on && aEnable)
+		{
+		LeaveIfErr(iSettings->SetPowerState(EBTPowerOn), _L("Couldn't set power state"));
+		}
+	}
+
+#endif