// 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 "hctlti.h"#include "hctltisender.h"#include "hctltireceiver.h"#include "controllermanager.h"#include "hctltiutils.h"#include <bluetooth/hci/hctleventobserver.h>#include <bluetooth/hci/hctldataobserver.h>#include <bluetooth/hci/hctlchannelobserver.h>#include <bluetooth/logger.h>#ifdef __FLOG_ACTIVE_LIT8(KLogComponent, LOG_COMPONENT_HCTL_TI);#endifCHCTLTi::CHCTLTi() { LOG_FUNC }CHCTLTi::~CHCTLTi() { LOG_FUNC HCI_LOG_UNLOAD(this); delete iReceiver; delete iSender; delete iControllerMan; }CHCTLTi* CHCTLTi::NewL() { LOG_STATIC_FUNC CHCTLTi* self = new(ELeave) CHCTLTi(); CleanupStack::PushL(self); self->ConstructL(); CleanupStack::Pop(); return self; }void CHCTLTi::ConstructL() { LOG_FUNC HCI_LOG_LOADL(this, KHCILoggerDatalinkTypeH4); // Initialises iSender and iReceiver via the PortOpenedL method. BaseConstructL(KIniFileName()); iControllerMan = CControllerManager::NewL(*this); }TAny* CHCTLTi::Interface(TUid aUid) { LOG_FUNC TAny* ret = NULL; switch(aUid.iUid) { case KHCTLInterfaceUid: ret = reinterpret_cast<TAny*>(static_cast<MHCTLInterface*>(this)); break; case KHCTLPowerInterfaceUid: ret = reinterpret_cast<TAny*>(static_cast<MHCTLPowerInterface*>(iControllerMan)); break; case KHctlConfigInterfaceUid: ret = reinterpret_cast<TAny*>(static_cast<MHctlConfigInterface*>(this)); break; case KHCHardResetUid: ret = reinterpret_cast<TAny*>(static_cast<MHardResetInitiator*>(this)); break; default: break; } return ret; }void CHCTLTi::DoConfigL() { LOG_FUNC Port().ResetBuffers(); TCommConfig conf; Port().Config(conf); // Get reference to TCommConfig config TCommConfigV01& config = conf(); // Set Config to 8bit char, 1 stop bit and no parity config.iDataBits = EData8; config.iStopBits = EStop1; config.iParity = EParityNone; config.iParityError = KConfigParityErrorIgnore; config.iHandshake = KConfigObeyCTS; LEAVEIFERRORL(Port().SetConfig(conf)); // allows HC to talk back to us! Port().SetSignals(KSignalRTS, KSignalDTEInputs); }//Implementation of pure virtuals from MHCTLInterfaceTInt CHCTLTi::MhiWriteAclData(const TDesC8& aData) { LOG_FUNC TInt rerr = KErrNotReady; // Send if the power is on. if(iCurrentPowerState == EBTOn) { // Add the packet indicator to the first byte of the buffer. SetPacketIndicator(EACLDataPacket, aData); rerr = iSender->Write(aData); HCI_LOG_FRAME_IF_NO_ERROR(rerr, this, KHCILoggerHostToController | KHCILoggerACLDataFrame, aData); } return rerr; }TInt CHCTLTi::MhiWriteSynchronousData(const TDesC8& aData) { LOG_FUNC TInt rerr = KErrNotReady; // Send if the power is on. if(iCurrentPowerState == EBTOn) { // Add the packet indicator to the first byte of the buffer. SetPacketIndicator(ESynchronousDataPacket, aData); rerr = iSender->Write(aData); HCI_LOG_FRAME_IF_NO_ERROR(rerr, this, KHCILoggerHostToController | KHCILoggerSynchronousDataFrame, aData); } return rerr; }TInt CHCTLTi::MhiWriteCommand(const TDesC8& aData) { LOG_FUNC TInt rerr = KErrNotReady; // Send if the power is on. if(iCurrentPowerState == EBTOn) { // Add the packet indicator to the first byte of the buffer. SetPacketIndicator(ECommandPacket, aData); rerr = iSender->Write(aData); HCI_LOG_FRAME_IF_NO_ERROR(rerr, this, KHCILoggerHostToController | KHCILoggerCommandOrEvent, aData); } return rerr; }void CHCTLTi::MhiSetQdpPluginInterfaceFinder(MQdpPluginInterfaceFinder& aQdpPluginInterfaceFinder) { iQdpPluginInterfaceFinder = &aQdpPluginInterfaceFinder; }void CHCTLTi::MhriStartHardReset() { __ASSERT_DEBUG(iControllerMan, PANIC(KTiPanic, ENoControllerManager)); iControllerMan->HardReset(); }void CHCTLTi::MhiGetAclDataTransportOverhead(TUint& aHeaderSize, TUint& aTrailerSize) const { // Return the transport overhead for ACL data. aHeaderSize = KHCTLAclDataHeaderSize; aTrailerSize = KHCTLAclDataTrailerSize; }void CHCTLTi::MhiGetSynchronousDataTransportOverhead(TUint& aHeaderSize, TUint& aTrailerSize) const { // Return the transport overhead for Synchronous data. aHeaderSize = KHCTLSynchronousDataHeaderSize; aTrailerSize = KHCTLSynchronousDataTrailerSize; }void CHCTLTi::MhiGetCommandTransportOverhead(TUint& aHeaderSize, TUint& aTrailerSize) const { // Return the transport overhead for HCI commands data. aHeaderSize = KHCTLCommandHeaderSize; aTrailerSize = KHCTLCommandTrailerSize; }/**This function is used by the receiver for informing HCI that ACL data has been receivedThe receiver doesn't have reference to iDataObserver. So this is merely a wrapper for iDataObserver*/void CHCTLTi::ProcessACLData(const TDesC8& aData) { iDataObserver->MhdoProcessAclData(aData); }/**This function is used by the receiver for informing HCI that Synchronous data has been receivedThe receiver doesn't have reference to iDataObserver. So this is merely a wrapper for iDataObserver*/void CHCTLTi::ProcessSynchronousData(const TDesC8& aData) { iDataObserver->MhdoProcessSynchronousData(aData); }/**This function is used by the receiver for informing HCI that event has been receivedThe receiver doesn't have reference to iEventObserver. So this is merely a wrapper for iDataObserver*/ void CHCTLTi::ProcessEvent(const TDesC8& aEvent) { iEventObserver->MheoProcessEvent(aEvent); }/**QdpPluginInterfaceFinder getter.@return returns iQdpPluginInterfaceFinder which could be NULL if it has not been given one.*/MQdpPluginInterfaceFinder* CHCTLTi::QdpPluginInterfaceFinder() { return iQdpPluginInterfaceFinder; }/**Sets the packet type indicator at the begining of the HCI packet.Hence the HC can recognise whether this packet is a command, ACL/SCO data.The packet preamble/indication is different between different HCTL implementations and are totally dependent upon the meduim used (UART, R2232 etc).*//*static*/ void CHCTLTi::SetPacketIndicator(THctlPacketType aType, const TDesC8& aData) { LOG_STATIC_FUNC TUint8* ptr = const_cast<TUint8*>(aData.Ptr()); *ptr = static_cast<TUint8>(aType); }// Implementation of pure virtual from CHCTLUartBasevoid CHCTLTi::PortOpenedL() { LOG_FUNC __ASSERT_DEBUG(Port().Handle(), PANIC(KTiPanic, EPortNotOpen)); if (iSender || iReceiver) { LEAVEIFERRORL(KErrAlreadyExists); } DoConfigL(); iCurrentPowerState = EBTOn; // The sender Active Object must be added to the Active Scheduler before // the receiver Active Object so that it gets preferential treatment. It // is reported that otherwise the response from a command can come in // before the sending client is told that the send has completed! iSender = CHCTLTiSender::NewL(Port()); iReceiver = CHCTLTiReceiver::NewL(*this, Port()); // Start reading from the UART iReceiver->Start(); }void CHCTLTi::MhiSetDataObserver(MHCTLDataObserver& aDataObserver) { iDataObserver = &aDataObserver; }void CHCTLTi::MhiSetEventObserver(MHCTLEventObserver& aEventObserver) { iEventObserver = &aEventObserver; }void CHCTLTi::MhiSetChannelObserver(MHCTLChannelObserver& aChannelObserver) { iChannelObserver = &aChannelObserver; iSender->SetChannelObserver(aChannelObserver); }void CHCTLTi::MhiSetControllerStateObserver(MControllerStateObserver& aControllerStateObserver) { iControllerStateObserver = &aControllerStateObserver; iControllerMan->SetControllerStateObserver(aControllerStateObserver); }void CHCTLTi::HandlePowerOff() { iCurrentPowerState = EBTOff; // Close all channels and cancel the sender and receiver. iSender->Cancel(); iReceiver->Cancel(); iChannelObserver->MhcoChannelClosed(KHCITransportAllChannels); }void CHCTLTi::HandlePowerOn() { iCurrentPowerState = EBTOn; iChannelObserver->MhcoChannelOpen(KHCITransportAllChannels); // Clear any spurious data from the buffer. Port().ResetBuffers(); iReceiver->Start(); // The sender will be activated when the first frame needs to be sent. }TBTPowerState CHCTLTi::CurrentPowerState() const { return iCurrentPowerState; }TInt CHCTLTi::MhciUpdateBaudRate(TUint32 aBaudRate) { // Call the base class method to process this change. TRAPD(rerr, SetPortBaudRateL(aBaudRate)); return rerr; }