emulator/emulatorbsp/test/exdriver/exdriver_pio/src/d_expio_emul.cpp
changeset 0 cec860690d41
equal deleted inserted replaced
-1:000000000000 0:cec860690d41
       
     1 // Copyright (c) 2007-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 // This file implements the DExUartPhysicalChannelEmul class functions. 
       
    15 // This is the implementation os serila port driver for emulator
       
    16 // target, i.e serial port of windows PC. This pdd is actually an
       
    17 // application for windows serial driver and therefore uses windows
       
    18 // API to access windows serial driver functionality
       
    19 // 
       
    20 //
       
    21 
       
    22 // include h4 specific header file
       
    23 #include "d_expio_emul.h"
       
    24 
       
    25 /** 
       
    26  PDD entry point
       
    27  This function is called when the PDD is loaded. This creates a factory
       
    28  object for PDD. DECLARE_STANDARD_PDD macro defines the first export to
       
    29  represent the DLL factory function, that will be called first by loader
       
    30  after loading the PDD. 
       
    31  */
       
    32 DECLARE_STANDARD_PDD()
       
    33 	{	
       
    34 	// Create a PDD factory object, i.e instance of DPhysicalDevice derived 
       
    35 	// class. This is the first step that is done after loading the driver.
       
    36 	// Physical device constructor inturn creates a Physical Channel.
       
    37 	//		
       
    38 	DExEmulPhysicalDevice* pD = new DExEmulPhysicalDevice;
       
    39 	if(pD)
       
    40 		{
       
    41 		// TDynamicDfcQue is used for creating and destroying a DFC as needed
       
    42 		// This extends TDfcQue with destroy method. This ensures there is
       
    43 		// no memory leak done while using DFC queue 
       
    44 		//
       
    45 		TDynamicDfcQue* pDfcQ;
       
    46 		// Create a new DFC queue using kernel API, Kern::DynamicDfcQCreate(). It 
       
    47 		// allocates a TDynamicDfcQue object on the heap and initializes it with 
       
    48 		// provided parameters like thread priority for the queue. Thread priority
       
    49 		// has to be chosen carefully, as priority higher than the kernel threads 
       
    50 		// used for timers may adversely effect the system performance, nano 
       
    51 		// kernel ticks.
       
    52 		//
       
    53 		TInt r = Kern::DynamicDfcQCreate(pDfcQ,KExEmulUartDfcPriority,
       
    54 														KExEmulUartDfcName);
       
    55 		if (KErrNone==r)
       
    56 			{
       
    57 			// Store the DFC thread pointer to return when required
       
    58 			pD->iDfcQueue = pDfcQ;
       
    59 			// Success return point
       
    60 			return pD;
       
    61 			}
       
    62 		// if DFCQ creation failed, then fail the PDD loading, hence asynchronously close	
       
    63 		// the LDD factory object created.
       
    64 		//
       
    65 		pD->AsyncClose();
       
    66 		}
       
    67 	// Failure exit point	
       
    68 	return NULL;
       
    69 	}
       
    70 
       
    71 /**
       
    72  PDD factory constructor. This is called while creating the PDD factory
       
    73  object as a part of the driver (PDD) loading. This is called after the
       
    74  base class constructor, i.e DExUartPhysicalDevice()
       
    75  */
       
    76 DExEmulPhysicalDevice::DExEmulPhysicalDevice()	
       
    77 	{	
       
    78 	// if multiple units are supported, then iUnitsMask is set here
       
    79 	// to indicate the units being supported by the driver.	
       
    80 	}
       
    81 
       
    82 /**
       
    83  Physical device destructor. This is called whicle unloading the PDD
       
    84  */
       
    85 DExEmulPhysicalDevice::~DExEmulPhysicalDevice()	
       
    86 	{	
       
    87 	// If a Dynamic Dfc Queue is created, delete it to ensure there is no
       
    88 	// memory leak.
       
    89 	//
       
    90 	if (iDfcQueue)
       
    91 		{
       
    92 		// Destroys the DFC queue.The function destroys the DFC queue, killing
       
    93 		// the DFC thread and deleting the TDynamicDfcQue object itself
       
    94 		//
       
    95 		iDfcQueue->Destroy();
       
    96 		}
       
    97 	}
       
    98 
       
    99 /** 
       
   100  PDD factory object (physical device) create. This is called by framework
       
   101  to create a physical channel. It is called in the context of the client 
       
   102  user-side thread that requested the creation of the logical channel. 
       
   103  This is a result of a user-side call to RBusLogicalChannel::DoCreate().
       
   104  
       
   105  @param 	aChannel
       
   106  			reference to the physical channel object created
       
   107  
       
   108  @return	KErrNone for success or KErrNoMemory for failure
       
   109  */ 
       
   110 TInt DExEmulPhysicalDevice::Create(DBase*& aChannel,TInt aUnit, const TDesC8* aInfo, 
       
   111 								const TVersion& aVer)
       
   112 	{		
       
   113 	// Create the Physical channel		
       
   114 	DExUartPhysicalChannelEmul *device = new DExUartPhysicalChannelEmul;
       
   115 	if (!device)
       
   116 		return KErrNoMemory;
       
   117 	
       
   118 	aChannel = device;
       
   119 	
       
   120 	// Call the second stage contructor of physical channel
       
   121 	return device->DoCreate(aUnit,aInfo,aVer);	
       
   122 	}		
       
   123 		
       
   124 /**
       
   125  Constructor for physical channel. Called after the base class constructor
       
   126  */
       
   127 DExUartPhysicalChannelEmul::DExUartPhysicalChannelEmul()
       
   128 :iConfigured(EFalse),
       
   129 iBytesRead(0),
       
   130  iRxPollTimer(RxPollTimerCallback,this)	// Timer to poll Rx data
       
   131 	{	
       
   132 	}
       
   133 
       
   134 /**
       
   135  Hardware peripheral class (uart) Destructor
       
   136  */
       
   137 DExUartPhysicalChannelEmul::~DExUartPhysicalChannelEmul()
       
   138 	{
       
   139 	// Cancel the Rx poll timer. NTimer.Cancel() Cancel a nanokernel 
       
   140 	// timer. Removes this timer from the nanokernel timer queue. 
       
   141 	// Does nothing if the timer is inactive or has already expired. 
       
   142 	// If the timer was queued and DFC callback requested it is possible 
       
   143 	// for the expiry handler to run even after Cancel() has been called.
       
   144 	//
       
   145 	if (iTimerStatus==KTimerStarted)
       
   146 		iRxPollTimer.Cancel();
       
   147 
       
   148 	// close the port if the handle is invalid
       
   149 	if (hCommPort!=INVALID_HANDLE_VALUE)
       
   150 	{
       
   151 		// Close the Serial Port after reading data
       
   152 		CloseHandle(hCommPort);
       
   153 		KEXDEBUG(Kern::Printf("Emulator::Serial Port Closed"));
       
   154 	}
       
   155 	}
       
   156 
       
   157 /**
       
   158  Physical channel second stage constructor. This is called from the DPhysicalDevice::Create()
       
   159  after creating the physical channel. Any further initializations as a part of the physical
       
   160  channel creation are done here.
       
   161  
       
   162  @param	aUnit
       
   163  		device unit number
       
   164  @param	aInfo
       
   165  		device related information
       
   166  @param	aVer
       
   167  		version number
       
   168  @return
       
   169  */
       
   170 TInt DExUartPhysicalChannelEmul::DoCreate(TInt aUnit, const TDesC8* aInfo, const TVersion& aVer)
       
   171     { 
       
   172     TInt r;
       
   173      
       
   174     // We are not using these parameters here, and therefore making them void to avoid any
       
   175     // warning messages during build. If multiple units are supported, creating the channel
       
   176     // w.r.t unit can be controlled here
       
   177     //
       
   178     (void)aUnit;     
       
   179     (void)aInfo;
       
   180     (void)aVer;
       
   181     
       
   182     // TCommConfigV01 structure defined in d32comm.h is used
       
   183  	// to hold the configuration details like baudrate, parity,
       
   184  	// databits etc for serial
       
   185  	//
       
   186     TCommConfigV01 cfg;
       
   187     // Configure the channel by default, (9600 baud rate)
       
   188     cfg.iRate = EBps9600;
       
   189     r = Configure(cfg);
       
   190     if (r!=KErrNone)
       
   191     	{
       
   192     	// Configuration failed, still continue by updating device state
       
   193     	iConfigured=EFalse;
       
   194     	}
       
   195     else
       
   196     	{
       
   197     	// Device configured successfully
       
   198         iConfigured=ETrue;		    
       
   199     	}
       
   200     
       
   201     // Physical channel creation is successful
       
   202     return KErrNone;    
       
   203     }
       
   204     
       
   205 /**   
       
   206  DfcQ - Creates a DFC queue dedicated for the tutorial driver. By default
       
   207  logical channel derived from DLogicalChannel has a DFCQ, and DFC thread 0
       
   208  is generally used. However, driver can choose o create it's own DFC and
       
   209  use it for queuing it's messages to this queue. In this case, PDD can 
       
   210  implement this function, DfcQ(), which is called by LDD to initialize it's
       
   211  messgage queue with this DFC.
       
   212  
       
   213  @return	refernce to the created TDynamicDfcQue object
       
   214  */
       
   215 TDynamicDfcQue* DExUartPhysicalChannelEmul::DfcQ()    
       
   216 	{
       
   217 	// return the dfc thread created for this driver. one per uint/device
       
   218 	return ((DExEmulPhysicalDevice*)iLdd->iPhysicalDevice)->iDfcQueue;		
       
   219 	}
       
   220 
       
   221 /** 
       
   222  Get the capabilities of the channel. This can be used by the user to get
       
   223  the capabilities for the channel from PSL.
       
   224  
       
   225  @param	aCaps
       
   226  		descriptor returned after filling with capabilities 
       
   227  */ 
       
   228 void DExUartPhysicalChannelEmul:: Caps(TDes8& aCaps)
       
   229 	{
       
   230 	// Package buffer of TCommCapsV03. This creates a descriptor
       
   231 	// for the commcaps structure, and provide compatibility
       
   232 	// to use with API using descriptors
       
   233 	//
       
   234 	TCommCaps3 capsBuf;    
       
   235 	  
       
   236 	// Retrieves the data structure from the package buffer. TCommCapsV03
       
   237 	// holds the uart capabilities information.
       
   238     //
       
   239 	TCommCapsV03 &caps=capsBuf();
       
   240 	
       
   241 	caps.iRate=KCapsBps9600;	// baudrate
       
   242 	caps.iDataBits=KCapsData8;	// data size
       
   243 	caps.iFifo=KCapsHasFifo;	// fifo enabled
       
   244 	caps.iBreakSupported=EFalse;// no braek support	
       
   245 
       
   246 	// [TDes8::MaxLength()] - Get the descriptor's length.
       
   247 	TInt len = aCaps.MaxLength();
       
   248 	
       
   249 	// [TDes8::FillZ(len)] -Fill the descriptor's data area with binary 
       
   250 	// zeroes, replacing any existing data and change its length. 
       
   251 	aCaps.FillZ(len);
       
   252 	
       
   253     TInt size = sizeof(caps);
       
   254     if (size>len)
       
   255     	size=len;
       
   256     
       
   257     // [TDes8::Copy()] - Copy the data of length (size) into aDes descriptor
       
   258     //  replacing any existing data in the descriptor.
       
   259     aCaps.Copy((TUint8*)&caps, size);
       
   260         	
       
   261 	aCaps=capsBuf.Left(Min(capsBuf.Length(),aCaps.MaxLength()));
       
   262 	}
       
   263 		
       
   264 /**
       
   265  Configure the hardware device (Uart). This is device specific API, that 
       
   266  provides functionality to configure the uart. Uart configuration settings are 
       
   267  passed to this function by user. User calls this by using 
       
   268  RBusLogicalChannel::DoControl() to LDD and ldd inturn calls this PDD function
       
   269  to do the actual operation on the device.
       
   270   
       
   271  @param	aConfig
       
   272  		configuration settings for the device
       
   273  
       
   274  @return	KErrNone or standard error code
       
   275  */
       
   276 TInt DExUartPhysicalChannelEmul::Configure(const TCommConfigV01& aConfig)
       
   277 	{
       
   278 
       
   279 	// if channel is already configured to same baud rate, then no need to 
       
   280 	// repeat the configuration
       
   281 	//
       
   282 	if (iConfigured!=EFalse)
       
   283 	{
       
   284 		if(iBaudRate==aConfig.iRate)
       
   285 			return KErrNone;
       
   286 	}
       
   287 	
       
   288 	iBaudRate = aConfig.iRate;
       
   289 
       
   290 	// variables used with the com port
       
   291 	BOOL     bPortReady;
       
   292 	DCB      dcb;
       
   293 	COMMTIMEOUTS commTimeouts;
       
   294 
       
   295 	bPortReady = TRUE; // everything is OK so far
       
   296 	
       
   297 	// Open a serial port device using the CreateFile() function by specifying
       
   298 	// a filename that refers to the specific port, such as COM1 or COM2.
       
   299 	// 
       
   300 	// When you open a serial port, it is opened automatically for exclusive access,
       
   301 	// so you should pass a zero for the CreateFile()'s third parameter and OPEN_EXISTING
       
   302 	// for the open mode (fifth parameter). You can add a combination of the special file
       
   303 	// mode flags to indicate overlapped I/O or any special buffering requirements, as normal.
       
   304 	// 
       
   305 	// If the serial port opens successfully, a Win32 file object handle is returned.
       
   306 	// Otherwise, INVALID_HANDLE_VALUE is returned.
       
   307 	//
       
   308 	hCommPort=CreateFileA((LPCSTR)"\\\\.\\com1",GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,NULL);
       
   309 	
       
   310 	if (hCommPort==INVALID_HANDLE_VALUE)	
       
   311 	{	
       
   312 		Kern::Printf("Emulator::Configure: FAILED");
       
   313 		
       
   314 		bPortReady = FALSE;
       
   315 
       
   316 		DWORD winErr=GetLastError();
       
   317 		switch (winErr)
       
   318 		{
       
   319 			case ERROR_INVALID_USER_BUFFER:
       
   320 			case ERROR_NOT_ENOUGH_MEMORY:
       
   321 			case ERROR_INSUFFICIENT_BUFFER:
       
   322 				return(KErrNoMemory);
       
   323 			case ERROR_ACCESS_DENIED:
       
   324 				return(KErrAccessDenied);
       
   325 			case ERROR_FILE_NOT_FOUND:		//	Reflects value returned by
       
   326 				return(KErrNotSupported);	//	corresponding MARM Pdd  
       
   327 			case ERROR_NOT_SUPPORTED:
       
   328 				return(KErrNotSupported);
       
   329 			default:
       
   330 				return(KErrGeneral);
       
   331 		}
       
   332 	}
       
   333 	
       
   334 	if (bPortReady)
       
   335 	{
       
   336 		bPortReady = SetupComm(hCommPort, 256, 256); // set buffer sizes
       
   337 		if (!bPortReady)
       
   338 		{
       
   339 			return(KErrNoMemory);
       
   340 		}
       
   341 	}
       
   342 	
       
   343     
       
   344     // After you open a serial port, you must set the many flags required to configure
       
   345     // the device. These flags are held in a device control block (DCB) structure.
       
   346     // You can either fill in the entire DCB structure or use one of the helper functions
       
   347     // to fill in some of the details. The GetCommState() function fills in a DCB structure
       
   348     // with the current settings from the hardware, and you can use a corresponding
       
   349     // SetCommState() function to specify the new settings from a DCB structure.
       
   350 	//
       
   351 	if (bPortReady)
       
   352 	{
       
   353 		bPortReady = GetCommState(hCommPort, &dcb);
       
   354 		if (!bPortReady)
       
   355 		{
       
   356 			return(KErrGeneral);
       
   357 		}
       
   358 	}
       
   359 	
       
   360 	if (bPortReady)
       
   361 	{
       
   362 		//baud rate
       
   363 		switch (aConfig.iRate)
       
   364 			{
       
   365 		case EBps9600:
       
   366 			dcb.BaudRate=9600;
       
   367 			break;
       
   368 		case EBps38400:
       
   369 			dcb.BaudRate=38400;
       
   370 			break;
       
   371 		case EBps115200:
       
   372 			dcb.BaudRate=115200;
       
   373 			break;
       
   374 		default:
       
   375 			dcb.BaudRate=9600;
       
   376 			break;
       
   377 			}
       
   378 			
       
   379 	   	//data bits
       
   380 	   	switch(aConfig.iDataBits)
       
   381 			{
       
   382 		case EData7:
       
   383 			dcb.ByteSize=7;
       
   384 			break;
       
   385 		case EData8:
       
   386 			dcb.ByteSize=8;
       
   387 			break;
       
   388 		default:
       
   389 			dcb.ByteSize=8;
       
   390 			break;
       
   391 			}
       
   392 
       
   393 		//stop bits
       
   394 		switch(aConfig.iStopBits)
       
   395 			{
       
   396 		case EStop1:
       
   397 			dcb.StopBits=ONESTOPBIT;
       
   398 			break;
       
   399 		case EStop2:
       
   400 			dcb.StopBits=TWOSTOPBITS;
       
   401 			break;
       
   402 		default:
       
   403 			dcb.StopBits = ONESTOPBIT;
       
   404 			break;	
       
   405 			}
       
   406 		
       
   407 		dcb.Parity = NOPARITY;
       
   408 
       
   409 		bPortReady = SetCommState(hCommPort, &dcb);
       
   410 		if (!bPortReady)
       
   411 		{
       
   412 			return(KErrGeneral);
       
   413 		}
       
   414 	}
       
   415 
       
   416 	if (bPortReady)
       
   417 	{		
       
   418 		// You can find the current timeout settings using the GetCommTimeout()
       
   419 		// function, which fills a passed COMMTIMEOUTS structure.	
       
   420 		//
       
   421 		bPortReady = GetCommTimeouts (hCommPort, &commTimeouts);
       
   422 		if (bPortReady)
       
   423 		{
       
   424 			// You can set ReadIntervalTimeout to MAXDWORD and set the
       
   425 			// ReadTotalTimeoutMultiplier and ReadTotalTimeoutConstant members
       
   426 			// to zero to indicate that the ReadFile() should return immediately.
       
   427 			//
       
   428 		    commTimeouts.ReadIntervalTimeout = MAXDWORD;
       
   429 		    commTimeouts.ReadTotalTimeoutConstant = 0;
       
   430 		    commTimeouts.ReadTotalTimeoutMultiplier = 0;
       
   431 		}
       
   432 		else
       
   433 		{
       
   434 			return(KErrGeneral);
       
   435 		}
       
   436 		if(!SetCommTimeouts(hCommPort, &commTimeouts))
       
   437 			return(KErrGeneral);
       
   438 		
       
   439 	}
       
   440 	return KErrNone;
       
   441 	}
       
   442 
       
   443 // After configuring the serial port, you can start transferring data via ReadFile()
       
   444 // and WriteFile() functions. However, you should remember that if you haven't specified
       
   445 // the FILE_FLAG_OVERLAPPED flag in the CreateFile() flags parameter,
       
   446 // ReadFile() will block waiting for input. This probably is good if your program spawns
       
   447 // another thread that specifically waits for incoming serial port characters, but not
       
   448 // if you want to issue a ReadFile() and periodically check to see whether any characters
       
   449 // have arrived.
       
   450 // 
       
   451 
       
   452 /**
       
   453  Transmit data over uart for emulator targte, i.e serial port for pc
       
   454  Transmit data buffer is filled and passed by user to the driver
       
   455  
       
   456  @param	aData
       
   457  			buffer for transmit data
       
   458  
       
   459  @return	KErrNone or standard error code
       
   460  */
       
   461 TInt DExUartPhysicalChannelEmul::TransmitData(const TDesC8& aData)
       
   462 	{
       
   463 	TInt r;
       
   464 	TInt count;
       
   465 	TInt size;
       
   466 	TInt offset=0;
       
   467 		
       
   468 	// if the device is not configured, try to configure the device again
       
   469 	if (iConfigured==EFalse)
       
   470 		{
       
   471 		// Configure the channel by default
       
   472     	TCommConfigV01 cfg;
       
   473     	cfg.iRate = EBps9600; // 9600 baudrate
       
   474     	r = Configure(cfg);
       
   475     	if (r!=KErrNone)
       
   476     		{
       
   477     		// configure failed again, abort the request
       
   478     		iConfigured=EFalse;
       
   479     		return KErrAbort;
       
   480     		}
       
   481     	// configured successfully, continue with Tx	
       
   482     	iConfigured=ETrue;	
       
   483 		}	
       
   484 	
       
   485 	// Size of the data to be transmitted is obtained from the descriptor. 
       
   486 	// TDesC8::Size() gets the size of the data interms of number of bytes occupied 
       
   487 	// by the data represented by the descriptor
       
   488 	//
       
   489 	count= aData.Size();
       
   490 	if (count<=0)
       
   491 		return KErrAbort;
       
   492 	
       
   493 	// Loop till all the data sent from LDD is transmitted in blocks of KTxFifoSize
       
   494  	while (count>0)
       
   495  		{
       
   496  		// Each block size can be max KTxFifoSize or less
       
   497  		size=(count<KTxFifoSize)?count:KTxFifoSize;
       
   498 		
       
   499 		BOOL bWriteRC;
       
   500 		DWORD iBytesWritten;
       
   501 
       
   502 		iBytesWritten = 0;
       
   503 		bWriteRC = WriteFile(hCommPort, aData.Ptr(), size, &iBytesWritten, NULL);
       
   504 
       
   505 		if (!bWriteRC || iBytesWritten == 0)
       
   506 			{
       
   507 			return(KErrGeneral);
       
   508 			}
       
   509 		
       
   510  		// calculate the offset
       
   511 		offset+=iBytesWritten;			
       
   512 		// calculate the remaining buffer size
       
   513 		count-=iBytesWritten;			
       
   514 		}
       
   515 		
       
   516 	return KErrNone;
       
   517 	}
       
   518 
       
   519 /**
       
   520  Receive data over uart for emulator target, i.e uart of pc
       
   521  Receive data buffer is filled and passed by driver to the user
       
   522  
       
   523  @param	aData
       
   524  			buffer for received data
       
   525  
       
   526  @return	KErrNone or standard error code
       
   527  */
       
   528 TInt DExUartPhysicalChannelEmul::ReceiveData(TDes8& aData,TInt aLen)
       
   529 	{	
       
   530 	TInt ret;
       
   531 	TInt size;
       
   532 	TInt count;
       
   533 	TInt bytesRcvd=0;
       
   534 	
       
   535 	// Size of the data to be transmitted is obtained from the descriptor. 
       
   536 	// TDesC8::Size() gets the size of the data interms of number of bytes occupied 
       
   537 	// by the data represented by the descriptor
       
   538 	//
       
   539 	size= aLen;
       
   540 	if (size<=0)
       
   541 		return KErrAbort; // Zero length request, exit and fail
       
   542 	
       
   543 	// Keep track of the requested size
       
   544 	count=size;	
       
   545 
       
   546  	// Loop till the requested amount of data from LDD is filled or a timeout
       
   547   	while (count>0)
       
   548  		{ 		
       
   549  		BOOL bReadRC;
       
   550 		char sBuffer[256];
       
   551 	
       
   552 		memset(sBuffer,0,sizeof(sBuffer));
       
   553  		// if no data and timer expired
       
   554  		while ((bReadRC=ReadFile(hCommPort, sBuffer, sizeof(sBuffer), &iBytesRead, NULL)) == 0
       
   555  				|| (iBytesRead==0)) 		
       
   556  			{
       
   557  			if (iTimerStatus==KTimerExpired)
       
   558  				{
       
   559  				aData.SetLength(bytesRcvd);
       
   560  				return KErrTimedOut;
       
   561  				}
       
   562  			}
       
   563  				 			
       
   564  		if (iTimerStatus==KTimerStarted)
       
   565 			{
       
   566 			// Cancel the Rx poll timer. NTimer.Cancel() Cancel a nanokernel 
       
   567 			// timer. Removes this timer from the nanokernel timer queue. 
       
   568 			// Does nothing if the timer is inactive or has already expired. 
       
   569 			// If the timer was queued and DFC callback requested it is possible 
       
   570 			// for the expiry handler to run even after Cancel() has been called.
       
   571 			//
       
   572 			iRxPollTimer.Cancel();
       
   573 			// Update status as Cancelled
       
   574 			iTimerStatus=KTimerCancelled;
       
   575 			}
       
   576 			
       
   577 		if (bReadRC && (iBytesRead>0))
       
   578 			{
       
   579 			if (iBytesRead>=static_cast<TUint>(size))			
       
   580 				iBytesRead=size;
       
   581 			aData.Append(TPtrC8((const TText8*)sBuffer,iBytesRead));		
       
   582 			bytesRcvd+=iBytesRead;
       
   583 			iBytesRead=0;
       
   584 			}
       
   585 		else
       
   586 			{
       
   587 			iTimerStatus = KTimerStarted;			 			
       
   588 			// Start a nanokernel timer in one-shot mode with ISR callback
       
   589 			// Queues the timer to expire in the specified number of nanokernel
       
   590 			// ticks. The actual wait time will be at least that much and 
       
   591 			// may be up to one tick more. The expiry handler will be called in
       
   592 			// ISR context.
       
   593 			//		 			
       
   594     		ret=iRxPollTimer.OneShot(KRxPollTimeout); 			
       
   595 			if(ret!=KErrNone) // timer creation failed
       
   596 				return ret;
       
   597 			}	
       
   598 
       
   599 		// If we have received the requested number of bytes, return
       
   600 		if (bytesRcvd>=size)
       
   601 			{					
       
   602 			if (iTimerStatus == KTimerStarted)
       
   603 				iRxPollTimer.Cancel();			
       
   604 			return KErrNone;
       
   605 			}
       
   606 						
       
   607 		// remaining bytes to be received	
       
   608 		count -= bytesRcvd;		 		 		
       
   609 		}		
       
   610 
       
   611 	return KErrNone;
       
   612 	}
       
   613 
       
   614 void DExUartPhysicalChannelEmul::RxPollTimerCallback(TAny* aPtr)
       
   615     {
       
   616     KEXDEBUG(Kern::Printf("EMUL UART::Rx Timer Expired, Data Flow Stopped"));
       
   617     ((DExUartPhysicalChannelEmul*)aPtr)->iTimerStatus=KTimerExpired;        
       
   618     }
       
   619 	
       
   620 //
       
   621 // End of d_expio_emul.cpp