bthci/bthci2/hctl/src/hctluartbase.cpp
changeset 0 29b1cd4cb562
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bthci/bthci2/hctl/src/hctluartbase.cpp	Fri Jan 15 08:13:17 2010 +0200
@@ -0,0 +1,340 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "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:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+/**
+ @file
+ @internalComponent
+*/
+
+#include "hctluartbase.h"
+#include "btbusdevcomm.h"
+
+#include <bluetooth/logger.h>
+#include <bluetooth/hci/hciutil.h>
+
+#ifdef __FLOG_ACTIVE
+_LIT8(KLogComponent, LOG_COMPONENT_HCTL_BASE);
+#endif
+
+EXPORT_C CHCTLUartBase::CHCTLUartBase()
+	{
+	LOG_FUNC
+	}
+
+EXPORT_C CHCTLUartBase::~CHCTLUartBase()
+	{
+	LOG_FUNC
+	if (iPort)
+		{
+		iPort->Close();
+		delete iPort;
+		}
+	}
+
+/**
+	Common method used by UART derivative HCTLs to check hardware is connected
+*/
+EXPORT_C TBool CHCTLUartBase::CheckHardwareConnected()
+	{
+	LOG_FUNC
+	TBool hwPresent = ETrue;
+
+	LOG1(_L8("\tsignals = 0x%02x"), iPort->Signals());
+
+	// If there are currently no signals assume the HW is not connected.
+	if(!iPort->Signals())
+		{
+		hwPresent = EFalse;
+
+		TRequestStatus lineStatus;
+		TRequestStatus timeStatus;
+
+		TUint testSignals;
+		RTimer timer;
+
+		TInt err = timer.CreateLocal();
+		if(err == KErrNone)
+			{
+			iPort->NotifySignalChange(lineStatus, testSignals);
+			timer.After(timeStatus, 5000000); // 5s
+			
+			User::WaitForRequest(lineStatus, timeStatus); // so we don't wait forever
+			
+			if (timeStatus.Int() == KErrNone)
+				{
+				// The guard timer has expired.
+				iPort->NotifySignalChangeCancel();
+				User::WaitForRequest(lineStatus);	// consume the request
+				}
+			else if ( lineStatus.Int() == KErrNone)
+				{
+				// The hardware is there.  Cancel the timer.
+				timer.Cancel();
+				User::WaitForRequest(timeStatus);	// consume the request
+				hwPresent = ETrue;
+				}
+			}
+		timer.Close();
+		}
+
+	LOG1(_L8("\thwPresent = %d"), hwPresent);
+	return hwPresent;
+	}
+
+/**
+Common method used by UART derivative HCTLs to open the available physical 
+UART connections for bluetooth hardware
+*/
+void CHCTLUartBase::OpenPortL(TUint aPortNo)
+	{
+	LOG_FUNC
+	LOG1(_L8("\taPortNo = %d"), aPortNo);
+	
+	TInt ret = iPort->Open(aPortNo);
+	
+	if(ret != KErrNone && ret != KErrAlreadyExists)
+		{
+		LEAVEIFERRORL(ret);
+		}
+	}
+
+// For debug emulator environments, we provide a mechanism to cycle through possible
+// port numbers until we find a port to use (it maybe be connected to something other
+// than Bluetooth hardware, but that has to be identified at a higher level).  This meant
+// users don't have to fiddle with esk or ini files, especially for the case where they're
+// running back to back on one PC. 
+// However, this slows down emulator start-up, so it is configured by ini file which does
+// mean potentially fiddling with ini files anyway ... c'est la vie.
+#if(defined(__WINS__) && defined(_DEBUG))
+#define SYMBIAN_INTERNAL_RETRY_BLUETOOTH_PORT_OPEN
+#pragma message("If configured, Bluetooth HCTL will scan UARTs to find a connected port")
+#endif
+
+#ifndef SYMBIAN_INTERNAL_RETRY_BLUETOOTH_PORT_OPEN
+
+void CHCTLUartBase::ScanAndOpenPortL(TUint /*aStartingPortNo*/)
+	{
+	LOG_FUNC
+	LEAVEL(KErrNotSupported);
+	}
+
+#else
+
+/**
+	Common method used by UART derivative HCTLs to scan the available physical UART connections
+	for bluetooth hardware
+*/
+void CHCTLUartBase::ScanAndOpenPortL(TUint aStartingPortNo)
+	{
+	LOG_FUNC
+	LOG1(_L8("\aStartingPortNo = %d"), aStartingPortNo);
+	TUint portNo = aStartingPortNo;
+	
+	TInt ret = KErrNone;
+	
+	// This is a limit set by windows.  RBusDevComm will panic if aPortNo of 32 or higher
+	// is used.  
+	const TInt KMaxPortNumber = 32;
+	
+	while(portNo < KMaxPortNumber)
+		{
+		LOG2(_L8("\tTRYING: port %d (PC COM Port %d)"), portNo, portNo + 1);
+		ret = iPort->Open(portNo);
+		
+		if(ret == KErrNone || ret == KErrAlreadyExists)
+			{
+			if(CheckHardwareConnected())
+				{
+				LOG2(_L8("\tUSING: port %d (PC COM Port %d)"), portNo, portNo + 1);
+				// Exit the loop, a port has been opened.
+				break;
+				}
+			else 
+				{
+				iPort->Close();	// close it - there was no HW there...
+				}
+			}
+		portNo++;  // try the next port
+		}
+	
+	if(ret != KErrNone && ret != KErrAlreadyExists)
+		{
+		// A port could not be found.
+		LEAVEIFERRORL(KErrHardwareNotAvailable);
+		}
+	}
+	
+#endif // SYMBIAN_INTERNAL_RETRY_BLUETOOTH_PORT_OPEN
+
+//Implementation of pure virtuals from CHCTLBase
+EXPORT_C TAny* CHCTLUartBase::Interface(TUid aUid)
+	{
+	TAny* ret = NULL;
+	switch(aUid.iUid)
+		{
+		case KHCTLInterfaceUid:
+			ret = reinterpret_cast<TAny*>(static_cast<MHCTLInterface*>(this));
+			break;
+
+		default:
+			break;
+		};
+
+	return ret;
+	}
+
+EXPORT_C void CHCTLUartBase::BaseConstructL(const TDesC& aIniFileName)
+	{
+	LOG_FUNC
+	
+	_LIT(KSection, "hctl");
+	_LIT(KVarPort, "port");
+	_LIT(KVarBaudRate, "baud_rate");
+	_LIT(KVarPwrCtrlMode, "pwr_ctrl_mode");
+	#ifdef SYMBIAN_INTERNAL_RETRY_BLUETOOTH_PORT_OPEN
+	_LIT(KVarScanPorts, "scan_ports");
+	#endif // SYMBIAN_INTERNAL_RETRY_BLUETOOTH_PORT_OPEN
+
+	// Create HCI Utility library
+	CHciUtil* hciUtil = CHciUtil::NewL(aIniFileName);
+	CleanupStack::PushL(hciUtil);
+	
+	hciUtil->OpenIniFileL();
+
+	TUint portNumber = hciUtil->GetValueFromFileL(KSection, KVarPort);
+	TUint baudRate = hciUtil->GetValueFromFileL(KSection, KVarBaudRate);
+	
+	// we don't want to leave if the param is not present. just consider
+	// the default value as true 
+	TRAPD(err, iPowerCtrlMode = static_cast<TPowerControlDetectionMode>(hciUtil->GetValueFromFileL(KSection, KVarPwrCtrlMode)));
+	if (err != KErrNone)
+		{
+		iPowerCtrlMode = EPwrCtrlCTSTimedLow;	// keeps back compatibility
+		}
+	
+#ifdef SYMBIAN_INTERNAL_RETRY_BLUETOOTH_PORT_OPEN
+	TBool scanPorts = EFalse;
+	TRAP(err, scanPorts = static_cast<TBool>(hciUtil->GetValueFromFileL(KSection, KVarScanPorts)));
+	if(err != KErrNone)
+		{
+		scanPorts = EFalse; // default to off because of stack boot time impact
+		}
+#endif // SYMBIAN_INTERNAL_RETRY_BLUETOOTH_PORT_OPEN
+	
+	// Remove the HCI UTIL instance. 
+	CleanupStack::PopAndDestroy();
+	
+	// Allocate the RBtBusDevComm port object
+	iPort = new (ELeave) RBtBusDevComm;
+	
+#ifdef SYMBIAN_INTERNAL_RETRY_BLUETOOTH_PORT_OPEN
+	if(scanPorts)
+		{
+		ScanAndOpenPortL(portNumber);
+		}
+	else
+#endif // SYMBIAN_INTERNAL_RETRY_BLUETOOTH_PORT_OPEN
+		{
+		OpenPortL(portNumber);
+		}
+	
+	SetPortBaudRateL(baudRate);
+
+	// Perform any HCTL specific initialisation. 
+	PortOpenedL();
+	}
+
+EXPORT_C void CHCTLUartBase::SetPortBaudRateL(TUint32 aBaudRate)
+	{	
+	LOG_FUNC
+
+	TCommConfig configPkg;
+	iPort->Config(configPkg);
+	TCommConfigV01& config = configPkg(); //Get reference to TCommConfig iConfig
+
+	switch(aBaudRate)
+		{
+		case 57600:
+			config.iRate = EBps57600;
+			break;
+
+		case 115200:
+			config.iRate = EBps115200;
+			break;
+
+		case 230400:
+			config.iRate = EBps230400;
+			break;
+
+		case 460800:
+			config.iRate = EBps460800;
+			break;
+
+		case 576000:
+			config.iRate = EBps576000;
+			break;
+
+		case 750000:
+			config.iRate = EBpsSpecial;
+			config.iSpecialRate=0; // 750000;
+			break;
+
+		case 1152000:
+			config.iRate = EBps1152000;
+			break;
+
+		case 921600:
+			config.iRate = EBps921600;
+			break;
+
+		case 1843200:
+			config.iRate = EBpsSpecial;
+			config.iSpecialRate=1; // 1843200;
+			break;
+
+		case 3686400:
+		case 3692300:
+		case 3600000:
+			config.iRate = EBpsSpecial;
+			config.iSpecialRate=2; // 3686400;
+			break;
+
+		case 3000000:
+			config.iRate = EBpsSpecial;
+			config.iSpecialRate = 3;
+			break;
+
+		default:
+			// Use default rate in case of error
+			config.iRate = EBps115200;
+			break;
+		};
+	
+	// Update the port configuration.
+	LEAVEIFERRORL(iPort->SetConfig(configPkg));
+	}
+
+// Accessor method for the port
+EXPORT_C RBusDevComm& CHCTLUartBase::Port()
+	{
+	// No check for a NULL iPort is needed because BaseConstructL will Leave if we
+	// fail to allocate the port object
+	return *iPort;
+	}
+
+EXPORT_C CHCTLUartBase::TPowerControlDetectionMode CHCTLUartBase::PowerCtrlMode() const
+	{
+	return iPowerCtrlMode;
+	}