os/boardsupport/emulator/emulatorbsp/test/exdriver/exdriver_pio/src/d_expio_emul.cpp
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/boardsupport/emulator/emulatorbsp/test/exdriver/exdriver_pio/src/d_expio_emul.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,621 @@
1.4 +// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +// This file implements the DExUartPhysicalChannelEmul class functions.
1.18 +// This is the implementation os serila port driver for emulator
1.19 +// target, i.e serial port of windows PC. This pdd is actually an
1.20 +// application for windows serial driver and therefore uses windows
1.21 +// API to access windows serial driver functionality
1.22 +//
1.23 +//
1.24 +
1.25 +// include h4 specific header file
1.26 +#include "d_expio_emul.h"
1.27 +
1.28 +/**
1.29 + PDD entry point
1.30 + This function is called when the PDD is loaded. This creates a factory
1.31 + object for PDD. DECLARE_STANDARD_PDD macro defines the first export to
1.32 + represent the DLL factory function, that will be called first by loader
1.33 + after loading the PDD.
1.34 + */
1.35 +DECLARE_STANDARD_PDD()
1.36 + {
1.37 + // Create a PDD factory object, i.e instance of DPhysicalDevice derived
1.38 + // class. This is the first step that is done after loading the driver.
1.39 + // Physical device constructor inturn creates a Physical Channel.
1.40 + //
1.41 + DExEmulPhysicalDevice* pD = new DExEmulPhysicalDevice;
1.42 + if(pD)
1.43 + {
1.44 + // TDynamicDfcQue is used for creating and destroying a DFC as needed
1.45 + // This extends TDfcQue with destroy method. This ensures there is
1.46 + // no memory leak done while using DFC queue
1.47 + //
1.48 + TDynamicDfcQue* pDfcQ;
1.49 + // Create a new DFC queue using kernel API, Kern::DynamicDfcQCreate(). It
1.50 + // allocates a TDynamicDfcQue object on the heap and initializes it with
1.51 + // provided parameters like thread priority for the queue. Thread priority
1.52 + // has to be chosen carefully, as priority higher than the kernel threads
1.53 + // used for timers may adversely effect the system performance, nano
1.54 + // kernel ticks.
1.55 + //
1.56 + TInt r = Kern::DynamicDfcQCreate(pDfcQ,KExEmulUartDfcPriority,
1.57 + KExEmulUartDfcName);
1.58 + if (KErrNone==r)
1.59 + {
1.60 + // Store the DFC thread pointer to return when required
1.61 + pD->iDfcQueue = pDfcQ;
1.62 + // Success return point
1.63 + return pD;
1.64 + }
1.65 + // if DFCQ creation failed, then fail the PDD loading, hence asynchronously close
1.66 + // the LDD factory object created.
1.67 + //
1.68 + pD->AsyncClose();
1.69 + }
1.70 + // Failure exit point
1.71 + return NULL;
1.72 + }
1.73 +
1.74 +/**
1.75 + PDD factory constructor. This is called while creating the PDD factory
1.76 + object as a part of the driver (PDD) loading. This is called after the
1.77 + base class constructor, i.e DExUartPhysicalDevice()
1.78 + */
1.79 +DExEmulPhysicalDevice::DExEmulPhysicalDevice()
1.80 + {
1.81 + // if multiple units are supported, then iUnitsMask is set here
1.82 + // to indicate the units being supported by the driver.
1.83 + }
1.84 +
1.85 +/**
1.86 + Physical device destructor. This is called whicle unloading the PDD
1.87 + */
1.88 +DExEmulPhysicalDevice::~DExEmulPhysicalDevice()
1.89 + {
1.90 + // If a Dynamic Dfc Queue is created, delete it to ensure there is no
1.91 + // memory leak.
1.92 + //
1.93 + if (iDfcQueue)
1.94 + {
1.95 + // Destroys the DFC queue.The function destroys the DFC queue, killing
1.96 + // the DFC thread and deleting the TDynamicDfcQue object itself
1.97 + //
1.98 + iDfcQueue->Destroy();
1.99 + }
1.100 + }
1.101 +
1.102 +/**
1.103 + PDD factory object (physical device) create. This is called by framework
1.104 + to create a physical channel. It is called in the context of the client
1.105 + user-side thread that requested the creation of the logical channel.
1.106 + This is a result of a user-side call to RBusLogicalChannel::DoCreate().
1.107 +
1.108 + @param aChannel
1.109 + reference to the physical channel object created
1.110 +
1.111 + @return KErrNone for success or KErrNoMemory for failure
1.112 + */
1.113 +TInt DExEmulPhysicalDevice::Create(DBase*& aChannel,TInt aUnit, const TDesC8* aInfo,
1.114 + const TVersion& aVer)
1.115 + {
1.116 + // Create the Physical channel
1.117 + DExUartPhysicalChannelEmul *device = new DExUartPhysicalChannelEmul;
1.118 + if (!device)
1.119 + return KErrNoMemory;
1.120 +
1.121 + aChannel = device;
1.122 +
1.123 + // Call the second stage contructor of physical channel
1.124 + return device->DoCreate(aUnit,aInfo,aVer);
1.125 + }
1.126 +
1.127 +/**
1.128 + Constructor for physical channel. Called after the base class constructor
1.129 + */
1.130 +DExUartPhysicalChannelEmul::DExUartPhysicalChannelEmul()
1.131 +:iConfigured(EFalse),
1.132 +iBytesRead(0),
1.133 + iRxPollTimer(RxPollTimerCallback,this) // Timer to poll Rx data
1.134 + {
1.135 + }
1.136 +
1.137 +/**
1.138 + Hardware peripheral class (uart) Destructor
1.139 + */
1.140 +DExUartPhysicalChannelEmul::~DExUartPhysicalChannelEmul()
1.141 + {
1.142 + // Cancel the Rx poll timer. NTimer.Cancel() Cancel a nanokernel
1.143 + // timer. Removes this timer from the nanokernel timer queue.
1.144 + // Does nothing if the timer is inactive or has already expired.
1.145 + // If the timer was queued and DFC callback requested it is possible
1.146 + // for the expiry handler to run even after Cancel() has been called.
1.147 + //
1.148 + if (iTimerStatus==KTimerStarted)
1.149 + iRxPollTimer.Cancel();
1.150 +
1.151 + // close the port if the handle is invalid
1.152 + if (hCommPort!=INVALID_HANDLE_VALUE)
1.153 + {
1.154 + // Close the Serial Port after reading data
1.155 + CloseHandle(hCommPort);
1.156 + KEXDEBUG(Kern::Printf("Emulator::Serial Port Closed"));
1.157 + }
1.158 + }
1.159 +
1.160 +/**
1.161 + Physical channel second stage constructor. This is called from the DPhysicalDevice::Create()
1.162 + after creating the physical channel. Any further initializations as a part of the physical
1.163 + channel creation are done here.
1.164 +
1.165 + @param aUnit
1.166 + device unit number
1.167 + @param aInfo
1.168 + device related information
1.169 + @param aVer
1.170 + version number
1.171 + @return
1.172 + */
1.173 +TInt DExUartPhysicalChannelEmul::DoCreate(TInt aUnit, const TDesC8* aInfo, const TVersion& aVer)
1.174 + {
1.175 + TInt r;
1.176 +
1.177 + // We are not using these parameters here, and therefore making them void to avoid any
1.178 + // warning messages during build. If multiple units are supported, creating the channel
1.179 + // w.r.t unit can be controlled here
1.180 + //
1.181 + (void)aUnit;
1.182 + (void)aInfo;
1.183 + (void)aVer;
1.184 +
1.185 + // TCommConfigV01 structure defined in d32comm.h is used
1.186 + // to hold the configuration details like baudrate, parity,
1.187 + // databits etc for serial
1.188 + //
1.189 + TCommConfigV01 cfg;
1.190 + // Configure the channel by default, (9600 baud rate)
1.191 + cfg.iRate = EBps9600;
1.192 + r = Configure(cfg);
1.193 + if (r!=KErrNone)
1.194 + {
1.195 + // Configuration failed, still continue by updating device state
1.196 + iConfigured=EFalse;
1.197 + }
1.198 + else
1.199 + {
1.200 + // Device configured successfully
1.201 + iConfigured=ETrue;
1.202 + }
1.203 +
1.204 + // Physical channel creation is successful
1.205 + return KErrNone;
1.206 + }
1.207 +
1.208 +/**
1.209 + DfcQ - Creates a DFC queue dedicated for the tutorial driver. By default
1.210 + logical channel derived from DLogicalChannel has a DFCQ, and DFC thread 0
1.211 + is generally used. However, driver can choose o create it's own DFC and
1.212 + use it for queuing it's messages to this queue. In this case, PDD can
1.213 + implement this function, DfcQ(), which is called by LDD to initialize it's
1.214 + messgage queue with this DFC.
1.215 +
1.216 + @return refernce to the created TDynamicDfcQue object
1.217 + */
1.218 +TDynamicDfcQue* DExUartPhysicalChannelEmul::DfcQ()
1.219 + {
1.220 + // return the dfc thread created for this driver. one per uint/device
1.221 + return ((DExEmulPhysicalDevice*)iLdd->iPhysicalDevice)->iDfcQueue;
1.222 + }
1.223 +
1.224 +/**
1.225 + Get the capabilities of the channel. This can be used by the user to get
1.226 + the capabilities for the channel from PSL.
1.227 +
1.228 + @param aCaps
1.229 + descriptor returned after filling with capabilities
1.230 + */
1.231 +void DExUartPhysicalChannelEmul:: Caps(TDes8& aCaps)
1.232 + {
1.233 + // Package buffer of TCommCapsV03. This creates a descriptor
1.234 + // for the commcaps structure, and provide compatibility
1.235 + // to use with API using descriptors
1.236 + //
1.237 + TCommCaps3 capsBuf;
1.238 +
1.239 + // Retrieves the data structure from the package buffer. TCommCapsV03
1.240 + // holds the uart capabilities information.
1.241 + //
1.242 + TCommCapsV03 &caps=capsBuf();
1.243 +
1.244 + caps.iRate=KCapsBps9600; // baudrate
1.245 + caps.iDataBits=KCapsData8; // data size
1.246 + caps.iFifo=KCapsHasFifo; // fifo enabled
1.247 + caps.iBreakSupported=EFalse;// no braek support
1.248 +
1.249 + // [TDes8::MaxLength()] - Get the descriptor's length.
1.250 + TInt len = aCaps.MaxLength();
1.251 +
1.252 + // [TDes8::FillZ(len)] -Fill the descriptor's data area with binary
1.253 + // zeroes, replacing any existing data and change its length.
1.254 + aCaps.FillZ(len);
1.255 +
1.256 + TInt size = sizeof(caps);
1.257 + if (size>len)
1.258 + size=len;
1.259 +
1.260 + // [TDes8::Copy()] - Copy the data of length (size) into aDes descriptor
1.261 + // replacing any existing data in the descriptor.
1.262 + aCaps.Copy((TUint8*)&caps, size);
1.263 +
1.264 + aCaps=capsBuf.Left(Min(capsBuf.Length(),aCaps.MaxLength()));
1.265 + }
1.266 +
1.267 +/**
1.268 + Configure the hardware device (Uart). This is device specific API, that
1.269 + provides functionality to configure the uart. Uart configuration settings are
1.270 + passed to this function by user. User calls this by using
1.271 + RBusLogicalChannel::DoControl() to LDD and ldd inturn calls this PDD function
1.272 + to do the actual operation on the device.
1.273 +
1.274 + @param aConfig
1.275 + configuration settings for the device
1.276 +
1.277 + @return KErrNone or standard error code
1.278 + */
1.279 +TInt DExUartPhysicalChannelEmul::Configure(const TCommConfigV01& aConfig)
1.280 + {
1.281 +
1.282 + // if channel is already configured to same baud rate, then no need to
1.283 + // repeat the configuration
1.284 + //
1.285 + if (iConfigured!=EFalse)
1.286 + {
1.287 + if(iBaudRate==aConfig.iRate)
1.288 + return KErrNone;
1.289 + }
1.290 +
1.291 + iBaudRate = aConfig.iRate;
1.292 +
1.293 + // variables used with the com port
1.294 + BOOL bPortReady;
1.295 + DCB dcb;
1.296 + COMMTIMEOUTS commTimeouts;
1.297 +
1.298 + bPortReady = TRUE; // everything is OK so far
1.299 +
1.300 + // Open a serial port device using the CreateFile() function by specifying
1.301 + // a filename that refers to the specific port, such as COM1 or COM2.
1.302 + //
1.303 + // When you open a serial port, it is opened automatically for exclusive access,
1.304 + // so you should pass a zero for the CreateFile()'s third parameter and OPEN_EXISTING
1.305 + // for the open mode (fifth parameter). You can add a combination of the special file
1.306 + // mode flags to indicate overlapped I/O or any special buffering requirements, as normal.
1.307 + //
1.308 + // If the serial port opens successfully, a Win32 file object handle is returned.
1.309 + // Otherwise, INVALID_HANDLE_VALUE is returned.
1.310 + //
1.311 + hCommPort=CreateFileA((LPCSTR)"\\\\.\\com1",GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,NULL);
1.312 +
1.313 + if (hCommPort==INVALID_HANDLE_VALUE)
1.314 + {
1.315 + Kern::Printf("Emulator::Configure: FAILED");
1.316 +
1.317 + bPortReady = FALSE;
1.318 +
1.319 + DWORD winErr=GetLastError();
1.320 + switch (winErr)
1.321 + {
1.322 + case ERROR_INVALID_USER_BUFFER:
1.323 + case ERROR_NOT_ENOUGH_MEMORY:
1.324 + case ERROR_INSUFFICIENT_BUFFER:
1.325 + return(KErrNoMemory);
1.326 + case ERROR_ACCESS_DENIED:
1.327 + return(KErrAccessDenied);
1.328 + case ERROR_FILE_NOT_FOUND: // Reflects value returned by
1.329 + return(KErrNotSupported); // corresponding MARM Pdd
1.330 + case ERROR_NOT_SUPPORTED:
1.331 + return(KErrNotSupported);
1.332 + default:
1.333 + return(KErrGeneral);
1.334 + }
1.335 + }
1.336 +
1.337 + if (bPortReady)
1.338 + {
1.339 + bPortReady = SetupComm(hCommPort, 256, 256); // set buffer sizes
1.340 + if (!bPortReady)
1.341 + {
1.342 + return(KErrNoMemory);
1.343 + }
1.344 + }
1.345 +
1.346 +
1.347 + // After you open a serial port, you must set the many flags required to configure
1.348 + // the device. These flags are held in a device control block (DCB) structure.
1.349 + // You can either fill in the entire DCB structure or use one of the helper functions
1.350 + // to fill in some of the details. The GetCommState() function fills in a DCB structure
1.351 + // with the current settings from the hardware, and you can use a corresponding
1.352 + // SetCommState() function to specify the new settings from a DCB structure.
1.353 + //
1.354 + if (bPortReady)
1.355 + {
1.356 + bPortReady = GetCommState(hCommPort, &dcb);
1.357 + if (!bPortReady)
1.358 + {
1.359 + return(KErrGeneral);
1.360 + }
1.361 + }
1.362 +
1.363 + if (bPortReady)
1.364 + {
1.365 + //baud rate
1.366 + switch (aConfig.iRate)
1.367 + {
1.368 + case EBps9600:
1.369 + dcb.BaudRate=9600;
1.370 + break;
1.371 + case EBps38400:
1.372 + dcb.BaudRate=38400;
1.373 + break;
1.374 + case EBps115200:
1.375 + dcb.BaudRate=115200;
1.376 + break;
1.377 + default:
1.378 + dcb.BaudRate=9600;
1.379 + break;
1.380 + }
1.381 +
1.382 + //data bits
1.383 + switch(aConfig.iDataBits)
1.384 + {
1.385 + case EData7:
1.386 + dcb.ByteSize=7;
1.387 + break;
1.388 + case EData8:
1.389 + dcb.ByteSize=8;
1.390 + break;
1.391 + default:
1.392 + dcb.ByteSize=8;
1.393 + break;
1.394 + }
1.395 +
1.396 + //stop bits
1.397 + switch(aConfig.iStopBits)
1.398 + {
1.399 + case EStop1:
1.400 + dcb.StopBits=ONESTOPBIT;
1.401 + break;
1.402 + case EStop2:
1.403 + dcb.StopBits=TWOSTOPBITS;
1.404 + break;
1.405 + default:
1.406 + dcb.StopBits = ONESTOPBIT;
1.407 + break;
1.408 + }
1.409 +
1.410 + dcb.Parity = NOPARITY;
1.411 +
1.412 + bPortReady = SetCommState(hCommPort, &dcb);
1.413 + if (!bPortReady)
1.414 + {
1.415 + return(KErrGeneral);
1.416 + }
1.417 + }
1.418 +
1.419 + if (bPortReady)
1.420 + {
1.421 + // You can find the current timeout settings using the GetCommTimeout()
1.422 + // function, which fills a passed COMMTIMEOUTS structure.
1.423 + //
1.424 + bPortReady = GetCommTimeouts (hCommPort, &commTimeouts);
1.425 + if (bPortReady)
1.426 + {
1.427 + // You can set ReadIntervalTimeout to MAXDWORD and set the
1.428 + // ReadTotalTimeoutMultiplier and ReadTotalTimeoutConstant members
1.429 + // to zero to indicate that the ReadFile() should return immediately.
1.430 + //
1.431 + commTimeouts.ReadIntervalTimeout = MAXDWORD;
1.432 + commTimeouts.ReadTotalTimeoutConstant = 0;
1.433 + commTimeouts.ReadTotalTimeoutMultiplier = 0;
1.434 + }
1.435 + else
1.436 + {
1.437 + return(KErrGeneral);
1.438 + }
1.439 + if(!SetCommTimeouts(hCommPort, &commTimeouts))
1.440 + return(KErrGeneral);
1.441 +
1.442 + }
1.443 + return KErrNone;
1.444 + }
1.445 +
1.446 +// After configuring the serial port, you can start transferring data via ReadFile()
1.447 +// and WriteFile() functions. However, you should remember that if you haven't specified
1.448 +// the FILE_FLAG_OVERLAPPED flag in the CreateFile() flags parameter,
1.449 +// ReadFile() will block waiting for input. This probably is good if your program spawns
1.450 +// another thread that specifically waits for incoming serial port characters, but not
1.451 +// if you want to issue a ReadFile() and periodically check to see whether any characters
1.452 +// have arrived.
1.453 +//
1.454 +
1.455 +/**
1.456 + Transmit data over uart for emulator targte, i.e serial port for pc
1.457 + Transmit data buffer is filled and passed by user to the driver
1.458 +
1.459 + @param aData
1.460 + buffer for transmit data
1.461 +
1.462 + @return KErrNone or standard error code
1.463 + */
1.464 +TInt DExUartPhysicalChannelEmul::TransmitData(const TDesC8& aData)
1.465 + {
1.466 + TInt r;
1.467 + TInt count;
1.468 + TInt size;
1.469 + TInt offset=0;
1.470 +
1.471 + // if the device is not configured, try to configure the device again
1.472 + if (iConfigured==EFalse)
1.473 + {
1.474 + // Configure the channel by default
1.475 + TCommConfigV01 cfg;
1.476 + cfg.iRate = EBps9600; // 9600 baudrate
1.477 + r = Configure(cfg);
1.478 + if (r!=KErrNone)
1.479 + {
1.480 + // configure failed again, abort the request
1.481 + iConfigured=EFalse;
1.482 + return KErrAbort;
1.483 + }
1.484 + // configured successfully, continue with Tx
1.485 + iConfigured=ETrue;
1.486 + }
1.487 +
1.488 + // Size of the data to be transmitted is obtained from the descriptor.
1.489 + // TDesC8::Size() gets the size of the data interms of number of bytes occupied
1.490 + // by the data represented by the descriptor
1.491 + //
1.492 + count= aData.Size();
1.493 + if (count<=0)
1.494 + return KErrAbort;
1.495 +
1.496 + // Loop till all the data sent from LDD is transmitted in blocks of KTxFifoSize
1.497 + while (count>0)
1.498 + {
1.499 + // Each block size can be max KTxFifoSize or less
1.500 + size=(count<KTxFifoSize)?count:KTxFifoSize;
1.501 +
1.502 + BOOL bWriteRC;
1.503 + DWORD iBytesWritten;
1.504 +
1.505 + iBytesWritten = 0;
1.506 + bWriteRC = WriteFile(hCommPort, aData.Ptr(), size, &iBytesWritten, NULL);
1.507 +
1.508 + if (!bWriteRC || iBytesWritten == 0)
1.509 + {
1.510 + return(KErrGeneral);
1.511 + }
1.512 +
1.513 + // calculate the offset
1.514 + offset+=iBytesWritten;
1.515 + // calculate the remaining buffer size
1.516 + count-=iBytesWritten;
1.517 + }
1.518 +
1.519 + return KErrNone;
1.520 + }
1.521 +
1.522 +/**
1.523 + Receive data over uart for emulator target, i.e uart of pc
1.524 + Receive data buffer is filled and passed by driver to the user
1.525 +
1.526 + @param aData
1.527 + buffer for received data
1.528 +
1.529 + @return KErrNone or standard error code
1.530 + */
1.531 +TInt DExUartPhysicalChannelEmul::ReceiveData(TDes8& aData,TInt aLen)
1.532 + {
1.533 + TInt ret;
1.534 + TInt size;
1.535 + TInt count;
1.536 + TInt bytesRcvd=0;
1.537 +
1.538 + // Size of the data to be transmitted is obtained from the descriptor.
1.539 + // TDesC8::Size() gets the size of the data interms of number of bytes occupied
1.540 + // by the data represented by the descriptor
1.541 + //
1.542 + size= aLen;
1.543 + if (size<=0)
1.544 + return KErrAbort; // Zero length request, exit and fail
1.545 +
1.546 + // Keep track of the requested size
1.547 + count=size;
1.548 +
1.549 + // Loop till the requested amount of data from LDD is filled or a timeout
1.550 + while (count>0)
1.551 + {
1.552 + BOOL bReadRC;
1.553 + char sBuffer[256];
1.554 +
1.555 + memset(sBuffer,0,sizeof(sBuffer));
1.556 + // if no data and timer expired
1.557 + while ((bReadRC=ReadFile(hCommPort, sBuffer, sizeof(sBuffer), &iBytesRead, NULL)) == 0
1.558 + || (iBytesRead==0))
1.559 + {
1.560 + if (iTimerStatus==KTimerExpired)
1.561 + {
1.562 + aData.SetLength(bytesRcvd);
1.563 + return KErrTimedOut;
1.564 + }
1.565 + }
1.566 +
1.567 + if (iTimerStatus==KTimerStarted)
1.568 + {
1.569 + // Cancel the Rx poll timer. NTimer.Cancel() Cancel a nanokernel
1.570 + // timer. Removes this timer from the nanokernel timer queue.
1.571 + // Does nothing if the timer is inactive or has already expired.
1.572 + // If the timer was queued and DFC callback requested it is possible
1.573 + // for the expiry handler to run even after Cancel() has been called.
1.574 + //
1.575 + iRxPollTimer.Cancel();
1.576 + // Update status as Cancelled
1.577 + iTimerStatus=KTimerCancelled;
1.578 + }
1.579 +
1.580 + if (bReadRC && (iBytesRead>0))
1.581 + {
1.582 + if (iBytesRead>=static_cast<TUint>(size))
1.583 + iBytesRead=size;
1.584 + aData.Append(TPtrC8((const TText8*)sBuffer,iBytesRead));
1.585 + bytesRcvd+=iBytesRead;
1.586 + iBytesRead=0;
1.587 + }
1.588 + else
1.589 + {
1.590 + iTimerStatus = KTimerStarted;
1.591 + // Start a nanokernel timer in one-shot mode with ISR callback
1.592 + // Queues the timer to expire in the specified number of nanokernel
1.593 + // ticks. The actual wait time will be at least that much and
1.594 + // may be up to one tick more. The expiry handler will be called in
1.595 + // ISR context.
1.596 + //
1.597 + ret=iRxPollTimer.OneShot(KRxPollTimeout);
1.598 + if(ret!=KErrNone) // timer creation failed
1.599 + return ret;
1.600 + }
1.601 +
1.602 + // If we have received the requested number of bytes, return
1.603 + if (bytesRcvd>=size)
1.604 + {
1.605 + if (iTimerStatus == KTimerStarted)
1.606 + iRxPollTimer.Cancel();
1.607 + return KErrNone;
1.608 + }
1.609 +
1.610 + // remaining bytes to be received
1.611 + count -= bytesRcvd;
1.612 + }
1.613 +
1.614 + return KErrNone;
1.615 + }
1.616 +
1.617 +void DExUartPhysicalChannelEmul::RxPollTimerCallback(TAny* aPtr)
1.618 + {
1.619 + KEXDEBUG(Kern::Printf("EMUL UART::Rx Timer Expired, Data Flow Stopped"));
1.620 + ((DExUartPhysicalChannelEmul*)aPtr)->iTimerStatus=KTimerExpired;
1.621 + }
1.622 +
1.623 +//
1.624 +// End of d_expio_emul.cpp