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