usbmgmt/usbmgr/device/classdrivers/acm/classimplementation/ecacm/src/AcmPort.cpp
changeset 0 c9bc50fca66e
child 15 f92a4f87e424
equal deleted inserted replaced
-1:000000000000 0:c9bc50fca66e
       
     1 /*
       
     2 * Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:
       
    15 *
       
    16 */
       
    17 
       
    18 #include <acminterface.h>
       
    19 #include <usb/usblogger.h>
       
    20 #include "AcmPort.h"
       
    21 #include "AcmPortFactory.h"
       
    22 #include "AcmUtils.h"
       
    23 #include "AcmWriter.h"
       
    24 #include "AcmReader.h"
       
    25 #include "AcmPanic.h"
       
    26 
       
    27 #ifdef __FLOG_ACTIVE
       
    28 _LIT8(KLogComponent, "ECACM");
       
    29 #endif
       
    30 
       
    31 const TUint KCapsRate=(   KCapsBps50
       
    32 						| KCapsBps75
       
    33 						| KCapsBps110
       
    34 						| KCapsBps134
       
    35 						| KCapsBps150
       
    36 						| KCapsBps300
       
    37 						| KCapsBps600
       
    38 						| KCapsBps1200
       
    39 						| KCapsBps1800
       
    40 						| KCapsBps2000
       
    41 						| KCapsBps2400
       
    42 						| KCapsBps3600
       
    43 						| KCapsBps4800
       
    44 						| KCapsBps7200
       
    45 						| KCapsBps9600
       
    46 						| KCapsBps19200
       
    47 						| KCapsBps38400
       
    48 						| KCapsBps57600
       
    49 						| KCapsBps115200
       
    50 						| KCapsBps230400
       
    51 						| KCapsBps460800
       
    52 						| KCapsBps576000
       
    53 						| KCapsBps115200
       
    54 						| KCapsBps4000000 );
       
    55 const TUint KCapsDataBits=KCapsData8;		
       
    56 const TUint KCapsStopBits=KCapsStop1;		
       
    57 const TUint KCapsParity=KCapsParityNone;	
       
    58 const TUint KCapsHandshaking=(
       
    59 						  KCapsSignalCTSSupported
       
    60 						| KCapsSignalDSRSupported
       
    61 						| KCapsSignalRTSSupported
       
    62 						| KCapsSignalDTRSupported); 
       
    63 const TUint KCapsSignals=(
       
    64 							KCapsSignalCTSSupported
       
    65 						|	KCapsSignalDSRSupported
       
    66 						|	KCapsSignalRTSSupported
       
    67 						|	KCapsSignalDTRSupported);
       
    68 const TUint KCapsFifo = 0;
       
    69 const TUint KCapsSIR = 0; ///< Serial Infrared capabilities
       
    70 const TUint KCapsNotification = KNotifySignalsChangeSupported;			
       
    71 const TUint KCapsRoles = 0; 				
       
    72 const TUint KCapsFlowControl = 0;							
       
    73 
       
    74 const TBps		KDefaultDataRate = EBps115200;		
       
    75 const TDataBits KDefaultDataBits = EData8;			
       
    76 const TParity	KDefaultParity	 = EParityNone; 	
       
    77 const TStopBits KDefaultStopBits = EStop1;			
       
    78 const TUint 	KDefaultHandshake = 0;	
       
    79 ///< Default XON character is <ctrl>Q				
       
    80 const TText8	KDefaultXon 	 = 17; 
       
    81 ///< Default XOFF character is <ctrl>S
       
    82 const TText8	KDefaultXoff	 = 19; 
       
    83 
       
    84 // Starting size of each of the receive and transmit buffers.
       
    85 const TUint KDefaultBufferSize = 0x1000;
       
    86 
       
    87 CAcmPort* CAcmPort::NewL(const TUint aUnit, MAcmPortObserver& aFactory)
       
    88 /**
       
    89  * Make a new CPort for the comm server
       
    90  *
       
    91  * @param aFactory The observer of the port, to be notified when the port 
       
    92  * closes.
       
    93  * @param aUnit The port number.
       
    94  * @return Ownership of a newly created CAcmPort object
       
    95  */
       
    96 	{
       
    97 	LOG_STATIC_FUNC_ENTRY
       
    98 
       
    99 	CAcmPort* self = new(ELeave) CAcmPort(aUnit, aFactory);
       
   100 	CleanupClosePushL(*self);
       
   101 	self->ConstructL();
       
   102 	CleanupStack::Pop();
       
   103 	return self;
       
   104 	}
       
   105 
       
   106 void CAcmPort::ConstructL()
       
   107 /**
       
   108  * Standard second phase constructor. Create owned classes and initialise the 
       
   109  * port.
       
   110  */
       
   111 	{
       
   112 	iReader = CAcmReader::NewL(*this, KDefaultBufferSize);
       
   113 	iWriter = CAcmWriter::NewL(*this, KDefaultBufferSize);
       
   114 
       
   115 	TName name;
       
   116 	name.Num(iUnit);
       
   117 	LEAVEIFERRORL(SetName(&name));
       
   118 
       
   119 	iCommServerConfig.iBufFlags = 0;
       
   120 	iCommServerConfig.iBufSize = iReader->BufSize();
       
   121 
       
   122 	iCommConfig.iRate			= KDefaultDataRate;
       
   123 	iCommConfig.iDataBits		= KDefaultDataBits;
       
   124 	iCommConfig.iParity 		= KDefaultParity;
       
   125 	iCommConfig.iStopBits		= KDefaultStopBits;
       
   126 	iCommConfig.iHandshake		= KDefaultHandshake;
       
   127 	iCommConfig.iParityError	= 0;
       
   128 	iCommConfig.iFifo			= 0;
       
   129 	iCommConfig.iSpecialRate	= 0;
       
   130 	iCommConfig.iTerminatorCount= 0;
       
   131 	iCommConfig.iXonChar		= KDefaultXon;
       
   132 	iCommConfig.iXoffChar		= KDefaultXoff;
       
   133 	iCommConfig.iParityErrorChar= 0;
       
   134 	iCommConfig.iSIREnable		= ESIRDisable;
       
   135 	iCommConfig.iSIRSettings	= 0;
       
   136 	}
       
   137 
       
   138 CAcmPort::CAcmPort(const TUint aUnit, MAcmPortObserver& aObserver) 
       
   139  :	iCommNotification(iCommNotificationDes()),
       
   140 	iObserver(aObserver),
       
   141 	iUnit(aUnit)
       
   142 /**
       
   143  * Constructor.
       
   144  *
       
   145  * @param aObserver The observer of the port, to be notified when the port 
       
   146  * closes.
       
   147  * @param aUnit The port number.
       
   148  */
       
   149 	{
       
   150 	}
       
   151 
       
   152 void CAcmPort::StartRead(const TAny* aClientBuffer, TInt aLength)
       
   153 /**
       
   154  * Downcall from C32. Queue a read.
       
   155  *
       
   156  * @param aClientBuffer pointer to the client's buffer
       
   157  * @param aLength number of bytes to read
       
   158  */
       
   159 	{
       
   160 	LOG_LINE
       
   161 	LOG_FUNC
       
   162 	LOGTEXT3(_L8("\taClientBuffer=0x%08x, aLength=%d"),
       
   163 		aClientBuffer, aLength);
       
   164 
       
   165 	if ( !iAcm )
       
   166 		{
       
   167 		LOGTEXT(_L8("\t***access denied"));
       
   168 		ReadCompleted(KErrAccessDenied);
       
   169 		return;
       
   170 		}
       
   171 
       
   172 	// Analyse the request and call the relevant API on the data reader. NB We 
       
   173 	// do not pass requests for zero bytes to the data reader. They are an 
       
   174 	// RComm oddity we should handle here.
       
   175 	__ASSERT_DEBUG(iReader, _USB_PANIC(KAcmPanicCat, EPanicInternalError));
       
   176 
       
   177 	if(iReader->IsNotifyDataAvailableQueryPending())
       
   178 		{
       
   179 		ReadCompleted(KErrInUse);
       
   180 		return;
       
   181 		}
       
   182 
       
   183 	if ( aLength < 0 )
       
   184 		{
       
   185 		iReader->ReadOneOrMore(aClientBuffer, static_cast<TUint>(-aLength));
       
   186 		}
       
   187 	else if ( aLength > 0 )
       
   188 		{
       
   189 		iReader->Read(aClientBuffer, static_cast<TUint>(aLength));
       
   190 		}
       
   191 	else
       
   192 		{
       
   193 		// Obscure RComm API feature- complete zero-length Read immediately, 
       
   194 		// to indicate that the hardware is powered up.
       
   195 		LOGTEXT(_L8("\tcompleting immediately with KErrNone"));
       
   196 		ReadCompleted(KErrNone);
       
   197 		}
       
   198 	}
       
   199 
       
   200 void CAcmPort::ReadCancel()
       
   201 /**
       
   202  * Downcall from C32. Cancel a read.
       
   203  */
       
   204 	{
       
   205 	LOG_LINE
       
   206 	LOG_FUNC
       
   207 
       
   208 	if ( !iAcm )
       
   209 		{
       
   210 		LOGTEXT(_L8("\t***access denied"));
       
   211 		return;
       
   212 		}
       
   213 
       
   214 	__ASSERT_DEBUG(iReader, _USB_PANIC(KAcmPanicCat, EPanicInternalError));
       
   215 	iReader->ReadCancel();
       
   216 	}
       
   217 
       
   218 TInt CAcmPort::QueryReceiveBuffer(TInt& aLength) const
       
   219 /**
       
   220  * Downcall from C32. Get the amount of data in the receive buffer.
       
   221  *
       
   222  * @param aLength reference to where the amount will be written to
       
   223  * @return Error.
       
   224  */
       
   225 	{
       
   226 	LOG_LINE
       
   227 	LOG_FUNC
       
   228 	
       
   229 	if ( !iAcm )
       
   230 		{
       
   231 		LOGTEXT(_L8("\t***access denied"));
       
   232 		return KErrAccessDenied;
       
   233 		}
       
   234 
       
   235 	__ASSERT_DEBUG(iReader, _USB_PANIC(KAcmPanicCat, EPanicInternalError));
       
   236 	aLength = static_cast<TInt>(iReader->BufLen());
       
   237 	LOGTEXT2(_L8("\tlength=%d"), aLength);
       
   238 	return KErrNone;
       
   239 	}
       
   240 
       
   241 void CAcmPort::ResetBuffers(TUint aFlags)
       
   242 /**
       
   243  * Downcall from C32. Reset zero or more of the Tx and Rx buffers.
       
   244  *
       
   245  * @param aFlags Flags indicating which buffer(s) to reset.
       
   246  */
       
   247 	{
       
   248 	LOG_LINE
       
   249 	LOGTEXT2(_L8(">>CAcmPort::ResetBuffers aFlags = %d"), aFlags);
       
   250 
       
   251 	if ( aFlags & KCommResetRx )
       
   252 		{
       
   253 		LOGTEXT(_L8("\tresetting Rx buffer"));
       
   254 		__ASSERT_DEBUG(iReader, _USB_PANIC(KAcmPanicCat, EPanicInternalError));
       
   255 		iReader->ResetBuffer();
       
   256 		}
       
   257 
       
   258 	if ( aFlags & KCommResetTx )
       
   259 		{
       
   260 		LOGTEXT(_L8("\tresetting Tx buffer"));
       
   261 		__ASSERT_DEBUG(iWriter, _USB_PANIC(KAcmPanicCat, EPanicInternalError));
       
   262 		iWriter->ResetBuffer();
       
   263 		}
       
   264 
       
   265 	LOGTEXT(_L8("<<CAcmPort::ResetBuffers"));
       
   266 	}
       
   267 
       
   268 void CAcmPort::StartWrite(const TAny* aClientBuffer, TInt aLength)
       
   269 /**
       
   270  * Downcall from C32. Queue a write
       
   271  *
       
   272  * @param aClientBuffer pointer to the Client's buffer
       
   273  * @param aLength number of bytes to write
       
   274  */
       
   275 	{
       
   276 	LOG_LINE
       
   277 	LOG_FUNC
       
   278 	LOGTEXT3(_L8("\taClientBuffer=0x%08x, aLength=%d"),
       
   279 		aClientBuffer, aLength);
       
   280 
       
   281 	if ( !iAcm )
       
   282 		{
       
   283 		LOGTEXT(_L8("\t***access denied"));
       
   284 		WriteCompleted(KErrAccessDenied);
       
   285 		return;
       
   286 		}
       
   287 
       
   288 	if ( aLength < 0 )
       
   289 		{
       
   290 		// Negative length makes no sense.
       
   291 		LOGTEXT(_L8("\taLength is negative- "
       
   292 			"completing immediately with KErrArgument"));
       
   293 		WriteCompleted(KErrArgument);
       
   294 		return;
       
   295 		}
       
   296 
       
   297 	// NB We pass zero-byte writes down to the LDD as normal. This results in 
       
   298 	// a zero-length packet being sent to the host.
       
   299 
       
   300 	__ASSERT_DEBUG(iWriter, _USB_PANIC(KAcmPanicCat, EPanicInternalError));
       
   301 	iWriter->Write(aClientBuffer, static_cast<TUint>(aLength));
       
   302 	}
       
   303 
       
   304 void CAcmPort::WriteCancel()
       
   305 /**
       
   306  * Downcall from C32. Cancel a pending write
       
   307  */
       
   308 	{
       
   309 	LOG_LINE
       
   310 	LOG_FUNC
       
   311 	
       
   312 	if ( !iAcm )
       
   313 		{
       
   314 		LOGTEXT(_L8("\t***access denied"));
       
   315 		return;
       
   316 		}
       
   317 
       
   318 	__ASSERT_DEBUG(iWriter, _USB_PANIC(KAcmPanicCat, EPanicInternalError));
       
   319 	iWriter->WriteCancel();
       
   320 	}
       
   321 
       
   322 void CAcmPort::Break(TInt aTime)
       
   323 /**
       
   324  * Downcall from C32. Send a break signal to the host.
       
   325  * Note that it is assumed that the NotifyBreak() request only applies to 
       
   326  * break signals sent from the host.
       
   327  *
       
   328  * @param aTime Length of break in microseconds
       
   329  */
       
   330 	{
       
   331 	LOG_LINE
       
   332 	LOG_FUNC
       
   333 	LOGTEXT2(_L8("\taTime=%d (microseconds)"), aTime);
       
   334 
       
   335 	if ( !iAcm )
       
   336 		{
       
   337 		LOGTEXT(_L8("\t***access denied"));
       
   338 		return;
       
   339 		}
       
   340 
       
   341 	iBreak = ETrue;
       
   342 	iCancellingBreak = EFalse;
       
   343 
       
   344 	// Use the time value directly as microseconds are given. We are a USB 
       
   345 	// 'device' so the RComm client is always on the device side.
       
   346 	TInt err = iAcm->BreakRequest(CBreakController::EDevice,
       
   347 		CBreakController::ETiming,
       
   348 		TTimeIntervalMicroSeconds32(aTime));
       
   349 	LOGTEXT2(_L8("\tBreakRequest = %d"), err);
       
   350 	// Note that the break controller may refuse our request if a host-driven 
       
   351 	// break is outstanding.
       
   352 	if ( err )
       
   353 		{
       
   354 		LOGTEXT2(_L8("\tcalling BreakCompleted with %d"), err);
       
   355 		iBreak = EFalse;
       
   356 		BreakCompleted(err);
       
   357 		}						
       
   358 	}
       
   359 
       
   360 void CAcmPort::BreakCancel()
       
   361 /**
       
   362  * Downcall from C32. Cancel a pending break.
       
   363  */
       
   364 	{
       
   365 	LOG_LINE
       
   366 	LOG_FUNC
       
   367 
       
   368 	if ( !iAcm )
       
   369 		{
       
   370 		LOGTEXT(_L8("\t***access denied"));
       
   371 		return;
       
   372 		}
       
   373 	
       
   374 	iCancellingBreak = ETrue;
       
   375 
       
   376 	TInt err = iAcm->BreakRequest(CBreakController::EDevice,
       
   377 		CBreakController::EInactive);
       
   378 	// Note that the device cannot turn off a break if there's a host-driven 
       
   379 	// break in progress.
       
   380 	LOGTEXT2(_L8("\tBreakRequest = %d"), err);
       
   381 	if ( err )
       
   382 		{
       
   383 		iCancellingBreak = EFalse;
       
   384 		}
       
   385 
       
   386 	// Whether BreakOff worked or not, reset our flag saying we're no longer 
       
   387 	// interested in any subsequent completion anyway.
       
   388 	iBreak = EFalse;
       
   389 	}
       
   390 
       
   391 TInt CAcmPort::GetConfig(TDes8& aDes) const
       
   392 /**
       
   393  * Downcall from C32. Pass a config request. Only supports V01.
       
   394  *
       
   395  * @param aDes config will be written to this descriptor 
       
   396  * @return Error.
       
   397  */
       
   398 	{
       
   399 	LOG_LINE
       
   400 	LOG_FUNC
       
   401 
       
   402 	if ( !iAcm )
       
   403 		{
       
   404 		LOGTEXT(_L8("\t***access denied"));
       
   405 		return KErrAccessDenied;
       
   406 		}
       
   407 
       
   408 	if ( aDes.Length() < static_cast<TInt>(sizeof(TCommConfigV01)) )
       
   409 		{
       
   410 		LOGTEXT(_L8("\t***not supported"));
       
   411 		return KErrNotSupported;
       
   412 		}
       
   413 
       
   414 	TCommConfig commConfigPckg;
       
   415 	TCommConfigV01& commConfig = commConfigPckg();
       
   416 	commConfig = iCommConfig;
       
   417 	
       
   418 	aDes.Copy(commConfigPckg);
       
   419 
       
   420 	LOGTEXT2(_L8("\tiCommConfig.iRate = %d"), iCommConfig.iRate);
       
   421 	LOGTEXT2(_L8("\tiCommConfig.iDataBits = %d"), iCommConfig.iDataBits);
       
   422 	LOGTEXT2(_L8("\tiCommConfig.iStopBits = %d"), iCommConfig.iStopBits);
       
   423 	LOGTEXT2(_L8("\tiCommConfig.iParity = %d"), iCommConfig.iParity);
       
   424 	LOGTEXT2(_L8("\tiCommConfig.iHandshake = %d"), iCommConfig.iHandshake);
       
   425 	LOGTEXT2(_L8("\tiCommConfig.iParityError = %d"), 
       
   426 		iCommConfig.iParityError);
       
   427 	LOGTEXT2(_L8("\tiCommConfig.iFifo = %d"), iCommConfig.iFifo);
       
   428 	LOGTEXT2(_L8("\tiCommConfig.iSpecialRate = %d"), 
       
   429 		iCommConfig.iSpecialRate);
       
   430 	LOGTEXT2(_L8("\tiCommConfig.iTerminatorCount = %d"), 
       
   431 		iCommConfig.iTerminatorCount);
       
   432 	LOGTEXT2(_L8("\tiCommConfig.iSIREnable = %d"), iCommConfig.iSIREnable);
       
   433 	LOGTEXT2(_L8("\tiCommConfig.iSIRSettings = %d"), 
       
   434 		iCommConfig.iSIRSettings);
       
   435 
       
   436 	return KErrNone;
       
   437 	}
       
   438 
       
   439 TInt CAcmPort::SetConfig(const TDesC8& aDes)
       
   440 /**
       
   441  * Downcall from C32. Set config on the port using a TCommConfigV01 package.
       
   442  *
       
   443  * @param aDes descriptor containing the new config
       
   444  * @return Error
       
   445  */
       
   446 	{
       
   447 	LOG_LINE
       
   448 	LOG_FUNC
       
   449 
       
   450 	if ( !iAcm )
       
   451 		{
       
   452 		LOGTEXT(_L8("\t***access denied"));
       
   453 		return KErrAccessDenied;
       
   454 		}
       
   455 
       
   456 	LOGTEXT4(_L8("\tlength of argument %d, TCommConfigV01 %d, "
       
   457 		"TCommConfigV02 %d"), 
       
   458 		aDes.Length(), 
       
   459 		(TInt)sizeof(TCommConfigV01),
       
   460 		(TInt)sizeof(TCommConfigV02));
       
   461 
       
   462 	if ( aDes.Length() < static_cast<TInt>(sizeof(TCommConfigV01)) )
       
   463 		{
       
   464 		LOGTEXT(_L8("\t***not supported"));
       
   465 		return KErrNotSupported;
       
   466 		}
       
   467 
       
   468 	TCommConfig configPckg;
       
   469 	configPckg.Copy(aDes);
       
   470 	TCommConfigV01& config = configPckg();
       
   471 
       
   472 	LOGTEXT2(_L8("\tiCommConfig.iRate = %d"), config.iRate);
       
   473 	LOGTEXT2(_L8("\tiCommConfig.iDataBits = %d"), config.iDataBits);
       
   474 	LOGTEXT2(_L8("\tiCommConfig.iStopBits = %d"), config.iStopBits);
       
   475 	LOGTEXT2(_L8("\tiCommConfig.iParity = %d"), config.iParity);
       
   476 	LOGTEXT2(_L8("\tiCommConfig.iHandshake = %d"), config.iHandshake);
       
   477 	LOGTEXT2(_L8("\tiCommConfig.iParityError = %d"), config.iParityError);
       
   478 	LOGTEXT2(_L8("\tiCommConfig.iFifo = %d"), config.iFifo);
       
   479 	LOGTEXT2(_L8("\tiCommConfig.iSpecialRate = %d"), config.iSpecialRate);
       
   480 	LOGTEXT2(_L8("\tiCommConfig.iTerminatorCount = %d"), 
       
   481 		config.iTerminatorCount);
       
   482 	LOGTEXT2(_L8("\tiCommConfig.iSIREnable = %d"), config.iSIREnable);
       
   483 	LOGTEXT2(_L8("\tiCommConfig.iSIRSettings = %d"), config.iSIRSettings);
       
   484 
       
   485 	// Tell the reader object about the new terminators. Pass the whole config 
       
   486 	// struct by reference for ease.
       
   487 	iReader->SetTerminators(config);
       
   488 
       
   489 	HandleConfigNotification(config.iRate,
       
   490 		config.iDataBits,
       
   491 		config.iParity,
       
   492 		config.iStopBits,
       
   493 		config.iHandshake);
       
   494 	iCommConfig = config;
       
   495 
       
   496 	return KErrNone;
       
   497 	}
       
   498 
       
   499 void CAcmPort::HandleConfigNotification(TBps aRate,
       
   500 										TDataBits aDataBits,
       
   501 										TParity aParity,
       
   502 										TStopBits aStopBits,
       
   503 										TUint aHandshake)
       
   504 /**
       
   505  * Construct and complete the config notification data structure.
       
   506  * @param aRate 		New data rate
       
   507  * @param aDataBits 	New number of data bits
       
   508  * @param aParity		New parity check setting
       
   509  * @param aStopBits 	New stop bit setting
       
   510  * @param aHandshake	New handshake setting
       
   511  */
       
   512 	{
       
   513 	LOGTEXT(_L8(">>CAcmPort::HandleConfigNotification"));
       
   514 	LOGTEXT2(_L8("\taRate = %d"), aRate);
       
   515 	LOGTEXT2(_L8("\taDataBits = %d"), aDataBits);
       
   516 	LOGTEXT2(_L8("\taStopBits = %d"), aStopBits);
       
   517 	LOGTEXT2(_L8("\taParity = %d"), aParity);
       
   518 	LOGTEXT2(_L8("\taHandshake = %d"), aHandshake);
       
   519 			
       
   520 	iCommNotification.iChangedMembers = 0;
       
   521 
       
   522 	iCommNotification.iRate = aRate;
       
   523 	if ( iCommConfig.iRate != aRate )
       
   524 		{
       
   525 		iCommNotification.iChangedMembers |= KRateChanged;
       
   526 		}
       
   527 
       
   528 	iCommNotification.iDataBits = aDataBits;
       
   529 	if ( iCommConfig.iDataBits != aDataBits )
       
   530 		{
       
   531 		iCommNotification.iChangedMembers |= KDataFormatChanged;
       
   532 		}
       
   533 
       
   534 	iCommNotification.iParity = aParity;
       
   535 	if ( iCommConfig.iParity != aParity )
       
   536 		{
       
   537 		iCommNotification.iChangedMembers |= KDataFormatChanged;
       
   538 		}
       
   539 
       
   540 	iCommNotification.iStopBits = aStopBits;
       
   541 	if ( iCommConfig.iStopBits != aStopBits )
       
   542 		{
       
   543 		iCommNotification.iChangedMembers |= KDataFormatChanged;
       
   544 		}
       
   545 
       
   546 	iCommNotification.iHandshake = aHandshake;
       
   547 	if ( iCommConfig.iHandshake != aHandshake )
       
   548 		{
       
   549 		iCommNotification.iChangedMembers |= KHandshakeChanged;
       
   550 		}
       
   551 
       
   552 	if ( iCommNotification.iChangedMembers )
       
   553 		{
       
   554 		LOGTEXT(_L8("\tcalling ConfigChangeCompleted with KErrNone"));
       
   555 		ConfigChangeCompleted(iCommNotificationDes,KErrNone);
       
   556 		iNotifyConfigChange = EFalse;
       
   557 		}
       
   558 
       
   559 	LOGTEXT(_L8("<<CAcmPort::HandleConfigNotification"));
       
   560 	}
       
   561 
       
   562 TInt CAcmPort::SetServerConfig(const TDesC8& aDes)
       
   563 /**
       
   564  * Downcall from C32. Set server config using a TCommServerConfigV01 package.
       
   565  *
       
   566  * @param aDes package with new server configurations
       
   567  * @return Error.
       
   568  */
       
   569 	{
       
   570 	LOG_LINE
       
   571 	LOG_FUNC
       
   572 
       
   573 	if ( !iAcm )
       
   574 		{
       
   575 		LOGTEXT(_L8("\t***access denied"));
       
   576 		return KErrAccessDenied;
       
   577 		}
       
   578 
       
   579 	if ( aDes.Length() < static_cast<TInt>(sizeof(TCommServerConfigV01)) )
       
   580 		{
       
   581 		LOGTEXT(_L8("\t***not supported"));
       
   582 		return KErrNotSupported;
       
   583 		}
       
   584 
       
   585 	TCommServerConfig serverConfigPckg;
       
   586 	serverConfigPckg.Copy(aDes);
       
   587 	TCommServerConfigV01& serverConfig = serverConfigPckg();
       
   588 
       
   589 	if ( serverConfig.iBufFlags != KCommBufferFull )
       
   590 		{
       
   591 		LOGTEXT(_L8("\t***not supported"));
       
   592 		return KErrNotSupported;
       
   593 		}
       
   594 
       
   595 	// Apply the buffer size setting to Rx and Tx buffers. 
       
   596 	TInt err = DoSetBufferLengths(serverConfig.iBufSize);
       
   597 	if ( err )
       
   598 		{
       
   599 		// Failure- the buffer lengths will have been left as they were, so 
       
   600 		// just return error.
       
   601 		LOGTEXT2(_L8("\t***DoSetBufferLengths=%d"), err);
       
   602 		return err;
       
   603 		}
       
   604 
       
   605 	// Changed buffer sizes OK. Note that new config.
       
   606 	iCommServerConfig = serverConfig;
       
   607 	return KErrNone;
       
   608 	}
       
   609 
       
   610 TInt CAcmPort::GetServerConfig(TDes8& aDes)
       
   611 /**
       
   612  * Downcall from C32. Get the server configs. Only supports V01.
       
   613  *
       
   614  * @param aDes server configs will be written to this descriptor
       
   615  * @return Error.
       
   616  */
       
   617 	{
       
   618 	LOG_LINE
       
   619 	LOG_FUNC
       
   620 
       
   621 	if ( !iAcm )
       
   622 		{
       
   623 		LOGTEXT(_L8("\t***access denied"));
       
   624 		return KErrAccessDenied;
       
   625 		}
       
   626 
       
   627 	if ( aDes.Length() < static_cast<TInt>(sizeof(TCommServerConfigV01)) )
       
   628 		{
       
   629 		LOGTEXT(_L8("\t***not supported"));
       
   630 		return KErrNotSupported;
       
   631 		}
       
   632 
       
   633 	TCommServerConfig* serverConfigPckg = 
       
   634 		reinterpret_cast<TCommServerConfig*>(&aDes);
       
   635 	TCommServerConfigV01& serverConfig = (*serverConfigPckg)();
       
   636 
       
   637 	serverConfig = iCommServerConfig;
       
   638 	return KErrNone;
       
   639 	}
       
   640 
       
   641 TInt CAcmPort::GetCaps(TDes8& aDes)
       
   642 /**
       
   643  * Downcall from C32. Get the port's capabilities. Supports V01 and V02. 
       
   644  *
       
   645  * @param aDes caps will be written to this descriptor
       
   646  * @return Error.
       
   647  */
       
   648 	{
       
   649 	LOG_LINE
       
   650 	LOG_FUNC
       
   651 
       
   652 	if ( !iAcm )
       
   653 		{
       
   654 		LOGTEXT(_L8("\t***access denied"));
       
   655 		return KErrAccessDenied;
       
   656 		}
       
   657 
       
   658 	TCommCaps2 capsPckg;
       
   659 	TCommCapsV02& caps = capsPckg();
       
   660 
       
   661 	switch ( aDes.Length() )
       
   662 		{
       
   663 	case sizeof(TCommCapsV02):
       
   664 		{
       
   665 		caps.iNotificationCaps = (KCapsNotification | KNotifyDataAvailableSupported);
       
   666 		caps.iRoleCaps = KCapsRoles;
       
   667 		caps.iFlowControlCaps = KCapsFlowControl;
       
   668 		}
       
   669 		// no break is deliberate
       
   670 	case sizeof(TCommCapsV01):
       
   671 		{
       
   672 		caps.iRate = KCapsRate;
       
   673 		caps.iDataBits = KCapsDataBits;
       
   674 		caps.iStopBits = KCapsStopBits;
       
   675 		caps.iParity = KCapsParity;
       
   676 		caps.iHandshake = KCapsHandshaking;
       
   677 		caps.iSignals = KCapsSignals;
       
   678 		caps.iFifo = KCapsFifo;
       
   679 		caps.iSIR = KCapsSIR;
       
   680 		}
       
   681 		break;
       
   682 	default:
       
   683 		{
       
   684 		LOGTEXT(_L8("\t***bad argument"));
       
   685 		return KErrArgument;
       
   686 		}
       
   687 		}
       
   688 
       
   689 	aDes.Copy(capsPckg.Left(aDes.Length()));
       
   690 
       
   691 	return KErrNone;
       
   692 	}
       
   693 
       
   694 TInt CAcmPort::GetSignals(TUint& aSignals)
       
   695 /**
       
   696  * Downcall from C32. Get the status of the signal pins
       
   697  *
       
   698  * @param aSignals signals will be written to this descriptor
       
   699  * @return Error.
       
   700  */
       
   701 	{
       
   702 	LOG_LINE
       
   703 	LOG_FUNC
       
   704 
       
   705 	if ( !iAcm )
       
   706 		{
       
   707 		LOGTEXT(_L8("\t***access denied"));
       
   708 		return KErrAccessDenied;
       
   709 		}
       
   710 
       
   711 	aSignals = ConvertSignals(iSignals);
       
   712 
       
   713 	LOGTEXT3(_L8("iSignals=0x%x, aSignals=0x%x"),
       
   714 		iSignals, aSignals);
       
   715 	return KErrNone;
       
   716 	}
       
   717 
       
   718 TInt CAcmPort::SetSignalsToMark(TUint aSignals)
       
   719 /**
       
   720  * Downcall from C32. Set selected signals to high (logical 1)
       
   721  *
       
   722  * @param aSignals bitmask with the signals to be set
       
   723  * @return Error.
       
   724  */
       
   725 	{
       
   726 	LOG_LINE
       
   727 	LOG_FUNC
       
   728 
       
   729 	if ( !iAcm )
       
   730 		{
       
   731 		LOGTEXT(_L8("\t***access denied"));
       
   732 		return KErrAccessDenied;
       
   733 		}
       
   734 
       
   735 	TUint32 newSignals = iSignals | ConvertAndFilterSignals(aSignals);
       
   736 	TInt err = SetSignals(newSignals);
       
   737 	if ( err )
       
   738 		{
       
   739 		LOGTEXT2(_L8("***SetSignals = %d"), err);
       
   740 		return err;
       
   741 		}
       
   742 
       
   743 	LOGTEXT3(_L8("iSignals=0x%x, aSignals=0x%x"),
       
   744 		iSignals, aSignals);
       
   745 	return KErrNone;
       
   746 	}
       
   747 
       
   748 TInt CAcmPort::SetSignalsToSpace(TUint aSignals)
       
   749 /**
       
   750  * Downcall from C32. Set selected signals to low (logical 0)
       
   751  *
       
   752  * @param aSignals bitmask with the signals to be cleared
       
   753  * @return Error.
       
   754  */
       
   755 	{
       
   756 	LOG_LINE
       
   757 	LOG_FUNC
       
   758 
       
   759 	if ( !iAcm )
       
   760 		{
       
   761 		LOGTEXT(_L8("\t***access denied"));
       
   762 		return KErrAccessDenied;
       
   763 		}
       
   764 
       
   765 	TUint32 newSignals = iSignals & ~ConvertAndFilterSignals(aSignals);
       
   766 	TInt err = SetSignals(newSignals);
       
   767 	if ( err )
       
   768 		{
       
   769 		LOGTEXT2(_L8("***SetSignals = %d"), err);
       
   770 		return err;
       
   771 		}
       
   772 
       
   773 	LOGTEXT3(_L8("iSignals=0x%x, aSignals=0x%x"),
       
   774 		iSignals, aSignals);
       
   775 	return KErrNone;
       
   776 	}
       
   777 
       
   778 TInt CAcmPort::SetSignals(TUint32 aNewSignals)
       
   779 /**
       
   780  * Handle a request by the client to change signal state. This function pushes 
       
   781  * the change to the host, completes any outstanding notifications, and stores
       
   782  * the new signals in iSignals if there are no errors.
       
   783  *
       
   784  * @param aSignals bitmask with the signals to be set
       
   785  * @return Error.
       
   786  */
       
   787 	{
       
   788 	LOG_FUNC
       
   789 
       
   790 	TBool ring =((aNewSignals & KSignalRNG)==KSignalRNG);
       
   791 	TBool dsr  =((aNewSignals & KSignalDSR)==KSignalDSR);
       
   792 	TBool dcd  =((aNewSignals & KSignalDCD)==KSignalDCD);
       
   793  
       
   794  
       
   795  	if ( !iAcm )
       
   796 		{
       
   797 		LOGTEXT(_L8("\t***access denied"));
       
   798 		return KErrAccessDenied;
       
   799 		}
       
   800 
       
   801 	TInt err = iAcm->SendSerialState(ring,dsr,dcd);
       
   802 	if ( err )
       
   803 		{
       
   804 		LOGTEXT2(_L8("\t***SendSerialState = %d- returning"), err);
       
   805 		return err;
       
   806 		}
       
   807 
       
   808 	// Report the new signals if they have changed and notification mask shows
       
   809 	// the upper layer wanted to be sensitive to these signals
       
   810 	if ( iNotifySignalChange )
       
   811 		{
       
   812 		TUint32 changedSignals = ( iSignals ^ aNewSignals ) & iNotifySignalMask;
       
   813 		if ( changedSignals != 0 )
       
   814 			{
       
   815 			// Mark which signals have changed
       
   816 			// Could do something like:
       
   817 			//     changedSignalsMask = ( changedSignals & (KSignalRNG|KSignalDCD|KSignalDSR) ) * KSignalChanged
       
   818 			// but this relies on the how the signal constants are formed in d32comm.h
       
   819 			TUint32 changedSignalsMask = 0;
       
   820 			if ( ( changedSignals & KSignalRNG ) != 0 )
       
   821 				{
       
   822 				changedSignalsMask |= KRNGChanged;
       
   823 				}
       
   824 			if ( ( changedSignals & KSignalDCD ) != 0 )
       
   825 				{
       
   826 				changedSignalsMask |= KDCDChanged;
       
   827 				}
       
   828 			if ( ( changedSignals & KSignalDSR ) != 0 )
       
   829 				{
       
   830 				changedSignalsMask |= KDSRChanged;
       
   831 				}
       
   832 
       
   833 			// Report correctly mapped signals that client asked for
       
   834 			LOGTEXT(_L8("\tcalling SignalChangeCompleted with KErrNone"));
       
   835 			TUint32 signals = ConvertSignals ( changedSignalsMask | ( aNewSignals & iNotifySignalMask ) );
       
   836 			SignalChangeCompleted ( signals, KErrNone );
       
   837 			iNotifySignalChange = EFalse;
       
   838 			}
       
   839 		}
       
   840 
       
   841 	// Store new signals in iSignals
       
   842 	iSignals = aNewSignals;
       
   843 
       
   844 	return KErrNone;
       
   845 	}
       
   846 
       
   847 TUint32 CAcmPort::ConvertAndFilterSignals(TUint32 aSignals) const
       
   848 /**
       
   849  * This function maps from signals used for the port's current role
       
   850  * to the DCE signals used internally, filtering out signals that are
       
   851  * inputs for the current role.
       
   852  *
       
   853  * This would be used, for example, to parse the signals specified by the 
       
   854  * client for a "SetSignals" request before storage in the iSignals member 
       
   855  * variable (always DCE).
       
   856  *
       
   857  * @param aSignals Input signals.
       
   858  * @return The signals, with the lines switched round according to the port's 
       
   859  * role.
       
   860  */
       
   861 	{
       
   862 	LOG_FUNC
       
   863 
       
   864 	TUint32 signals = 0;
       
   865 
       
   866 	// note that this never allows the client to use this method
       
   867 	// to diddle the BREAK state
       
   868 
       
   869 	// handle role-specific mapping
       
   870 	if ( iRole == ECommRoleDTE )
       
   871 		{
       
   872 		// Ignore DSR, DCD, RI and CTS as these are DTE inputs.
       
   873 
       
   874 		// Map DTR to DSR
       
   875 		if((aSignals&KSignalDTR)==KSignalDTR)
       
   876 			{
       
   877 			signals|=KSignalDSR;
       
   878 			}
       
   879 
       
   880 		// Map RTS to CTS
       
   881 		if((aSignals&KSignalRTS)==KSignalRTS)
       
   882 			{
       
   883 			signals|=KSignalCTS;
       
   884 			}
       
   885 		}
       
   886 	else	// iRole==EDce
       
   887 		{
       
   888 		// Ignore RTS and DTR as these are DCE inputs and therefore cannot be set.
       
   889 		// Keep mapping of DSR, CTS, DCD and RI.
       
   890 		signals |= aSignals & 
       
   891 			(	KSignalDSR
       
   892 			|	KSignalCTS
       
   893 			|	KSignalDCD
       
   894 			|	KSignalRNG);
       
   895 		}
       
   896 
       
   897 	return signals;
       
   898 	}
       
   899 
       
   900 TUint32 CAcmPort::ConvertSignals(TUint32 aSignals) const
       
   901 /**
       
   902  * This function converts the given signals between the internal mapping
       
   903  * and the client mapping, taking into account the port's currnt role.
       
   904  * As the mapping is one to one, the input can be either the client or
       
   905  * internal signals.
       
   906  *
       
   907  * This would be used, for example, to parse the signals being sent to the 
       
   908  * client in a "GetSignals" request, or to parse the signals sent from the
       
   909  * client when setting up a notification.
       
   910  *
       
   911  * It should not be used for "SetSignals", as it does not take into account
       
   912  * what signals are inputs or outputs for the current role.
       
   913  *
       
   914  * @param aSignals Input signals (internal or client).
       
   915  * @return Output signals.
       
   916  * port is.
       
   917  */
       
   918 	{
       
   919 	LOG_FUNC
       
   920 
       
   921 	// Swap signals around if the client is expecting DTE signalling
       
   922 	if ( iRole == ECommRoleDTE )
       
   923 		{
       
   924 		TUint32 swappedSignals = 0;
       
   925 
       
   926 		// Map DSR to DTR
       
   927 		if ( ( aSignals & KSignalDSR ) == KSignalDSR )
       
   928 			{
       
   929 			swappedSignals |= KSignalDTR;
       
   930 			}
       
   931 		if ( ( aSignals & KSignalDTR ) == KSignalDTR )
       
   932 			{
       
   933 			swappedSignals |= KSignalDSR;
       
   934 			}
       
   935 		if ( ( aSignals & KDSRChanged ) != 0 )
       
   936 			{
       
   937 			swappedSignals |= KDTRChanged;
       
   938 			}
       
   939 		if ( ( aSignals & KDTRChanged ) != 0 )
       
   940 			{
       
   941 			swappedSignals |= KDSRChanged;
       
   942 			}
       
   943 
       
   944 		// Map CTS to RTS
       
   945 		if ( ( aSignals&KSignalCTS ) == KSignalCTS )
       
   946 			{
       
   947 			swappedSignals|=KSignalRTS;
       
   948 			}
       
   949 		if ( ( aSignals&KSignalRTS ) == KSignalRTS )
       
   950 			{
       
   951 			swappedSignals|=KSignalCTS;
       
   952 			}
       
   953 		if ( ( aSignals & KCTSChanged ) != 0 )
       
   954 			{
       
   955 			swappedSignals |= KRTSChanged;
       
   956 			}
       
   957 		if ( ( aSignals & KRTSChanged ) != 0 )
       
   958 			{
       
   959 			swappedSignals |= KCTSChanged;
       
   960 			}
       
   961 
       
   962 		// Put remapped signals back in
       
   963 		const TUint32 KSwapSignals = KSignalDSR | KSignalDTR | KSignalCTS | KSignalRTS
       
   964 									| KDSRChanged | KDTRChanged | KCTSChanged | KRTSChanged;
       
   965 		aSignals = ( aSignals & ~KSwapSignals ) | swappedSignals;
       
   966 		}
       
   967 
       
   968 	return aSignals;
       
   969 	}
       
   970 
       
   971 TInt CAcmPort::GetReceiveBufferLength(TInt& aLength) const
       
   972 /**
       
   973  * Downcall from C32. Get size of Rx buffer. Note that the Rx and Tx 
       
   974  * buffers are assumed by the RComm API to always have the same size. 
       
   975  * We don't check here, but the value returned should be the size of the Tx 
       
   976  * buffer also.
       
   977  *
       
   978  * @param aLength reference to where the length will be written to
       
   979  * @return Error.
       
   980  */
       
   981 	{
       
   982 	LOG_LINE
       
   983 	LOG_FUNC
       
   984 
       
   985 	if ( !iAcm )
       
   986 		{
       
   987 		LOGTEXT(_L8("\t***access denied"));
       
   988 		return KErrAccessDenied;
       
   989 		}
       
   990 
       
   991 	__ASSERT_DEBUG(iReader, _USB_PANIC(KAcmPanicCat, EPanicInternalError));
       
   992 	aLength = static_cast<TInt>(iReader->BufSize());
       
   993 	LOGTEXT2(_L8("\tlength=%d"), aLength);
       
   994 	return KErrNone;
       
   995 	}
       
   996 
       
   997 TInt CAcmPort::DoSetBufferLengths(TUint aLength)
       
   998 /**
       
   999  * Utility to set the sizes of the Rx and Tx buffers. On failure, the buffers 
       
  1000  * will be left at the size they were.
       
  1001  *
       
  1002  * @param aLength The size required.
       
  1003  * @return Error.
       
  1004  */
       
  1005 	{
       
  1006 	LOG_FUNC
       
  1007 	LOGTEXT2(_L8("\taLength=%d"), aLength);
       
  1008 
       
  1009 	__ASSERT_DEBUG(iReader, _USB_PANIC(KAcmPanicCat, EPanicInternalError));
       
  1010 	// Sart trying to resize buffers. Start with the reader. 
       
  1011 	// Before we start though, set some stuff up we may need later (see 
       
  1012 	// comments below).
       
  1013 	const TUint oldSize = iReader->BufSize();
       
  1014 	HBufC* dummyBuffer = HBufC::New(static_cast<TInt>(oldSize));
       
  1015 	if ( !dummyBuffer )
       
  1016 		{
       
  1017 		// If we can't allocate the dummy buffer, we can't guarantee that we 
       
  1018 		// can roll back this API safely if it fails halfway through. So abort 
       
  1019 		// the entire operation.
       
  1020 		LOGTEXT(_L8("\t***failed to allocate dummy buffer- "
       
  1021 			"returning KErrNoMemory"));
       
  1022 		return KErrNoMemory;
       
  1023 		}
       
  1024 
       
  1025 	TInt ret = iReader->SetBufSize(aLength);
       
  1026 	if ( ret )
       
  1027 		{
       
  1028 		// A failure in SetBufSize will have maintained the old buffer 
       
  1029 		// (i.e. at its old size). This is a safe failure case- simply 
       
  1030 		// clean up and return the error to the client.
       
  1031 		delete dummyBuffer;
       
  1032 		LOGTEXT2(_L8("\t***SetBufSize on reader failed with %d"), ret);
       
  1033 		return ret;
       
  1034 		}
       
  1035 
       
  1036 	// OK, the Rx buffer has been resized, now for the Tx buffer...
       
  1037 	__ASSERT_DEBUG(iWriter, _USB_PANIC(KAcmPanicCat, EPanicInternalError));
       
  1038 	ret = iWriter->SetBufSize(aLength);
       
  1039 	if ( ret )
       
  1040 		{
       
  1041 		// Failure! The Tx buffer is still safe, at its old size. However, 
       
  1042 		// to maintain the integrity of the API we need to reset the Rx 
       
  1043 		// buffer back to the old size. To make sure that this will work, free 
       
  1044 		// the dummy buffer we initially allocated.
       
  1045 		delete dummyBuffer;
       
  1046 		LOGTEXT2(_L8("\t***SetBufSize on writer failed with %d"), ret);
       
  1047 		TInt err = iReader->SetBufSize(oldSize);
       
  1048 		__ASSERT_DEBUG(!err, _USB_PANIC(KAcmPanicCat, EPanicInternalError));
       
  1049 		static_cast<void>(err);
       
  1050 		// Now both buffers are at the size they started at, and the 
       
  1051 		// request failed with error code 'ret'.
       
  1052 		return ret;
       
  1053 		}
       
  1054 
       
  1055 	// We seem to have successfully resized both buffers... clean up and 
       
  1056 	// return.
       
  1057 	delete dummyBuffer;
       
  1058 	
       
  1059 	LOGTEXT(_L8("\treturning KErrNone"));
       
  1060 	return KErrNone;
       
  1061 	}
       
  1062 
       
  1063 TInt CAcmPort::SetReceiveBufferLength(TInt aLength)
       
  1064 /**
       
  1065  * Downcall from C32. Set the size of Rx buffer. Note that the Rx and Tx 
       
  1066  * buffers are assumed by the RComm API to always have the same size. 
       
  1067  * Therefore set the size of the Tx buffer also.
       
  1068  *
       
  1069  * @param aLength new length of Tx and Rx buffer
       
  1070  * @return Error.
       
  1071  */
       
  1072 	{
       
  1073 	LOG_LINE
       
  1074 	LOG_FUNC
       
  1075 	LOGTEXT2(_L8("\taLength=%d"), aLength);
       
  1076 
       
  1077 	if ( !iAcm )
       
  1078 		{
       
  1079 		LOGTEXT(_L8("\t***access denied"));
       
  1080 		return KErrAccessDenied;
       
  1081 		}
       
  1082 
       
  1083 	TInt ret = DoSetBufferLengths(static_cast<TUint>(aLength));
       
  1084 	LOGTEXT2(_L8("\tDoSetBufferLengths=%d"), ret);
       
  1085 	LOGTEXT2(_L8("\treturning %d"), ret);
       
  1086 	return ret;
       
  1087 	}
       
  1088 
       
  1089 void CAcmPort::Destruct()
       
  1090 /**
       
  1091  * Downcall from C32. Destruct - we must (eventually) call delete this
       
  1092  */
       
  1093 	{
       
  1094 	LOG_FUNC
       
  1095 
       
  1096 	delete this;
       
  1097 	}
       
  1098 
       
  1099 void CAcmPort::FreeMemory()
       
  1100 /**
       
  1101  * Downcall from C32. Attempt to reduce our memory foot print.
       
  1102  * Implemented to do nothing.
       
  1103  */
       
  1104 	{
       
  1105 	LOG_LINE
       
  1106 	LOG_FUNC
       
  1107 	}
       
  1108 
       
  1109 void CAcmPort::NotifyDataAvailable()
       
  1110 /**
       
  1111  * Downcall from C32. Notify client when data is available. 
       
  1112  */
       
  1113 	{
       
  1114 	LOG_LINE
       
  1115 	LOG_FUNC
       
  1116 
       
  1117 	if ( !iAcm )
       
  1118 		{
       
  1119 		LOGTEXT(_L8("\t***access denied"));
       
  1120 		NotifyDataAvailableCompleted(KErrAccessDenied);
       
  1121 		return;
       
  1122 		}
       
  1123 	__ASSERT_DEBUG(iReader, _USB_PANIC(KAcmPanicCat, EPanicInternalError));
       
  1124 
       
  1125 	iReader->NotifyDataAvailable();		
       
  1126 	}
       
  1127 
       
  1128 void CAcmPort::NotifyDataAvailableCancel()
       
  1129 /**
       
  1130  * Downcall from C32. Cancel an outstanding data available notification. Note 
       
  1131  * that C32 actually completes the client's request for us.
       
  1132  */
       
  1133 	{
       
  1134 	LOG_LINE
       
  1135 	LOG_FUNC
       
  1136 
       
  1137 	if ( !iAcm )
       
  1138 		{
       
  1139 		LOGTEXT(_L8("\t***access denied"));
       
  1140 		return;
       
  1141 		}
       
  1142 	__ASSERT_DEBUG(iReader, _USB_PANIC(KAcmPanicCat, EPanicInternalError));
       
  1143 
       
  1144 	iReader->NotifyDataAvailableCancel();
       
  1145 	}
       
  1146 
       
  1147 TInt CAcmPort::GetFlowControlStatus(TFlowControl& /*aFlowControl*/)
       
  1148 /**
       
  1149  * Downcall from C32. Get the flow control status. NB This is not supported.
       
  1150  *
       
  1151  * @param aFlowControl flow control status will be written to this descriptor
       
  1152  * @return Error.
       
  1153  */
       
  1154 	{
       
  1155 	LOG_LINE
       
  1156 	LOG_FUNC
       
  1157 
       
  1158 	if ( !iAcm )
       
  1159 		{
       
  1160 		LOGTEXT(_L8("\t***access denied"));
       
  1161 		return KErrAccessDenied;
       
  1162 		}
       
  1163 
       
  1164 	LOGTEXT(_L8("\t***not supported"));
       
  1165 	return KErrNotSupported;
       
  1166 	}
       
  1167 
       
  1168 void CAcmPort::NotifyOutputEmpty()
       
  1169 /**
       
  1170  * Downcall from C32. Notify the client when the output buffer is empty. Note 
       
  1171  * that this is not supported. Write requests only complete when the data has 
       
  1172  * been sent to the LDD (KConfigWriteBufferedComplete is not supported) so 
       
  1173  * it's not very useful.
       
  1174  */
       
  1175 	{
       
  1176 	LOG_LINE
       
  1177 	LOG_FUNC
       
  1178 
       
  1179 	if ( !iAcm )
       
  1180 		{
       
  1181 		LOGTEXT(_L8("\t***access denied"));
       
  1182 		NotifyOutputEmptyCompleted(KErrAccessDenied);
       
  1183 		return;
       
  1184 		}
       
  1185 
       
  1186 	LOGTEXT(_L8("\t***not supported"));
       
  1187 	NotifyOutputEmptyCompleted(KErrNotSupported);
       
  1188 	}
       
  1189 
       
  1190 void CAcmPort::NotifyOutputEmptyCancel()
       
  1191 /**
       
  1192  * Downcall from C32. Cancel a pending request to be notified when the output 
       
  1193  * buffer is empty. Note that C32 actually completes the client's request for 
       
  1194  * us.
       
  1195  */
       
  1196 	{
       
  1197 	LOG_LINE
       
  1198 	LOG_FUNC
       
  1199 	}
       
  1200 
       
  1201 void CAcmPort::NotifyBreak()
       
  1202 /**
       
  1203  * Downcall from C32. Notify a client of a host-driven break on the serial 
       
  1204  * line.
       
  1205  */
       
  1206 	{
       
  1207 	LOG_LINE
       
  1208 	LOG_FUNC
       
  1209 
       
  1210 	if ( !iAcm )
       
  1211 		{
       
  1212 		LOGTEXT(_L8("\t***access denied"));
       
  1213 		BreakNotifyCompleted(KErrAccessDenied);
       
  1214 		return;
       
  1215 		}
       
  1216 
       
  1217 	// C32 protects us against this.
       
  1218 	__ASSERT_DEBUG(!iNotifyBreak, 
       
  1219 		_USB_PANIC(KAcmPanicCat, EPanicInternalError));
       
  1220 
       
  1221 	iNotifyBreak = ETrue;
       
  1222 	}
       
  1223 
       
  1224 void CAcmPort::NotifyBreakCancel()
       
  1225 /**
       
  1226  * Downcall from C32. Cancel a pending notification of a serial line break. 
       
  1227  * Note that C32 actually completes the client's request for us.
       
  1228  */
       
  1229 	{
       
  1230 	LOG_LINE
       
  1231 	LOG_FUNC
       
  1232 
       
  1233 	if ( !iAcm )
       
  1234 		{
       
  1235 		LOGTEXT(_L8("\t***access denied"));
       
  1236 		return;
       
  1237 		}
       
  1238 
       
  1239 	iNotifyBreak = EFalse;
       
  1240 	}
       
  1241 
       
  1242 void CAcmPort::BreakRequestCompleted()
       
  1243 /**
       
  1244  * Callback for completion of a break request. 
       
  1245  * This is called when the break state next goes inactive after a break has 
       
  1246  * been requested from the ACM port. 
       
  1247  * This is implemented to complete the RComm client's Break request.
       
  1248  */
       
  1249  	{
       
  1250 	LOG_FUNC
       
  1251 
       
  1252 	if ( !iCancellingBreak )
       
  1253 		{
       
  1254 		LOGTEXT(_L8("\tcalling BreakCompleted with KErrNone"));
       
  1255 		BreakCompleted(KErrNone);
       
  1256 		}
       
  1257 	else
       
  1258 		{
       
  1259 		LOGTEXT(_L8("\tbreak is being cancelled- "
       
  1260 			"letting C32 complete the request"));
       
  1261 		}
       
  1262 	// In the event of an RComm::BreakCancel, this function is called 
       
  1263 	// sychronously with CAcmPort::BreakCancel, and C32 will complete the 
       
  1264 	// original RComm::Break request with KErrCancel when that returns. So we 
       
  1265 	// only need to complete it if there isn't a cancel going on.
       
  1266 	iBreak = EFalse;
       
  1267 	iCancellingBreak = EFalse;
       
  1268 	}
       
  1269 
       
  1270 void CAcmPort::BreakStateChange()
       
  1271 /**
       
  1272  * Callback for a change in the break state. 
       
  1273  * This is called both when the break state changes because the RComm client 
       
  1274  * wanted it to, and when the break state changes because the host asked us 
       
  1275  * to.
       
  1276  * This is implemented to update our signal line flags, complete 
       
  1277  * NotifySignalChange requests, and complete NotifyBreak requests.
       
  1278  */
       
  1279  	{
       
  1280 	LOG_FUNC
       
  1281 
       
  1282 	// TODO: what if no iAcm?
       
  1283 
       
  1284 	// Take a copy of the current signal state for comparison later
       
  1285 	TUint32 oldSignals = iSignals;
       
  1286 
       
  1287 	// grab the state of the BREAK from the ACM class that manages
       
  1288 	// it and apply the appropriate flag state to the local iSignals
       
  1289 	if ( iAcm && iAcm->BreakActive() )
       
  1290 		{
       
  1291 		LOGTEXT(_L8("\tbreak is active"));
       
  1292 		iSignals |= KSignalBreak;
       
  1293 		}
       
  1294 	else
       
  1295 		{
       
  1296 		LOGTEXT(_L8("\tbreak is inactive"));
       
  1297 		iSignals &= ~KSignalBreak;
       
  1298 		}
       
  1299 
       
  1300 	// first tell the client (if interested, and if it's not a client-driven 
       
  1301 	// break) that there has been a BREAK event of some sort (either into or 
       
  1302 	// out of the break-active condition...
       
  1303 	if ( iNotifyBreak && !iBreak )
       
  1304 		{
       
  1305 		LOGTEXT(_L8("\tcalling BreakNotifyCompleted with KErrNone"));
       
  1306 		BreakNotifyCompleted(KErrNone);
       
  1307 		iNotifyBreak = EFalse;
       
  1308 		}
       
  1309 
       
  1310 	// and now tell the client (again if interested) the new state
       
  1311 	// of the BREAK signal, if it has changed
       
  1312 	if (	iNotifySignalChange
       
  1313 		&&	( ( iNotifySignalMask & ( iSignals ^ oldSignals ) ) != 0 ) )
       
  1314 		{
       
  1315 		// Report correctly mapped signals that client asked for
       
  1316 		LOGTEXT(_L8("\tcalling SignalChangeCompleted with KErrNone"));
       
  1317 		TUint32 signals = ConvertSignals ( KBreakChanged | ( iSignals & iNotifySignalMask ) );
       
  1318 		SignalChangeCompleted( signals, KErrNone);
       
  1319 		iNotifySignalChange = EFalse;
       
  1320 		}
       
  1321 	}
       
  1322 
       
  1323 void CAcmPort::NotifyFlowControlChange()
       
  1324 /**
       
  1325  * Downcall from C32. Notify a client of a change in the flow control state. 
       
  1326  * Note that this is not supported.
       
  1327  */
       
  1328 	{
       
  1329 	LOG_LINE
       
  1330 	LOG_FUNC
       
  1331 
       
  1332 	if ( !iAcm )
       
  1333 		{
       
  1334 		LOGTEXT(_L8("\t***access denied"));
       
  1335 		FlowControlChangeCompleted(EFlowControlOn, KErrAccessDenied);
       
  1336 		return;
       
  1337 		}
       
  1338 
       
  1339 	LOGTEXT(_L8("\t***not supported"));
       
  1340 	FlowControlChangeCompleted(EFlowControlOn,KErrNotSupported);
       
  1341 	}
       
  1342 
       
  1343 void CAcmPort::NotifyFlowControlChangeCancel()
       
  1344 /**
       
  1345  * Downcall from C32. Cancel a pending request to be notified when the flow 
       
  1346  * control state changes. Note that C32 actually completes the client's 
       
  1347  * request for us.
       
  1348  */
       
  1349 	{
       
  1350 	LOG_LINE
       
  1351 	LOG_FUNC
       
  1352 	}
       
  1353 
       
  1354 void CAcmPort::NotifyConfigChange()
       
  1355 /**
       
  1356  * Downcall from C32. Notify a client of a change to the serial port 
       
  1357  * configuration.
       
  1358  */
       
  1359 	{
       
  1360 	LOG_LINE
       
  1361 	LOG_FUNC
       
  1362 
       
  1363 	if ( !iAcm )
       
  1364 		{
       
  1365 		LOGTEXT(_L8("\t***access denied"));
       
  1366 		ConfigChangeCompleted(iCommNotificationDes, KErrAccessDenied);
       
  1367 		return;
       
  1368 		}
       
  1369 
       
  1370 	if ( iNotifyConfigChange )
       
  1371 		{
       
  1372 		LOGTEXT(_L8("\t***in use"));
       
  1373 		ConfigChangeCompleted(iCommNotificationDes,KErrInUse);
       
  1374 		}
       
  1375 	else
       
  1376 		{
       
  1377 		iNotifyConfigChange = ETrue;
       
  1378 		}
       
  1379 	}
       
  1380 
       
  1381 void CAcmPort::NotifyConfigChangeCancel()
       
  1382 /**
       
  1383  * Downcall from C32. Cancel a pending request to be notified of a change to 
       
  1384  * the serial port configuration. Note that C32 actually completes the 
       
  1385  * client's request for us.
       
  1386  */
       
  1387 	{
       
  1388 	LOG_LINE
       
  1389 	LOG_FUNC
       
  1390 
       
  1391 	if ( !iAcm )
       
  1392 		{
       
  1393 		LOGTEXT(_L8("\t***access denied"));
       
  1394 		return;
       
  1395 		}
       
  1396 
       
  1397 	iNotifyConfigChange = EFalse;
       
  1398 	}
       
  1399 
       
  1400 void CAcmPort::HostConfigChange(const TCommConfigV01& aConfig)
       
  1401 /**
       
  1402  * Callback from a "host-pushed" configuration change packet.
       
  1403  *
       
  1404  * @param aConfig	New configuration data.
       
  1405  */
       
  1406 	{
       
  1407 	LOG_FUNC
       
  1408 
       
  1409 	HandleConfigNotification(aConfig.iRate,
       
  1410 		aConfig.iDataBits,
       
  1411 		aConfig.iParity,
       
  1412 		aConfig.iStopBits,
       
  1413 		iCommConfig.iHandshake);
       
  1414 	iCommConfig.iRate = aConfig.iRate;
       
  1415 	iCommConfig.iDataBits = aConfig.iDataBits;
       
  1416 	iCommConfig.iParity = aConfig.iParity;
       
  1417 	iCommConfig.iStopBits = aConfig.iStopBits;
       
  1418 	}
       
  1419 
       
  1420 void CAcmPort::NotifySignalChange(TUint aSignalMask)
       
  1421 /**
       
  1422  * Downcall from C32. Notify a client of a change to the signal lines.
       
  1423  */
       
  1424 	{
       
  1425 	LOG_LINE
       
  1426 	LOGTEXT2(_L8(">>CAcmPort::NotifySignalChange aSignalMask=0x%08x"), 
       
  1427 		aSignalMask);
       
  1428 
       
  1429 	if ( iNotifySignalChange )
       
  1430 		{
       
  1431 		if ( !iAcm )
       
  1432 			{
       
  1433 			LOGTEXT(_L8("\t***access denied"));
       
  1434 			SignalChangeCompleted(0, KErrAccessDenied);
       
  1435 			}
       
  1436 		else
       
  1437 			{
       
  1438 			LOGTEXT(_L8("\t***in use"));
       
  1439 			SignalChangeCompleted(0, KErrInUse);
       
  1440 			}
       
  1441 		}
       
  1442 	else
       
  1443 		{
       
  1444 		iNotifySignalChange = ETrue;
       
  1445 		// convert signals to internal format
       
  1446 		// no need to filter as can notify on inputs or outputs
       
  1447 		iNotifySignalMask = ConvertSignals(aSignalMask);
       
  1448 		}
       
  1449 
       
  1450 	LOGTEXT(_L8("<<CAcmPort::NotifySignalChange"));
       
  1451 	}
       
  1452 
       
  1453 void CAcmPort::NotifySignalChangeCancel()
       
  1454 /**
       
  1455  * Downcall from C32. Cancel a pending client request to be notified about a 
       
  1456  * change to the signal lines. Note that C32 actually completes the client's 
       
  1457  * request for us.
       
  1458  */
       
  1459 	{
       
  1460 	LOG_LINE
       
  1461 	LOG_FUNC
       
  1462 
       
  1463 	if ( !iAcm )
       
  1464 		{
       
  1465 		LOGTEXT(_L8("\t***access denied"));
       
  1466 		return;
       
  1467 		}
       
  1468 
       
  1469 	iNotifySignalChange = EFalse;
       
  1470 	}
       
  1471 
       
  1472 void CAcmPort::HostSignalChange(TBool aDtr, TBool aRts)
       
  1473 /**
       
  1474  * Callback from a "host-pushed" line state change.
       
  1475  *
       
  1476  * @param aDtr The state of the DTR signal.
       
  1477  * @param aRts The state of the RTS signal.
       
  1478  */
       
  1479 	{
       
  1480 	LOGTEXT3(_L8(">>CAcmPort::HostSignalChange aDtr=%d, aRts=%d"), aDtr, aRts);
       
  1481 
       
  1482 	// Take a copy of the current signal state for comparison later
       
  1483 	TUint32 oldSignals = iSignals;
       
  1484 
       
  1485 	if ( aDtr )
       
  1486 		{
       
  1487 		iSignals |= KSignalDTR;
       
  1488 		}
       
  1489 	else
       
  1490 		{
       
  1491 		iSignals &= (~KSignalDTR);
       
  1492 		}
       
  1493 
       
  1494 	if ( aRts )
       
  1495 		{
       
  1496 		iSignals |= KSignalRTS;
       
  1497 		}
       
  1498 	else
       
  1499 		{
       
  1500 		iSignals &= (~KSignalRTS);
       
  1501 		}
       
  1502 
       
  1503 	// Report the new state of the signals if they have changed
       
  1504 	// and the mask shows the upper layer wanted to be sensitive to these signals.
       
  1505 	if ( iNotifySignalChange )
       
  1506 		{
       
  1507 		// Create bitfield of changed signals that client is interested in
       
  1508 		TUint32 changedSignals = ( iSignals ^ oldSignals ) & iNotifySignalMask;
       
  1509 		LOGTEXT5(_L8("\tiSignals=%x, oldSignals=%x, changedSignals=%x, iNotifySignalMask=%x")
       
  1510 						,iSignals, oldSignals, changedSignals, iNotifySignalMask);
       
  1511 		if ( changedSignals != 0 )
       
  1512 			{
       
  1513 			// Mark which signals have changed
       
  1514 			TUint32 changedSignalsMask = 0;
       
  1515 			if ( ( changedSignals & KSignalDTR ) != 0 )
       
  1516 				{
       
  1517 				changedSignalsMask |= KDTRChanged;
       
  1518 				}
       
  1519 			if ( ( changedSignals & KSignalRTS ) != 0 )
       
  1520 				{
       
  1521 				changedSignalsMask |= KRTSChanged;
       
  1522 				}
       
  1523 			LOGTEXT2(_L8("\tchangedSignalsMask=%x"), changedSignalsMask);
       
  1524 
       
  1525 			// Report correctly mapped signals that client asked for
       
  1526 			TUint32 signals = ConvertSignals ( changedSignalsMask | ( iSignals & iNotifySignalMask ) );
       
  1527 			LOGTEXT2(_L8("\tcalling SignalChangeCompleted with KErrNone, signals=%x"), signals);
       
  1528 			SignalChangeCompleted( signals, KErrNone);
       
  1529 			iNotifySignalChange = EFalse;
       
  1530 			}
       
  1531 		}
       
  1532 
       
  1533 	LOGTEXT(_L8("<<CAcmPort::HostSignalChange"));
       
  1534 	}
       
  1535 
       
  1536 TInt CAcmPort::GetRole(TCommRole& aRole)
       
  1537 /**
       
  1538  * Downcall from C32. Get the role of this port unit
       
  1539  *
       
  1540  * @param aRole reference to where the role will be written to
       
  1541  * @return Error.
       
  1542  */
       
  1543 	{
       
  1544 	LOG_LINE
       
  1545 	LOG_FUNC
       
  1546 
       
  1547 	if ( !iAcm )
       
  1548 		{
       
  1549 		LOGTEXT(_L8("\t***access denied"));
       
  1550 		return KErrAccessDenied;
       
  1551 		}
       
  1552 
       
  1553 	aRole = iRole;
       
  1554 	LOGTEXT2(_L8("\trole=%d"), aRole);
       
  1555 	return KErrNone;
       
  1556 	}
       
  1557 
       
  1558 TInt CAcmPort::SetRole(TCommRole aRole)
       
  1559 /**
       
  1560  * Downcall from C32. Set the role of this port unit
       
  1561  *
       
  1562  * @param aRole the new role
       
  1563  * @return Error.
       
  1564  */
       
  1565 	{
       
  1566 	LOG_LINE
       
  1567 	LOGTEXT2(_L8(">>CAcmPort::SetRole aRole=%d"), aRole);
       
  1568 
       
  1569 	TInt ret = KErrNone;
       
  1570 	if ( !iAcm )
       
  1571 		{
       
  1572 		ret = KErrAccessDenied;
       
  1573 		}
       
  1574 	else
       
  1575 		{
       
  1576 		iRole = aRole;
       
  1577 		}
       
  1578 
       
  1579 	LOGTEXT2(_L8("<<CAcmPort::SetRole ret=%d"), ret);
       
  1580 	return ret;
       
  1581 	}
       
  1582 
       
  1583 void CAcmPort::SetAcm(CCdcAcmClass* aAcm)
       
  1584 /**
       
  1585  * Called by the factory when the ACM interface for this port is about to be 
       
  1586  * either created or destroyed. 
       
  1587  * If it's going to be destroyed, we must cancel any currently outstanding 
       
  1588  * requests on the reader and writer objects, complete any outstanding 
       
  1589  * requests with KErrAccessDenied, and refuse any new requests with the same 
       
  1590  * error until the registration port is back open again. 
       
  1591  * If it's going to be opened, we simply remember it and use it to pass future 
       
  1592  * client requests onto the bus.
       
  1593  *
       
  1594  * @param aAcm The new ACM (may be NULL).
       
  1595  */
       
  1596 	{
       
  1597 	LOGTEXT3(_L8(">>CAcmPort::SetAcm aAcm = 0x%08x, iAcm = 0x%08x"), aAcm, iAcm);
       
  1598 	
       
  1599 	if ( !aAcm )
       
  1600 		{
       
  1601 		// Cancel any outstanding operations on the reader and writer.
       
  1602 		__ASSERT_DEBUG(iReader, _USB_PANIC(KAcmPanicCat, EPanicInternalError));
       
  1603 		iReader->ReadCancel();
       
  1604 		__ASSERT_DEBUG(iWriter, _USB_PANIC(KAcmPanicCat, EPanicInternalError));
       
  1605 		iWriter->WriteCancel();
       
  1606 
       
  1607 		// Complete any outstanding requests
       
  1608 		LOGTEXT(_L8("\tcompleting outstanding requests with KErrAccessDenied"));
       
  1609 		SignalChangeCompleted(iSignals,KErrAccessDenied);
       
  1610 		ReadCompleted(KErrAccessDenied);
       
  1611 		WriteCompleted(KErrAccessDenied);
       
  1612 		ConfigChangeCompleted(iCommNotificationDes,KErrAccessDenied);
       
  1613 		NotifyDataAvailableCompleted(KErrAccessDenied);
       
  1614 		NotifyOutputEmptyCompleted(KErrAccessDenied);
       
  1615 		BreakNotifyCompleted(KErrAccessDenied);
       
  1616 		FlowControlChangeCompleted(EFlowControlOn, KErrAccessDenied);
       
  1617 		}
       
  1618 	else
       
  1619 		{
       
  1620 		__ASSERT_DEBUG(!iAcm, _USB_PANIC(KAcmPanicCat, EPanicInternalError));
       
  1621 		aAcm->SetCallback(this);
       
  1622 		// Set the port as the observer of break events.
       
  1623 		aAcm->SetBreakCallback(this);
       
  1624 		}
       
  1625 
       
  1626 	iAcm = aAcm;
       
  1627 	
       
  1628 	LOGTEXT(_L8("<<CAcmPort::SetAcm"));
       
  1629 	}
       
  1630 
       
  1631 CAcmPort::~CAcmPort()
       
  1632 /**
       
  1633  * Destructor.
       
  1634  */
       
  1635 	{
       
  1636 	LOG_FUNC
       
  1637 
       
  1638 	delete iReader;
       
  1639 	delete iWriter;
       
  1640 	
       
  1641 	// Remove this as a sink for the ACM class to call back about host-pushed 
       
  1642 	// changes.
       
  1643 	if ( iAcm )
       
  1644 		{
       
  1645 		LOGTEXT(_L8("\tiAcm exists- calling SetCallback(NULL)"));
       
  1646 		iAcm->SetCallback(NULL);
       
  1647 		}
       
  1648 
       
  1649 	LOGTEXT(_L8("\tcalling AcmPortClosed on observer"));
       
  1650 	iObserver.AcmPortClosed(iUnit);
       
  1651 	}
       
  1652 
       
  1653 //
       
  1654 // End of file