usbmgmt/usbmgr/device/classdrivers/acm/classimplementation/ecacm/src/CdcDataInterface.cpp
changeset 0 c9bc50fca66e
child 6 96e575696901
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 <e32std.h>
       
    19 #include "CdcDataInterface.h"
       
    20 #include "ActiveReader.h"
       
    21 #include "ActiveWriter.h"
       
    22 #include "AcmPanic.h"
       
    23 #include "AcmUtils.h"
       
    24 #include "ActiveReadOneOrMoreReader.h"
       
    25 #include "ActiveDataAvailableNotifier.h"
       
    26 #include "inifile.h"
       
    27 #include <usb/usblogger.h>
       
    28 
       
    29 #ifdef __FLOG_ACTIVE
       
    30 _LIT8(KLogComponent, "ECACM");
       
    31 #endif
       
    32 
       
    33 #ifdef __HEADLESS_ACM_TEST_CODE__
       
    34 #pragma message ("Building headless ACM (performance test code for RDevUsbcClient)")
       
    35 #endif // __HEADLESS_ACM_TEST_CODE__
       
    36 
       
    37 CCdcDataInterface::CCdcDataInterface(const TDesC16& aIfcName)
       
    38 /**
       
    39  * Overloaded Constructor using interface name.
       
    40  * @param aIfcName contains the interface name
       
    41  */
       
    42  :	CCdcInterfaceBase(aIfcName),
       
    43  	iPacketSize(KDefaultMaxPacketTypeBulk)
       
    44 	{
       
    45 	}
       
    46 
       
    47 CCdcDataInterface* CCdcDataInterface::NewL(const TDesC16& aIfcName)
       
    48 /**
       
    49  * Create a new CCdcDataInterface object and construct it using interface name
       
    50  * This call will return an object with a valid USB configuration
       
    51  *
       
    52  * @param aParent Observer.
       
    53  * @param aIfcName Contains the interface name
       
    54  * @return A pointer to the new object
       
    55  */
       
    56 	{
       
    57 	LOG_STATIC_FUNC_ENTRY
       
    58 
       
    59 	LOGTEXT2(_L("\tData Ifc Name = %S"), &aIfcName);
       
    60 
       
    61 	CCdcDataInterface* self = new (ELeave) CCdcDataInterface(aIfcName);
       
    62 	CleanupStack::PushL(self);
       
    63 	self->ConstructL();
       
    64 	CLEANUPSTACK_POP(self);
       
    65 	return self;
       
    66 	}
       
    67 
       
    68 void CCdcDataInterface::ConstructL()
       
    69 /**
       
    70  * Construct the object
       
    71  * This call registers the object with the USB device driver
       
    72  *
       
    73  * @param aParent Observer.
       
    74  */
       
    75 	{
       
    76 	BaseConstructL();
       
    77 
       
    78 	iReadOneOrMoreReader  = CActiveReadOneOrMoreReader::NewL(*this, iLdd, EEndpoint2);
       
    79 	iReader = CActiveReader::NewL(*this, iLdd, EEndpoint2);
       
    80 	iDataAvailableNotifier = CActiveDataAvailableNotifier::NewL(*this, iLdd, EEndpoint2);
       
    81 	iWriter = CActiveWriter::NewL(*this, iLdd, EEndpoint1);
       
    82 	iLinkState = CLinkStateNotifier::NewL(*this, iLdd);
       
    83 	
       
    84 	iLinkState->Start();
       
    85 
       
    86 	LOGTEXT(_L8("\tchecking ecacm.ini"));
       
    87 	iHostCanHandleZLPs = EFalse;
       
    88 	GetHostZLPHandlingFromFile();
       
    89 	LOGTEXT(_L8("\tfinished checking ecacm.ini"));
       
    90 	}
       
    91 
       
    92 TInt CCdcDataInterface::SetUpInterface()
       
    93 /**
       
    94  * Retrieves the device capabilities and searches for suitable input and 
       
    95  * output bulk endpoints. If suitable endpoints are found, an interface 
       
    96  * descriptor for the endpoints is registered with the LDD.
       
    97  */
       
    98 	{
       
    99 	LOGTEXT(_L8(">>CCdcDataInterface::SetUpInterface"));
       
   100 
       
   101 	TUsbDeviceCaps dCaps;
       
   102 	TInt ret = iLdd.DeviceCaps(dCaps);
       
   103 	LOGTEXT(_L8("\tchecking result of DeviceCaps"));
       
   104 	if ( ret )
       
   105 		{
       
   106 		LOGTEXT2(_L8("<<CCdcDataInterface::SetUpInterface ret=%d"), ret);
       
   107 		return ret;
       
   108 		}
       
   109 
       
   110 	TInt maxBulkPacketSize = (dCaps().iHighSpeed) ? KMaxPacketTypeBulkHS : KMaxPacketTypeBulkFS;
       
   111 	const TUint KRequiredNumberOfEndpoints = 2;
       
   112 
       
   113 	const TUint totalEndpoints = static_cast<TUint>(dCaps().iTotalEndpoints);
       
   114 	LOGTEXT2(_L8("\tiTotalEndpoints = %d"), totalEndpoints);
       
   115 	if ( totalEndpoints < KRequiredNumberOfEndpoints )
       
   116 		{
       
   117 		LOGTEXT2(_L8("<<CCdcDataInterface::SetUpInterface ret=%d"), 
       
   118 			KErrGeneral);
       
   119 		return KErrGeneral;
       
   120 		}
       
   121 	
       
   122 	// Endpoints
       
   123 	TUsbcEndpointData data[KUsbcMaxEndpoints];
       
   124 	TPtr8 dataptr(reinterpret_cast<TUint8*>(data), sizeof(data), sizeof(data));
       
   125 	ret = iLdd.EndpointCaps(dataptr);
       
   126 	LOGTEXT(_L8("\tchecking result of EndpointCaps"));
       
   127 	if ( ret )
       
   128 		{
       
   129 		LOGTEXT2(_L8("<<CCdcDataInterface::SetUpInterface ret=%d"), ret);
       
   130 		return ret;
       
   131 		}
       
   132 
       
   133 	// 
       
   134 	TUsbcInterfaceInfoBuf ifc;
       
   135 	TBool foundIn = EFalse;
       
   136 	TBool foundOut = EFalse;
       
   137 
       
   138 	for ( TUint i = 0; !(foundIn && foundOut) && i < totalEndpoints; i++ )
       
   139 		{
       
   140 		const TUsbcEndpointCaps* caps = &data[i].iCaps;
       
   141 		__ASSERT_DEBUG(caps, 
       
   142 			_USB_PANIC(KAcmPanicCat, EPanicInternalError));
       
   143 		if (data[i].iInUse)
       
   144 			continue;
       
   145 
       
   146 		//get the max packet size it can potentially support
       
   147 		//it's possible that it can support Isoch (1023) which is greater
       
   148 		//than max for Bulk at 64
       
   149 		const TInt maxSize = Min (	maxBulkPacketSize, 
       
   150 									caps->MaxPacketSize() );
       
   151 
       
   152 		const TUint KBulkInFlags = KUsbEpTypeBulk | KUsbEpDirIn;
       
   153 		const TUint KBulkOutFlags = KUsbEpTypeBulk | KUsbEpDirOut;
       
   154 
       
   155 		// use EEndPoint1 for TX (IN) EEndpoint1
       
   156 		if (! foundIn && (caps->iTypesAndDir & KBulkInFlags) == KBulkInFlags)
       
   157 			{
       
   158 
       
   159 			ifc().iEndpointData[0].iType  = KUsbEpTypeBulk;
       
   160 			ifc().iEndpointData[0].iDir   = KUsbEpDirIn; 
       
   161 
       
   162 			//get the max packet size it can potentially support
       
   163 			//it's possible that it can support Isoch (1023) which is greater
       
   164 			//than max for Bulk at 64
       
   165 			ifc().iEndpointData[0].iSize  = maxSize;
       
   166 			foundIn = ETrue;
       
   167 			}
       
   168 		// use EEndPoint2 for RX (OUT) endpoint
       
   169 		else if (	!foundOut 
       
   170 			&&		(caps->iTypesAndDir & KBulkOutFlags) == KBulkOutFlags
       
   171 			)
       
   172 			{
       
   173 			// EEndpoint2 is going to be our RX (OUT, read) endpoint
       
   174 			ifc().iEndpointData[1].iType  = KUsbEpTypeBulk;
       
   175 			ifc().iEndpointData[1].iDir   = KUsbEpDirOut;
       
   176 
       
   177 			//get the max packet size it can potentially support
       
   178 			//it's possible that it can support Isoch (1023) which is greater
       
   179 			//than max for Bulk at 64
       
   180 			ifc().iEndpointData[1].iSize  = maxSize;
       
   181 			foundOut = ETrue;
       
   182 			}
       
   183 		}
       
   184 
       
   185 	if (! (foundIn && foundOut))
       
   186 		{
       
   187 		LOGTEXT2(_L8("<<CCdcDataInterface::SetUpInterface ret=%d"), 
       
   188 			KErrGeneral);
       
   189 		return KErrGeneral;
       
   190 		}
       
   191 
       
   192 		// If the device supports USB High-speed, then we request 64KB buffers
       
   193 		// (otherwise the default 4KB ones will do).
       
   194 
       
   195 	TUint bandwidthPriority = (EUsbcBandwidthOUTDefault | EUsbcBandwidthINDefault);
       
   196 	if (dCaps().iHighSpeed)
       
   197 		{
       
   198 		bandwidthPriority = (EUsbcBandwidthOUTPlus2 | EUsbcBandwidthINPlus2);
       
   199 		}
       
   200 
       
   201 	ifc().iString = &iIfcName;
       
   202 	ifc().iTotalEndpointsUsed = KRequiredNumberOfEndpoints;
       
   203 	ifc().iClass.iClassNum	  = 0x0A; // Table 18- Data Interface Class
       
   204 	ifc().iClass.iSubClassNum = 0x00; // Section 4.6- unused.
       
   205 	ifc().iClass.iProtocolNum = 0x00; // Table 19- no class specific protocol required
       
   206 
       
   207 	// Indicate that this interface does not expect any control transfers 
       
   208 	// from EP0.
       
   209 	ifc().iFeatureWord |= KUsbcInterfaceInfo_NoEp0RequestsPlease;
       
   210 
       
   211 	LOGTEXT(_L8("\tcalling SetInterface"));
       
   212 	// Zero effectively indicates that alternate interfaces are not used.
       
   213 	ret = iLdd.SetInterface(0, ifc, bandwidthPriority);
       
   214 
       
   215 	LOGTEXT2(_L8("<<CCdcDataInterface::SetUpInterface ret=%d"), ret);
       
   216 	return ret;
       
   217 	}
       
   218 
       
   219 
       
   220 void CCdcDataInterface::MLSOStateChange(TInt aPacketSize)
       
   221 	{
       
   222 	iPacketSize = aPacketSize;
       
   223 	}
       
   224 
       
   225 
       
   226 CCdcDataInterface::~CCdcDataInterface()
       
   227 /**
       
   228  * Destructor. Cancel and destroy the child classes.
       
   229  */
       
   230 	{
       
   231 	LOG_FUNC
       
   232 
       
   233 	delete iLinkState;
       
   234 	delete iReadOneOrMoreReader;
       
   235 	delete iReader;
       
   236 	delete iWriter;
       
   237 	delete iDataAvailableNotifier;
       
   238 	}
       
   239 
       
   240 void CCdcDataInterface::Write(MWriteObserver& aObserver, 
       
   241 						  const TDesC8& aDes, 
       
   242 						  TInt aLen)
       
   243 /**
       
   244  * Write data down the interface
       
   245  * 
       
   246  * @param aObserver The observer to notify of completion.
       
   247  * @param aDes Descriptor containing the data to be sent
       
   248  * @param aLen Length of the data to be sent
       
   249  */
       
   250 	{
       
   251 	LOG_FUNC
       
   252 
       
   253 	__ASSERT_DEBUG(!iWriteObserver, 
       
   254 		_USB_PANIC(KAcmPanicCat, EPanicInternalError));
       
   255 
       
   256 	iWriteObserver = &aObserver;
       
   257 
       
   258 	__ASSERT_DEBUG(iWriter, _USB_PANIC(KAcmPanicCat, EPanicInternalError));
       
   259 	
       
   260 	if ( iHostCanHandleZLPs )
       
   261 		{
       
   262 		
       
   263 		// Make sure the driver sends a Zero Length Packet if required (i.e. if the 
       
   264 		// data size is an exact multiple of the endpoint's packet size). 
       
   265 		TBool requestZlp = ( aLen % iPacketSize ) ? EFalse : ETrue;
       
   266 		iWriter->Write(aDes, aLen, requestZlp); 
       
   267 		}
       
   268 	else
       
   269 		{
       
   270 		iWriter->Write(aDes, aLen, EFalse); 
       
   271 		}
       
   272 		
       
   273 	LOGTEXT(_L8("<<CCdcDataInterface::Write"));
       
   274 	}
       
   275 
       
   276 void CCdcDataInterface::WriteCompleted(TInt aError)
       
   277 /**
       
   278  * Called when a write request completes.
       
   279  *
       
   280  * @param aError Error.
       
   281  */
       
   282 	{
       
   283 	LOGTEXT2(_L8(">>CCdcDataInterface::WriteCompleted aError=%d"), aError);
       
   284 
       
   285 #ifdef __HEADLESS_ACM_TEST_CODE__
       
   286 	// Issue another Read or ReadOneOrMore as appropriate.
       
   287 	// If the Write completed with an error, we panic, as it's invalidating 
       
   288 	// the test.
       
   289 	__ASSERT_DEBUG(aError == KErrNone, 
       
   290 		_USB_PANIC(KAcmPanicCat, EPanicInternalError));
       
   291 	switch ( iHeadlessReadType )
       
   292 		{
       
   293 	case ERead:
       
   294 		LOGTEXT2(_L8("__HEADLESS_ACM_TEST_CODE__- issuing Read for %d bytes"), 
       
   295 			iHeadlessReadLength);
       
   296 		__ASSERT_DEBUG(iReader, _USB_PANIC(KAcmPanicCat, EPanicInternalError));
       
   297 		iReader->Read(iHeadlessAcmBuffer, iHeadlessReadLength);
       
   298 		break;
       
   299 	case EReadOneOrMore:
       
   300 		LOGTEXT2(_L8("__HEADLESS_ACM_TEST_CODE__- issuing ReadOneOrMore for %d bytes"), 
       
   301 			iHeadlessReadLength);
       
   302 		__ASSERT_DEBUG(iReadOneOrMoreReader, _USB_PANIC(KAcmPanicCat, EPanicInternalError));
       
   303 		iReadOneOrMoreReader->ReadOneOrMore(iHeadlessAcmBuffer, iHeadlessReadLength);
       
   304 		break;
       
   305 	case EUnknown:
       
   306 	default:
       
   307 		_USB_PANIC(KAcmPanicCat, EPanicInternalError);
       
   308 		break;
       
   309 		}
       
   310 #else
       
   311 	// In case the write observer wants to post another write synchronously on 
       
   312 	// being informed that this write has completed, use this little 'temp' 
       
   313 	// fiddle.
       
   314 	__ASSERT_DEBUG(iWriteObserver, 
       
   315 		_USB_PANIC(KAcmPanicCat, EPanicInternalError));
       
   316 	MWriteObserver* temp = iWriteObserver;
       
   317 	iWriteObserver = NULL;
       
   318 	LOGTEXT(_L8("\tcalling WriteCompleted on observer"));
       
   319 	temp->WriteCompleted(aError);
       
   320 #endif // __HEADLESS_ACM_TEST_CODE__
       
   321 
       
   322 	LOGTEXT(_L8("<<CCdcDataInterface::WriteCompleted"));
       
   323 	}
       
   324 
       
   325 void CCdcDataInterface::CancelWrite()
       
   326 /**
       
   327  * Cancel an outstanding write request
       
   328  */
       
   329 	{
       
   330 	LOG_FUNC
       
   331 	
       
   332 	__ASSERT_DEBUG(iWriter, _USB_PANIC(KAcmPanicCat, EPanicInternalError));
       
   333 
       
   334 	iWriter->Cancel();
       
   335 
       
   336 	iWriteObserver = NULL;
       
   337 	}
       
   338 
       
   339 void CCdcDataInterface::Read(MReadObserver& aObserver, 
       
   340 							 TDes8& aDes, 
       
   341 							 TInt aMaxLen)
       
   342 /**
       
   343  * Read data from the interface. As the LDD supports an appropriate function, 
       
   344  * this request can be passed straight down. 
       
   345  *
       
   346  * @param aObserver The observer to notify of completion.
       
   347  * @param aDes Descriptor to put the read data in
       
   348  * @param aMaxLen Number of bytes to read
       
   349  */
       
   350 	{
       
   351 	LOG_FUNC
       
   352 
       
   353 #ifdef __HEADLESS_ACM_TEST_CODE__
       
   354 	LOGTEXT(_L8("__HEADLESS_ACM_TEST_CODE__"));
       
   355 	// Issue a Read using our special internal buffer.
       
   356 	iHeadlessReadType = ERead;
       
   357 	iHeadlessReadLength = aMaxLen;
       
   358 	static_cast<void>(&aObserver);
       
   359 	static_cast<void>(&aDes);
       
   360 	__ASSERT_DEBUG(aMaxLen <= iHeadlessAcmBuffer.MaxLength(), 
       
   361 		_USB_PANIC(KAcmPanicCat, EPanicInternalError));
       
   362 	__ASSERT_DEBUG(iReader, _USB_PANIC(KAcmPanicCat, EPanicInternalError));
       
   363 	iReader->Read(iHeadlessAcmBuffer, aMaxLen);
       
   364 #else
       
   365 	__ASSERT_DEBUG(!iReadObserver, 
       
   366 		_USB_PANIC(KAcmPanicCat, EPanicInternalError));
       
   367 	iReadObserver = &aObserver;
       
   368 
       
   369 	__ASSERT_DEBUG(iReader, _USB_PANIC(KAcmPanicCat, EPanicInternalError));
       
   370 	iReader->Read(aDes, aMaxLen);
       
   371 #endif // __HEADLESS_ACM_TEST_CODE__
       
   372 	}
       
   373 
       
   374 void CCdcDataInterface::ReadOneOrMore(MReadOneOrMoreObserver& aObserver, 
       
   375 								  TDes8& aDes, 
       
   376 								  TInt aMaxLen)
       
   377 /**
       
   378  * Read a given amount of data from the interface, but complete if any data 
       
   379  * arrives.
       
   380  *
       
   381  * @param aObserver The observer to notify of completion.
       
   382  * @param aDes Descriptor to put the read data in
       
   383  * @param aMaxLen Number of bytes to read
       
   384  */
       
   385 	{
       
   386 	LOG_FUNC
       
   387 
       
   388 #ifdef __HEADLESS_ACM_TEST_CODE__
       
   389 	LOGTEXT(_L8("__HEADLESS_ACM_TEST_CODE__"));
       
   390 	// Issue a ReadOneOrMore using our special internal buffer.
       
   391 	iHeadlessReadType = EReadOneOrMore;
       
   392 	iHeadlessReadLength = aMaxLen;
       
   393 	static_cast<void>(&aObserver);
       
   394 	static_cast<void>(&aDes);
       
   395 	__ASSERT_DEBUG(aMaxLen <= iHeadlessAcmBuffer.MaxLength(), 
       
   396 		_USB_PANIC(KAcmPanicCat, EPanicInternalError));
       
   397 	__ASSERT_DEBUG(iReadOneOrMoreReader, 
       
   398 		_USB_PANIC(KAcmPanicCat, EPanicInternalError));
       
   399 	iReadOneOrMoreReader->ReadOneOrMore(iHeadlessAcmBuffer, aMaxLen);
       
   400 #else
       
   401 	__ASSERT_DEBUG(!iReadOneOrMoreObserver, 
       
   402 		_USB_PANIC(KAcmPanicCat, EPanicInternalError));
       
   403 	iReadOneOrMoreObserver = &aObserver;
       
   404 
       
   405 	__ASSERT_DEBUG(iReadOneOrMoreReader, 
       
   406 		_USB_PANIC(KAcmPanicCat, EPanicInternalError));
       
   407 	iReadOneOrMoreReader->ReadOneOrMore(aDes, aMaxLen);
       
   408 #endif // __HEADLESS_ACM_TEST_CODE__
       
   409 	}
       
   410 
       
   411 void CCdcDataInterface::ReadOneOrMoreCompleted(TInt aError)
       
   412 /**
       
   413  * The completion function, called when a ReadOneOrMore request is completed 
       
   414  * by the LDD.
       
   415  *
       
   416  * @param aError The result of the read request.
       
   417  */
       
   418 	{
       
   419 	LOGTEXT2(_L8(">>CCdcDataInterface::ReadOneOrMoreCompleted aError=%d"), 
       
   420 		aError);
       
   421 
       
   422 #ifdef __HEADLESS_ACM_TEST_CODE__
       
   423 	LOGTEXT2(_L8("__HEADLESS_ACM_TEST_CODE__- issuing Write for %d bytes"),
       
   424 		iHeadlessAcmBuffer.Length());
       
   425 	// Write back the data just read.
       
   426 	// If the ReadOneOrMore completed with an error, we panic, as it's 
       
   427 	// invalidating the test.
       
   428 	__ASSERT_DEBUG(aError == KErrNone, 
       
   429 		_USB_PANIC(KAcmPanicCat, EPanicInternalError));
       
   430 	__ASSERT_DEBUG(iWriter, _USB_PANIC(KAcmPanicCat, EPanicInternalError));
       
   431 	iWriter->Write(iHeadlessAcmBuffer, iHeadlessAcmBuffer.Length(), EFalse); 
       
   432 #else
       
   433 	__ASSERT_DEBUG(iReadOneOrMoreObserver, 
       
   434 		_USB_PANIC(KAcmPanicCat, EPanicInternalError));
       
   435 
       
   436 	// See comment in WriteCompleted.
       
   437 	MReadOneOrMoreObserver* temp = iReadOneOrMoreObserver;
       
   438 	iReadOneOrMoreObserver = NULL;
       
   439 	LOGTEXT(_L8("\tcalling ReadOneOrMoreCompleted on observer"));
       
   440 	temp->ReadOneOrMoreCompleted(aError);
       
   441 #endif // __HEADLESS_ACM_TEST_CODE__
       
   442 
       
   443 	LOGTEXT(_L8("<<CCdcDataInterface::ReadOneOrMoreCompleted"));
       
   444 	}
       
   445 
       
   446 void CCdcDataInterface::ReadCompleted(TInt aError)
       
   447 /**
       
   448  * Called by the active reader object when it completes.
       
   449  *
       
   450  * @param aError Error.
       
   451  */
       
   452 	{
       
   453 	LOGTEXT2(_L8(">>CCdcDataInterface::ReadCompleted aError=%d"), aError);
       
   454 
       
   455 #ifdef __HEADLESS_ACM_TEST_CODE__
       
   456 	LOGTEXT2(_L8("__HEADLESS_ACM_TEST_CODE__- issuing Write for %d bytes"),
       
   457 		iHeadlessAcmBuffer.Length());
       
   458 	// Write back the data just read.
       
   459 	// If the Read completed with an error, we panic, as it's invalidating the 
       
   460 	// test.				 
       
   461 	__ASSERT_DEBUG(aError == KErrNone,
       
   462 		_USB_PANIC(KAcmPanicCat, EPanicInternalError));
       
   463 	__ASSERT_DEBUG(iWriter, _USB_PANIC(KAcmPanicCat, EPanicInternalError));
       
   464 	iWriter->Write(iHeadlessAcmBuffer, iHeadlessAcmBuffer.Length(), EFalse); 
       
   465 #else
       
   466 	__ASSERT_DEBUG(iReadObserver, 
       
   467 		_USB_PANIC(KAcmPanicCat, EPanicInternalError));
       
   468 
       
   469 	// See comment in WriteCompleted.
       
   470 	MReadObserver* temp = iReadObserver;
       
   471 	iReadObserver = NULL;
       
   472 	LOGTEXT(_L8("\tcalled ReadCompleted on observer"));
       
   473 	temp->ReadCompleted(aError);
       
   474 #endif // __HEADLESS_ACM_TEST_CODE__
       
   475 
       
   476 	LOGTEXT(_L8("<<CCdcDataInterface::ReadCompleted"));
       
   477 	}
       
   478 
       
   479 void CCdcDataInterface::CancelRead()
       
   480 /**
       
   481  * Cancel an outstanding read request
       
   482  */
       
   483 	{
       
   484 	LOG_FUNC
       
   485 
       
   486 	__ASSERT_DEBUG(iReader, _USB_PANIC(KAcmPanicCat, EPanicInternalError));
       
   487 	__ASSERT_DEBUG(iReadOneOrMoreReader, 
       
   488 		_USB_PANIC(KAcmPanicCat, EPanicInternalError));
       
   489 
       
   490 	iReader->Cancel();
       
   491 	iReadOneOrMoreReader->Cancel();
       
   492 	iReadObserver = NULL;
       
   493 	iReadOneOrMoreObserver = NULL;
       
   494 	}
       
   495 
       
   496 
       
   497 void CCdcDataInterface::GetHostZLPHandlingFromFile()
       
   498 /**
       
   499  * Opens the ECACM.ini file to check on the capabilities of the host device.
       
   500  * If the ini file cannot be found or read successfully, the default setting i.e. the
       
   501  * host device CANNOT handle Zero Length Packets (set in CCdcAcmClass::ConstructL()),
       
   502  * is kept.		
       
   503  */
       
   504 	{
       
   505 	LOG_FUNC
       
   506 	
       
   507 	CIniFile* iniFile = NULL;
       
   508 
       
   509 	_LIT(KEcacmIniFilename, "ecacm.ini" );
       
   510 	_LIT(KEcacmIniFilePath, "\\system\\data\\" );
       
   511 	
       
   512 	TRAPD(error, iniFile = CIniFile::NewL(KEcacmIniFilename, KEcacmIniFilePath));
       
   513 
       
   514 	if (error == KErrNone)
       
   515 		{
       
   516 		TInt hostHandlesZLPs = 1;
       
   517 	
       
   518 		_LIT(KHostUSBDeviceDriver, "HostUSBDeviceDriver");
       
   519 		_LIT(KCanHandleZLP, "CanHandleZLP");
       
   520 	
       
   521 		if ( iniFile->FindVar(KHostUSBDeviceDriver, KCanHandleZLP(), hostHandlesZLPs))
       
   522 			{			
       
   523 			iHostCanHandleZLPs = (( hostHandlesZLPs == 1 ) ? ETrue : EFalse ); 
       
   524 		
       
   525 			LOGTEXT2(_L8("\tecacm.ini: CanHandleZLP=%d"), hostHandlesZLPs);
       
   526 			}
       
   527 			
       
   528 		delete iniFile;	
       
   529 		}
       
   530 	}
       
   531 	
       
   532 void CCdcDataInterface::NotifyDataAvailableCompleted(TInt aError)
       
   533 /**
       
   534  * Called by the active data available notifier object when it completes.
       
   535  *
       
   536  * @param aError Error.
       
   537  */
       
   538 	{
       
   539 	LOGTEXT2(_L8(">>CCdcDataInterface::NotifyDataAvailableCompleted aError=%d"), aError);	
       
   540 	
       
   541 	// See comment in WriteCompleted.
       
   542 	MNotifyDataAvailableObserver* temp = iNotifyDataAvailableObserver;
       
   543 	iNotifyDataAvailableObserver = NULL;
       
   544 	LOGTEXT(_L8("\tcalled NotifyDataAvailableCompleted on observer"));
       
   545 	temp->NotifyDataAvailableCompleted(aError);
       
   546 	
       
   547 	LOGTEXT(_L8("<<CCdcDataInterface::NotifyDataAvailableCompleted"));
       
   548 	}
       
   549 	
       
   550 void CCdcDataInterface::NotifyDataAvailable(MNotifyDataAvailableObserver& aObserver)
       
   551 /**
       
   552  * Complete if any data arrives.
       
   553  *
       
   554  * @param aObserver The observer to notify of completion.
       
   555  */
       
   556 	{
       
   557 	LOG_FUNC
       
   558 		
       
   559 	__ASSERT_DEBUG(!iNotifyDataAvailableObserver, _USB_PANIC(KAcmPanicCat, EPanicInternalError));
       
   560 	iNotifyDataAvailableObserver = &aObserver;
       
   561 
       
   562 	__ASSERT_DEBUG(iDataAvailableNotifier, 
       
   563 		_USB_PANIC(KAcmPanicCat, EPanicInternalError));
       
   564 	iDataAvailableNotifier->NotifyDataAvailable();
       
   565 	}
       
   566 
       
   567 void CCdcDataInterface::CancelNotifyDataAvailable()
       
   568 /**
       
   569  * Cancel notification of arrival of data.
       
   570  */
       
   571 	{
       
   572 	LOG_FUNC
       
   573 
       
   574 	__ASSERT_DEBUG(iDataAvailableNotifier, _USB_PANIC(KAcmPanicCat, EPanicInternalError));
       
   575 
       
   576 	iDataAvailableNotifier->Cancel();
       
   577 	iNotifyDataAvailableObserver = NULL;	
       
   578 	}
       
   579 
       
   580 //
       
   581 // End of file