--- a/basebandadaptationplugins/basebandchanneladaptorforc32/src/C32Bca.cpp Mon May 03 13:37:20 2010 +0300
+++ b/basebandadaptationplugins/basebandchanneladaptorforc32/src/C32Bca.cpp Thu May 06 15:10:38 2010 +0100
@@ -1,1198 +1,1198 @@
-// Copyright (c) 2004-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:
-// C32 Baseband Channel Adaptor(BCA) APIs implementation.
-// This file contains all the API implementation of the C32BCA interface for Symbian OS.
-//
-//
-
-/**
- @file
- @internalComponent
-*/
-
-#include "C32Bca.h"
-#include <cdbcols.h>
-#include <commsdat_partner.h>
-
-using namespace BasebandChannelAdaptation;
-using namespace BasebandChannelAdaptation::C32Bca;
-
-const static TUint KVersion = ((static_cast<TUint>(KC32BcaMajorVersionNumber)) << 16) | KC32BcaMinorVersionNumber;
-
-
-/**
-C++ constructor for an object representing a c32 async user
-
-@param aUser the target of the notifications originating in C32
-@param aPort the C32 port to be used with this object
-@param aAoPriority the priority to assign to this active object
-*/
-CCommBase::CCommBase(MC32User& aUser, RComm& aPort, TInt aAoPriority):
- CActive(aAoPriority),
- iUser(aUser),
- iPort(aPort)
- {
- CActiveScheduler::Add(this);
- __FLOG_OPEN(KC32BcaLogFolder, KC32BcaLogFile); // Connect to the BCA logger
- }
-
-/**
-C++ destructor */
-CCommBase::~CCommBase()
- {
- __FLOG_CLOSE;
- }
-
-/**
-C++ constructor
-The comm-reader has a higher priority than the comm-writer, to
-ensure the reader gets the chance to receive the incomming data
-
-@param aUser the target of the notifications originating in C32
-@param aPort the C32 port to be used with this object
-*/
-CCommReader::CCommReader(MC32User& aUser, RComm& aPort):
- CCommBase(aUser, aPort, EPriorityHigh)
- {
- }
-
-/**
-C++ destructor */
-CCommReader::~CCommReader()
- {
- Cancel();
- }
-
-/**
-Cancels the outstanding read */
-void CCommReader::DoCancel()
- {
- iPort.ReadCancel();
- }
-
-/**
-Issues a read on the serial port
-
-@param aBuf the buffer to read to */
-void CCommReader::Read(TDes8& aBuf)
- {
- iPort.ReadOneOrMore(iStatus, aBuf);
- SetActive();
- }
-
-/**
-Called on read completion */
-void CCommReader::RunL()
- {
- iUser.CommReadComplete(iStatus.Int());
- }
-
-/**
-C++ constructor
-The comm-writer has a lower priority than the comm-reader, to
-ensure the reader gets the chance to receive the incomming data
-
-@param aUser the target of the notifications originating in C32
-@param aPort the C32 port to be used with this object */
-CCommWriter::CCommWriter(MC32User& aUser, RComm& aPort):
- CCommBase(aUser, aPort, EPriorityUserInput)
- {
- }
-
-/**
-C++ destructor */
-CCommWriter::~CCommWriter()
- {
- Cancel();
- }
-
-/**
-Issues a write on the serial port */
-void CCommWriter::Write(const TDesC8& aBuf)
- {
- iPort.Write(iStatus, aBuf);
- SetActive();
- }
-
-/**
-Called when the write completes
-*/
-void CCommWriter::RunL()
- {
- iUser.CommWriteComplete(iStatus.Int());
- }
-
-/**
-Cancels the outstanding write
-*/
-void CCommWriter::DoCancel()
- {
- iPort.WriteCancel();
- }
-
-/**
-C++ constructor
-
-@param aUser the target of the notifications originating in C32
-@param aPort the C32 port to be used with this object
-
-
-Note on Monitor AO priority:
-
-Monitor AO is the same priority as the Reader / Writer by design.
-
-We do NOT want link failure notification to complete before all possible outstanding reads / writes
-have completed, to make sure that we do not lose any data that was already received from the
-baseband and is buffered by the driver or the CSY.
-Consider a scenario where a UDP datagram is received by the CSY, and then the serial link is
-severed (e.g. cable is unplugged by the user). If the Monitor has higher priority than reader/writer,
-we may get failure notification before we are notified on the read of this UDP datagram, potentially
-resulting in its loss (E.g. PPP shuts down when on Link Down notification.)
-*/
-CCommLinkMonitor::CCommLinkMonitor(MC32User& aUser, RComm& aPort):
- CCommBase(aUser, aPort, EPriorityStandard)
- {
- }
-
-/**
-Sets the object to monitor the link for the configured Role, DTE or DCE
-
-@param aMask DTE or DCE: determines when the link is considered to be down.
-*/
-void CCommLinkMonitor::Setup(TUint32 aMask)
- {
- iNotifyChangeSignalMask = aMask;
- __FLOG_1(_L8("CommLinkMonitor setup: Notify on signal mask [0x%X]"),iNotifyChangeSignalMask);
- }
-
-/**
-Requests to be notified when the link is down.
-
-Can be called an more than once
-*/
-void CCommLinkMonitor::NotifyLinkDown()
- {
- ASSERT(!IsActive());
-
- // get the current state of the line so when we get notification we can tell if it really has changed
- iSavedSignalState = iPort.Signals(iNotifyChangeSignalMask) & iNotifyChangeSignalMask;
- iPort.NotifySignalChange(iStatus, iSignals, iNotifyChangeSignalMask);
-
- __FLOG_1(_L8("CommLinkMonitor::NotifyLinkDown: initial signals: [0x%X]"), iSavedSignalState);
-
- SetActive();
- }
-
-/**
-Called when EIA-232 signals change,i.e. on potential link failure
-*/
-void CCommLinkMonitor::RunL()
- {
- __FLOG_2(_L8("CommLinkMonitor::RunL: Signals changed [0x%X]; new signals [0x%X]"), iSignals & (~0x1F), iSignals & 0x1F);
-
- // We report link failure if and only if a monitored line went from high to low.
- // Method: mask the saved signals using inverted monitored bits in the signal bitmask,
- // to filter out all transitions except for high -> low.
- // 1 & ~0 = 1; 1 & ~1 = 0; 0 & ~1 = 0; 0 & ~0 = 0
- // This is necessary, because we may be monitoring more than one signal, and the change can be arbitrary.
- if ((~(iNotifyChangeSignalMask & iSignals)) & iSavedSignalState)
- {
- iUser.CommLinkDown(KErrCommsLineFail);
- }
- iSavedSignalState = iSignals & iNotifyChangeSignalMask; // update saved state with relevant bits
- iPort.NotifySignalChange(iStatus, iSignals, iNotifyChangeSignalMask);
- SetActive();
- // Note: If the link went down, the user will likely shutdown the BCA on outstanding signal notification.
- }
-
-/**
-Cancels notification request of link failure */
-void CCommLinkMonitor::DoCancel()
- {
- __FLOG(_L8("CommLinkMonitor::DoCancel: Cancelling signal change notification."));
- iPort.NotifySignalChangeCancel();
- }
-
-
-
-
-
-/**
-* default constructor to create a C32Bca instance.
-*/
-CC32Bca::CC32Bca()
- {
- __FLOG_OPEN(KC32BcaLogFolder,KC32BcaLogFile);
- __FLOG_2(_L8("====== CC32Bca::CC32Bca: Shim BCA for C32 [Vesion: major= %d minor= %d] Constructed. ======"), KC32BcaMajorVersionNumber, KC32BcaMinorVersionNumber);
- }
-
-/**
-2nd phase of construction: allocates member objects
-
-
-@leave when members cannot be constructed. */
-void CC32Bca::ConstructL()
- {
- __ASSERT_DEBUG(!iReader, Panic(EReaderAlreadyExists));
- __ASSERT_DEBUG(!iWriter, Panic(EWriterAlreadyExists));
- __ASSERT_DEBUG(!iLinkMonitor, Panic(EMonitorAlreadyExists));
-
- // Comm is not initialized yet. We have to be Opened before it can be used. C32 panics otherwise.
- iReader = new (ELeave)CCommReader(*this, iComm);
- iWriter = new (ELeave)CCommWriter(*this, iComm);
- // Monitor is created upon user request only, we may never need it at all.
- }
-
-/**
-* Destructor
-*/
-CC32Bca::~CC32Bca()
-
- {
- __FLOG(_L8("CC32Bca::~CC32Bca: releasing resources..."));
-
- CloseCommDbConnection();
- CloseCommPort(); // Cancels reader / writer / monitor
-
- // N.B.:
- // It is critical that these objects are cancelled before deletion. Else DoCancel operates on closed C32 port,
- // causing C32 to panic.
- delete iReader;
- delete iWriter;
- delete iLinkMonitor; // Note: may have never been created.
-
- __FLOG(_L8("CC32Bca::~CC32Bca: CC32Bca destroyed."));
- __FLOG_CLOSE;
- }
-
-/** This method deletes the BCA itself.*/
-void CC32Bca::Release()
- {
- __FLOG(_L8("CC32Bca::Release"));
- delete this;
- }
-
-/**
-* Informs that the BCA is required by the client(for instance, Raw IP NIF).Comms Server is
-* connected, and serial port is opened.
-
-* @param aStatus complete status, KErrNone if successful, C32 error code otherwise.
-* @param aChannelId comm port name.
-*/
-void CC32Bca::Open(TRequestStatus& aStatus, const TDesC& aChannelId)
- {
- // We don't have the ConstructL, so we have to allocate memory here.
-
- aStatus = KRequestPending;
- // avoid compiler warning.
- TRequestStatus* ptrStatus = &aStatus;
- if(iCommPortOpen)
- {
- __FLOG(_L8("Warning: C32Bca is already Opened."));
-
- User::RequestComplete(ptrStatus,KErrNone);
- return;
- }
-
- if(aChannelId == KChannelIdNotOverridden) // Channel ID is not supplied - Comm Port Name is not overriden.
- { // Read it from CommDB.
- // Fetch port name from CommDB.
- TRAPD(commPortErr, ReadCommPortFromCommDbL(iCommPort));
-
- // If the column is missing from CommDB, we can get an empty string with KErrNone.
- // Opening RComm with empty string as Port name fails with ECUART, LOOOPBACK CSYs.
- // with different error codes on 8.1 and 9.0.
- // It would be better to intercept such invalid value and fail here.
- // This is not done, because theoretically it is possible to write a CSY that somehow takes an
- // emty descriptor as a port name. As of December 2004, C32 does not allow that, however, this
- // may change in the future.
- // So, we just log a warning.
- if(KErrNone == commPortErr && iCommPort.Size() == 0)
- {
- __FLOG(_L8("Warning: Null string read from CommDB. Will try to open Comm Port anyway."));
- }
-
- if(KErrNone != commPortErr) // Fatal: we do not have a port name. Can't open RComm.
- {
- __FLOG(_L8("Error: Failed to get C32 PortName from CommDB "));
- CloseCommDbConnection();
- User::RequestComplete(ptrStatus, commPortErr);
- return;
- }
- }
- else // Channel ID supplied - use it as Port Name.
- {
- _LIT(KDoubleColon, "::");
- TInt len1 = aChannelId.Find(KDoubleColon);
-
- if (len1 < KErrNone)
- {
- __FLOG(_L8("** ERROR: No :: (Double Colon) in aChannelId **"));
- User::RequestComplete(ptrStatus, KErrBadName);
- return;
- }
- else
- {
- TUint numPos = len1 + KDoubleColon.iTypeLength;
-
- TInt len2 = (aChannelId.Mid(numPos)).Find(KDoubleColon);
-
- if (len2 < KErrNone)
- {
- iCommPort = aChannelId;
- }
- else
- {
- iCommPort = aChannelId.Mid(numPos);
- iCsyName = aChannelId.Mid(0, len1);
- iCsyNameOverride = ETrue;
- }
- }
- }
- // We have the Port Name at this point: either supplied as a parameter, or read from CommDB.
-
- if(!iCsyNameOverride) // CSY name is not provisioned by Ioctl: read it from CommDB.
- {
- TRAPD(getCsyErr, ReadCsyNameFromCommDbL(iCsyName));
- if(KErrNone != getCsyErr) // Fatal: we do not have a CSY name. Can't load CSY module.
- {
- // We do not use a hardcoded value (e.g. ECUART), because the client code or the environment are
- // confused - it is better to fail them, rather than mask their problems.
- __FLOG(_L8("Error: Failed to get CSY name from CommDB "));
- CloseCommDbConnection();
- User::RequestComplete(ptrStatus,getCsyErr);
- return;
- }
- }
- // We have the CSY name at this point, either provisioned via Ioctl, or read from CommDB.
-
- // Decide the Comm Role (DCE / DTE) of the port.
- TBool isCommRoleDefault = EFalse;
- // We use a concept of "Default Comm Role", because C32 has it. We could use DTE as a default
- // setting, but we prefer to call the "default" method on C32 and let it decide what the role should be.
-
- if(!iCommRoleOverride) // Port role not overriden via Ioctl
- {
- TRAPD(getCommRoleErr, ReadCommRoleFromCommDbL(iCommRole));
- if(KErrNone != getCommRoleErr) // Port role not specified via CommDb
- {
- isCommRoleDefault = ETrue; // Port role not specified via Ioctl or CommDb
- }
- }
- // We have the Comm Role: provisioned via Ioctl, read from CommDB, or default(DTE)
-
- CloseCommDbConnection(); // We do not read any settings once the connection is opened.
- // We have all the necessary C32 settings at this point.
- // Open the actual C32 session:
-
- TInt ret = iCommServ.Connect();
- if(ret)
- {
- __FLOG_1(_L8("Open: C32 Server connection error %d"), ret);
- User::RequestComplete(ptrStatus,ret);
- return;
- }
- ret = iCommServ.LoadCommModule(iCsyName);
-
- __FLOG_2(_L16("Open: CSY module [%S] loaded with error %d"), &iCsyName, ret);
-
- if(ret)
- {
- User::RequestComplete(ptrStatus,ret);
- return;
- }
-
- if(isCommRoleDefault)
- {
- ret = iComm.Open(iCommServ, iCommPort, ECommShared);
- }
- else
- {
- ret = iComm.Open(iCommServ, iCommPort, ECommShared, iCommRole);
- }
-
- __FLOG_2(_L16("Open: C32 port [%S] opened with error %d"), &iCommPort, ret);
-
- if(ret)
- {
- User::RequestComplete(ptrStatus,ret);
- return;
- }
- //
- //Open successfull, we update our state.
- //
-
- // We may have been closed, and are being reopened now. Make sure no errors persist from the previous session.
- iErrorOnNextRead = KErrNone;
- iErrorOnNextWrite = KErrNone;
- iCommPortOpen = ETrue;
-
- User::RequestComplete(ptrStatus,KErrNone);
- // Don't start control line monitoring. This is done on user request via Ioctl only.
- }
-
-/**
- Shuts the BCA channel down in a graceful manner. BCA releases its resources.
- Cancels all outstanding operations: Writes, Reads and Ioctls.
-
- Due to the specifics of C32Bca implementation, this call completes immediately and is identical to ::Close.
-
- @param aStatus completion status: Always KErrNone.
-*/
-void CC32Bca::Shutdown(TRequestStatus& aStatus)
- {
- aStatus = KRequestPending;
-
- CloseCommPort();
-
- // Don't notify reader / writer / monitor. Read / Write should not be called after this anyway. Let C32 panic.
-
- TRequestStatus* request = &aStatus;
- User::RequestComplete(request, KErrNone);
- __FLOG_1(_L8("C32Bca::Shutdown: BCA shut down with error %d"), KErrNone);
- }
-
-/**
-* Closes the BCA immediately. BCA releases its resources.
-* cancels all Writes, Reads and Controls.
-*/
-void CC32Bca::Close()
- {
- CloseCommPort();
- __FLOG_1(_L8("C32Bca::Close:Close: BCA closed with error %d"), KErrNone);
- }
-
-/**
-* Queues a Read on C32 serial port.
-
-* @param aStatus complete status, KErrNone if successful, C32 error code otherwise.
-* @param aBuf buffer for data to be read.
-* @note The buffer is owned by the client. Client must not access / modify the buffer until the Read completes.
-*/
-void CC32Bca::Read(TRequestStatus& aStatus,TDes8& aBuf)
- {
- iReadRequest = &aStatus;
- *iReadRequest = KRequestPending;
-
- if(iErrorOnNextRead)
- {
- User::RequestComplete(iReadRequest, iErrorOnNextRead);
- // Error persists until the BCA is closed and opened
- }
- else
- {
- iReader->Read(aBuf);
- }
- }
-
-/**
-* Queues a Write on C32 serial port.
-
-* @param aStatus the complete status, KErrNone if successful, C32 error code otherwise.
-* @param aBuf the buffer to sent.
-* @note The buffer is owned by the client. Client must not access / modify the buffer until the Write completes.
-*/
-void CC32Bca::Write(TRequestStatus& aStatus,const TDesC8& aBuf)
- {
- iWriteRequest = &aStatus;
- *iWriteRequest = KRequestPending;
-
- if(iErrorOnNextWrite)
- {
- User::RequestComplete(iWriteRequest, iErrorOnNextWrite);
- // Error persists until BCA is closed and opened.
- }
- else
- {
- iWriter->Write(aBuf);
- }
- }
-
-/**
- Cancels the outstanding Read operation.(best effort operation: the read may have been completed already.)
-*/
-void CC32Bca:: CancelRead()
-
- {
- __FLOG(_L8("CancelRead: Read is cancelled by client."));
- iReader->Cancel();
-
- if(iReadRequest != NULL)
- {
- User::RequestComplete(iReadRequest, KErrCancel);
- }
- }
-
-/**
- Cancels all Write operations.(best effort attempt: the write may have been completed already.)
-*/
-void CC32Bca::CancelWrite()
-
- {
- __FLOG(_L8("CancelWrite: Write is cancelled by client."));
-
- iWriter->Cancel();
-
- if(iWriteRequest != NULL)
- {
- User::RequestComplete(iWriteRequest, KErrCancel);
- }
- }
-
-
-// Debug dumps:
-#ifdef __FLOG_ACTIVE
-
-_LIT8(KLitOptLevelGeneric, "KBcaOptLevelGeneric");
-_LIT8(KLitOptLevelExtSerial, "KBcaOptLevelExtSerial");
-_LIT8(KLitOptLevelUnsupported, "**Unsupported**");
-
-/**
-Returns a string for an option level
-
-@param aOptLevel BCA Option Level
-@return readable string for aOptLevel
-*/
-static const TDesC8& IoctlOptLevelStr(TUint32 aOptLevel)
- {
- switch(aOptLevel)
- {
- case KBcaOptLevelGeneric:
- return KLitOptLevelGeneric;
- case KBcaOptLevelExtSerial:
- return KLitOptLevelExtSerial;
- default:
- return KLitOptLevelUnsupported;
- }
- }
-
-
-_LIT8(KLitOptNameBcaVersionNumber, "KBcaOptNameVersionNumber");
-_LIT8(KLitOptNameBcaCaps, "KBcaOptNameBcaCaps");
-_LIT8(KLitOptNameBcaSetIapId, "KBcaOptNameBcaSetIapId");
-_LIT8(KLitOptNameBcaSetBcaStack, "KBcaOptNameBcaSetBcaStack");
-_LIT8(KLitOptNameBcaResetBuffers, "KBcaOptNameBcaResetBuffers");
-_LIT8(KLitOptNameSerialPortName, "KBcaOptNameSerialPortName");
-_LIT8(KLitOptNameSerialConfig, "KBcaOptNameSerialSerialConfig");
-_LIT8(KLitOptNameSerialSetConfig, "KBcaOptNameSerialSerialSetConfig");
-_LIT8(KLitOptNameSerialSetCsyName, "KBcaOptNameBcaSetCsyName");
-_LIT8(KLitOptNameSerialSetCommRole, "KBcaOptNameSetCommRole");
-_LIT8(KLitSerialSetTxRxBufferSize, "KSerialSetTxRxBufferSize");
-_LIT8(KLitSerialTxRxBufferSize, "KSerialTxRxBufferSize");
-_LIT8(KLitSerialMonitorControlLines, "KSerialMonitorControlLines");
-_LIT8(KLitSerialSetControlLines, "KSerialSetControlLines");
-_LIT8(KLitOptNameUnsupported, "**Unsupported**");
-
-
-/**
-Returns a string for the given option name
-
-@param aOptLevel BCA Option Name
-@return readable string for aOptName
-*/
-static const TDesC8& IoctlOptNameStr(TUint32 aOptName)
- {
- switch(aOptName)
- {
- case KBCACaps:
- return KLitOptNameBcaCaps;
- case KVersionNumber:
- return KLitOptNameBcaVersionNumber;
- case KBCASetIapId:
- return KLitOptNameBcaSetIapId;
- case KBCASetBcaStack:
- return KLitOptNameBcaSetBcaStack;
- case KBCAResetBuffers:
- return KLitOptNameBcaResetBuffers;
- case KSerialPortName:
- return KLitOptNameSerialPortName;
- case KSerialConfig:
- return KLitOptNameSerialConfig;
- case KSerialSetConfig:
- return KLitOptNameSerialSetConfig;
- case KSerialSetCsyName:
- return KLitOptNameSerialSetCsyName;
- case KSerialSetCommRole:
- return KLitOptNameSerialSetCommRole;
- case KSerialSetTxRxBufferSize:
- return KLitSerialSetTxRxBufferSize;
- case KSerialTxRxBufferSize:
- return KLitSerialTxRxBufferSize;
- case KSerialMonitorControlLines:
- return KLitSerialMonitorControlLines;
- case KSerialSetControlLines:
- return KLitSerialSetControlLines;
- default:
- return KLitOptNameUnsupported;
- }
- }
-#endif // __FLOG_ACTIVE
-
-
-#ifdef __FLOG_ACTIVE
-/**
-Print debug output of the TCommComfig parameters.
-
-@param The configuration whose parameters should be logged.
-*/
-void CC32Bca::LogCommConfig(TCommConfig& c)
- {
- __FLOG_5(_L8("Rate[%d] DataBits[%d] StopBits[%d] Parity[%d] Handshake[0x%x]"), c().iRate, c().iDataBits, c().iStopBits, c().iParity, c().iHandshake);
- __FLOG_4(_L8("ParityError[%d] Fifo[%d] SpecialRate[%d] terminatorCount[%d]"), c().iParityError, c().iFifo, c().iSpecialRate, c().iTerminatorCount);
- __FLOG_1(_L8("Terminator[0x%x]"), c().iTerminator);
- }
-#endif // __FLOG_ACTIVE
-
-
-/**
-* Ioctl: asynchronously controls the C32Bca.
-
-* @param aStatus complete status, KErrNone if successful, system-wide error code otherwise.
-* @param aOptLevel option level to be used.
-* @param aOptName option name to be used.
-* @param aOpt an optional parameter,holds the option value on return or the option value to be set.
-*/
-void CC32Bca::Ioctl(TRequestStatus& aStatus, TUint aOptLevel, TUint aOptName, TDes8& aOpt)
-
- {
- __FLOG_4(_L8("Ioctl: Level[%S](0x%X) Name[%S](0x%X)."), &IoctlOptLevelStr(aOptLevel), aOptLevel, &IoctlOptNameStr(aOptName), aOptName);
-
- aStatus = KRequestPending;
-
- TInt ret(KErrNone); // If operation fails, this will be set to the failure code explicitly.
-
- // Don't check the port status. Let C32 panic. It's the caller's responsibility to make sure that
- // the port is in a valid state (for most operations, open & not having any Tx Rx ops outstanding)
- if(aOptLevel == KBcaOptLevelGeneric)
- {
- switch(aOptName)
- {
- case KBCACaps:
- {
- const TPckg<TUint> capPckg(KBcaCapSerial);
- aOpt = capPckg;
- break;
- }
-
- case KVersionNumber:
- {
- const TPckg<TUint> versionPckg(KVersion); //lower 16 contains KC32BcaMinorversionNumber, upper 16 bit contains KC32BcaMajorVersionNumber.
- aOpt = versionPckg;
- break;
- }
-
- case KBCASetIapId:
- {
- TUint32 tempIapId = *(reinterpret_cast<const TUint32*>(aOpt.Ptr()));
-
- __FLOG_1(_L8("Ioctl: IAP ID [%d] specified."),tempIapId);
-
- if(tempIapId < 1 )
- {
- ret = KErrArgument;
- }
- else
- {
- iIapId = tempIapId;
- }
- break;
- }
-
- case KBCAResetBuffers:
- {
- TUint resetBufMaskArg = *(reinterpret_cast<const TUint32*>(aOpt.Ptr()));
- TUint resetBufMask(0x0);
-
- if(resetBufMaskArg & KResetRxBuf)
- {
- resetBufMask |= KCommResetRx;
- }
- if(resetBufMaskArg & KResetTxBuf)
- {
- resetBufMask |= KCommResetTx;
- }
- ret = iComm.ResetBuffers(resetBufMask);
- break;
- }
-
-
- default:
- {
- ret = KErrNotSupported;
- }
- }
- }
- else if(aOptLevel == KBcaOptLevelExtSerial)
- {
- switch(aOptName)
- {
- case KSerialCaps:
- {
- iComm.Caps(aOpt);
- break;
- }
-
- case KSerialConfig:
- {
- __FLOG(_L8("Ioctl: KSerialConfig"));
-
- TCommConfig cfg;
- iComm.Config(cfg);
-
-#ifdef __FLOG_ACTIVE
- LogCommConfig(cfg);
-#endif // __FLOG_ACTIVE
-
- TPckgBuf<TCommConfig> cfgBuf(cfg);
- aOpt.Copy(cfgBuf);
- break;
- }
-
- case KSerialSetConfig:
- {
- __FLOG(_L8("Ioctl: KSerialSetConfig"));
-
- TCommConfig cfg(*(reinterpret_cast<const TCommConfig*>(aOpt.Ptr())));
-
-#ifdef __FLOG_ACTIVE
- LogCommConfig(cfg);
-#endif // __FLOG_ACTIVE
-
- ret = iComm.SetConfig(cfg);
- break;
- }
-
- case KSerialPortName:
- {
- aOpt.Copy(iCommPort);
- break;
- }
-
- case KSerialSetCsyName:
- {
- if(!iCommPortOpen)
- {
- iCsyName.Copy(*(
- reinterpret_cast<const TName*>(aOpt.Ptr())
- ));
- iCsyNameOverride = ETrue;
- __FLOG_1(_L8("Ioctl: CSY Name set to [%S]"), &iCsyName);
- }
- else
- {
- __FLOG(_L8("Ioctl: Warning: Cannot set the CSY name because the Comm Port is already open."));
- ret = KErrAlreadyExists;
- }
-
- break;
- }
-
- case KSerialSetCommRole:
- {
- if(!iCommPortOpen)
- {
- iCommRole = *(reinterpret_cast<const TCommRole*>(aOpt.Ptr()));
- iCommRoleOverride = ETrue;
- __FLOG_1(_L8("Ioctl: Comm Role set to [%d]"), iCommRole);
- }
- else
- {
- __FLOG(_L8("Ioctl: Warning: Cannot set Comm Role because the Comm Port is already open."));
- ret = KErrAlreadyExists;
- }
- break;
- }
-
- case KSerialSetTxRxBufferSize:
- {
- TInt bufSize = *(reinterpret_cast<const TInt*>(aOpt.Ptr()));
- __FLOG_1(_L8("Ioctl: Setting Rx Tx buffer size to [%d]"), bufSize);
-
- iComm.SetReceiveBufferLength(bufSize);
- break;
- }
-
- case KSerialMonitorControlLines:
- {
- TRAP(ret, MonitorControlLinesL(*(reinterpret_cast<const TUint*>(aOpt.Ptr()))));
- break;
- }
-
- case KSerialSetControlLines:
- {
- if (aOpt.Length() != sizeof(TSerialSetControlLines))
- {
- ret = KErrArgument;
- }
- else
- {
- const TSerialSetControlLines& lines = *(reinterpret_cast<const TSerialSetControlLines*>(aOpt.Ptr()));
- __FLOG_2(_L8("Ioctl: Setting/clearing control lines %x/%x"), lines.iSetMask, lines.iClearMask);
- iComm.SetSignals(lines.iSetMask, lines.iClearMask);
- ret = KErrNone;
- }
- break;
- }
-
- default:
- ret = KErrNotSupported;
- }
- }
- else
- {
- ret = KErrNotSupported;
- }
-
-
- __FLOG_1(_L8("Ioctl completed with error %d"), ret);
-
- TRequestStatus* ptrStatus = &aStatus;
- User::RequestComplete(ptrStatus, ret);
- }
-
-/** Enables / Disables monitoring & link down reporting on the specified control lines
-
-@param aMask bitmaks specifying the lines to monitor, OR
- KMonitorOff to turn monitoring off, OR
- KConfigFailBcaSpecificOnly to set up monitoring according to Comm Role only
-
-@leave if the monitoring object cannot be constructed, typically due to OOM.
-*/
-void CC32Bca::MonitorControlLinesL(TUint32 aArgMask)
- {
- __FLOG_1(_L8("Ioctl: argument bitmask = [0x%X] "), aArgMask);
-
- if(iLinkMonitor) // We may have never started...
- {
- // We are called to either stop or change the monitoring options.
- iLinkMonitor->Cancel(); // If we are not monitoring, this has no effect.
- }
-
- if(KMonitorOff == aArgMask) // Stop monitoring:
- {
- __FLOG(_L8("MonitorControlLinesL: Stopping Control Lines monitoring."));
- // We either never started, or we just cancelled above.
- }
- else // Start Monitoring, or change the monitored lines.
- {
- __FLOG(_L8("MonitorControlLinesL: Starting to monitor Control Lines."));
-
- if(!iLinkMonitor) // We are starting to monitor for the first time
- {
- iLinkMonitor = new (ELeave)CCommLinkMonitor(*this, iComm);
- }
- // At this point we have a monitoring object that isn't active.
-
- // A CSY does not necessarily handle the KConfigFail* correctly. For example, if
- // a DTR is initially low, because the terminal was not plugged in yet, we get a failure straight away,
- // So, we translate the failure arguments and monitor the relevant lines ourselves. We fail only when a line
- // is disasserted. This is absolutely necessary to support server-mode PPP, because we may need to wait
- // an arbitrary period of time for the user to plug the terminal in.
- TUint32 lineMask(0x0);
- if(KFailBcaSpecificOnly == aArgMask) // We decide what lines to monitor
- {
- // N.B. When a DTE, fail on low DSR. This is necessary to detect a disconnection on serial links that
- // do not utilise DCD.
- lineMask = (ECommRoleDCE == iCommRole) ? KSignalDTR : KSignalDCD | KSignalDSR;
- }
- else // User explicitly specified the control lines.
- {
- // Don't bother with sanity checks on the lines. Let C32 handle it.
-
- if(KConfigFailCTS & aArgMask)
- {
- lineMask |= KSignalCTS;
- }
- if(KConfigFailDSR & aArgMask)
- {
- lineMask |= KSignalDSR;
- }
- if(KConfigFailDCD & aArgMask)
- {
- lineMask |= KSignalDCD;
- }
- if(KConfigFailDTR & aArgMask)
- {
- lineMask |= KSignalDTR;
- }
- if(KConfigFailRTS & aArgMask)
- {
- lineMask |= KSignalRTS;
- }
- }
-
- iLinkMonitor->Setup(lineMask);
- iLinkMonitor->NotifyLinkDown();
-
- __FLOG(_L8("MonitorControlLinesL: Control Lines monitoring started."));
- }
- }
-
-/**
-Closes the connection to CommDB, if it is open */
-void CC32Bca::CloseCommDbConnection()
- {
- delete iCommsDat;
- iCommsDat = NULL;
- }
-
-/**
-Read Comm Port from CommDB bearer record
-@param aPortName
-@leave if the value could not be read */
-void CC32Bca::ReadCommPortFromCommDbL(TDes& aPortName)
- {
- __FLOG(_L8("CC32Bca::ReadCommPortFromCommDbL()"));
- ConnectToCommDbBearerRecordL();
-
- TInt ret(0);
- CMDBField<TDesC>* portField = new(ELeave) CMDBField<TDesC>(KCDTIdPortName);
- CleanupStack::PushL(portField);
-
- portField->SetRecordId(iModemId);
- portField->SetMaxLengthL(KMaxTextLength);
- TRAP(ret,portField->LoadL(*iCommsDat));
-
- if(ret!=KErrNone)
- {
- __FLOG_1(_L8("portField->LoadL(*iCommsDat) left with[%d] "), ret);
- User::Leave(ret);
- }
-
- aPortName = *portField;
- CleanupStack::PopAndDestroy(portField);
- }
-
-/**
-Read the CSY name from CommDB bearer record.
-@param aCsyName the CSY name
-@leave if the value could not be read */
-void CC32Bca::ReadCsyNameFromCommDbL(TDes& aCsyName)
- {
- __FLOG(_L8("CC32Bca::ReadCsyNameFromCommDbL()"));
- ConnectToCommDbBearerRecordL();
-
- TInt ret(0);
- CMDBField<TDesC>* csyField = new(ELeave) CMDBField<TDesC>(KCDTIdCsyName);
- CleanupStack::PushL(csyField);
-
- csyField->SetRecordId(iModemId);
- csyField->SetMaxLengthL(KMaxTextLength);
- TRAP(ret,csyField->LoadL(*iCommsDat));
-
- if(ret!=KErrNone)
- {
- __FLOG_1(_L8("csyField->LoadL(*iCommsDat) left with[%d] "), ret);
- User::Leave(ret);
- }
-
- aCsyName = *csyField;
- CleanupStack::PopAndDestroy(csyField);
- }
-
-/**
-Read the specified Comm role (DTE / DCE) from CommDB bearer record
-
-@param aCommRole the specified role.
-@leave if the value could not be read */
-void CC32Bca::ReadCommRoleFromCommDbL(TCommRole& aCommRole)
- {
- __FLOG(_L8("CC32Bca::ReadCommRoleFromCommDbL()"));
- ConnectToCommDbBearerRecordL();
- TUint32 role(0);
-
- TInt ret(0);
- CMDBField<TUint32>* roleField = new(ELeave) CMDBField<TUint32>(KCDTIdCommRole);
- CleanupStack::PushL(roleField);
-
- roleField->SetRecordId(iModemId);
- TRAP(ret,roleField->LoadL(*iCommsDat));
-
- if(ret!=KErrNone)
- {
- __FLOG_1(_L8("roleField->LoadL(*iCommsDat) left with[%d] "), ret);
- User::Leave(ret);
- }
-
- role = *roleField;
- CleanupStack::PopAndDestroy(roleField);
-
- aCommRole = (0 == (role & KModemCommRoleDCE)) ? ECommRoleDTE : ECommRoleDCE;
- }
-
-/**
-Opens a connection to the ModemBearer record specified by the provisioned IAP ID.
-
-@leave KErrNotReady, if the provisioned IAP id is invalid. System-wide error code
- if the connection cannot be opened for some other reason.
-*/
-void CC32Bca::ConnectToCommDbBearerRecordL()
- {
- __FLOG(_L8("CC32Bca::ConnectToCommDbBearerRecordL()"));
- if(iCommsDat != NULL) // CommDB is already open, we don't need to do anything
- {
- return;
- }
-
- if(iIapId < 1) // Can't access CommDB if IAP ID is unknown
- {
- __FLOG_1(_L8("iIapId[%d] is unknown"), iIapId);
- User::Leave(KErrNotReady);
- }
-
- //
- // Open connecton to CommDB Bearer record specified by the IAP.
- //
-#ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
- iCommsDat = CMDBSession::NewL(KCDVersion1_2);
-#else
- iCommsDat = CMDBSession::NewL(KCDVersion1_1);
-#endif
-
- CCDIAPRecord *iapRecord = static_cast<CCDIAPRecord*>(CCDRecordBase::RecordFactoryL(KCDTIdIAPRecord));
- CleanupStack::PushL(iapRecord);
-
- iapRecord->SetRecordId(iIapId);
-
- TBool hiddenAttributeMaskValue = iCommsDat->IsSetAttributeMask(ECDHidden);
- TBool privateAttributeMaskValue = iCommsDat->IsSetAttributeMask(ECDPrivate);
-
- // Check to see if viewing hidden records is enabled or not
- if(!hiddenAttributeMaskValue || !privateAttributeMaskValue)
- {
- // Reveal hidden or private IAP records if a licensee has chosen to protect a record
- // using one of these flags - the API to do this is public so internal components
- // have to support the use of such records.
- iCommsDat->SetAttributeMask(ECDHidden | ECDPrivate);
- }
-
- TRAPD(ret,iapRecord->LoadL(*iCommsDat));
- if (ret != KErrNone)
- {
- __FLOG_1(_L8("iapRecord->LoadL(*iCommsDat) left with[%d] "), ret);
- User::Leave(ret);
- }
-
- // If we enabled viewing hidden records now disable viewing them.
- if(!hiddenAttributeMaskValue)
- {
- iCommsDat->ClearAttributeMask(ECDHidden);
- }
- if(!privateAttributeMaskValue)
- {
- iCommsDat->ClearAttributeMask(ECDPrivate);
- }
-
-
- iModemId = iapRecord->iBearer;
- CleanupStack::PopAndDestroy(iapRecord);
-
- if(iModemId == 0) // ID not found.
- {
- __FLOG_1(_L8("iModemId[%d] is not found"), iModemId);
- User::Leave(KErrNotFound);
- }
- }
-
-
-/** Cancels an outstanding Ioctl, if any. */
-void CC32Bca::CancelIoctl()
- {
- __FLOG(_L8("CancelIoctl(): Ioctl cancel request. No Ioctl to cancel."));
- }
-
-
-/** Closes the Comm port and Comm Server.*/
-void CC32Bca::CloseCommPort()
- {
- __ASSERT_ALWAYS(iReader, Panic(ENullReaderOnClose));
- __ASSERT_ALWAYS(iWriter, Panic(ENullWriterOnClose));
-
- // When we close the port, all async requests outstanding are cancelled.
- // We must make sure nobody is waiting on them. If the underlying request is cancelled,
- // but the owner AO is not, Cancel() on such AO hangs waiting for the request to complete.
-
- iReader->Cancel();
- iWriter->Cancel();
- if(iLinkMonitor) // Link monitor is constructed on client request only.
- {
- iLinkMonitor->Cancel();
- }
-
- if (iCommPortOpen)
- {
- iComm.Close();
- iCommServ.Close();
- iCommPortOpen = EFalse;
- }
- __FLOG(_L8("CloseCommPort(): Session with C32 & RComm closed."));
- }
-
-/**
-C32Bca Panic function
-@internalComponent
-*/
-void C32Bca::Panic(TC32BcaPanic aPanic)
- {
- __FLOG_STATIC2(KC32BcaLogFolder,KC32BcaLogFile,_L8("%S Panic %d"), &KC32BcaPanic(), aPanic);
- User::Panic(KC32BcaPanic, aPanic);
- }
-
-
-// MC32User implementation:
-
-// Read has completed.
-void CC32Bca::CommReadComplete(TInt aErr)
- {
- __ASSERT_ALWAYS(iReadRequest, Panic(ENullReadRequestStatus));
- __ASSERT_DEBUG(KRequestPending == iReadRequest->Int(), Panic(EReadRequestNotPending));
-
- User::RequestComplete(iReadRequest, aErr);
- }
-
-// Write has completed.
-void CC32Bca::CommWriteComplete(TInt aErr)
- {
- __ASSERT_ALWAYS(iWriteRequest, Panic(ENullWriteRequestStatus));
- __ASSERT_DEBUG(KRequestPending == iWriteRequest->Int(), Panic(EWriteRequestNotPending));
-
- User::RequestComplete(iWriteRequest, aErr);
- }
-
-// Upcall from the link monitor: Link has gone down.
-void CC32Bca::CommLinkDown(TInt aErr)
- {
- __FLOG_1(_L8("CommLinkDown: Warning: serial link has gone down with error[%d]. Erroring the outstanding Read & Write."), aErr);
-
- __ASSERT_DEBUG(KErrNone != aErr, Panic(EGeneralLogicError)); // If KErrNone, use has no way to know that the read has failed.
- if(iReader->IsActive())
- {
- CommReadComplete(aErr);
- iReader->Cancel();
- }
- else
- {
- iErrorOnNextRead = aErr;
- }
-
- if(iWriter->IsActive())
- {
- CommWriteComplete(aErr);
- iWriter->Cancel();
- }
- else
- {
- iErrorOnNextWrite = aErr;
- }
- }
+// Copyright (c) 2004-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:
+// C32 Baseband Channel Adaptor(BCA) APIs implementation.
+// This file contains all the API implementation of the C32BCA interface for Symbian OS.
+//
+//
+
+/**
+ @file
+ @internalComponent
+*/
+
+#include "C32Bca.h"
+#include <cdbcols.h>
+#include <commsdat_partner.h>
+
+using namespace BasebandChannelAdaptation;
+using namespace BasebandChannelAdaptation::C32Bca;
+
+const static TUint KVersion = ((static_cast<TUint>(KC32BcaMajorVersionNumber)) << 16) | KC32BcaMinorVersionNumber;
+
+
+/**
+C++ constructor for an object representing a c32 async user
+
+@param aUser the target of the notifications originating in C32
+@param aPort the C32 port to be used with this object
+@param aAoPriority the priority to assign to this active object
+*/
+CCommBase::CCommBase(MC32User& aUser, RComm& aPort, TInt aAoPriority):
+ CActive(aAoPriority),
+ iUser(aUser),
+ iPort(aPort)
+ {
+ CActiveScheduler::Add(this);
+ __FLOG_OPEN(KC32BcaLogFolder, KC32BcaLogFile); // Connect to the BCA logger
+ }
+
+/**
+C++ destructor */
+CCommBase::~CCommBase()
+ {
+ __FLOG_CLOSE;
+ }
+
+/**
+C++ constructor
+The comm-reader has a higher priority than the comm-writer, to
+ensure the reader gets the chance to receive the incomming data
+
+@param aUser the target of the notifications originating in C32
+@param aPort the C32 port to be used with this object
+*/
+CCommReader::CCommReader(MC32User& aUser, RComm& aPort):
+ CCommBase(aUser, aPort, EPriorityHigh)
+ {
+ }
+
+/**
+C++ destructor */
+CCommReader::~CCommReader()
+ {
+ Cancel();
+ }
+
+/**
+Cancels the outstanding read */
+void CCommReader::DoCancel()
+ {
+ iPort.ReadCancel();
+ }
+
+/**
+Issues a read on the serial port
+
+@param aBuf the buffer to read to */
+void CCommReader::Read(TDes8& aBuf)
+ {
+ iPort.ReadOneOrMore(iStatus, aBuf);
+ SetActive();
+ }
+
+/**
+Called on read completion */
+void CCommReader::RunL()
+ {
+ iUser.CommReadComplete(iStatus.Int());
+ }
+
+/**
+C++ constructor
+The comm-writer has a lower priority than the comm-reader, to
+ensure the reader gets the chance to receive the incomming data
+
+@param aUser the target of the notifications originating in C32
+@param aPort the C32 port to be used with this object */
+CCommWriter::CCommWriter(MC32User& aUser, RComm& aPort):
+ CCommBase(aUser, aPort, EPriorityUserInput)
+ {
+ }
+
+/**
+C++ destructor */
+CCommWriter::~CCommWriter()
+ {
+ Cancel();
+ }
+
+/**
+Issues a write on the serial port */
+void CCommWriter::Write(const TDesC8& aBuf)
+ {
+ iPort.Write(iStatus, aBuf);
+ SetActive();
+ }
+
+/**
+Called when the write completes
+*/
+void CCommWriter::RunL()
+ {
+ iUser.CommWriteComplete(iStatus.Int());
+ }
+
+/**
+Cancels the outstanding write
+*/
+void CCommWriter::DoCancel()
+ {
+ iPort.WriteCancel();
+ }
+
+/**
+C++ constructor
+
+@param aUser the target of the notifications originating in C32
+@param aPort the C32 port to be used with this object
+
+
+Note on Monitor AO priority:
+
+Monitor AO is the same priority as the Reader / Writer by design.
+
+We do NOT want link failure notification to complete before all possible outstanding reads / writes
+have completed, to make sure that we do not lose any data that was already received from the
+baseband and is buffered by the driver or the CSY.
+Consider a scenario where a UDP datagram is received by the CSY, and then the serial link is
+severed (e.g. cable is unplugged by the user). If the Monitor has higher priority than reader/writer,
+we may get failure notification before we are notified on the read of this UDP datagram, potentially
+resulting in its loss (E.g. PPP shuts down when on Link Down notification.)
+*/
+CCommLinkMonitor::CCommLinkMonitor(MC32User& aUser, RComm& aPort):
+ CCommBase(aUser, aPort, EPriorityStandard)
+ {
+ }
+
+/**
+Sets the object to monitor the link for the configured Role, DTE or DCE
+
+@param aMask DTE or DCE: determines when the link is considered to be down.
+*/
+void CCommLinkMonitor::Setup(TUint32 aMask)
+ {
+ iNotifyChangeSignalMask = aMask;
+ __FLOG_1(_L8("CommLinkMonitor setup: Notify on signal mask [0x%X]"),iNotifyChangeSignalMask);
+ }
+
+/**
+Requests to be notified when the link is down.
+
+Can be called an more than once
+*/
+void CCommLinkMonitor::NotifyLinkDown()
+ {
+ ASSERT(!IsActive());
+
+ // get the current state of the line so when we get notification we can tell if it really has changed
+ iSavedSignalState = iPort.Signals(iNotifyChangeSignalMask) & iNotifyChangeSignalMask;
+ iPort.NotifySignalChange(iStatus, iSignals, iNotifyChangeSignalMask);
+
+ __FLOG_1(_L8("CommLinkMonitor::NotifyLinkDown: initial signals: [0x%X]"), iSavedSignalState);
+
+ SetActive();
+ }
+
+/**
+Called when EIA-232 signals change,i.e. on potential link failure
+*/
+void CCommLinkMonitor::RunL()
+ {
+ __FLOG_2(_L8("CommLinkMonitor::RunL: Signals changed [0x%X]; new signals [0x%X]"), iSignals & (~0x1F), iSignals & 0x1F);
+
+ // We report link failure if and only if a monitored line went from high to low.
+ // Method: mask the saved signals using inverted monitored bits in the signal bitmask,
+ // to filter out all transitions except for high -> low.
+ // 1 & ~0 = 1; 1 & ~1 = 0; 0 & ~1 = 0; 0 & ~0 = 0
+ // This is necessary, because we may be monitoring more than one signal, and the change can be arbitrary.
+ if ((~(iNotifyChangeSignalMask & iSignals)) & iSavedSignalState)
+ {
+ iUser.CommLinkDown(KErrCommsLineFail);
+ }
+ iSavedSignalState = iSignals & iNotifyChangeSignalMask; // update saved state with relevant bits
+ iPort.NotifySignalChange(iStatus, iSignals, iNotifyChangeSignalMask);
+ SetActive();
+ // Note: If the link went down, the user will likely shutdown the BCA on outstanding signal notification.
+ }
+
+/**
+Cancels notification request of link failure */
+void CCommLinkMonitor::DoCancel()
+ {
+ __FLOG(_L8("CommLinkMonitor::DoCancel: Cancelling signal change notification."));
+ iPort.NotifySignalChangeCancel();
+ }
+
+
+
+
+
+/**
+* default constructor to create a C32Bca instance.
+*/
+CC32Bca::CC32Bca()
+ {
+ __FLOG_OPEN(KC32BcaLogFolder,KC32BcaLogFile);
+ __FLOG_2(_L8("====== CC32Bca::CC32Bca: Shim BCA for C32 [Vesion: major= %d minor= %d] Constructed. ======"), KC32BcaMajorVersionNumber, KC32BcaMinorVersionNumber);
+ }
+
+/**
+2nd phase of construction: allocates member objects
+
+
+@leave when members cannot be constructed. */
+void CC32Bca::ConstructL()
+ {
+ __ASSERT_DEBUG(!iReader, Panic(EReaderAlreadyExists));
+ __ASSERT_DEBUG(!iWriter, Panic(EWriterAlreadyExists));
+ __ASSERT_DEBUG(!iLinkMonitor, Panic(EMonitorAlreadyExists));
+
+ // Comm is not initialized yet. We have to be Opened before it can be used. C32 panics otherwise.
+ iReader = new (ELeave)CCommReader(*this, iComm);
+ iWriter = new (ELeave)CCommWriter(*this, iComm);
+ // Monitor is created upon user request only, we may never need it at all.
+ }
+
+/**
+* Destructor
+*/
+CC32Bca::~CC32Bca()
+
+ {
+ __FLOG(_L8("CC32Bca::~CC32Bca: releasing resources..."));
+
+ CloseCommDbConnection();
+ CloseCommPort(); // Cancels reader / writer / monitor
+
+ // N.B.:
+ // It is critical that these objects are cancelled before deletion. Else DoCancel operates on closed C32 port,
+ // causing C32 to panic.
+ delete iReader;
+ delete iWriter;
+ delete iLinkMonitor; // Note: may have never been created.
+
+ __FLOG(_L8("CC32Bca::~CC32Bca: CC32Bca destroyed."));
+ __FLOG_CLOSE;
+ }
+
+/** This method deletes the BCA itself.*/
+void CC32Bca::Release()
+ {
+ __FLOG(_L8("CC32Bca::Release"));
+ delete this;
+ }
+
+/**
+* Informs that the BCA is required by the client(for instance, Raw IP NIF).Comms Server is
+* connected, and serial port is opened.
+
+* @param aStatus complete status, KErrNone if successful, C32 error code otherwise.
+* @param aChannelId comm port name.
+*/
+void CC32Bca::Open(TRequestStatus& aStatus, const TDesC& aChannelId)
+ {
+ // We don't have the ConstructL, so we have to allocate memory here.
+
+ aStatus = KRequestPending;
+ // avoid compiler warning.
+ TRequestStatus* ptrStatus = &aStatus;
+ if(iCommPortOpen)
+ {
+ __FLOG(_L8("Warning: C32Bca is already Opened."));
+
+ User::RequestComplete(ptrStatus,KErrNone);
+ return;
+ }
+
+ if(aChannelId == KChannelIdNotOverridden) // Channel ID is not supplied - Comm Port Name is not overriden.
+ { // Read it from CommDB.
+ // Fetch port name from CommDB.
+ TRAPD(commPortErr, ReadCommPortFromCommDbL(iCommPort));
+
+ // If the column is missing from CommDB, we can get an empty string with KErrNone.
+ // Opening RComm with empty string as Port name fails with ECUART, LOOOPBACK CSYs.
+ // with different error codes on 8.1 and 9.0.
+ // It would be better to intercept such invalid value and fail here.
+ // This is not done, because theoretically it is possible to write a CSY that somehow takes an
+ // emty descriptor as a port name. As of December 2004, C32 does not allow that, however, this
+ // may change in the future.
+ // So, we just log a warning.
+ if(KErrNone == commPortErr && iCommPort.Size() == 0)
+ {
+ __FLOG(_L8("Warning: Null string read from CommDB. Will try to open Comm Port anyway."));
+ }
+
+ if(KErrNone != commPortErr) // Fatal: we do not have a port name. Can't open RComm.
+ {
+ __FLOG(_L8("Error: Failed to get C32 PortName from CommDB "));
+ CloseCommDbConnection();
+ User::RequestComplete(ptrStatus, commPortErr);
+ return;
+ }
+ }
+ else // Channel ID supplied - use it as Port Name.
+ {
+ _LIT(KDoubleColon, "::");
+ TInt len1 = aChannelId.Find(KDoubleColon);
+
+ if (len1 < KErrNone)
+ {
+ __FLOG(_L8("** ERROR: No :: (Double Colon) in aChannelId **"));
+ User::RequestComplete(ptrStatus, KErrBadName);
+ return;
+ }
+ else
+ {
+ TUint numPos = len1 + KDoubleColon.iTypeLength;
+
+ TInt len2 = (aChannelId.Mid(numPos)).Find(KDoubleColon);
+
+ if (len2 < KErrNone)
+ {
+ iCommPort = aChannelId;
+ }
+ else
+ {
+ iCommPort = aChannelId.Mid(numPos);
+ iCsyName = aChannelId.Mid(0, len1);
+ iCsyNameOverride = ETrue;
+ }
+ }
+ }
+ // We have the Port Name at this point: either supplied as a parameter, or read from CommDB.
+
+ if(!iCsyNameOverride) // CSY name is not provisioned by Ioctl: read it from CommDB.
+ {
+ TRAPD(getCsyErr, ReadCsyNameFromCommDbL(iCsyName));
+ if(KErrNone != getCsyErr) // Fatal: we do not have a CSY name. Can't load CSY module.
+ {
+ // We do not use a hardcoded value (e.g. ECUART), because the client code or the environment are
+ // confused - it is better to fail them, rather than mask their problems.
+ __FLOG(_L8("Error: Failed to get CSY name from CommDB "));
+ CloseCommDbConnection();
+ User::RequestComplete(ptrStatus,getCsyErr);
+ return;
+ }
+ }
+ // We have the CSY name at this point, either provisioned via Ioctl, or read from CommDB.
+
+ // Decide the Comm Role (DCE / DTE) of the port.
+ TBool isCommRoleDefault = EFalse;
+ // We use a concept of "Default Comm Role", because C32 has it. We could use DTE as a default
+ // setting, but we prefer to call the "default" method on C32 and let it decide what the role should be.
+
+ if(!iCommRoleOverride) // Port role not overriden via Ioctl
+ {
+ TRAPD(getCommRoleErr, ReadCommRoleFromCommDbL(iCommRole));
+ if(KErrNone != getCommRoleErr) // Port role not specified via CommDb
+ {
+ isCommRoleDefault = ETrue; // Port role not specified via Ioctl or CommDb
+ }
+ }
+ // We have the Comm Role: provisioned via Ioctl, read from CommDB, or default(DTE)
+
+ CloseCommDbConnection(); // We do not read any settings once the connection is opened.
+ // We have all the necessary C32 settings at this point.
+ // Open the actual C32 session:
+
+ TInt ret = iCommServ.Connect();
+ if(ret)
+ {
+ __FLOG_1(_L8("Open: C32 Server connection error %d"), ret);
+ User::RequestComplete(ptrStatus,ret);
+ return;
+ }
+ ret = iCommServ.LoadCommModule(iCsyName);
+
+ __FLOG_2(_L16("Open: CSY module [%S] loaded with error %d"), &iCsyName, ret);
+
+ if(ret)
+ {
+ User::RequestComplete(ptrStatus,ret);
+ return;
+ }
+
+ if(isCommRoleDefault)
+ {
+ ret = iComm.Open(iCommServ, iCommPort, ECommShared);
+ }
+ else
+ {
+ ret = iComm.Open(iCommServ, iCommPort, ECommShared, iCommRole);
+ }
+
+ __FLOG_2(_L16("Open: C32 port [%S] opened with error %d"), &iCommPort, ret);
+
+ if(ret)
+ {
+ User::RequestComplete(ptrStatus,ret);
+ return;
+ }
+ //
+ //Open successfull, we update our state.
+ //
+
+ // We may have been closed, and are being reopened now. Make sure no errors persist from the previous session.
+ iErrorOnNextRead = KErrNone;
+ iErrorOnNextWrite = KErrNone;
+ iCommPortOpen = ETrue;
+
+ User::RequestComplete(ptrStatus,KErrNone);
+ // Don't start control line monitoring. This is done on user request via Ioctl only.
+ }
+
+/**
+ Shuts the BCA channel down in a graceful manner. BCA releases its resources.
+ Cancels all outstanding operations: Writes, Reads and Ioctls.
+
+ Due to the specifics of C32Bca implementation, this call completes immediately and is identical to ::Close.
+
+ @param aStatus completion status: Always KErrNone.
+*/
+void CC32Bca::Shutdown(TRequestStatus& aStatus)
+ {
+ aStatus = KRequestPending;
+
+ CloseCommPort();
+
+ // Don't notify reader / writer / monitor. Read / Write should not be called after this anyway. Let C32 panic.
+
+ TRequestStatus* request = &aStatus;
+ User::RequestComplete(request, KErrNone);
+ __FLOG_1(_L8("C32Bca::Shutdown: BCA shut down with error %d"), KErrNone);
+ }
+
+/**
+* Closes the BCA immediately. BCA releases its resources.
+* cancels all Writes, Reads and Controls.
+*/
+void CC32Bca::Close()
+ {
+ CloseCommPort();
+ __FLOG_1(_L8("C32Bca::Close:Close: BCA closed with error %d"), KErrNone);
+ }
+
+/**
+* Queues a Read on C32 serial port.
+
+* @param aStatus complete status, KErrNone if successful, C32 error code otherwise.
+* @param aBuf buffer for data to be read.
+* @note The buffer is owned by the client. Client must not access / modify the buffer until the Read completes.
+*/
+void CC32Bca::Read(TRequestStatus& aStatus,TDes8& aBuf)
+ {
+ iReadRequest = &aStatus;
+ *iReadRequest = KRequestPending;
+
+ if(iErrorOnNextRead)
+ {
+ User::RequestComplete(iReadRequest, iErrorOnNextRead);
+ // Error persists until the BCA is closed and opened
+ }
+ else
+ {
+ iReader->Read(aBuf);
+ }
+ }
+
+/**
+* Queues a Write on C32 serial port.
+
+* @param aStatus the complete status, KErrNone if successful, C32 error code otherwise.
+* @param aBuf the buffer to sent.
+* @note The buffer is owned by the client. Client must not access / modify the buffer until the Write completes.
+*/
+void CC32Bca::Write(TRequestStatus& aStatus,const TDesC8& aBuf)
+ {
+ iWriteRequest = &aStatus;
+ *iWriteRequest = KRequestPending;
+
+ if(iErrorOnNextWrite)
+ {
+ User::RequestComplete(iWriteRequest, iErrorOnNextWrite);
+ // Error persists until BCA is closed and opened.
+ }
+ else
+ {
+ iWriter->Write(aBuf);
+ }
+ }
+
+/**
+ Cancels the outstanding Read operation.(best effort operation: the read may have been completed already.)
+*/
+void CC32Bca:: CancelRead()
+
+ {
+ __FLOG(_L8("CancelRead: Read is cancelled by client."));
+ iReader->Cancel();
+
+ if(iReadRequest != NULL)
+ {
+ User::RequestComplete(iReadRequest, KErrCancel);
+ }
+ }
+
+/**
+ Cancels all Write operations.(best effort attempt: the write may have been completed already.)
+*/
+void CC32Bca::CancelWrite()
+
+ {
+ __FLOG(_L8("CancelWrite: Write is cancelled by client."));
+
+ iWriter->Cancel();
+
+ if(iWriteRequest != NULL)
+ {
+ User::RequestComplete(iWriteRequest, KErrCancel);
+ }
+ }
+
+
+// Debug dumps:
+#ifdef __FLOG_ACTIVE
+
+_LIT8(KLitOptLevelGeneric, "KBcaOptLevelGeneric");
+_LIT8(KLitOptLevelExtSerial, "KBcaOptLevelExtSerial");
+_LIT8(KLitOptLevelUnsupported, "**Unsupported**");
+
+/**
+Returns a string for an option level
+
+@param aOptLevel BCA Option Level
+@return readable string for aOptLevel
+*/
+static const TDesC8& IoctlOptLevelStr(TUint32 aOptLevel)
+ {
+ switch(aOptLevel)
+ {
+ case KBcaOptLevelGeneric:
+ return KLitOptLevelGeneric;
+ case KBcaOptLevelExtSerial:
+ return KLitOptLevelExtSerial;
+ default:
+ return KLitOptLevelUnsupported;
+ }
+ }
+
+
+_LIT8(KLitOptNameBcaVersionNumber, "KBcaOptNameVersionNumber");
+_LIT8(KLitOptNameBcaCaps, "KBcaOptNameBcaCaps");
+_LIT8(KLitOptNameBcaSetIapId, "KBcaOptNameBcaSetIapId");
+_LIT8(KLitOptNameBcaSetBcaStack, "KBcaOptNameBcaSetBcaStack");
+_LIT8(KLitOptNameBcaResetBuffers, "KBcaOptNameBcaResetBuffers");
+_LIT8(KLitOptNameSerialPortName, "KBcaOptNameSerialPortName");
+_LIT8(KLitOptNameSerialConfig, "KBcaOptNameSerialSerialConfig");
+_LIT8(KLitOptNameSerialSetConfig, "KBcaOptNameSerialSerialSetConfig");
+_LIT8(KLitOptNameSerialSetCsyName, "KBcaOptNameBcaSetCsyName");
+_LIT8(KLitOptNameSerialSetCommRole, "KBcaOptNameSetCommRole");
+_LIT8(KLitSerialSetTxRxBufferSize, "KSerialSetTxRxBufferSize");
+_LIT8(KLitSerialTxRxBufferSize, "KSerialTxRxBufferSize");
+_LIT8(KLitSerialMonitorControlLines, "KSerialMonitorControlLines");
+_LIT8(KLitSerialSetControlLines, "KSerialSetControlLines");
+_LIT8(KLitOptNameUnsupported, "**Unsupported**");
+
+
+/**
+Returns a string for the given option name
+
+@param aOptLevel BCA Option Name
+@return readable string for aOptName
+*/
+static const TDesC8& IoctlOptNameStr(TUint32 aOptName)
+ {
+ switch(aOptName)
+ {
+ case KBCACaps:
+ return KLitOptNameBcaCaps;
+ case KVersionNumber:
+ return KLitOptNameBcaVersionNumber;
+ case KBCASetIapId:
+ return KLitOptNameBcaSetIapId;
+ case KBCASetBcaStack:
+ return KLitOptNameBcaSetBcaStack;
+ case KBCAResetBuffers:
+ return KLitOptNameBcaResetBuffers;
+ case KSerialPortName:
+ return KLitOptNameSerialPortName;
+ case KSerialConfig:
+ return KLitOptNameSerialConfig;
+ case KSerialSetConfig:
+ return KLitOptNameSerialSetConfig;
+ case KSerialSetCsyName:
+ return KLitOptNameSerialSetCsyName;
+ case KSerialSetCommRole:
+ return KLitOptNameSerialSetCommRole;
+ case KSerialSetTxRxBufferSize:
+ return KLitSerialSetTxRxBufferSize;
+ case KSerialTxRxBufferSize:
+ return KLitSerialTxRxBufferSize;
+ case KSerialMonitorControlLines:
+ return KLitSerialMonitorControlLines;
+ case KSerialSetControlLines:
+ return KLitSerialSetControlLines;
+ default:
+ return KLitOptNameUnsupported;
+ }
+ }
+#endif // __FLOG_ACTIVE
+
+
+#ifdef __FLOG_ACTIVE
+/**
+Print debug output of the TCommComfig parameters.
+
+@param The configuration whose parameters should be logged.
+*/
+void CC32Bca::LogCommConfig(TCommConfig& c)
+ {
+ __FLOG_5(_L8("Rate[%d] DataBits[%d] StopBits[%d] Parity[%d] Handshake[0x%x]"), c().iRate, c().iDataBits, c().iStopBits, c().iParity, c().iHandshake);
+ __FLOG_4(_L8("ParityError[%d] Fifo[%d] SpecialRate[%d] terminatorCount[%d]"), c().iParityError, c().iFifo, c().iSpecialRate, c().iTerminatorCount);
+ __FLOG_1(_L8("Terminator[0x%x]"), c().iTerminator);
+ }
+#endif // __FLOG_ACTIVE
+
+
+/**
+* Ioctl: asynchronously controls the C32Bca.
+
+* @param aStatus complete status, KErrNone if successful, system-wide error code otherwise.
+* @param aOptLevel option level to be used.
+* @param aOptName option name to be used.
+* @param aOpt an optional parameter,holds the option value on return or the option value to be set.
+*/
+void CC32Bca::Ioctl(TRequestStatus& aStatus, TUint aOptLevel, TUint aOptName, TDes8& aOpt)
+
+ {
+ __FLOG_4(_L8("Ioctl: Level[%S](0x%X) Name[%S](0x%X)."), &IoctlOptLevelStr(aOptLevel), aOptLevel, &IoctlOptNameStr(aOptName), aOptName);
+
+ aStatus = KRequestPending;
+
+ TInt ret(KErrNone); // If operation fails, this will be set to the failure code explicitly.
+
+ // Don't check the port status. Let C32 panic. It's the caller's responsibility to make sure that
+ // the port is in a valid state (for most operations, open & not having any Tx Rx ops outstanding)
+ if(aOptLevel == KBcaOptLevelGeneric)
+ {
+ switch(aOptName)
+ {
+ case KBCACaps:
+ {
+ const TPckg<TUint> capPckg(KBcaCapSerial);
+ aOpt = capPckg;
+ break;
+ }
+
+ case KVersionNumber:
+ {
+ const TPckg<TUint> versionPckg(KVersion); //lower 16 contains KC32BcaMinorversionNumber, upper 16 bit contains KC32BcaMajorVersionNumber.
+ aOpt = versionPckg;
+ break;
+ }
+
+ case KBCASetIapId:
+ {
+ TUint32 tempIapId = *(reinterpret_cast<const TUint32*>(aOpt.Ptr()));
+
+ __FLOG_1(_L8("Ioctl: IAP ID [%d] specified."),tempIapId);
+
+ if(tempIapId < 1 )
+ {
+ ret = KErrArgument;
+ }
+ else
+ {
+ iIapId = tempIapId;
+ }
+ break;
+ }
+
+ case KBCAResetBuffers:
+ {
+ TUint resetBufMaskArg = *(reinterpret_cast<const TUint32*>(aOpt.Ptr()));
+ TUint resetBufMask(0x0);
+
+ if(resetBufMaskArg & KResetRxBuf)
+ {
+ resetBufMask |= KCommResetRx;
+ }
+ if(resetBufMaskArg & KResetTxBuf)
+ {
+ resetBufMask |= KCommResetTx;
+ }
+ ret = iComm.ResetBuffers(resetBufMask);
+ break;
+ }
+
+
+ default:
+ {
+ ret = KErrNotSupported;
+ }
+ }
+ }
+ else if(aOptLevel == KBcaOptLevelExtSerial)
+ {
+ switch(aOptName)
+ {
+ case KSerialCaps:
+ {
+ iComm.Caps(aOpt);
+ break;
+ }
+
+ case KSerialConfig:
+ {
+ __FLOG(_L8("Ioctl: KSerialConfig"));
+
+ TCommConfig cfg;
+ iComm.Config(cfg);
+
+#ifdef __FLOG_ACTIVE
+ LogCommConfig(cfg);
+#endif // __FLOG_ACTIVE
+
+ TPckgBuf<TCommConfig> cfgBuf(cfg);
+ aOpt.Copy(cfgBuf);
+ break;
+ }
+
+ case KSerialSetConfig:
+ {
+ __FLOG(_L8("Ioctl: KSerialSetConfig"));
+
+ TCommConfig cfg(*(reinterpret_cast<const TCommConfig*>(aOpt.Ptr())));
+
+#ifdef __FLOG_ACTIVE
+ LogCommConfig(cfg);
+#endif // __FLOG_ACTIVE
+
+ ret = iComm.SetConfig(cfg);
+ break;
+ }
+
+ case KSerialPortName:
+ {
+ aOpt.Copy(iCommPort);
+ break;
+ }
+
+ case KSerialSetCsyName:
+ {
+ if(!iCommPortOpen)
+ {
+ iCsyName.Copy(*(
+ reinterpret_cast<const TName*>(aOpt.Ptr())
+ ));
+ iCsyNameOverride = ETrue;
+ __FLOG_1(_L8("Ioctl: CSY Name set to [%S]"), &iCsyName);
+ }
+ else
+ {
+ __FLOG(_L8("Ioctl: Warning: Cannot set the CSY name because the Comm Port is already open."));
+ ret = KErrAlreadyExists;
+ }
+
+ break;
+ }
+
+ case KSerialSetCommRole:
+ {
+ if(!iCommPortOpen)
+ {
+ iCommRole = *(reinterpret_cast<const TCommRole*>(aOpt.Ptr()));
+ iCommRoleOverride = ETrue;
+ __FLOG_1(_L8("Ioctl: Comm Role set to [%d]"), iCommRole);
+ }
+ else
+ {
+ __FLOG(_L8("Ioctl: Warning: Cannot set Comm Role because the Comm Port is already open."));
+ ret = KErrAlreadyExists;
+ }
+ break;
+ }
+
+ case KSerialSetTxRxBufferSize:
+ {
+ TInt bufSize = *(reinterpret_cast<const TInt*>(aOpt.Ptr()));
+ __FLOG_1(_L8("Ioctl: Setting Rx Tx buffer size to [%d]"), bufSize);
+
+ iComm.SetReceiveBufferLength(bufSize);
+ break;
+ }
+
+ case KSerialMonitorControlLines:
+ {
+ TRAP(ret, MonitorControlLinesL(*(reinterpret_cast<const TUint*>(aOpt.Ptr()))));
+ break;
+ }
+
+ case KSerialSetControlLines:
+ {
+ if (aOpt.Length() != sizeof(TSerialSetControlLines))
+ {
+ ret = KErrArgument;
+ }
+ else
+ {
+ const TSerialSetControlLines& lines = *(reinterpret_cast<const TSerialSetControlLines*>(aOpt.Ptr()));
+ __FLOG_2(_L8("Ioctl: Setting/clearing control lines %x/%x"), lines.iSetMask, lines.iClearMask);
+ iComm.SetSignals(lines.iSetMask, lines.iClearMask);
+ ret = KErrNone;
+ }
+ break;
+ }
+
+ default:
+ ret = KErrNotSupported;
+ }
+ }
+ else
+ {
+ ret = KErrNotSupported;
+ }
+
+
+ __FLOG_1(_L8("Ioctl completed with error %d"), ret);
+
+ TRequestStatus* ptrStatus = &aStatus;
+ User::RequestComplete(ptrStatus, ret);
+ }
+
+/** Enables / Disables monitoring & link down reporting on the specified control lines
+
+@param aMask bitmaks specifying the lines to monitor, OR
+ KMonitorOff to turn monitoring off, OR
+ KConfigFailBcaSpecificOnly to set up monitoring according to Comm Role only
+
+@leave if the monitoring object cannot be constructed, typically due to OOM.
+*/
+void CC32Bca::MonitorControlLinesL(TUint32 aArgMask)
+ {
+ __FLOG_1(_L8("Ioctl: argument bitmask = [0x%X] "), aArgMask);
+
+ if(iLinkMonitor) // We may have never started...
+ {
+ // We are called to either stop or change the monitoring options.
+ iLinkMonitor->Cancel(); // If we are not monitoring, this has no effect.
+ }
+
+ if(KMonitorOff == aArgMask) // Stop monitoring:
+ {
+ __FLOG(_L8("MonitorControlLinesL: Stopping Control Lines monitoring."));
+ // We either never started, or we just cancelled above.
+ }
+ else // Start Monitoring, or change the monitored lines.
+ {
+ __FLOG(_L8("MonitorControlLinesL: Starting to monitor Control Lines."));
+
+ if(!iLinkMonitor) // We are starting to monitor for the first time
+ {
+ iLinkMonitor = new (ELeave)CCommLinkMonitor(*this, iComm);
+ }
+ // At this point we have a monitoring object that isn't active.
+
+ // A CSY does not necessarily handle the KConfigFail* correctly. For example, if
+ // a DTR is initially low, because the terminal was not plugged in yet, we get a failure straight away,
+ // So, we translate the failure arguments and monitor the relevant lines ourselves. We fail only when a line
+ // is disasserted. This is absolutely necessary to support server-mode PPP, because we may need to wait
+ // an arbitrary period of time for the user to plug the terminal in.
+ TUint32 lineMask(0x0);
+ if(KFailBcaSpecificOnly == aArgMask) // We decide what lines to monitor
+ {
+ // N.B. When a DTE, fail on low DSR. This is necessary to detect a disconnection on serial links that
+ // do not utilise DCD.
+ lineMask = (ECommRoleDCE == iCommRole) ? KSignalDTR : KSignalDCD | KSignalDSR;
+ }
+ else // User explicitly specified the control lines.
+ {
+ // Don't bother with sanity checks on the lines. Let C32 handle it.
+
+ if(KConfigFailCTS & aArgMask)
+ {
+ lineMask |= KSignalCTS;
+ }
+ if(KConfigFailDSR & aArgMask)
+ {
+ lineMask |= KSignalDSR;
+ }
+ if(KConfigFailDCD & aArgMask)
+ {
+ lineMask |= KSignalDCD;
+ }
+ if(KConfigFailDTR & aArgMask)
+ {
+ lineMask |= KSignalDTR;
+ }
+ if(KConfigFailRTS & aArgMask)
+ {
+ lineMask |= KSignalRTS;
+ }
+ }
+
+ iLinkMonitor->Setup(lineMask);
+ iLinkMonitor->NotifyLinkDown();
+
+ __FLOG(_L8("MonitorControlLinesL: Control Lines monitoring started."));
+ }
+ }
+
+/**
+Closes the connection to CommDB, if it is open */
+void CC32Bca::CloseCommDbConnection()
+ {
+ delete iCommsDat;
+ iCommsDat = NULL;
+ }
+
+/**
+Read Comm Port from CommDB bearer record
+@param aPortName
+@leave if the value could not be read */
+void CC32Bca::ReadCommPortFromCommDbL(TDes& aPortName)
+ {
+ __FLOG(_L8("CC32Bca::ReadCommPortFromCommDbL()"));
+ ConnectToCommDbBearerRecordL();
+
+ TInt ret(0);
+ CMDBField<TDesC>* portField = new(ELeave) CMDBField<TDesC>(KCDTIdPortName);
+ CleanupStack::PushL(portField);
+
+ portField->SetRecordId(iModemId);
+ portField->SetMaxLengthL(KMaxTextLength);
+ TRAP(ret,portField->LoadL(*iCommsDat));
+
+ if(ret!=KErrNone)
+ {
+ __FLOG_1(_L8("portField->LoadL(*iCommsDat) left with[%d] "), ret);
+ User::Leave(ret);
+ }
+
+ aPortName = *portField;
+ CleanupStack::PopAndDestroy(portField);
+ }
+
+/**
+Read the CSY name from CommDB bearer record.
+@param aCsyName the CSY name
+@leave if the value could not be read */
+void CC32Bca::ReadCsyNameFromCommDbL(TDes& aCsyName)
+ {
+ __FLOG(_L8("CC32Bca::ReadCsyNameFromCommDbL()"));
+ ConnectToCommDbBearerRecordL();
+
+ TInt ret(0);
+ CMDBField<TDesC>* csyField = new(ELeave) CMDBField<TDesC>(KCDTIdCsyName);
+ CleanupStack::PushL(csyField);
+
+ csyField->SetRecordId(iModemId);
+ csyField->SetMaxLengthL(KMaxTextLength);
+ TRAP(ret,csyField->LoadL(*iCommsDat));
+
+ if(ret!=KErrNone)
+ {
+ __FLOG_1(_L8("csyField->LoadL(*iCommsDat) left with[%d] "), ret);
+ User::Leave(ret);
+ }
+
+ aCsyName = *csyField;
+ CleanupStack::PopAndDestroy(csyField);
+ }
+
+/**
+Read the specified Comm role (DTE / DCE) from CommDB bearer record
+
+@param aCommRole the specified role.
+@leave if the value could not be read */
+void CC32Bca::ReadCommRoleFromCommDbL(TCommRole& aCommRole)
+ {
+ __FLOG(_L8("CC32Bca::ReadCommRoleFromCommDbL()"));
+ ConnectToCommDbBearerRecordL();
+ TUint32 role(0);
+
+ TInt ret(0);
+ CMDBField<TUint32>* roleField = new(ELeave) CMDBField<TUint32>(KCDTIdCommRole);
+ CleanupStack::PushL(roleField);
+
+ roleField->SetRecordId(iModemId);
+ TRAP(ret,roleField->LoadL(*iCommsDat));
+
+ if(ret!=KErrNone)
+ {
+ __FLOG_1(_L8("roleField->LoadL(*iCommsDat) left with[%d] "), ret);
+ User::Leave(ret);
+ }
+
+ role = *roleField;
+ CleanupStack::PopAndDestroy(roleField);
+
+ aCommRole = (0 == (role & KModemCommRoleDCE)) ? ECommRoleDTE : ECommRoleDCE;
+ }
+
+/**
+Opens a connection to the ModemBearer record specified by the provisioned IAP ID.
+
+@leave KErrNotReady, if the provisioned IAP id is invalid. System-wide error code
+ if the connection cannot be opened for some other reason.
+*/
+void CC32Bca::ConnectToCommDbBearerRecordL()
+ {
+ __FLOG(_L8("CC32Bca::ConnectToCommDbBearerRecordL()"));
+ if(iCommsDat != NULL) // CommDB is already open, we don't need to do anything
+ {
+ return;
+ }
+
+ if(iIapId < 1) // Can't access CommDB if IAP ID is unknown
+ {
+ __FLOG_1(_L8("iIapId[%d] is unknown"), iIapId);
+ User::Leave(KErrNotReady);
+ }
+
+ //
+ // Open connecton to CommDB Bearer record specified by the IAP.
+ //
+#ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
+ iCommsDat = CMDBSession::NewL(KCDVersion1_2);
+#else
+ iCommsDat = CMDBSession::NewL(KCDVersion1_1);
+#endif
+
+ CCDIAPRecord *iapRecord = static_cast<CCDIAPRecord*>(CCDRecordBase::RecordFactoryL(KCDTIdIAPRecord));
+ CleanupStack::PushL(iapRecord);
+
+ iapRecord->SetRecordId(iIapId);
+
+ TBool hiddenAttributeMaskValue = iCommsDat->IsSetAttributeMask(ECDHidden);
+ TBool privateAttributeMaskValue = iCommsDat->IsSetAttributeMask(ECDPrivate);
+
+ // Check to see if viewing hidden records is enabled or not
+ if(!hiddenAttributeMaskValue || !privateAttributeMaskValue)
+ {
+ // Reveal hidden or private IAP records if a licensee has chosen to protect a record
+ // using one of these flags - the API to do this is public so internal components
+ // have to support the use of such records.
+ iCommsDat->SetAttributeMask(ECDHidden | ECDPrivate);
+ }
+
+ TRAPD(ret,iapRecord->LoadL(*iCommsDat));
+ if (ret != KErrNone)
+ {
+ __FLOG_1(_L8("iapRecord->LoadL(*iCommsDat) left with[%d] "), ret);
+ User::Leave(ret);
+ }
+
+ // If we enabled viewing hidden records now disable viewing them.
+ if(!hiddenAttributeMaskValue)
+ {
+ iCommsDat->ClearAttributeMask(ECDHidden);
+ }
+ if(!privateAttributeMaskValue)
+ {
+ iCommsDat->ClearAttributeMask(ECDPrivate);
+ }
+
+
+ iModemId = iapRecord->iBearer;
+ CleanupStack::PopAndDestroy(iapRecord);
+
+ if(iModemId == 0) // ID not found.
+ {
+ __FLOG_1(_L8("iModemId[%d] is not found"), iModemId);
+ User::Leave(KErrNotFound);
+ }
+ }
+
+
+/** Cancels an outstanding Ioctl, if any. */
+void CC32Bca::CancelIoctl()
+ {
+ __FLOG(_L8("CancelIoctl(): Ioctl cancel request. No Ioctl to cancel."));
+ }
+
+
+/** Closes the Comm port and Comm Server.*/
+void CC32Bca::CloseCommPort()
+ {
+ __ASSERT_ALWAYS(iReader, Panic(ENullReaderOnClose));
+ __ASSERT_ALWAYS(iWriter, Panic(ENullWriterOnClose));
+
+ // When we close the port, all async requests outstanding are cancelled.
+ // We must make sure nobody is waiting on them. If the underlying request is cancelled,
+ // but the owner AO is not, Cancel() on such AO hangs waiting for the request to complete.
+
+ iReader->Cancel();
+ iWriter->Cancel();
+ if(iLinkMonitor) // Link monitor is constructed on client request only.
+ {
+ iLinkMonitor->Cancel();
+ }
+
+ if (iCommPortOpen)
+ {
+ iComm.Close();
+ iCommServ.Close();
+ iCommPortOpen = EFalse;
+ }
+ __FLOG(_L8("CloseCommPort(): Session with C32 & RComm closed."));
+ }
+
+/**
+C32Bca Panic function
+@internalComponent
+*/
+void C32Bca::Panic(TC32BcaPanic aPanic)
+ {
+ __FLOG_STATIC2(KC32BcaLogFolder,KC32BcaLogFile,_L8("%S Panic %d"), &KC32BcaPanic(), aPanic);
+ User::Panic(KC32BcaPanic, aPanic);
+ }
+
+
+// MC32User implementation:
+
+// Read has completed.
+void CC32Bca::CommReadComplete(TInt aErr)
+ {
+ __ASSERT_ALWAYS(iReadRequest, Panic(ENullReadRequestStatus));
+ __ASSERT_DEBUG(KRequestPending == iReadRequest->Int(), Panic(EReadRequestNotPending));
+
+ User::RequestComplete(iReadRequest, aErr);
+ }
+
+// Write has completed.
+void CC32Bca::CommWriteComplete(TInt aErr)
+ {
+ __ASSERT_ALWAYS(iWriteRequest, Panic(ENullWriteRequestStatus));
+ __ASSERT_DEBUG(KRequestPending == iWriteRequest->Int(), Panic(EWriteRequestNotPending));
+
+ User::RequestComplete(iWriteRequest, aErr);
+ }
+
+// Upcall from the link monitor: Link has gone down.
+void CC32Bca::CommLinkDown(TInt aErr)
+ {
+ __FLOG_1(_L8("CommLinkDown: Warning: serial link has gone down with error[%d]. Erroring the outstanding Read & Write."), aErr);
+
+ __ASSERT_DEBUG(KErrNone != aErr, Panic(EGeneralLogicError)); // If KErrNone, use has no way to know that the read has failed.
+ if(iReader->IsActive())
+ {
+ CommReadComplete(aErr);
+ iReader->Cancel();
+ }
+ else
+ {
+ iErrorOnNextRead = aErr;
+ }
+
+ if(iWriter->IsActive())
+ {
+ CommWriteComplete(aErr);
+ iWriter->Cancel();
+ }
+ else
+ {
+ iErrorOnNextWrite = aErr;
+ }
+ }