//
// * Copyright 2004 Neusoft America Inc.
// * 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".
// *
// * Contributors:
// * Keith Collins (Neusoft America Inc.) original software development and additional code and modifications.
// * Thomas Gahagen (Neusoft America Inc.) additional code and modifications.
// * Zhen Yuan (Neusoft America Inc.) additional code and modifications.
// *
// * Description: This file contains the implementation for the class CPortFactory.
// * This class is used to create C32 port interface instances.
//
// PortFactory.cpp
/** @file PortFactory.cpp
*
*/
/*! \mainpage CSY 27.010 Documentation
*
* \section intro Introduction
*
* This CSY has been designed and implemented by TapRoot Systems.
* This CSY is part of the TapRoot Systems Communications Platform (CommP)
* product family for Symbian OS. Please contact TapRoot Systems for
* information on CommP.
* <p>
* A CSY is a specialized type of DLL that implements API interfaces
* required by the C32 Serial Communications Server. "CSY" is the file
* name extension used by CSY modules as in "ecuart.csy", which is the
* name of Symbian's generic CSY for non-multiplexed serial ports.
* TapRoot Systems 27.010 CSY (gsm0701.csy) is compatible with the
* 3GPP 27.010 v5.0.0 specification.
* <p>
* The CSY has been designed and tested with the Intel Lubbock application
* processor, TI Condat baseband processor and Symbian OS 8.0a.
* The CSY is not guaranteed to work with other AP's, BP's or Symbian OS versions.
* The CSY has been integrated with Symbian OS supplied TSY and NIF IP.
* The CSY is not guaranteed to work with other TSY's and NIF's.
*
* \section feat Features
*
* The CSY supports the 27.010 Basic Option. The 3GPP 27.010 specification
* is derived from the GSM 07.10 specification. 3GPP 27.010 defines a mechanism
* whereby multiple commands and data streams can be carried over the same
* physical link. This specification defines a multiplexing protocol between
* a Terminal Equipment (TE) and a Mobile Station (MS) allowing multiple
* simultaneous sessions over a single start-stop, framed, serial link.
* Each session (channel) can carry different types of data including voice,
* fax, data, SMS, CBS, phonebook maintenance, battery status, GPRS, USSD, etc.
* <p>
* The multiplexer has three operating options, basic, advanced without error
* recovery and advanced with error recovery. CSY 27.010 supports the
* basic option. The basic option is recommended on highly reliable links.
* Advanced options are not supported by the CSY. The characteristics of the
* basic option are:
* <li> Length indicator used instead of the HDLC transparency mechanism
* <li> Different flag octet from that used by HDLC
* <li> Cannot be used on links that use XON/XOFF flow control
* <li> May have longer recovery procedure from loss of synchronization
* <p>
* Each channel between the TE and MS is called a Data Link Connection (DLC).
* A special DLC called "control channel" is used to exchange management
* information (e.g. parameter negotiation), power saving control information,
* testing, flow control, close down, etc. between the TE and MS.
* <p>
* The multiplexer is activated with the 3GPP 27.007 AT+CMUX command.
* <p>
*
* \section install Installation
*
* Refer to the readme.txt file for installation and build instructions.
* <br>
* Please contact TapRoot Systems for information on product updates and
* additional support.
*/
/** @file PortFactory.cpp
* This file contains the implementation for the class CPortFactory.
* This class is used to create C32 port interface instances.
*/
#include <cs_port.h>
#include <f32file.h>
#include <commsdattypesv1_1.h>
#include <commsdat_partner.h>
using namespace CommsDat;
#include "Portfactory.h"
#include "CsyGlobals.h"
#include "Mux0710Protocol.h"
#include "ChannelMgrCtrl.h"
#include "ChannelMgrCmdData.h"
#include "PortC32InterfaceBase.h"
#include "PortC32Interface.h"
#include "PortC32InterfaceIp.h"
#include "CommFrameWriterAo.h"
#include "CommFrameReaderAo.h"
#include "CsyDebugLogger.h"
CPortFactory* CPortFactory::NewL()
/**
* This method uses two phase construction and the cleanup stack to create
* an instance of class CPortFactory. This method is invoked when the user
* invokes the C32 comm server's LoadCommModule() method to load the CSY.
* Note that multiple instances of CPortFactory can be created by C32,
* so no memory allocation or objects should be created when the
* port factory is first created.
*
* @return Pointer to the created instance of CPortFactory
*/
{
_LOG_L4C1("CPortFactory::NewL");
CPortFactory* self = new(ELeave) CPortFactory;
TCleanupItem closeSelf(CPortFactory::CloseObject, self);
CleanupStack::PushL(closeSelf);
self->ConstructL();
CleanupStack::Pop(self);
return (self);
}
CPortFactory::CPortFactory()
: iPortC32InterfaceList(_FOFF(CPortC32Interface, iLink)),
iPortC32InterfaceIter(iPortC32InterfaceList),
iDataChannelList(_FOFF(CChannelMgrCmdData, iLink)),
iDataChannelIter(iDataChannelList)
/**
* Constructor.
*/
{
_LOG_L4C1("CPortFactory::CPortFactory");
}
CPortFactory::~CPortFactory()
/**
* Destructor. Delete all objects and memory created/allocated by this class.
*/
{
_LOG_L4C1(">>CPortFactory::~CPortFactory");
// check if the CSY's objects have been created
// C32 creates a new instance of the port factory each time a client
// loads the CSY. The C32 recognizes a redundant CSerial name and promptly
// destroys the redundant CSY.
if (iMuxObjectsCreated)
{
// client channels
CChannelMgrCmdData* anyChannel = NULL;
iDataChannelIter.SetToFirst();
while ((anyChannel = iDataChannelIter++) != NULL)
{
iDataChannelList.Remove(*anyChannel);
delete anyChannel;
}
// control channel
delete iChannelCtrl;
delete iCommWriterAo;
delete iCommReaderAo;
delete iMux0710Protocol;
// may not be necessary ???
// MAF /\ what does this comment mean
// delete any remaining C32 port objects that were not closed by the client
CPortC32InterfaceBase* port = NULL;
iPortC32InterfaceIter.SetToFirst();
while ((port = iPortC32InterfaceIter++) != NULL)
{
delete port;
}
iCommPort.Close();
}
//iMuxObjectsCreated = EFalse;
_LOG_L4C1("<<CPortFactory::~CPortFactory");
_LOG_L3C1(" ");
}
void CPortFactory::ConstructL()
/**
* 2nd-phase construction. Registers the CSY Name with C32.
*/
{
_LOG_L4C1("CPortFactory::ConstructL");
#ifdef _DEBUG
TInt usedCellCount;
TInt freeCellCount;
usedCellCount = User::CountAllocCells(freeCellCount);
_LOG_L4C3("Cell Counts Used = %d Free = %d", usedCellCount, freeCellCount);
#endif
// inform C32 of the CSY name
TName name(KCSY_Gsm0710ServerName);
TInt retVal1 = SetName(&name);
if (retVal1 != KErrNone)
{
_LOG_L1C3("** Failed to set CSY:%S in C32. Err: %d **", &name, retVal1);
User::Leave(retVal1);
}
iVersion = TVersion(KCSY_Gsm0710MinorVersionNumber,
KCSY_Gsm0710MajorVersionNumber,
KCSY_Gsm0710BuildVersionNumber);
}
void CPortFactory::CreateCsyObjectsL()
/**
* This method is called to create the CSY objects for the multiplexing channels,
* message queues, i/o interface, etc. This method should be called when the
* 1st client request to create a port is received by the CSY via NewPortL().
*/
{
_LOG_L4C1(">>CPortFactory::CreateCsyObjectsL");
// set flag
iMuxObjectsCreated = ETrue;
iOpenPortFailed = EFalse;
// load physical device drivers for serial port(s)
#ifdef __WINS__
// 1st make sure the file server is running
RFs fileServer;
User::LeaveIfError(fileServer.Connect());
fileServer.Close();
_LIT(KPDDName, "ECDRV");
TInt retVal1 = User::LoadPhysicalDevice(KPDDName);
if ((retVal1 != KErrNone) && (retVal1 != KErrAlreadyExists))
User::Leave(retVal1);
#else // target
TBuf<20> commPddName;
TInt retVal1;
commPddName.Copy(KCsyDefaultPDDNameComm1);
retVal1 = User::LoadPhysicalDevice(commPddName);
if ((retVal1 != KErrNone) && (retVal1 != KErrAlreadyExists))
User::Leave(retVal1);
// only load 2nd PDD if debugging is enabled
#ifdef __DEBUGSERIALPORT__
commPddName.Copy(KCsyDefaultPDDNameComm2);
retVal1 = User::LoadPhysicalDevice(commPddName);
if ((retVal1 != KErrNone) && (retVal1 != KErrAlreadyExists))
User::Leave(retVal1);
#endif //__DEBUGSERIALPORT__
#endif //__WINS__
// load logical device driver for serial ports
_LIT(KLDDName, "ECOMM");
retVal1 = User::LoadLogicalDevice(KLDDName);
if ((retVal1 != KErrNone) && (retVal1 != KErrAlreadyExists))
User::Leave(retVal1);
ConfigurePhysicalCommPortL();
// create 27.010 framer and comm i/o objects
iMux0710Protocol = CMux0710Protocol::NewL(*this);
iCommWriterAo = CCommFrameWriterAo::NewL(this, iMux0710Protocol);
iMux0710Protocol->SetCommWriter(iCommWriterAo);
iCommReaderAo = CCommFrameReaderAo::NewL(this, iMux0710Protocol);
iCommReaderAo->Read(); // start it
// create the Multiplexer Control Channel
iChannelCtrl = CChannelMgrCtrl::NewL(*this, *iMux0710Protocol);
// create All Multiplexer Channels
for (TUint8 i=1; i < KCsyDefaultMaxDLCChannels; i++)
{
CChannelMgrCmdData* channelMgrCmd =
CChannelMgrCmdData::NewL(i, *this, *iMux0710Protocol);
iDataChannelList.AddLast(*channelMgrCmd);
}
// switch to multiplexer mode
iMux0710Protocol->SwitchToMuxMode();
#ifdef _DEBUG
TInt usedCellCount;
TInt freeCellCount;
usedCellCount = User::CountAllocCells(freeCellCount);
_LOG_L4C3("Cell Counts Used = %d Free = %d", usedCellCount, freeCellCount);
#endif
_LOG_L4C1("<<CPortFactory::CreateCsyObjectsL");
}
void CPortFactory::CloseObject(TAny* aObject)
/**
* Utility to close objects created by the port factory.
* Used during construction with the cleanup stack.
*
* @param aObject - The CObject to close.
* @return void
*/
{
reinterpret_cast<CObject*>(aObject)->Close();
}
CPort* CPortFactory::NewPortL(const TUint aUnit)
/**
* This method is called by C32 when a port is opened via RComm::Open().
* An instance of the CSY's class CPortC32Interface is created.
* The instance is assigned a channel manager and then is added to
* the list of C32 port interface objects.
*
* @param aUnit - Numeric portion of the port identifier
* @return Pointer to the created C32 port interface object
*/
{
_LOG_L4C2(">>CPortFactory::NewPortL [aUnit=%d]", aUnit);
TC32PortInfo portInfo;
portInfo.iClientType = GetClientType(aUnit);
portInfo.iPortNumber = aUnit;
// check if port number is valid and translates to a client type
if (portInfo.iClientType == EC32ClientUndefined)
{
_LOG_L4C1("<<CPortFactory::NewPortL - ** Unknown client **");
return NULL;
}
// check if this is the 1st port to be opened
if (!iMuxObjectsCreated)
{
_LOG_L4C1("first port to be opened");
CreateCsyObjectsL();
}
else if (iChannelCtrl->GetChannelReady() == EFalse)
{
_LOG_L4C1("CSY objects already exist");
// switch to multiplexer mode
iMux0710Protocol->SwitchToMuxMode();
}
// first make sure control channel is already connected
iChannelCtrl->WaitForChannelReady();
if (! iOpenPortFailed)
{
// create a new C32 Interface Port based on port number
CPortC32InterfaceBase* port = NULL;
if (portInfo.iClientType == EC32ClientIpNif)
{
_LOG_L4C1("Raw IP port");
port = CPortC32InterfaceIp::NewL(*this, portInfo);
}
else
{
_LOG_L4C1("Normal port");
port = CPortC32Interface::NewL(*this, portInfo);
}
CleanupStack::PushL(port);
CChannelMgrCmdData* channel = FindChannelMgr(aUnit);
if (channel == NULL)
{
_LOG_L2C1("** channel is null, delete interface **");
CleanupStack::PopAndDestroy(port);
User::Leave(KErrNotFound);
}
TName name;
name.Format(_L("%d"), aUnit);
port->SetName(&name);
// channel->Open() will add this port to it's port list, and connect channel if needed
// Make sure that during channel init we do not tx/rx through channel
channel->Open(port);
iNumOfOpenPorts++;
_LOG_L4C2("No. of ports = %d",iNumOfOpenPorts);
port->SetMuxChannel(channel);
channel->WaitForChannelReady();
//Need to wait for the channel to be ready. How to wait for something without blocking whole thread?
// add it to list of ports
iPortC32InterfaceList.AddLast(*port);
CleanupStack::Pop(port);
#ifdef _DEBUG
TInt usedCellCount;
TInt freeCellCount;
usedCellCount = User::CountAllocCells(freeCellCount);
_LOG_L4C3("Cell Counts Used = %d Free = %d", usedCellCount, freeCellCount);
#endif
_LOG_L4C2("<<CPortFactory::NewPortL [port=%d]", port);
return port;
}
else //iPortOpenFailed == ETrue
{
_LOG_L4C1("<<CPortFactory::NewPortL [port=NULL]");
User::Leave(KErrTimedOut);
return NULL;
}
}
void CPortFactory::Info(TSerialInfo& aSerialInfo)
/**
* Called by C32 to identify the CSY module.
* @param aSerialInfo - Reference holder for information to be populated by the function.
* @return void
*/
{
_LOG_L4C1("CPortFactory::Info");
aSerialInfo.iDescription = KCSY_Description;
aSerialInfo.iName = KCSY_Gsm0710ServerName;
aSerialInfo.iLowUnit = KCSY_Gsm0710LowUnit;
aSerialInfo.iHighUnit = KCSY_Gsm0710HighUnit;
}
CPortFactory::TC32ClientType CPortFactory::GetClientType(TInt aC32PortNum)
/**
* Returns the ClientType for the specified C32 port number.
* @param aC32PortNum - C32 port number
* @return Client type - TSY or NIF
*/
{
_LOG_L4C2("CPortFactory::GetClientType [aC32PortNum=%d]", aC32PortNum);
if (aC32PortNum >= KCOMMP_IP_NIF_OFFSET)
{
_LOG_L4C1("Raw Ip");
return CPortFactory::EC32ClientIpNif;
}
else if (aC32PortNum == KCOMMP_CSD_PPP_NUMBER)
{
_LOG_L4C1("Csd PPP");
return CPortFactory::EC32ClientNif;
}
_LOG_L4C1("Tsy");
return CPortFactory::EC32ClientTsy;
}
CPortC32InterfaceBase* CPortFactory::FindPortC32Interface(const TUint8 aDlcNum)
/**
* This method returns a pointer to the C32 port interface object
* that is associated with the specified DLC number.
*
* @param aDlcNum - DLC number
* @return Pointer to C32 port interface object or NULL if not found
*/
{
_LOG_L4C2(">>CPortFactory::FindPortC32Interface [aDlcNum=%d]", aDlcNum);
CPortC32InterfaceBase* port = NULL;
CChannelMgrCmdData* anyChannel = NULL;
iDataChannelIter.SetToFirst();
while ((anyChannel = iDataChannelIter++) != NULL)
{
if (anyChannel->GetDlcNumber() == aDlcNum)
{
_LOG_L4C1("AT channel");
port = anyChannel->GetC32Port();
break;
}
}
_LOG_L4C2("<<CPortFactory::FindPortC32Interface [port=0x%x]",port);
return port;
}
CChannelMgrCmdData* CPortFactory::FindChannelMgr(const TUint aC32PortNum)
/**
* This method is only called when a port is created.
*
* @param aC32PortNum - C32 port number
* @return Pointer to the channel manager object or NULL
*/
{
_LOG_L4C2(">>CPortFactory::FindChannelMgr [aC32PortNum=%d]", aC32PortNum);
TUint dlcNum = ++iLastDlcNum;
_LOG_L4C2("iLastDlcNum: %d", iLastDlcNum);
//
// MAF Horrible
// This just counts through the array of channel pointers
// and returns a pointer when the count gets to the correct value.
//
// We should be able to use an array here and directly access it using
// the dlc number!?!?
//
TUint count = 1;
CChannelMgrCmdData* anyChannelCmd;
iDataChannelIter.SetToFirst();
while ((anyChannelCmd = iDataChannelIter++) != NULL)
{
if (count == dlcNum)
{
_LOG_L4C2("<<CPortFactory::FindChannelMgr() - found, count %d",count);
return anyChannelCmd;
}
count++;
}
_LOG_L4C1("<<CPortFactory::FindChannelMgr() - *** NOT FOUND ***");
return NULL;
}
CChannelMgrCmdData* CPortFactory::FindChannelMgrByDlcNum(const TUint8 aDlcNum)
/**
* This method returns a pointer to the channel manager object
* that has the specified DLC number.
*
* @param aDlcNum - DLC number
* @return Pointer to the channel manager object or NULL
*/
{
_LOG_L4C2(">>CPortFactory::FindChannelMgrByDlcNum [aDlcNum=%d]", aDlcNum);
CChannelMgrCmdData* channel = NULL;
iDataChannelIter.SetToFirst();
while ((channel = iDataChannelIter++) != NULL)
{
if (channel->GetDlcNumber() == aDlcNum)
{
_LOG_L4C1("AT channel");
return channel;
}
}
_LOG_L2C1("<<CPortFactory::FindChannelMgrByDlcNum() - NOT FOUND");
return NULL;
}
TInt CPortFactory::ConfigurePhysicalCommPortL()
/**
* This method is used to configure the specified physical comm port.
* The parameters are read from CommDb or supplied by C32.
* @param aPhysPortNum - Physical port number
* @return KErrorNone or KErrAccessDenied.
*/
{
_LOG_L4C1(">>CPortFactory::ConfigurePhysicalCommPortL");
// create a package pointer
TPckgBuf<TCommConfigV01> newCfg;
TInt ret, len;
// get the modem table - Get port settings from CommDB.
CMDBSession* db = CMDBSession::NewL(KCDLatestVersion);
CleanupStack::PushL(db);
TUint32 modemId = 0;
// We are using the same modem as TSY
// Accessing the ModemPhoneServicesSMS field in the Global Settings Table
CMDBField<TUint32>* globalSettingsField = new(ELeave) CMDBField<TUint32>(KCDTIdModemPhoneServicesSMS);
CleanupStack::PushL(globalSettingsField);
globalSettingsField->SetRecordId(1);
globalSettingsField->LoadL(*db);
modemId = *globalSettingsField; // The field value gives the record id in the Modem Bearer Table.
CleanupStack::PopAndDestroy(globalSettingsField);
_LOG_L4C2("Accessing modem entry %d in the modem table", modemId);
TUint32 rate;
TUint32 dataBits;
TUint32 stopBits;
TUint32 parity;
TUint32 handshake;
TPckgBuf<TCommConfigV01> config;
TUint port = 0;
TBuf<KCommsDbSvrMaxFieldLength> controlPort;
// Accessing the ControlChannelPort Name from the ModemBearer Table in the record number
//corresponding to modemId
CMDBField<TDesC>* portField = new(ELeave) CMDBField<TDesC>(KCDTIdControlChannelPortName);
CleanupStack::PushL(portField);
portField->SetRecordId(modemId);
portField->SetMaxLengthL(KMaxTextLength);
portField->LoadL(*db);
controlPort = *portField;
CleanupStack::PopAndDestroy(portField);
// Diagnostics - control port
if (controlPort.Length())
{
TBuf8<16> portName;
portName.Copy(controlPort.Left(16));
_LOG_L4C2("Control port(MODEM_CONTROL_CHANNEL_PORT_NAME) '%S'",
&portName);
// Get number of port out of the port descriptor.
_LIT(KDoubleColon, "::");
TInt len = controlPort.Find(KDoubleColon);
if (len < KErrNone)
{
_LOG_L1C1("** finding :: in control port failed **");
User::Leave(KErrGeneral);
}
TUint numPos = len + KDoubleColon.iTypeLength;
TPtrC numPtr(&controlPort[numPos], controlPort.Length() - numPos);
TLex lexer(numPtr);
TInt ret = lexer.Val(port);
if (ret)
{
_LOG_L1C1("** lexing to get port number failed **");
User::Leave(ret);
}
}
else
{
_LOG_L1C1("** Control port not set in commDb **");
User::Leave(KErrGeneral);
}
// Accessing the Rate from the ModemBearer Table in the record number
//corresponding to modemId
CMDBField<TUint32>* rateField = new(ELeave) CMDBField<TUint32>(KCDTIdRate);
CleanupStack::PushL(rateField);
rateField->SetRecordId(modemId);
rateField->LoadL(*db);
rate = *rateField;
CleanupStack::PopAndDestroy(rateField);
// Accessing the DataBits from the ModemBearer Table in the record number
//corresponding to modemId
CMDBField<TUint32>* dataBitsField = new(ELeave) CMDBField<TUint32>(KCDTIdDataBits);
CleanupStack::PushL(dataBitsField);
dataBitsField->SetRecordId(modemId);
dataBitsField->LoadL(*db);
dataBits = *dataBitsField;
CleanupStack::PopAndDestroy(dataBitsField);
// Accessing the StopBits from the ModemBearer Table in the record number
//corresponding to modemId
CMDBField<TUint32>* stopBitsField = new(ELeave) CMDBField<TUint32>(KCDTIdStopBits);
CleanupStack::PushL(stopBitsField);
stopBitsField->SetRecordId(modemId);
stopBitsField->LoadL(*db);
stopBits = *stopBitsField;
CleanupStack::PopAndDestroy(stopBitsField);
// Accessing the Parity from the ModemBearer Table in the record number
//corresponding to modemId
CMDBField<TUint32>* parityField = new(ELeave) CMDBField<TUint32>(KCDTIdParity);
CleanupStack::PushL(parityField);
parityField->SetRecordId(modemId);
parityField->LoadL(*db);
parity = *parityField;
CleanupStack::PopAndDestroy(parityField);
// Accessing the HandShake from the ModemBearer Table in the record number
//corresponding to modemId
CMDBField<TUint32>* handshakeField = new(ELeave) CMDBField<TUint32>(KCDTIdHandshaking);
CleanupStack::PushL(handshakeField);
handshakeField->SetRecordId(modemId);
handshakeField->LoadL(*db);
handshake = *handshakeField;
CleanupStack::PopAndDestroy(handshakeField);
config().iRate = (TBps)rate;
config().iDataBits = (TDataBits)dataBits;
config().iStopBits = (TStopBits)stopBits;
config().iParity = (TParity)parity;
config().iHandshake = (TUint)handshake;
config().iParityError = KConfigParityErrorIgnore;
config().iFifo = static_cast<TUint>(EFifoEnable);
newCfg.Copy(config);
ret = iCommPort.Open(port);
if (ret)
{
_LOG_L1C3("** Failed CommPort.Open(%d) ret=%d **", port,ret);
User::Leave(ret);
}
// Configure the port
len = iCommPort.ReceiveBufferLength();
if (len < KErrNone)
{
_LOG_L1C2("** Leave: CommPort.ReceiveBufferLength() len=%d **", len);
User::Leave(KErrGeneral);
}
// Increase the receive buffer to make sure we can operate as slowly as we
// can without filling up the LDD's receive buffer with incoming signals
len *= KCSY_ReceiveBufferSizeIncreaseFactor;
ret = iCommPort.SetReceiveBufferLength(len);
TCommConfig cbuf;
TCommConfigV01 &cfg = cbuf();
iCommPort.Config(cbuf); // Get the Configuration Parameters
cfg.iRate = newCfg().iRate;
cfg.iDataBits = newCfg().iDataBits;
cfg.iStopBits = newCfg().iStopBits;
cfg.iParity = newCfg().iParity;
cfg.iHandshake = newCfg().iHandshake;
cfg.iParityError = newCfg().iParityError;
cfg.iFifo = newCfg().iFifo;
_LOG_L4C2(" Set Phys Port Config for Port %d", port);
_LOG_L4C2(" Rate = 0x%x", cfg.iRate);
_LOG_L4C2(" DataBits = 0x%x", cfg.iDataBits);
_LOG_L4C2(" Stop Bits = 0x%x", cfg.iStopBits);
_LOG_L4C2(" Parity = 0x%x", cfg.iParity);
_LOG_L4C2(" Handshake = 0x%x", cfg.iHandshake);
_LOG_L4C2(" Parity Error = 0x%x", cfg.iParityError);
_LOG_L4C2(" Fifo = 0x%x", cfg.iFifo);
ret = iCommPort.SetConfig(cbuf); // Set the Configuration Parameters
if (ret)
{
_LOG_L1C2("** CommPort.SetConfig ret=%d **", ret);
User::Leave(KErrNotSupported);
}
// Clean up the stack
CleanupStack::PopAndDestroy(db);
_LOG_L4C2("<<CPortFactory::ConfigurePhysicalCommPortL [ret=%d]", ret);
return ret;
}
void CPortFactory::ConnectControlChannel()
/**
* This method is called to connect the 27.010 control channel,
* which is DLC 0.
*/
{
_LOG_L4C1("CPortFactory::ConnectControlChannel");
TInt ret = iChannelCtrl->Connect();
if (ret != KErrNone)
{
_LOG_L4C2(("<<CCPortFactory::ConnectControlChannel ret=%d"),ret);
}
}
void CPortFactory::DisconnectControlChannel()
/**
* This method is called to set the 27.010 control channel to the "disconnect" state.
*/
{
_LOG_L4C1("CPortFactory::DisconnectAllChannels");
iChannelCtrl->Disconnect();
}
void CPortFactory::ChannelCtrlDoCancel()
/**
* This method is called when the port has been opened and the max number of retries has been reached.
*/
{
_LOG_L4C1(">>CPortFactory::ChannelCtrlDoCancel");
iOpenPortFailed = ETrue;
iChannelCtrl->NotifyChannelReady();
_LOG_L4C1("<<CPortFactory::ChannelCtrlDoCancel");
}
void CPortFactory::RemoveC32Port(CPortC32InterfaceBase* aPort)
/**
* This method removes the specified C32 port object from the
* port factory's list of current/open C32 port objects.
* This will allow another client to open that port.
* @param aPort - Pointer to C32 port object
* @return void
*/
{
_LOG_L4C2(">>CPortFactory::RemoveC32Port [aPort=%d]", aPort->GetPortNumber());
CPortC32InterfaceBase* port = NULL;
iPortC32InterfaceIter.SetToFirst();
while ((port = iPortC32InterfaceIter++) != NULL)
{
if (port == aPort)
{
iPortC32InterfaceList.Remove(*port);
_LOG_L4C1("<<CPortFactory::RemoveC32Port - okay");
return;
}
}
// MAF this is a bad condition
_LOG_L4C1("<<CPortFactory::RemoveC32Port ** Not Removed? **");
}
void CPortFactory::ConnectIpNifPort(const TUint8 aDlcNum)
/**
* This method connects the port interface object
* in the CSY that are used for a data interface to a NIF.
* @param void
*/
{
_LOG_L4C2("CPortFactory::ConnectIpNifPort [aDlcNum=%d]",aDlcNum);
CPortC32InterfaceBase* port = FindPortC32Interface(aDlcNum);
if (port)
{
CChannelMgrCmdData* iMuxChannel = port->GetMuxChannel();
if (iMuxChannel)
{
TInt err = iMuxChannel->Connect();
if (err != KErrNone)
{
_LOG_L1C2("iMuxChannel->Connect() error =%d",err);
}
}
else
{
// MAF assert here
_LOG_L1C2("** Could not find channel for port [0x%x] **",port);
}
}
else
{
// MAF assert here
_LOG_L1C1("** Could not find port for dlcnumber **");
}
}
TBool CPortFactory::FindDlcToEnable()
/**
* We have resources again. Find a dlc that has had its flow control
* set and re-enable.
*
* @return ETrue if there are still dlcs that are stopped due to flow control.
*/
{
_LOG_L4C1(">>CPortFactory::FindDlcToEnable");
TInt numberOfStopped = 0;
TBool dlcsStillToEnable = EFalse;
CChannelMgrCmdData* channel = NULL;
iDataChannelIter.SetToFirst();
while ((channel = iDataChannelIter++) != NULL)
{
if (channel->CsyToModemFlowControl() == EFlowControlOn)
{
numberOfStopped++;
if (numberOfStopped == 1)
{
_LOG_L4C1("Found a dlc to re-enable");
if (channel->SetCsyToModemFlowControl(EFlowControlOff))
{
_LOG_L4C1("Re-enable failed");
dlcsStillToEnable = ETrue;
break;
}
}
else
{
_LOG_L4C1("Other dlc still to re-enable");
dlcsStillToEnable = ETrue;
}
}
}
_LOG_L4C2("<<CPortFactory::FindDlcToEnable numberOfStopped=%d",numberOfStopped);
return dlcsStillToEnable;
}
void CPortFactory::FindActiveDataDlcToStop()
/**
* MAF come up with a better algorithm. Currently this scans sequentially for a data
* DLC to stop.
* Check the data dlcs to see if one of them can be stopped
*/
{
_LOG_L4C1(">>CPortFactory::FindActiveDataDlcToStop");
CChannelMgrCmdData* channel = NULL;
CPortC32InterfaceBase* port = NULL;
iDataChannelIter.SetToFirst();
while ((channel = iDataChannelIter++) != NULL)
{
port = channel->GetC32Port();
if ((port)&&(port->GetClientType() == EC32ClientIpNif))
{
if (channel->CsyToModemFlowControl() == EFlowControlOff)
{
_LOG_L4C1("Found a data dlc to stop");
if (channel->SetCsyToModemFlowControl(EFlowControlOn))
{
_LOG_L4C1("Failed to stop dlc");
}
else
break;
}
}
}
_LOG_L4C1("<<CPortFactory::FindActiveDataDlcToStop");
}
void CPortFactory::StopAnyDlc()
/**
* Time for drastic action - enforce flow control on any DLC (except ctrl).
*/
{
_LOG_L4C1(">>CPortFactory::StopAnyDlc");
CChannelMgrCmdData* channel = NULL;
iDataChannelIter.SetToFirst();
while ((channel = iDataChannelIter++) != NULL)
{
if (channel->CsyToModemFlowControl() == EFlowControlOff)
{
_LOG_L4C1("Found a dlc to stop");
if (channel->SetCsyToModemFlowControl(EFlowControlOn))
{
_LOG_L4C1("Failed to stop dlc");
}
else
break;
}
}
_LOG_L4C1("<<CPortFactory::StopAnyDlc");
}
TBool CPortFactory::DecrementNumOfOpenPorts()
/**
* Used to decrement the number of open ports and disconnect if number = 0
*
* aReturn returns EFalse if Num of Ports is 0; ETrue otherwise
*/
{
if (iNumOfOpenPorts==0)
return EFalse;
else if (--iNumOfOpenPorts == 0)
{
_LOG_L4C1("******* DISCONNECT ALL *********");
DisconnectControlChannel();
iLastDlcNum = 0;
return EFalse;
}
return ETrue;
}
TSecurityPolicy CPortFactory::PortPlatSecCapability(TUint /*aPort*/) const
/**
* This method returns the capabilities required to open the given port number
* This 27.010 CSY requires the same capabilities for all port numbers
*
* @param aPort - The port number to check against
* @return TSecurityPolicy - containing the required capabilities to use this CSY
*/
{
return TSecurityPolicy(ECapabilityNetworkServices, ECapabilityNetworkControl, ECapabilityReadUserData, ECapabilityWriteUserData);
}