diff -r 000000000000 -r 29b1cd4cb562 bthci/bthci2/hctl/src/hctluartbase.cpp --- /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 +#include + +#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(static_cast(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(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(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; + }