basebandadaptationplugins/basebandchanneladaptorforc32/src/C32Bca.cpp
changeset 0 3553901f7fa8
child 19 630d2f34d719
equal deleted inserted replaced
-1:000000000000 0:3553901f7fa8
       
     1 // Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // C32 Baseband Channel Adaptor(BCA) APIs implementation.
       
    15 // This file contains all the API implementation of the C32BCA interface for Symbian OS.
       
    16 // 
       
    17 //
       
    18 
       
    19 /**
       
    20  @file
       
    21  @internalComponent
       
    22 */
       
    23 
       
    24 #include "C32Bca.h"
       
    25 #include <cdbcols.h>
       
    26 #include <commsdat_partner.h>
       
    27 
       
    28 using namespace BasebandChannelAdaptation;
       
    29 using namespace BasebandChannelAdaptation::C32Bca;
       
    30 
       
    31 const static TUint KVersion = ((static_cast<TUint>(KC32BcaMajorVersionNumber)) << 16) | KC32BcaMinorVersionNumber;
       
    32 
       
    33 
       
    34 /**
       
    35 C++ constructor for an object representing a c32 async user
       
    36 
       
    37 @param aUser the target of the notifications originating in C32
       
    38 @param aPort the C32 port to be used with this object
       
    39 @param aAoPriority the priority to assign to this active object
       
    40 */
       
    41 CCommBase::CCommBase(MC32User& aUser, RComm& aPort, TInt aAoPriority):
       
    42 	CActive(aAoPriority),
       
    43 	iUser(aUser),
       
    44 	iPort(aPort)
       
    45 	{
       
    46 	CActiveScheduler::Add(this);
       
    47 	__FLOG_OPEN(KC32BcaLogFolder, KC32BcaLogFile); // Connect to the BCA logger			
       
    48 	}
       
    49 		
       
    50 /**
       
    51 C++ destructor */		
       
    52 CCommBase::~CCommBase()
       
    53 	{
       
    54 	__FLOG_CLOSE;
       
    55 	}
       
    56 
       
    57 /**
       
    58 C++ constructor 
       
    59 The comm-reader has a higher priority than the comm-writer, to
       
    60 ensure the reader gets the chance to receive the incomming data
       
    61 
       
    62 @param aUser the target of the notifications originating in C32
       
    63 @param aPort the C32 port to be used with this object
       
    64 */
       
    65 CCommReader::CCommReader(MC32User& aUser, RComm& aPort):
       
    66 	CCommBase(aUser, aPort, EPriorityHigh)
       
    67 	{
       
    68 	}
       
    69 
       
    70 /** 
       
    71 C++ destructor */
       
    72 CCommReader::~CCommReader()
       
    73 	{
       
    74 	Cancel();
       
    75 	}
       
    76 
       
    77 /**
       
    78 Cancels the outstanding read */
       
    79 void CCommReader::DoCancel()
       
    80 	{
       
    81 	iPort.ReadCancel();
       
    82 	}
       
    83 		
       
    84 /**
       
    85 Issues a read on the serial port 
       
    86 
       
    87 @param aBuf the buffer to read to */		
       
    88 void CCommReader::Read(TDes8& aBuf)
       
    89 	{
       
    90 	iPort.ReadOneOrMore(iStatus, aBuf);	
       
    91 	SetActive();
       
    92 	}
       
    93 
       
    94 /**
       
    95 Called on read completion */	
       
    96 void CCommReader::RunL()
       
    97 	{
       
    98 	iUser.CommReadComplete(iStatus.Int());
       
    99 	}
       
   100 	
       
   101 /**
       
   102 C++ constructor
       
   103 The comm-writer has a lower priority than the comm-reader, to
       
   104 ensure the reader gets the chance to receive the incomming data
       
   105 
       
   106 @param aUser the target of the notifications originating in C32
       
   107 @param aPort the C32 port to be used with this object */	
       
   108 CCommWriter::CCommWriter(MC32User& aUser, RComm& aPort):
       
   109 	CCommBase(aUser, aPort, EPriorityUserInput)
       
   110 	{
       
   111 	}
       
   112 
       
   113 /** 
       
   114 C++ destructor */
       
   115 CCommWriter::~CCommWriter()
       
   116 	{
       
   117 	Cancel();
       
   118 	}
       
   119 
       
   120 /**
       
   121 Issues a write on the serial port */
       
   122 void CCommWriter::Write(const TDesC8& aBuf)
       
   123 	{
       
   124 	iPort.Write(iStatus, aBuf);
       
   125 	SetActive();
       
   126 	}
       
   127 		
       
   128 /**
       
   129 Called when the write completes
       
   130 */
       
   131 void CCommWriter::RunL()
       
   132 	{
       
   133 	iUser.CommWriteComplete(iStatus.Int());
       
   134 	}
       
   135 
       
   136 /**
       
   137 Cancels the outstanding write
       
   138 */
       
   139 void CCommWriter::DoCancel()
       
   140 	{
       
   141 	iPort.WriteCancel();
       
   142 	}
       
   143 		
       
   144 /**
       
   145 C++ constructor
       
   146 
       
   147 @param aUser the target of the notifications originating in C32
       
   148 @param aPort the C32 port to be used with this object
       
   149 
       
   150 
       
   151 Note on Monitor AO priority:
       
   152 
       
   153 Monitor AO is the same priority as the Reader / Writer by design. 
       
   154 
       
   155 We do NOT want link failure notification to complete before all possible outstanding reads / writes
       
   156 have completed, to make sure that we do not lose any data that was already received from the
       
   157 baseband and is buffered by the driver or the CSY.
       
   158 Consider a scenario where a UDP datagram is received by the CSY, and then the serial link is
       
   159 severed (e.g. cable is unplugged by the user). If the Monitor has higher priority than reader/writer,
       
   160 we may get failure notification before we are notified on the read of this UDP datagram, potentially
       
   161 resulting in its loss (E.g. PPP shuts down when on Link Down notification.)
       
   162 */	
       
   163 CCommLinkMonitor::CCommLinkMonitor(MC32User& aUser, RComm& aPort):
       
   164 	CCommBase(aUser, aPort, EPriorityStandard) 
       
   165 	{
       
   166 	}
       
   167 
       
   168 /**
       
   169 Sets the object to monitor the link for the configured Role, DTE or DCE
       
   170 
       
   171 @param aMask DTE or DCE: determines when the link is considered to be down.
       
   172 */
       
   173 void CCommLinkMonitor::Setup(TUint32 aMask)
       
   174 	{
       
   175 	iNotifyChangeSignalMask = aMask;	
       
   176 	__FLOG_1(_L8("CommLinkMonitor setup: Notify on signal mask [0x%X]"),iNotifyChangeSignalMask);
       
   177 	}
       
   178 
       
   179 /**
       
   180 Requests to be notified when the link is down.
       
   181 
       
   182 Can be called an more than once
       
   183 */
       
   184 void CCommLinkMonitor::NotifyLinkDown()
       
   185 	{
       
   186 	ASSERT(!IsActive());
       
   187 		
       
   188 	// get the current state of the line so when we get notification we can tell if it really has changed	
       
   189 	iSavedSignalState = iPort.Signals(iNotifyChangeSignalMask) & iNotifyChangeSignalMask;
       
   190 	iPort.NotifySignalChange(iStatus, iSignals, iNotifyChangeSignalMask);
       
   191 
       
   192 	__FLOG_1(_L8("CommLinkMonitor::NotifyLinkDown: initial signals: [0x%X]"), iSavedSignalState);
       
   193 	
       
   194 	SetActive();
       
   195 	}
       
   196 
       
   197 /**	
       
   198 Called when EIA-232 signals change,i.e. on potential link failure
       
   199 */
       
   200 void CCommLinkMonitor::RunL()
       
   201 	{
       
   202 	__FLOG_2(_L8("CommLinkMonitor::RunL: Signals changed [0x%X]; new signals [0x%X]"), iSignals & (~0x1F), iSignals & 0x1F);
       
   203 	
       
   204 	// We report link failure if and only if a monitored line went from high to low.
       
   205 	// Method: mask the saved signals using inverted monitored bits in the signal bitmask,
       
   206 	// to filter out all transitions except for high -> low. 
       
   207 	// 1 & ~0 = 1;    1 & ~1 = 0; 0 & ~1 = 0; 0 & ~0 = 0
       
   208 	// This is necessary, because we may be monitoring more than one signal, and the change can be arbitrary.
       
   209 	if ((~(iNotifyChangeSignalMask & iSignals)) & iSavedSignalState) 
       
   210 		{		
       
   211 		iUser.CommLinkDown(KErrCommsLineFail);
       
   212 		}
       
   213 	iSavedSignalState = iSignals & iNotifyChangeSignalMask;	// update saved state with relevant bits	
       
   214 	iPort.NotifySignalChange(iStatus, iSignals, iNotifyChangeSignalMask);
       
   215 	SetActive(); 
       
   216 	// Note: If the link went down, the user will likely shutdown the BCA on outstanding signal notification. 
       
   217 	}
       
   218 
       
   219 /**
       
   220 Cancels notification request of link failure */	
       
   221 void CCommLinkMonitor::DoCancel()
       
   222 	{
       
   223 	__FLOG(_L8("CommLinkMonitor::DoCancel: Cancelling signal change notification."));
       
   224 	iPort.NotifySignalChangeCancel();
       
   225 	}
       
   226 	
       
   227 
       
   228 
       
   229 
       
   230 
       
   231 /**
       
   232 * default constructor to create a C32Bca instance.
       
   233 */
       
   234 CC32Bca::CC32Bca()	
       
   235 	{
       
   236 	__FLOG_OPEN(KC32BcaLogFolder,KC32BcaLogFile);
       
   237 	__FLOG_2(_L8("====== CC32Bca::CC32Bca: Shim BCA for C32 [Vesion: major= %d minor= %d] Constructed. ======"), KC32BcaMajorVersionNumber, KC32BcaMinorVersionNumber);
       
   238 	}
       
   239 
       
   240 /**
       
   241 2nd phase of construction: allocates member objects 
       
   242 
       
   243 
       
   244 @leave when members cannot be constructed. */
       
   245 void CC32Bca::ConstructL()
       
   246 	{
       
   247 	__ASSERT_DEBUG(!iReader, Panic(EReaderAlreadyExists));
       
   248 	__ASSERT_DEBUG(!iWriter, Panic(EWriterAlreadyExists));
       
   249 	__ASSERT_DEBUG(!iLinkMonitor, Panic(EMonitorAlreadyExists));
       
   250 	
       
   251 	// Comm is not initialized yet. We have to be Opened before it can be used. C32 panics otherwise.
       
   252 	iReader = new (ELeave)CCommReader(*this, iComm);
       
   253 	iWriter = new (ELeave)CCommWriter(*this, iComm);
       
   254 	// Monitor is created upon user request only, we may never need it at all.
       
   255 	}
       
   256 
       
   257 /**
       
   258 * Destructor 
       
   259 */	
       
   260 CC32Bca::~CC32Bca()
       
   261 	
       
   262 	{
       
   263 	__FLOG(_L8("CC32Bca::~CC32Bca: releasing resources..."));
       
   264 		
       
   265 	CloseCommDbConnection(); 
       
   266 	CloseCommPort(); 	// Cancels reader / writer / monitor
       
   267 	
       
   268 	// N.B.: 
       
   269 	// It is critical that these objects are cancelled before deletion. Else DoCancel operates on closed C32 port, 
       
   270 	// causing C32 to panic. 
       
   271 	delete iReader;
       
   272 	delete iWriter;
       
   273 	delete iLinkMonitor; // Note: may have never been created.
       
   274 
       
   275 	__FLOG(_L8("CC32Bca::~CC32Bca: CC32Bca destroyed."));
       
   276 	__FLOG_CLOSE;
       
   277 	}
       
   278 	
       
   279 /** This method deletes the BCA itself.*/
       
   280 void CC32Bca::Release()
       
   281 	{
       
   282 	__FLOG(_L8("CC32Bca::Release"));
       
   283 	delete this;
       
   284 	}
       
   285 	
       
   286 /**
       
   287 * Informs that the BCA is required by the client(for instance, Raw IP NIF).Comms Server is
       
   288 * connected, and serial port is opened.
       
   289 	
       
   290 * @param aStatus complete status, KErrNone if successful, C32 error code otherwise.
       
   291 * @param aChannelId comm port name.
       
   292 */	
       
   293 void CC32Bca::Open(TRequestStatus& aStatus, const TDesC& aChannelId)
       
   294 	{
       
   295 	// We don't have the ConstructL, so we have to allocate memory here.
       
   296 	
       
   297 	aStatus = KRequestPending;
       
   298 	// avoid compiler warning.
       
   299 	TRequestStatus* ptrStatus = &aStatus;
       
   300 	if(iCommPortOpen)
       
   301 		{
       
   302 		__FLOG(_L8("Warning: C32Bca is already Opened."));
       
   303 	
       
   304 		User::RequestComplete(ptrStatus,KErrNone);
       
   305 		return;	
       
   306 		}
       
   307 	
       
   308 	if(aChannelId == KChannelIdNotOverridden) // Channel ID is not supplied - Comm Port Name is not overriden.
       
   309 		{									 // Read it from CommDB.
       
   310 		// Fetch port name from CommDB.
       
   311 		TRAPD(commPortErr, ReadCommPortFromCommDbL(iCommPort));
       
   312 		
       
   313 		// If the column is missing from CommDB, we can get an empty string with KErrNone.
       
   314 		// Opening RComm with empty string as Port name fails with ECUART, LOOOPBACK CSYs. 
       
   315 		// with different error codes on 8.1 and 9.0. 
       
   316 		// It would be better to intercept such invalid value and fail here.
       
   317 		// This is not done, because theoretically it is possible to write a CSY that somehow takes an 
       
   318 		// emty descriptor as a port name. As of December 2004, C32 does not allow that, however, this
       
   319 		// may change in the future.
       
   320 		// So, we just log a warning.
       
   321 		if(KErrNone == commPortErr && iCommPort.Size() == 0)
       
   322 			{
       
   323 			__FLOG(_L8("Warning: Null string read from CommDB. Will try to open Comm Port anyway."));
       
   324 			}		
       
   325 		
       
   326 		if(KErrNone != commPortErr) // Fatal: we do not have a port name. Can't open RComm.
       
   327 			{
       
   328 			__FLOG(_L8("Error: Failed to get C32 PortName from CommDB "));
       
   329 			CloseCommDbConnection();
       
   330 			User::RequestComplete(ptrStatus, commPortErr);
       
   331 			return;
       
   332 			}		
       
   333 		}
       
   334 	else // Channel ID supplied - use it as Port Name.
       
   335 		{
       
   336 		_LIT(KDoubleColon, "::");
       
   337 		TInt len1 = aChannelId.Find(KDoubleColon);
       
   338 
       
   339 		if (len1 < KErrNone)
       
   340 			{
       
   341 			__FLOG(_L8("** ERROR: No :: (Double Colon) in aChannelId **"));
       
   342 			User::RequestComplete(ptrStatus, KErrBadName);
       
   343 			return;	
       
   344 			}
       
   345 		else
       
   346 			{
       
   347 			TUint numPos = len1 + KDoubleColon.iTypeLength;
       
   348 						
       
   349 			TInt len2 = (aChannelId.Mid(numPos)).Find(KDoubleColon);
       
   350 			
       
   351 			if (len2 < KErrNone)
       
   352 				{
       
   353 				iCommPort = aChannelId;
       
   354 				}
       
   355 			else
       
   356 				{
       
   357 				iCommPort = aChannelId.Mid(numPos);
       
   358 				iCsyName = aChannelId.Mid(0, len1);
       
   359 				iCsyNameOverride = ETrue;
       
   360 				}
       
   361 			}
       
   362 		}
       
   363 	// We have the Port Name at this point: either supplied as a parameter, or read from CommDB.
       
   364 
       
   365 	if(!iCsyNameOverride) // CSY name is not provisioned by Ioctl: read it from CommDB.
       
   366 		{
       
   367 		TRAPD(getCsyErr, ReadCsyNameFromCommDbL(iCsyName));
       
   368 		if(KErrNone != getCsyErr) // Fatal: we do not have a CSY name. Can't load CSY module.
       
   369 			{
       
   370 			// We do not use a hardcoded value (e.g. ECUART), because the client code or the environment are
       
   371 			// confused - it is better to fail them, rather than mask their problems.
       
   372 			__FLOG(_L8("Error: Failed to get CSY name from CommDB "));
       
   373 			CloseCommDbConnection();
       
   374 			User::RequestComplete(ptrStatus,getCsyErr);
       
   375 			return;
       
   376 			}
       
   377 		}
       
   378 	// We have the CSY name at this point, either provisioned via Ioctl, or read from CommDB.
       
   379 
       
   380 	// Decide the Comm Role (DCE / DTE) of the port.
       
   381 	TBool isCommRoleDefault = EFalse;
       
   382 	// We use a concept of "Default Comm Role", because C32 has it. We could use DTE as a default
       
   383 	// setting, but we prefer to call the "default" method on C32 and let it decide what the role should be.
       
   384 
       
   385 	if(!iCommRoleOverride) // Port role not overriden via Ioctl
       
   386 		{
       
   387 		TRAPD(getCommRoleErr, ReadCommRoleFromCommDbL(iCommRole));
       
   388 		if(KErrNone != getCommRoleErr) // Port role not specified via CommDb
       
   389 			{
       
   390 			isCommRoleDefault = ETrue; // Port role not specified via Ioctl or CommDb
       
   391 			}
       
   392 		}
       
   393 	// We have the Comm Role: provisioned via Ioctl, read from CommDB, or default(DTE)
       
   394 	
       
   395 	CloseCommDbConnection(); // We do not read any settings once the connection is opened. 	
       
   396 	// We have all the necessary C32 settings at this point.
       
   397 	// Open the actual C32 session:
       
   398 	
       
   399 	TInt ret = iCommServ.Connect();
       
   400 	if(ret)
       
   401 		{
       
   402 		__FLOG_1(_L8("Open: C32 Server connection error %d"), ret);
       
   403 		User::RequestComplete(ptrStatus,ret);
       
   404 		return;
       
   405 		}
       
   406 	ret = iCommServ.LoadCommModule(iCsyName);
       
   407 	
       
   408 	__FLOG_2(_L16("Open: CSY module [%S] loaded with error %d"), &iCsyName, ret);
       
   409 		
       
   410 	if(ret)
       
   411 		{
       
   412 		User::RequestComplete(ptrStatus,ret);
       
   413 		return;
       
   414 		}
       
   415 	
       
   416 	if(isCommRoleDefault)
       
   417 		{
       
   418 		ret = iComm.Open(iCommServ, iCommPort, ECommShared);
       
   419 		}
       
   420 	else
       
   421 		{
       
   422 		ret = iComm.Open(iCommServ, iCommPort, ECommShared, iCommRole);	
       
   423 		}
       
   424 	
       
   425 	__FLOG_2(_L16("Open: C32 port [%S] opened with error %d"), &iCommPort, ret);
       
   426 					
       
   427 	if(ret)
       
   428 		{
       
   429 		User::RequestComplete(ptrStatus,ret);
       
   430 		return;
       
   431 		}
       
   432 	//
       
   433 	//Open successfull, we update our state.
       
   434 	//
       
   435 	
       
   436 	// We may have been closed, and are being reopened now. Make sure no errors persist from the previous session.
       
   437 	iErrorOnNextRead  = KErrNone; 
       
   438 	iErrorOnNextWrite = KErrNone;
       
   439 	iCommPortOpen = ETrue;
       
   440 	
       
   441 	User::RequestComplete(ptrStatus,KErrNone);
       
   442 	// Don't start control line monitoring. This is done on user request via Ioctl only.
       
   443 	}
       
   444 	
       
   445 /**
       
   446  Shuts the BCA channel down in a graceful manner. BCA releases its resources.
       
   447  Cancels all outstanding operations: Writes, Reads and Ioctls.
       
   448 
       
   449  Due to the specifics of C32Bca implementation, this call completes immediately and is identical to ::Close.
       
   450  
       
   451  @param aStatus completion status: Always KErrNone.
       
   452 */	
       
   453 void CC32Bca::Shutdown(TRequestStatus& aStatus)
       
   454 	{
       
   455 	aStatus = KRequestPending;
       
   456 	
       
   457 	CloseCommPort();
       
   458 	
       
   459 	// Don't notify reader / writer / monitor. Read / Write should not be called after this anyway. Let C32 panic.
       
   460 	
       
   461 	TRequestStatus* request = &aStatus;
       
   462 	User::RequestComplete(request, KErrNone);
       
   463 	__FLOG_1(_L8("C32Bca::Shutdown: BCA shut down with error %d"), KErrNone);
       
   464 	}
       
   465 
       
   466 /**
       
   467 * Closes the BCA immediately. BCA releases its resources.
       
   468 * cancels all Writes, Reads and Controls.
       
   469 */	
       
   470 void CC32Bca::Close()
       
   471 	{
       
   472 	CloseCommPort();
       
   473 	__FLOG_1(_L8("C32Bca::Close:Close: BCA closed with error %d"), KErrNone);
       
   474 	}
       
   475 
       
   476 /**
       
   477 * Queues a Read on C32 serial port.
       
   478 
       
   479 * @param aStatus complete status, KErrNone if successful, C32 error code otherwise.
       
   480 * @param aBuf buffer for data to be read.
       
   481 * @note The buffer is owned by the client. Client must not access / modify the buffer until the Read completes.
       
   482 */	
       
   483 void CC32Bca::Read(TRequestStatus& aStatus,TDes8& aBuf)
       
   484 	{
       
   485 	iReadRequest = &aStatus;
       
   486 	*iReadRequest = KRequestPending;
       
   487 
       
   488 	if(iErrorOnNextRead)
       
   489 		{
       
   490 		User::RequestComplete(iReadRequest, iErrorOnNextRead);
       
   491 		// Error persists until the BCA is closed and opened
       
   492 		}
       
   493 	else
       
   494 		{
       
   495 		iReader->Read(aBuf);	
       
   496 		}
       
   497 	}
       
   498 
       
   499 /**
       
   500 * Queues a Write on C32 serial port.
       
   501 
       
   502 * @param aStatus the complete status, KErrNone if successful, C32 error code otherwise.
       
   503 * @param aBuf the buffer to sent.
       
   504 * @note The buffer is owned by the client. Client must not access / modify the buffer until the Write completes.
       
   505 */	
       
   506 void CC32Bca::Write(TRequestStatus& aStatus,const TDesC8& aBuf)
       
   507 	{
       
   508 	iWriteRequest = &aStatus;
       
   509 	*iWriteRequest = KRequestPending;
       
   510 	
       
   511 	if(iErrorOnNextWrite)
       
   512 		{
       
   513 		User::RequestComplete(iWriteRequest, iErrorOnNextWrite);
       
   514 		// Error persists until BCA is closed and opened.
       
   515 		}
       
   516 	else
       
   517 		{
       
   518 		iWriter->Write(aBuf);	
       
   519 		}
       
   520 	}
       
   521 
       
   522 /**
       
   523  Cancels the outstanding Read operation.(best effort operation: the read may have been completed already.)
       
   524 */	
       
   525 void CC32Bca:: CancelRead()
       
   526 	
       
   527 	{
       
   528 	__FLOG(_L8("CancelRead: Read is cancelled by client."));
       
   529 	iReader->Cancel();
       
   530 
       
   531 	if(iReadRequest != NULL)
       
   532 		{
       
   533 		User::RequestComplete(iReadRequest, KErrCancel);
       
   534 		}
       
   535 	}
       
   536 
       
   537 /**
       
   538  Cancels all Write operations.(best effort attempt: the write may have been completed already.)
       
   539 */	
       
   540 void CC32Bca::CancelWrite()
       
   541 
       
   542     {
       
   543     __FLOG(_L8("CancelWrite: Write is cancelled by client."));
       
   544 
       
   545     iWriter->Cancel();
       
   546 
       
   547     if(iWriteRequest != NULL)
       
   548     	{
       
   549     	User::RequestComplete(iWriteRequest, KErrCancel);
       
   550     	}
       
   551     }
       
   552     
       
   553 
       
   554 // Debug dumps:
       
   555 #ifdef __FLOG_ACTIVE
       
   556 
       
   557 _LIT8(KLitOptLevelGeneric,    "KBcaOptLevelGeneric");
       
   558 _LIT8(KLitOptLevelExtSerial,   "KBcaOptLevelExtSerial");
       
   559 _LIT8(KLitOptLevelUnsupported, "**Unsupported**");
       
   560 
       
   561 /**
       
   562 Returns a string for an option level
       
   563 
       
   564 @param aOptLevel BCA Option Level 
       
   565 @return readable string for aOptLevel
       
   566 */
       
   567 static const TDesC8& IoctlOptLevelStr(TUint32 aOptLevel)
       
   568 	{
       
   569 	switch(aOptLevel)
       
   570 		{
       
   571 		case KBcaOptLevelGeneric:
       
   572 			return KLitOptLevelGeneric;
       
   573 		case KBcaOptLevelExtSerial:
       
   574 			return KLitOptLevelExtSerial;
       
   575 		default: 
       
   576 			return KLitOptLevelUnsupported;
       
   577 		}
       
   578 	}
       
   579 
       
   580 
       
   581 _LIT8(KLitOptNameBcaVersionNumber, "KBcaOptNameVersionNumber");
       
   582 _LIT8(KLitOptNameBcaCaps,    	   "KBcaOptNameBcaCaps");
       
   583 _LIT8(KLitOptNameBcaSetIapId,      "KBcaOptNameBcaSetIapId");
       
   584 _LIT8(KLitOptNameBcaSetBcaStack,   "KBcaOptNameBcaSetBcaStack");
       
   585 _LIT8(KLitOptNameBcaResetBuffers,  "KBcaOptNameBcaResetBuffers");
       
   586 _LIT8(KLitOptNameSerialPortName,   "KBcaOptNameSerialPortName");
       
   587 _LIT8(KLitOptNameSerialConfig,     "KBcaOptNameSerialSerialConfig");
       
   588 _LIT8(KLitOptNameSerialSetConfig,  "KBcaOptNameSerialSerialSetConfig");
       
   589 _LIT8(KLitOptNameSerialSetCsyName,  "KBcaOptNameBcaSetCsyName");
       
   590 _LIT8(KLitOptNameSerialSetCommRole, "KBcaOptNameSetCommRole");
       
   591 _LIT8(KLitSerialSetTxRxBufferSize,  "KSerialSetTxRxBufferSize");
       
   592 _LIT8(KLitSerialTxRxBufferSize, 	"KSerialTxRxBufferSize");
       
   593 _LIT8(KLitSerialMonitorControlLines, "KSerialMonitorControlLines");
       
   594 _LIT8(KLitSerialSetControlLines,	"KSerialSetControlLines");
       
   595 _LIT8(KLitOptNameUnsupported,  	   "**Unsupported**");	
       
   596 
       
   597 
       
   598 /**
       
   599 Returns a string for the given option name
       
   600 
       
   601 @param aOptLevel BCA Option Name 
       
   602 @return readable string for aOptName
       
   603 */
       
   604 static const TDesC8& IoctlOptNameStr(TUint32 aOptName)
       
   605 	{
       
   606 	switch(aOptName)
       
   607 		{
       
   608 		case KBCACaps:
       
   609 			return KLitOptNameBcaCaps;
       
   610 		case KVersionNumber:
       
   611 			return KLitOptNameBcaVersionNumber;
       
   612 		case KBCASetIapId:
       
   613 			return KLitOptNameBcaSetIapId;
       
   614 		case KBCASetBcaStack:
       
   615 			return KLitOptNameBcaSetBcaStack;
       
   616 		case KBCAResetBuffers:
       
   617 			return KLitOptNameBcaResetBuffers;
       
   618 		case KSerialPortName:
       
   619 			return KLitOptNameSerialPortName;
       
   620 		case KSerialConfig:
       
   621 			return KLitOptNameSerialConfig;
       
   622 		case KSerialSetConfig:
       
   623 			return KLitOptNameSerialSetConfig;
       
   624 		case KSerialSetCsyName:
       
   625 			return KLitOptNameSerialSetCsyName;
       
   626 		case KSerialSetCommRole:
       
   627 			return KLitOptNameSerialSetCommRole;
       
   628 		case KSerialSetTxRxBufferSize:
       
   629 			return KLitSerialSetTxRxBufferSize;
       
   630 		case KSerialTxRxBufferSize:
       
   631 			return KLitSerialTxRxBufferSize;
       
   632 		case KSerialMonitorControlLines:
       
   633 			return KLitSerialMonitorControlLines;		
       
   634 		case KSerialSetControlLines:
       
   635 			return KLitSerialSetControlLines;
       
   636 		default:
       
   637 			return KLitOptNameUnsupported;		
       
   638 		}
       
   639 	}
       
   640 #endif // __FLOG_ACTIVE
       
   641 
       
   642 
       
   643 #ifdef __FLOG_ACTIVE
       
   644 /**
       
   645 Print debug output of the TCommComfig parameters.
       
   646 
       
   647 @param The configuration whose parameters should be logged.
       
   648 */
       
   649 void CC32Bca::LogCommConfig(TCommConfig& c)
       
   650 	{
       
   651 	__FLOG_5(_L8("Rate[%d] DataBits[%d] StopBits[%d] Parity[%d] Handshake[0x%x]"), c().iRate, c().iDataBits, c().iStopBits, c().iParity, c().iHandshake);	
       
   652 	__FLOG_4(_L8("ParityError[%d] Fifo[%d] SpecialRate[%d] terminatorCount[%d]"), c().iParityError, c().iFifo, c().iSpecialRate, c().iTerminatorCount);	
       
   653 	__FLOG_1(_L8("Terminator[0x%x]"), c().iTerminator);	
       
   654 	}
       
   655 #endif // __FLOG_ACTIVE
       
   656 
       
   657 
       
   658 /**
       
   659 * Ioctl: asynchronously controls the C32Bca.
       
   660 
       
   661 * @param aStatus complete status, KErrNone if successful, system-wide error code otherwise.
       
   662 * @param aOptLevel option level to be used.
       
   663 * @param aOptName option name to be used.
       
   664 * @param aOpt an optional parameter,holds the option value on return or the option value to be set.
       
   665 */  
       
   666 void CC32Bca::Ioctl(TRequestStatus& aStatus, TUint aOptLevel, TUint aOptName, TDes8& aOpt)
       
   667 
       
   668 	{
       
   669 	__FLOG_4(_L8("Ioctl: Level[%S](0x%X) Name[%S](0x%X)."), &IoctlOptLevelStr(aOptLevel), aOptLevel, &IoctlOptNameStr(aOptName), aOptName);	
       
   670 	
       
   671 	aStatus = KRequestPending;
       
   672 	
       
   673 	TInt ret(KErrNone); // If operation fails, this will be set to the failure code explicitly.
       
   674 	
       
   675 	// Don't check the port status. Let C32 panic. It's the caller's responsibility to make sure that
       
   676 	// the port is in a valid state (for most operations, open & not having any Tx Rx ops outstanding)
       
   677 	if(aOptLevel == KBcaOptLevelGeneric)
       
   678 		{
       
   679 		switch(aOptName)
       
   680 			{
       
   681 			case KBCACaps:
       
   682 				{
       
   683 				const TPckg<TUint> capPckg(KBcaCapSerial);
       
   684 				aOpt = capPckg;			
       
   685 				break;
       
   686 				}
       
   687 				
       
   688 			case KVersionNumber:
       
   689 				{
       
   690 				const TPckg<TUint> versionPckg(KVersion); //lower 16 contains KC32BcaMinorversionNumber, upper 16 bit contains KC32BcaMajorVersionNumber.
       
   691 				aOpt = versionPckg;
       
   692 				break;
       
   693 				}
       
   694 				
       
   695 			case KBCASetIapId:
       
   696 				{
       
   697 				TUint32 tempIapId = *(reinterpret_cast<const TUint32*>(aOpt.Ptr()));
       
   698 				
       
   699 				__FLOG_1(_L8("Ioctl: IAP ID [%d] specified."),tempIapId);	
       
   700 				
       
   701 				if(tempIapId < 1 )
       
   702 					{
       
   703 					ret = KErrArgument;
       
   704 					}
       
   705 				else
       
   706 					{
       
   707 					iIapId = tempIapId;
       
   708 					}
       
   709 				break;
       
   710 				}
       
   711 				
       
   712 			case KBCAResetBuffers:
       
   713 				{
       
   714 				TUint resetBufMaskArg = *(reinterpret_cast<const TUint32*>(aOpt.Ptr()));
       
   715 				TUint resetBufMask(0x0);
       
   716 		
       
   717 				if(resetBufMaskArg & KResetRxBuf)
       
   718 					{
       
   719 					resetBufMask |= KCommResetRx;
       
   720 					}
       
   721 				if(resetBufMaskArg & KResetTxBuf)
       
   722 					{
       
   723 					resetBufMask |= KCommResetTx;
       
   724 					}
       
   725 				ret = iComm.ResetBuffers(resetBufMask);
       
   726 				break;
       
   727 				}
       
   728 			
       
   729 				
       
   730 			default:
       
   731 				{
       
   732 				ret = KErrNotSupported;
       
   733 				}
       
   734 			}
       
   735 		}		
       
   736 	else if(aOptLevel == KBcaOptLevelExtSerial)
       
   737 		{
       
   738 		switch(aOptName)
       
   739 			{
       
   740 		case KSerialCaps:
       
   741 			{
       
   742 			iComm.Caps(aOpt);
       
   743 			break;
       
   744 			}
       
   745 			
       
   746 		case KSerialConfig:
       
   747 			{
       
   748 			__FLOG(_L8("Ioctl: KSerialConfig"));	
       
   749 
       
   750 			TCommConfig cfg;
       
   751 			iComm.Config(cfg);
       
   752 
       
   753 #ifdef __FLOG_ACTIVE
       
   754 			LogCommConfig(cfg);
       
   755 #endif // __FLOG_ACTIVE
       
   756 
       
   757 			TPckgBuf<TCommConfig> cfgBuf(cfg);
       
   758 			aOpt.Copy(cfgBuf);
       
   759 			break;
       
   760 			}
       
   761 
       
   762 		case KSerialSetConfig:
       
   763 			{
       
   764 			__FLOG(_L8("Ioctl: KSerialSetConfig"));	
       
   765 
       
   766 			TCommConfig cfg(*(reinterpret_cast<const TCommConfig*>(aOpt.Ptr())));
       
   767 
       
   768 #ifdef __FLOG_ACTIVE
       
   769 			LogCommConfig(cfg);
       
   770 #endif // __FLOG_ACTIVE
       
   771 
       
   772 			ret = iComm.SetConfig(cfg);
       
   773 			break;
       
   774 			}
       
   775 			
       
   776 		case KSerialPortName:
       
   777 			{
       
   778 			aOpt.Copy(iCommPort);
       
   779 			break;
       
   780 			}
       
   781 			
       
   782 		case KSerialSetCsyName:
       
   783 			{
       
   784 			if(!iCommPortOpen)
       
   785 				{
       
   786 				iCsyName.Copy(*(
       
   787 			   				reinterpret_cast<const TName*>(aOpt.Ptr())
       
   788 			   				));
       
   789 				iCsyNameOverride = ETrue;
       
   790 				__FLOG_1(_L8("Ioctl: CSY Name set to [%S]"), &iCsyName);	
       
   791 				}
       
   792 			else
       
   793 				{
       
   794 				__FLOG(_L8("Ioctl: Warning: Cannot set the CSY name because the Comm Port is already open."));
       
   795 				ret = KErrAlreadyExists;
       
   796 				}
       
   797 			
       
   798 			break;
       
   799 			}
       
   800 			
       
   801 		case KSerialSetCommRole:
       
   802 			{
       
   803 			if(!iCommPortOpen)
       
   804 				{
       
   805 				iCommRole = *(reinterpret_cast<const TCommRole*>(aOpt.Ptr()));
       
   806 				iCommRoleOverride = ETrue;
       
   807 				__FLOG_1(_L8("Ioctl: Comm Role set to [%d]"), iCommRole);	
       
   808 				}
       
   809 			else
       
   810 				{
       
   811 				__FLOG(_L8("Ioctl: Warning: Cannot set Comm Role because the Comm Port is already open."));
       
   812 				ret = KErrAlreadyExists;
       
   813 				}
       
   814 			break;	
       
   815 			}
       
   816 		
       
   817 		case KSerialSetTxRxBufferSize:
       
   818 			{
       
   819 			TInt bufSize = *(reinterpret_cast<const TInt*>(aOpt.Ptr()));
       
   820 			__FLOG_1(_L8("Ioctl: Setting Rx Tx buffer size to [%d]"), bufSize); 
       
   821 			
       
   822 			iComm.SetReceiveBufferLength(bufSize);
       
   823 			break;
       
   824 			}
       
   825 			
       
   826 		case KSerialMonitorControlLines:
       
   827 			{
       
   828 			TRAP(ret, MonitorControlLinesL(*(reinterpret_cast<const TUint*>(aOpt.Ptr()))));
       
   829 			break;
       
   830 			}			
       
   831 							
       
   832 		case KSerialSetControlLines:
       
   833 			{
       
   834 			if (aOpt.Length() != sizeof(TSerialSetControlLines))
       
   835 				{
       
   836 				ret = KErrArgument;
       
   837 				}
       
   838 			else
       
   839 				{
       
   840 				const TSerialSetControlLines& lines = *(reinterpret_cast<const TSerialSetControlLines*>(aOpt.Ptr()));
       
   841 				__FLOG_2(_L8("Ioctl: Setting/clearing control lines %x/%x"), lines.iSetMask, lines.iClearMask); 
       
   842 				iComm.SetSignals(lines.iSetMask, lines.iClearMask);
       
   843 				ret = KErrNone;
       
   844 				}
       
   845 			break;
       
   846 			}
       
   847 
       
   848 		default:
       
   849 			ret = KErrNotSupported;
       
   850 			}		
       
   851 		}
       
   852 	else
       
   853 		{
       
   854 		ret = KErrNotSupported;
       
   855 		}
       
   856 		
       
   857 	
       
   858 	__FLOG_1(_L8("Ioctl completed with error %d"), ret);			
       
   859 	
       
   860 	TRequestStatus* ptrStatus = &aStatus;
       
   861 	User::RequestComplete(ptrStatus, ret);
       
   862 	}
       
   863 	
       
   864 /** Enables / Disables monitoring & link down reporting on the specified control lines
       
   865 
       
   866 @param aMask bitmaks specifying the lines to monitor, OR
       
   867 	KMonitorOff to turn monitoring off, OR
       
   868 	KConfigFailBcaSpecificOnly to set up monitoring according to Comm Role only 
       
   869 	
       
   870 @leave if the monitoring object cannot be constructed, typically due to OOM.
       
   871 */
       
   872 void CC32Bca::MonitorControlLinesL(TUint32 aArgMask)
       
   873 	{
       
   874 	__FLOG_1(_L8("Ioctl: argument bitmask = [0x%X] "), aArgMask);	
       
   875 			
       
   876 	if(iLinkMonitor) // We may have never started...  
       
   877 			{
       
   878 			// We are called to either stop or change the monitoring options.
       
   879 			iLinkMonitor->Cancel(); // If we are not monitoring, this has no effect.
       
   880 			}
       
   881 	
       
   882 	if(KMonitorOff == aArgMask) // Stop monitoring:
       
   883 		{
       
   884 		__FLOG(_L8("MonitorControlLinesL: Stopping Control Lines monitoring."));
       
   885 		// We either never started, or we just cancelled above.
       
   886 		}
       
   887 	else // Start Monitoring, or change the monitored lines.
       
   888 		{
       
   889 		__FLOG(_L8("MonitorControlLinesL: Starting to monitor Control Lines."));	
       
   890 		
       
   891 		if(!iLinkMonitor) // We are starting to monitor for the first time 
       
   892 			{			
       
   893 			iLinkMonitor = new (ELeave)CCommLinkMonitor(*this, iComm);
       
   894 			}		
       
   895 		// At this point we have a monitoring object that isn't active.
       
   896 			
       
   897 		// A CSY does not necessarily handle the KConfigFail* correctly. For example, if 
       
   898 		// a DTR is initially low, because the terminal was not plugged in yet, we get a failure straight away,
       
   899 		// So, we translate the failure arguments and monitor the relevant lines ourselves. We fail only when a line
       
   900 		// is disasserted. This is absolutely necessary to support server-mode PPP, because we may need to wait 
       
   901 		// an arbitrary period of time for the user to plug the terminal in.
       
   902 		TUint32 lineMask(0x0);
       
   903 		if(KFailBcaSpecificOnly == aArgMask) // We decide what lines to monitor
       
   904 			{
       
   905 			// N.B. When a DTE, fail on low DSR. This is necessary to detect a disconnection on serial links that
       
   906 			// do not utilise DCD.
       
   907 			lineMask = (ECommRoleDCE == iCommRole) ? KSignalDTR : KSignalDCD | KSignalDSR;
       
   908 			}
       
   909 		else // User explicitly specified the control lines.
       
   910 			{
       
   911 			// Don't bother with sanity checks on the lines. Let C32 handle it.
       
   912 
       
   913 			if(KConfigFailCTS & aArgMask)
       
   914 				{
       
   915 				lineMask |= KSignalCTS;
       
   916 				}
       
   917 			if(KConfigFailDSR & aArgMask)
       
   918 				{
       
   919 				lineMask |= KSignalDSR;
       
   920 				}
       
   921 			if(KConfigFailDCD & aArgMask)
       
   922 				{
       
   923 				lineMask |= KSignalDCD;
       
   924 				}
       
   925 			if(KConfigFailDTR & aArgMask)
       
   926 				{
       
   927 				lineMask |= KSignalDTR;
       
   928 				}
       
   929 			if(KConfigFailRTS & aArgMask)
       
   930 				{
       
   931 				lineMask |= KSignalRTS;
       
   932 				}
       
   933 			}
       
   934 			
       
   935 		iLinkMonitor->Setup(lineMask);
       
   936 		iLinkMonitor->NotifyLinkDown();
       
   937 		
       
   938 		__FLOG(_L8("MonitorControlLinesL: Control Lines monitoring started."));	
       
   939 		}				
       
   940 	}
       
   941 
       
   942 /**
       
   943 Closes the connection to CommDB, if it is open */
       
   944 void CC32Bca::CloseCommDbConnection()
       
   945 	{
       
   946 	delete iCommsDat;
       
   947 	iCommsDat = NULL;
       
   948 	}
       
   949 
       
   950 /**
       
   951 Read Comm Port from CommDB bearer record 
       
   952 @param aPortName
       
   953 @leave if the value could not be read */
       
   954 void CC32Bca::ReadCommPortFromCommDbL(TDes& aPortName)
       
   955 	{
       
   956 	__FLOG(_L8("CC32Bca::ReadCommPortFromCommDbL()"));
       
   957 	ConnectToCommDbBearerRecordL();
       
   958 
       
   959 	TInt ret(0);
       
   960 	CMDBField<TDesC>* portField = new(ELeave) CMDBField<TDesC>(KCDTIdPortName);
       
   961 	CleanupStack::PushL(portField);
       
   962 
       
   963 	portField->SetRecordId(iModemId);
       
   964 	portField->SetMaxLengthL(KMaxTextLength);
       
   965 	TRAP(ret,portField->LoadL(*iCommsDat));
       
   966 
       
   967 	if(ret!=KErrNone)
       
   968 		{
       
   969 		__FLOG_1(_L8("portField->LoadL(*iCommsDat) left with[%d] "), ret);
       
   970 		User::Leave(ret);	
       
   971 		}
       
   972 
       
   973 	aPortName = *portField;
       
   974 	CleanupStack::PopAndDestroy(portField);	
       
   975 	}
       
   976 	
       
   977 /** 
       
   978 Read the CSY name from CommDB bearer record.
       
   979 @param aCsyName the CSY name
       
   980 @leave if the value could not be read */
       
   981 void CC32Bca::ReadCsyNameFromCommDbL(TDes& aCsyName)
       
   982 	{
       
   983 	__FLOG(_L8("CC32Bca::ReadCsyNameFromCommDbL()"));
       
   984 	ConnectToCommDbBearerRecordL();
       
   985 
       
   986 	TInt ret(0);
       
   987 	CMDBField<TDesC>* csyField = new(ELeave) CMDBField<TDesC>(KCDTIdCsyName);
       
   988 	CleanupStack::PushL(csyField);
       
   989 
       
   990 	csyField->SetRecordId(iModemId);
       
   991 	csyField->SetMaxLengthL(KMaxTextLength);
       
   992 	TRAP(ret,csyField->LoadL(*iCommsDat));
       
   993 
       
   994 	if(ret!=KErrNone)
       
   995 		{
       
   996 		__FLOG_1(_L8("csyField->LoadL(*iCommsDat) left with[%d] "), ret);
       
   997 		User::Leave(ret);	
       
   998 		}
       
   999 
       
  1000 	aCsyName = *csyField;
       
  1001 	CleanupStack::PopAndDestroy(csyField);
       
  1002 	}
       
  1003 	
       
  1004 /**
       
  1005 Read the specified Comm role (DTE / DCE) from CommDB bearer record
       
  1006 
       
  1007 @param aCommRole the specified role.
       
  1008 @leave if the value could not be read */	
       
  1009 void CC32Bca::ReadCommRoleFromCommDbL(TCommRole& aCommRole)
       
  1010 	{
       
  1011 	__FLOG(_L8("CC32Bca::ReadCommRoleFromCommDbL()"));
       
  1012 	ConnectToCommDbBearerRecordL();
       
  1013 	TUint32 role(0);
       
  1014 
       
  1015 	TInt ret(0);
       
  1016 	CMDBField<TUint32>* roleField = new(ELeave) CMDBField<TUint32>(KCDTIdCommRole);
       
  1017 	CleanupStack::PushL(roleField);
       
  1018 
       
  1019 	roleField->SetRecordId(iModemId);
       
  1020 	TRAP(ret,roleField->LoadL(*iCommsDat));
       
  1021 
       
  1022 	if(ret!=KErrNone)
       
  1023 		{
       
  1024 		__FLOG_1(_L8("roleField->LoadL(*iCommsDat) left with[%d] "), ret);
       
  1025 		User::Leave(ret);	
       
  1026 		}
       
  1027 
       
  1028 	role = *roleField;
       
  1029 	CleanupStack::PopAndDestroy(roleField);
       
  1030 
       
  1031 	aCommRole = (0 == (role & KModemCommRoleDCE)) ? ECommRoleDTE : ECommRoleDCE;
       
  1032 	}
       
  1033 
       
  1034 /** 
       
  1035 Opens a connection to the ModemBearer record specified by the provisioned IAP ID.
       
  1036 
       
  1037 @leave KErrNotReady, if the provisioned IAP id is invalid. System-wide error code
       
  1038        if the connection cannot be opened for some other reason.
       
  1039 */
       
  1040 void CC32Bca::ConnectToCommDbBearerRecordL()
       
  1041 	{
       
  1042 	__FLOG(_L8("CC32Bca::ConnectToCommDbBearerRecordL()"));
       
  1043 	if(iCommsDat != NULL) // CommDB is already open, we don't need to do anything
       
  1044 		{
       
  1045 		return;	
       
  1046 		}
       
  1047 	
       
  1048 	if(iIapId < 1) // Can't access CommDB if IAP ID is unknown
       
  1049 		{
       
  1050 		__FLOG_1(_L8("iIapId[%d] is unknown"), iIapId);
       
  1051 		User::Leave(KErrNotReady);	
       
  1052 		}
       
  1053 
       
  1054 	//
       
  1055 	// Open connecton to CommDB Bearer record specified by the IAP.
       
  1056 	//
       
  1057 #ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
       
  1058 	iCommsDat = CMDBSession::NewL(KCDVersion1_2);
       
  1059 #else
       
  1060 	iCommsDat = CMDBSession::NewL(KCDVersion1_1);
       
  1061 #endif
       
  1062 	
       
  1063 	CCDIAPRecord *iapRecord = static_cast<CCDIAPRecord*>(CCDRecordBase::RecordFactoryL(KCDTIdIAPRecord));
       
  1064   	CleanupStack::PushL(iapRecord);
       
  1065   	
       
  1066   	iapRecord->SetRecordId(iIapId);
       
  1067   	
       
  1068   	TBool hiddenAttributeMaskValue = iCommsDat->IsSetAttributeMask(ECDHidden);
       
  1069    	TBool privateAttributeMaskValue = iCommsDat->IsSetAttributeMask(ECDPrivate);
       
  1070   	
       
  1071   	// Check to see if viewing hidden records is enabled or not
       
  1072 	if(!hiddenAttributeMaskValue || !privateAttributeMaskValue)
       
  1073 		{
       
  1074 		// Reveal hidden or private IAP records if a licensee has chosen to protect a record
       
  1075 		// using one of these flags - the API to do this is public so internal components
       
  1076 		// have to support the use of such records.
       
  1077 		iCommsDat->SetAttributeMask(ECDHidden | ECDPrivate);
       
  1078 		}		  	
       
  1079   	
       
  1080   	TRAPD(ret,iapRecord->LoadL(*iCommsDat));
       
  1081 	if (ret != KErrNone)
       
  1082 		{
       
  1083 		__FLOG_1(_L8("iapRecord->LoadL(*iCommsDat) left with[%d] "), ret);
       
  1084 		User::Leave(ret);
       
  1085 		}    
       
  1086     
       
  1087     // If we enabled viewing hidden records now disable viewing them.
       
  1088     if(!hiddenAttributeMaskValue)
       
  1089     	{
       
  1090     	iCommsDat->ClearAttributeMask(ECDHidden);
       
  1091     	}
       
  1092  	if(!privateAttributeMaskValue)
       
  1093 		{
       
  1094 		iCommsDat->ClearAttributeMask(ECDPrivate);
       
  1095 		}		  	
       
  1096    	
       
  1097 
       
  1098 	iModemId = iapRecord->iBearer;
       
  1099 	CleanupStack::PopAndDestroy(iapRecord);
       
  1100 	
       
  1101 	if(iModemId == 0) // ID not found.
       
  1102 		{
       
  1103 		__FLOG_1(_L8("iModemId[%d] is not found"), iModemId);
       
  1104 		User::Leave(KErrNotFound);	
       
  1105 		}
       
  1106 	}
       
  1107 
       
  1108 
       
  1109 /** Cancels an outstanding Ioctl, if any. */
       
  1110 void CC32Bca::CancelIoctl()
       
  1111 	{
       
  1112 	__FLOG(_L8("CancelIoctl(): Ioctl cancel request. No Ioctl to cancel."));
       
  1113 	}
       
  1114 	
       
  1115 
       
  1116 /** Closes the Comm port and Comm Server.*/
       
  1117 void CC32Bca::CloseCommPort()
       
  1118 	{
       
  1119 	__ASSERT_ALWAYS(iReader,      Panic(ENullReaderOnClose));
       
  1120 	__ASSERT_ALWAYS(iWriter,     Panic(ENullWriterOnClose));
       
  1121 		
       
  1122 	// When we close the port, all async requests outstanding are cancelled.
       
  1123 	// We must make sure nobody is waiting on them. If the underlying request is cancelled,
       
  1124 	// but the owner AO is not, Cancel() on such AO hangs waiting for the request to complete.
       
  1125 	
       
  1126 	iReader->Cancel();
       
  1127 	iWriter->Cancel();
       
  1128 	if(iLinkMonitor) // Link monitor is constructed on client request only.
       
  1129 		{
       
  1130 		iLinkMonitor->Cancel();
       
  1131 		}
       
  1132 	
       
  1133 	if (iCommPortOpen)
       
  1134 		{
       
  1135 		iComm.Close(); 
       
  1136 		iCommServ.Close();	
       
  1137 		iCommPortOpen = EFalse;
       
  1138 		}
       
  1139 	__FLOG(_L8("CloseCommPort(): Session with C32 & RComm closed."));
       
  1140 	}
       
  1141 
       
  1142 /**
       
  1143 C32Bca Panic function
       
  1144 @internalComponent
       
  1145 */		
       
  1146 void C32Bca::Panic(TC32BcaPanic aPanic)
       
  1147 	{
       
  1148 	__FLOG_STATIC2(KC32BcaLogFolder,KC32BcaLogFile,_L8("%S Panic %d"), &KC32BcaPanic(), aPanic);
       
  1149 	User::Panic(KC32BcaPanic, aPanic);
       
  1150 	}
       
  1151 	
       
  1152 
       
  1153 // MC32User implementation:
       
  1154 
       
  1155 // Read has completed. 
       
  1156 void CC32Bca::CommReadComplete(TInt aErr)
       
  1157 	{
       
  1158 	__ASSERT_ALWAYS(iReadRequest, Panic(ENullReadRequestStatus));
       
  1159 	__ASSERT_DEBUG(KRequestPending == iReadRequest->Int(), Panic(EReadRequestNotPending));
       
  1160 	
       
  1161 	User::RequestComplete(iReadRequest, aErr);
       
  1162 	}
       
  1163 
       
  1164 // Write has completed.
       
  1165 void CC32Bca::CommWriteComplete(TInt aErr)
       
  1166 	{
       
  1167 	__ASSERT_ALWAYS(iWriteRequest, Panic(ENullWriteRequestStatus));	
       
  1168 	__ASSERT_DEBUG(KRequestPending == iWriteRequest->Int(), Panic(EWriteRequestNotPending));
       
  1169 	
       
  1170 	User::RequestComplete(iWriteRequest, aErr);
       
  1171 	}
       
  1172 
       
  1173 // Upcall from the link monitor: Link has gone down.	
       
  1174 void CC32Bca::CommLinkDown(TInt aErr)
       
  1175 	{
       
  1176 	__FLOG_1(_L8("CommLinkDown: Warning: serial link has gone down with error[%d]. Erroring the outstanding Read & Write."), aErr);
       
  1177 	
       
  1178 	__ASSERT_DEBUG(KErrNone != aErr, Panic(EGeneralLogicError)); // If KErrNone, use has no way to know that the read has failed.
       
  1179 	if(iReader->IsActive())
       
  1180 		{
       
  1181 		CommReadComplete(aErr);
       
  1182 		iReader->Cancel();					
       
  1183 		}
       
  1184 	else
       
  1185 		{
       
  1186 		iErrorOnNextRead = aErr;
       
  1187 		}
       
  1188 	
       
  1189 	if(iWriter->IsActive())
       
  1190 		{
       
  1191 		CommWriteComplete(aErr);
       
  1192 		iWriter->Cancel();		
       
  1193 		}
       
  1194 	else
       
  1195 		{
       
  1196 		iErrorOnNextWrite = aErr;
       
  1197 		}
       
  1198 	}