os/ossrv/genericopenlibs/cstdlib/USTLIB/USERIAL.CPP
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/ossrv/genericopenlibs/cstdlib/USTLIB/USERIAL.CPP	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,869 @@
     1.4 +// Copyright (c) 1997-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 +// Implementation of STDLIB serialports.
    1.18 +// 
    1.19 +//
    1.20 +
    1.21 +#include "FDESC.H"
    1.22 +#include <sys/types.h>
    1.23 +#include <string.h>		// for memcpy
    1.24 +#include <sys/errno.h>		// for ENOTSOCK
    1.25 +#include <sys/socket.h>
    1.26 +#include <sys/ioctl.h>
    1.27 +#include <sys/serial.h>
    1.28 +#include <c32comm.h>
    1.29 +
    1.30 +
    1.31 +//define this to allow the code to be built for ER5U without most of the notifications
    1.32 +//leave commented for all notifications
    1.33 +//#define ER5U_NOTIFICATION_SUPPORT_ONLY
    1.34 +#ifdef _DEBUG
    1.35 +_LIT(KCSerialDescPanic, "CSerialDesc");
    1.36 +#endif
    1.37 +
    1.38 +//
    1.39 +//
    1.40 +// -----> CSerialTimer (implementation)
    1.41 +//
    1.42 +//
    1.43 +CSerialTimer::CSerialTimer()
    1.44 +	: CTimer(CActive::EPriorityHigh)
    1.45 +	  // Construct standard-priority active object
    1.46 +	{};
    1.47 +
    1.48 +CSerialTimer* CSerialTimer::NewLC(CFileDescBase* aFile)
    1.49 +	{
    1.50 +	CSerialTimer* self=new (ELeave) CSerialTimer;
    1.51 +	CleanupStack::PushL(self);
    1.52 +	self->ConstructL(aFile);
    1.53 +	return self;
    1.54 +	}
    1.55 +
    1.56 +CSerialTimer* CSerialTimer::NewL(CFileDescBase* aFile)
    1.57 +	{
    1.58 +	CSerialTimer* self = NewLC(aFile);
    1.59 +	CleanupStack::Pop();
    1.60 +	return self;
    1.61 +	}
    1.62 +
    1.63 +void CSerialTimer::ConstructL(CFileDescBase* aFile)
    1.64 +	{
    1.65 +	  // Base class second-phase construction.
    1.66 +	CTimer::ConstructL();
    1.67 +	iFile = aFile;
    1.68 +	  // Add active object to active scheduler
    1.69 +	CActiveScheduler::Add(this); 
    1.70 +	}
    1.71 +
    1.72 +
    1.73 +CSerialTimer::~CSerialTimer()
    1.74 +	{
    1.75 +	  // Make sure we're cancelled
    1.76 +	Cancel();
    1.77 +	}
    1.78 +
    1.79 +void CSerialTimer::DoCancel()
    1.80 +	{
    1.81 +	  // Base class
    1.82 +	CTimer::DoCancel(); 
    1.83 +	}
    1.84 +
    1.85 +void CSerialTimer::IssueRequest()
    1.86 +	{
    1.87 +	  // There should never be an outstanding request at this point.
    1.88 +	__ASSERT_DEBUG(!IsActive(),User::Panic(KCSerialDescPanic,1));
    1.89 +
    1.90 +	  // Request
    1.91 +	CTimer::After(iFile->TimeoutValue()*1000);
    1.92 +	}
    1.93 +
    1.94 +void CSerialTimer::RunL()
    1.95 +	{
    1.96 +		//the timer has gone off.
    1.97 +	iFile->ReadCancel();
    1.98 +	iFile->TimedMessage = NULL;
    1.99 +	iFile->ReadIsTimed = EFalse;
   1.100 +	iFile->ReadWasCancelled = ETrue;
   1.101 +	delete this;
   1.102 +	}
   1.103 +
   1.104 +
   1.105 +
   1.106 +/****/
   1.107 +NONSHARABLE_CLASS(CNotifier) : public CActive
   1.108 +	{
   1.109 +	public:
   1.110 +		CNotifier();
   1.111 +		~CNotifier();
   1.112 +		void IssueRequest(TInt aRequest, TInt* aRequestParams=NULL);
   1.113 +		static CNotifier* NewLC(CSerialDesc* aPort);
   1.114 +		static CNotifier* NewL(CSerialDesc* aPort);
   1.115 +		void Construct(CSerialDesc* aPort);
   1.116 +		void Complete(TInt aVal);
   1.117 +
   1.118 +	private:
   1.119 +		enum RequestTypes {None, DataAvailable, OutputEmpty, Break, Signals, WriteErrors};
   1.120 +		void DoCancel();
   1.121 +		void RunL();
   1.122 +		CSerialDesc * iSerialPort;
   1.123 +		enum RequestTypes iRequest;
   1.124 +		TUint iRequestData;
   1.125 +		TInt* iRequestParams;
   1.126 +
   1.127 +} ;
   1.128 +
   1.129 +CNotifier::CNotifier() : CActive(CActive::EPriorityStandard), iRequest(None), iRequestData(0), iRequestParams(NULL)
   1.130 +	{
   1.131 +	}
   1.132 +
   1.133 +
   1.134 +void CNotifier::IssueRequest(TInt aRequest, TInt* aRequestParams)
   1.135 +	{
   1.136 +	iRequestParams = aRequestParams;
   1.137 +	
   1.138 +#ifndef ER5U_NOTIFICATION_SUPPORT_ONLY
   1.139 +	if (KNotifyDataAvailable == aRequest)
   1.140 +		{
   1.141 +		iRequest = DataAvailable;
   1.142 +		iSerialPort->NotifyDataAvailable(iStatus);
   1.143 +		}
   1.144 +
   1.145 +	else if (KNotifyOutputEmpty == aRequest)
   1.146 +		{
   1.147 +		iRequest = OutputEmpty;
   1.148 +		iSerialPort->NotifyOutputEmpty(iStatus);
   1.149 +		}
   1.150 +	
   1.151 +	else if (KNotifyBreakInt == aRequest)
   1.152 +		{
   1.153 +		iRequest = Break;
   1.154 +		iSerialPort->NotifyBreak(iStatus);
   1.155 +		}
   1.156 +	
   1.157 +	else if (aRequest & (KNotifyCD|KNotifyCTS|KNotifyDSR|KNotifyRI))	//signals
   1.158 +		{
   1.159 +		TUint signalsRequested = 0;
   1.160 +
   1.161 +		//build up the mask of signals to request
   1.162 +		if (aRequest & KNotifyCD) signalsRequested |=  KSignalDCD;
   1.163 +		if (aRequest & KNotifyCTS) signalsRequested |=  KSignalCTS;
   1.164 +		if (aRequest & KNotifyDSR) signalsRequested |=  KSignalDSR;
   1.165 +		if (aRequest & KNotifyRI) signalsRequested |=  KSignalRNG;
   1.166 +		iRequest = Signals;
   1.167 +		iSerialPort->NotifySignalChange(iStatus, iRequestData, signalsRequested);
   1.168 +		}
   1.169 +	
   1.170 +	else 
   1.171 +#endif	//ER5U_NOTIFICATION_SUPPORT_ONLY
   1.172 +		if (aRequest & (KNotifyFramingError|KNotifyOverrunError|KNotifyParityError))
   1.173 +		{
   1.174 +		iRequest = WriteErrors;
   1.175 +		iSerialPort->NotifyWriteErrors(iStatus, &iRequestData, aRequest);
   1.176 +		}
   1.177 +		
   1.178 +	SetActive();
   1.179 +	}
   1.180 +
   1.181 +void CNotifier::RunL()
   1.182 +	{
   1.183 +	//now what!
   1.184 +	//cancel all the others
   1.185 +	//use iRequest to determine what we are doing here
   1.186 +
   1.187 +	CNotifier** ppn = NULL;
   1.188 +	switch (iRequest)
   1.189 +		{
   1.190 +#ifndef ER5U_NOTIFICATION_SUPPORT_ONLY
   1.191 +
   1.192 +		case DataAvailable:
   1.193 +			iSerialPort->iNotifyParamPtr[0] = KNotifyDataAvailable;
   1.194 +			ppn = &iSerialPort->iDataAvailableNotifier;
   1.195 +			break;
   1.196 +
   1.197 +		case OutputEmpty:
   1.198 +			iSerialPort->iNotifyParamPtr[0] = KNotifyOutputEmpty;
   1.199 +			ppn = &iSerialPort->iOutputEmptyNotifier;
   1.200 +			break;
   1.201 +
   1.202 +		case Break:
   1.203 +			iSerialPort->iNotifyParamPtr[0] = KNotifyBreakInt;
   1.204 +			ppn = &iSerialPort->iBreakNotifier;
   1.205 +			break;
   1.206 +
   1.207 +		case Signals:
   1.208 +			{
   1.209 +			ppn = &iSerialPort->iSignalsNotifier;
   1.210 +			iSerialPort->iNotifyParamPtr[0] = 0;
   1.211 +			iSerialPort->iNotifyParamPtr[1] = 0;
   1.212 +			if (iRequestData & KDCDChanged)
   1.213 +				{
   1.214 +				iSerialPort->iNotifyParamPtr[0] |=  KNotifyCD;
   1.215 +				iSerialPort->iNotifyParamPtr[1] |=  (iRequestData & KSignalDCD);
   1.216 +				}
   1.217 +
   1.218 +			if (iRequestData & KCTSChanged)
   1.219 +				{
   1.220 +				iSerialPort->iNotifyParamPtr[0] |=  KNotifyCTS;
   1.221 +				iSerialPort->iNotifyParamPtr[1] |=  (iRequestData & KSignalCTS);
   1.222 +				}
   1.223 +
   1.224 +			if (iRequestData & KDSRChanged)
   1.225 +				{
   1.226 +				iSerialPort->iNotifyParamPtr[0] |=  KNotifyDSR;
   1.227 +				iSerialPort->iNotifyParamPtr[1] |=  (iRequestData & KSignalDSR);
   1.228 +				}
   1.229 +
   1.230 +			if (iRequestData & KRNGChanged)
   1.231 +				{
   1.232 +				iSerialPort->iNotifyParamPtr[0] |=  KNotifyRI;
   1.233 +				iSerialPort->iNotifyParamPtr[1] |=  (iRequestData & KSignalRNG);
   1.234 +				}
   1.235 +
   1.236 +			}
   1.237 +			break;
   1.238 +#endif //ER5U_NOTIFICATION_SUPPORT_ONLY
   1.239 +		case WriteErrors:
   1.240 +			{
   1.241 +			iSerialPort->iNotifyParamPtr[0] = iRequestData;
   1.242 +			iSerialPort->iNotifyParamPtr[1] = 0;
   1.243 +			ppn = &iSerialPort->iErrorsNotifier;
   1.244 +			}
   1.245 +			break;
   1.246 +
   1.247 +		default:
   1.248 +			__ASSERT_DEBUG(EFalse, User::Panic(KCSerialDescPanic, 1));
   1.249 +			break;
   1.250 +		}
   1.251 +
   1.252 +	//cancel all the others
   1.253 +	iSerialPort->CancelNotifiers(this);	//telling it who we are.
   1.254 +
   1.255 +	//and complete the outstanding user request
   1.256 +	User::RequestComplete(iSerialPort->iNotifyStatus, iStatus.Int());
   1.257 +	delete this;
   1.258 +	if (ppn) *ppn = NULL;
   1.259 +	}
   1.260 +
   1.261 +void CNotifier::DoCancel()
   1.262 +	{
   1.263 +	switch (iRequest)
   1.264 +		{
   1.265 +#ifndef ER5U_NOTIFICATION_SUPPORT_ONLY
   1.266 +
   1.267 +		case DataAvailable:
   1.268 +			iSerialPort->NotifyDataAvailableCancel();
   1.269 +			break;
   1.270 +
   1.271 +		case OutputEmpty:
   1.272 +			iSerialPort->NotifyOutputEmptyCancel();
   1.273 +			break;
   1.274 +
   1.275 +		case Break:
   1.276 +			iSerialPort->NotifyBreakCancel();
   1.277 +			break;
   1.278 +
   1.279 +		case Signals:
   1.280 +			iSerialPort->NotifySignalChangeCancel();
   1.281 +			break;
   1.282 +#endif //ER5U_NOTIFICATION_SUPPORT_ONLY
   1.283 +		case WriteErrors:
   1.284 +			iSerialPort->NotifyWriteErrorsCancel();
   1.285 +			break;
   1.286 +
   1.287 +		default:
   1.288 +			break;
   1.289 +		}
   1.290 +
   1.291 +
   1.292 +	}
   1.293 +
   1.294 +
   1.295 +void CNotifier::Complete(TInt aVal)
   1.296 +	{
   1.297 +	TRequestStatus* ps = &iStatus;
   1.298 +	User::RequestComplete(ps, aVal);
   1.299 +	}
   1.300 +
   1.301 +
   1.302 +CNotifier* CNotifier::NewLC(CSerialDesc* aPort)
   1.303 +	{
   1.304 +	CNotifier* self=new (ELeave) CNotifier;
   1.305 +	CleanupStack::PushL(self);
   1.306 +	self->Construct(aPort);
   1.307 +	return self;
   1.308 +	}
   1.309 +
   1.310 +CNotifier* CNotifier::NewL(CSerialDesc* aPort)
   1.311 +	{
   1.312 +	CNotifier* self = NewLC(aPort);
   1.313 +	CleanupStack::Pop();
   1.314 +	return self;
   1.315 +	}
   1.316 +
   1.317 +void CNotifier::Construct(CSerialDesc* aPort)
   1.318 +	{
   1.319 +	iSerialPort = aPort;
   1.320 +	CActiveScheduler::Add(this) ;  // add to active scheduler
   1.321 +	}
   1.322 +
   1.323 +CNotifier::~CNotifier()
   1.324 +	{
   1.325 +	Cancel();
   1.326 +	}
   1.327 +
   1.328 +
   1.329 +/****/
   1.330 +
   1.331 +
   1.332 +
   1.333 +// The Serial descriptor class
   1.334 +
   1.335 +TInt CSerialDesc::Open(RCommServ& aSession, const wchar_t* name, int mode, int /*perms*/)
   1.336 +	{
   1.337 +	//the name will be a wide version of COM?: or IRCOM?: where ? is a number 1 to 9.
   1.338 +	//this has already been checked in the call to CFileDescBase open.
   1.339 +
   1.340 +	
   1.341 +	
   1.342 +	TInt err = KErrArgument;
   1.343 +	if (L'C' == name[0])
   1.344 +		{
   1.345 +		//serial port
   1.346 +		//load the comms module we require
   1.347 +		err = aSession.LoadCommModule(_L("ECUART"));
   1.348 +		if (KErrAlreadyExists != err && KErrNone != err)	//problem
   1.349 +			return err;
   1.350 +		//convert the name into an epoc port name
   1.351 +		//eg COMM::0
   1.352 +		TBuf<7> epocName(_L("COMM::0"));
   1.353 +		epocName[6] = (TText)(name[3] - 1);
   1.354 +
   1.355 +		//try opening as a dte or a dce
   1.356 +		err = iCommPort.Open(aSession, epocName, (enum TCommAccess)mode, ECommRoleDTE);
   1.357 +		if (err) 			
   1.358 +			err = iCommPort.Open(aSession, epocName, (enum TCommAccess)mode, ECommRoleDCE);
   1.359 +		}
   1.360 +	else
   1.361 +		{
   1.362 +		//IR port
   1.363 +		err = aSession.LoadCommModule(_L("IrCOMM"));
   1.364 +		if (KErrAlreadyExists != err && KErrNone != err)	//problem
   1.365 +			return err;
   1.366 +		//convert the name into an epoc port name
   1.367 +		//eg COMM::0
   1.368 +		TBuf<9> epocName(_L("IrCOMM::0"));
   1.369 +		epocName[8] = (TText)(name[5] - 1);
   1.370 +
   1.371 +		//try opening as a dte or a dce
   1.372 +		err = iCommPort.Open(aSession, epocName, (enum TCommAccess)mode, ECommRoleDTE);
   1.373 +		if (err) 			
   1.374 +			err = iCommPort.Open(aSession, epocName, (enum TCommAccess)mode, ECommRoleDCE);
   1.375 +		}
   1.376 +	return err;
   1.377 +	}
   1.378 +
   1.379 +void CSerialDesc::UserClose()
   1.380 +	{
   1.381 +	IoctlCancel();
   1.382 +	}
   1.383 +
   1.384 +TInt CSerialDesc::FinalClose()
   1.385 +	{
   1.386 +	iCommPort.Close();
   1.387 +	return 0;
   1.388 +	}
   1.389 +
   1.390 +
   1.391 +
   1.392 +
   1.393 +TBool CSerialDesc::TimedRead()
   1.394 +	{
   1.395 +		//if we have a timeout without a threshold we need an external timer
   1.396 +		return (-1 != iReadTimeout && -1 == iReadThreshold);
   1.397 +	}
   1.398 +
   1.399 +
   1.400 +void CSerialDesc::Read(TDes8& aBuf, TRequestStatus& aStatus)
   1.401 +	{
   1.402 +	//do a read..
   1.403 +	//4 different ones
   1.404 +	if (-1 == iReadThreshold)
   1.405 +		{
   1.406 +		iCommPort.ReadOneOrMore(aStatus, aBuf);
   1.407 +		}
   1.408 +	else
   1.409 +		{
   1.410 +		TInt len = (iReadThreshold < aBuf.MaxLength() ? iReadThreshold : aBuf.MaxLength());
   1.411 +		if (-1 == iReadTimeout)
   1.412 +			{
   1.413 +			//read threshold with no timeout
   1.414 +			iCommPort.Read(aStatus, aBuf, len);
   1.415 +			}
   1.416 +		else
   1.417 +			{
   1.418 +			//read threshold and timeout
   1.419 +			TTimeIntervalMicroSeconds32 timeout(iReadTimeout*1000);
   1.420 +			iCommPort.Read(aStatus, timeout, aBuf, len);
   1.421 +			}
   1.422 +		}
   1.423 +
   1.424 +	}
   1.425 +
   1.426 +
   1.427 +void CSerialDesc::Write (TDes8& aBuf, TRequestStatus& aStatus)
   1.428 +	{
   1.429 +	iCommPort.Write(aStatus, aBuf);
   1.430 +	}
   1.431 +
   1.432 +
   1.433 +void CSerialDesc::Ioctl(int aCmd, void* aParam, TRequestStatus& aStatus)
   1.434 +	{
   1.435 +	TInt ret=KErrNone;
   1.436 +	if (aParam)
   1.437 +		{
   1.438 +		
   1.439 +		aCmd &= ~0x4000;	//mask off the queue bit!
   1.440 +
   1.441 +		switch (aCmd)
   1.442 +			{
   1.443 +			case COMMIOCTL_SETSIGNALS:
   1.444 +				{
   1.445 +				int* param =REINTERPRET_CAST(int*,aParam);
   1.446 +				TUint setMask = (TUint)param[0];
   1.447 +				TUint clearMask = (TUint)param[1];
   1.448 +				iCommPort.SetSignals(setMask, clearMask);
   1.449 +				}
   1.450 +				break;
   1.451 +
   1.452 +			case COMMIOCTL_GETSIGNALS:
   1.453 +				{
   1.454 +				int* param =REINTERPRET_CAST(int*,aParam);
   1.455 +				TUint signals = iCommPort.Signals();
   1.456 +				*param = (int)signals;
   1.457 +				}
   1.458 +				break;
   1.459 +
   1.460 +			case COMMIOCTL_SETCONFIG:	
   1.461 +				{
   1.462 +				SerialConfig * param =REINTERPRET_CAST(SerialConfig *,aParam);
   1.463 +				TCommConfig cfg;
   1.464 +
   1.465 +				TCommConfigV01& cfg01 =cfg();
   1.466 +				
   1.467 +				cfg01.iRate = (enum TBps)param->iRate; 
   1.468 +				cfg01.iDataBits = (enum TDataBits)param->iDataBits;
   1.469 +				cfg01.iStopBits = (enum TStopBits)param->iStopBits; 
   1.470 +				cfg01.iParity = (enum TParity)param->iParity; 
   1.471 +				cfg01.iHandshake = param->iHandshake;
   1.472 +				cfg01.iParityError = param->iParityError;
   1.473 +				cfg01.iFifo = param->iFifo;
   1.474 +				cfg01.iSpecialRate = param->iSpecialRate;
   1.475 +				cfg01.iTerminatorCount = param->iTerminatorCount;
   1.476 +				cfg01.iXonChar = param->iXonChar; 
   1.477 +				cfg01.iXoffChar = param->iXoffChar; 
   1.478 +				cfg01.iParityErrorChar = param->iParityErrorChar; 
   1.479 +				cfg01.iSIREnable = (enum TSir)param->iSIREnable; 
   1.480 +				cfg01.iSIRSettings = param->iSIRSettings;
   1.481 +
   1.482 +				for (int i =0; i < ConfigMaxTerminators; i++)
   1.483 +					cfg01.iTerminator[i] = param->iTerminator[i];
   1.484 +
   1.485 +				iCommPort.SetConfig(cfg);
   1.486 +				}
   1.487 +				break;
   1.488 +
   1.489 +			case COMMIOCTL_GETCONFIG:	
   1.490 +				{
   1.491 +				SerialConfig * param =REINTERPRET_CAST(SerialConfig *,aParam);
   1.492 +				TCommConfig cfg;
   1.493 +				iCommPort.Config(cfg);
   1.494 +				TCommConfigV01& cfg01 =cfg();
   1.495 +				
   1.496 +				param->iRate = (enum Bps)cfg01.iRate;
   1.497 +				param->iDataBits = (enum DataBits)cfg01.iDataBits;
   1.498 +				param->iStopBits = (enum StopBits)cfg01.iStopBits;
   1.499 +				param->iParity = (enum Parity)cfg01.iParity;
   1.500 +				param->iHandshake = cfg01.iHandshake;
   1.501 +				param->iParityError = cfg01.iParityError;
   1.502 +				param->iFifo = cfg01.iFifo;
   1.503 +				param->iSpecialRate = cfg01.iSpecialRate;
   1.504 +				param->iTerminatorCount = cfg01.iTerminatorCount;
   1.505 +				for (int i =0; i < ConfigMaxTerminators; i++)
   1.506 +					param->iTerminator[i] = cfg01.iTerminator[i];
   1.507 +				param->iXonChar = cfg01.iXonChar;
   1.508 +				param->iXoffChar = cfg01.iXoffChar;
   1.509 +				param->iParityErrorChar = cfg01.iParityErrorChar;
   1.510 +				param->iSIREnable = (enum Sir)cfg01.iSIREnable;
   1.511 +				param->iSIRSettings = cfg01.iSIRSettings;
   1.512 +				}
   1.513 +				break;
   1.514 +
   1.515 +			case COMMIOCTL_BREAK:	
   1.516 +				{
   1.517 +				int* param =REINTERPRET_CAST(int*,aParam);
   1.518 +				TTimeIntervalMicroSeconds32 time(*param);
   1.519 +				iCommPort.Break(aStatus, time);
   1.520 +				return;
   1.521 +				}
   1.522 +
   1.523 +			case COMMIOCTL_SETREADTIMEOUT:
   1.524 +				{
   1.525 +				int* param =REINTERPRET_CAST(int*,aParam);
   1.526 +				iReadTimeout = *param;
   1.527 +				}
   1.528 +				break;
   1.529 +
   1.530 +			case COMMIOCTL_GETREADTIMEOUT:
   1.531 +				{
   1.532 +				int* param =REINTERPRET_CAST(int*,aParam);
   1.533 +				*param = iReadTimeout;
   1.534 +				}
   1.535 +				break;
   1.536 +
   1.537 +			case COMMIOCTL_SETREADTHRESHOLD:
   1.538 +				{
   1.539 +				int* param =REINTERPRET_CAST(int*,aParam);
   1.540 +				iReadThreshold = *param;
   1.541 +				}
   1.542 +				break;
   1.543 +
   1.544 +			case COMMIOCTL_GETREADTHRESHOLD:
   1.545 +				{
   1.546 +				int* param =REINTERPRET_CAST(int*,aParam);
   1.547 +				*param = iReadThreshold;
   1.548 +				}
   1.549 +				break;
   1.550 +
   1.551 +			case COMMIOCTL_SETBUFFERLENGTH:
   1.552 +				{
   1.553 +				int* param =REINTERPRET_CAST(int*,aParam);
   1.554 +				iCommPort.SetReceiveBufferLength(TInt(*param));
   1.555 +				}
   1.556 +				break;
   1.557 +
   1.558 +			case COMMIOCTL_GETBUFFERLENGTH:
   1.559 +				{
   1.560 +				int* param =REINTERPRET_CAST(int*,aParam);
   1.561 +				*param = iCommPort.ReceiveBufferLength();
   1.562 +				}
   1.563 +				break;
   1.564 +
   1.565 +			case COMMIOCTL_NOTIFYSUPPORTED:
   1.566 +				{
   1.567 +				int* param =REINTERPRET_CAST(int*,aParam);
   1.568 +				*param = NotifiesSupported();
   1.569 +				}
   1.570 +				break;
   1.571 +
   1.572 +			case REAL_COMMIOCTL_NOTIFY:
   1.573 +				{
   1.574 +				int* param =REINTERPRET_CAST(int*,aParam);
   1.575 +				//if they are supported
   1.576 +				if (RequestedNotifiesSupported(*param))
   1.577 +					{
   1.578 +					//see if we need real notifications or we are to fake them
   1.579 +					//always use aStatus for the final thing
   1.580 +					TBool wantDataAvailable = *param & KNotifyDataAvailable;
   1.581 +					TBool wantOutputEmpty = *param & KNotifyOutputEmpty;
   1.582 +					TBool wantBreakInt = *param & KNotifyBreakInt;
   1.583 +					TBool wantSignals = *param & (KNotifyCD|KNotifyCTS|KNotifyDSR|KNotifyRI);
   1.584 +					TBool wantErrors = *param & (KNotifyFramingError|KNotifyOverrunError|KNotifyParityError);
   1.585 +
   1.586 +					iDataAvailableNotifier = NULL;
   1.587 +					iOutputEmptyNotifier = NULL;
   1.588 +					iBreakNotifier = NULL;
   1.589 +					iSignalsNotifier = NULL;
   1.590 +					iErrorsNotifier = NULL;
   1.591 +
   1.592 +					TRAPD(tRes,
   1.593 +						{
   1.594 +						if (wantDataAvailable) iDataAvailableNotifier = CNotifier::NewL(this);
   1.595 +						if (wantOutputEmpty) iOutputEmptyNotifier = CNotifier::NewL(this);
   1.596 +						if (wantBreakInt) iBreakNotifier = CNotifier::NewL(this);
   1.597 +						if (wantSignals) iSignalsNotifier = CNotifier::NewL(this);
   1.598 +						if (wantErrors) iErrorsNotifier = CNotifier::NewL(this);
   1.599 +						});
   1.600 +					
   1.601 +					if (KErrNone == tRes)
   1.602 +						{
   1.603 +						//smashing, no failure, request those events
   1.604 +						if (wantDataAvailable) iDataAvailableNotifier->IssueRequest(KNotifyDataAvailable);
   1.605 +						if (wantOutputEmpty) iOutputEmptyNotifier->IssueRequest(KNotifyOutputEmpty);
   1.606 +						if (wantBreakInt) iBreakNotifier->IssueRequest(KNotifyBreakInt);
   1.607 +						if (wantSignals) iSignalsNotifier->IssueRequest(*param & (KNotifyCD|KNotifyCTS|KNotifyDSR|KNotifyRI));
   1.608 +						if (wantErrors) iErrorsNotifier->IssueRequest(*param & (KNotifyFramingError|KNotifyOverrunError|KNotifyParityError));
   1.609 +
   1.610 +						iRequestedSignals = *param;
   1.611 +						iNotifyParamPtr = REINTERPRET_CAST(unsigned int*,aParam);
   1.612 +						iNotifyStatus = &aStatus;
   1.613 +						aStatus = KRequestPending;
   1.614 +						return;			//on an async call here
   1.615 +						}
   1.616 +					else
   1.617 +						{
   1.618 +						//deal with the problem
   1.619 +						//we're going to have to tidy up, delete things etc
   1.620 +						delete iDataAvailableNotifier;
   1.621 +						delete iOutputEmptyNotifier;
   1.622 +						delete iBreakNotifier;
   1.623 +						delete iSignalsNotifier;
   1.624 +						delete iErrorsNotifier;
   1.625 +						iDataAvailableNotifier = NULL;
   1.626 +						iOutputEmptyNotifier = NULL;
   1.627 +						iBreakNotifier = NULL;
   1.628 +						iSignalsNotifier = NULL;
   1.629 +						iErrorsNotifier = NULL;
   1.630 +						ret = tRes;
   1.631 +						}
   1.632 +
   1.633 +					}
   1.634 +				else
   1.635 +					{
   1.636 +					ret = KErrNotSupported;
   1.637 +					*param &=~NotifiesSupported();
   1.638 +					}
   1.639 +				}
   1.640 +				break;
   1.641 +
   1.642 +				
   1.643 +			default:
   1.644 +				ret=KErrNotSupported;
   1.645 +				break;
   1.646 +			}
   1.647 +		}
   1.648 +		else
   1.649 +			ret = KErrArgument;
   1.650 + 
   1.651 +	Complete(aStatus,ret);
   1.652 +	}
   1.653 +
   1.654 +
   1.655 +TInt CSerialDesc::IoctlCompletion(int /*aCmd*/, void* /*aParam*/, TInt aStatus)
   1.656 +	{
   1.657 +	return aStatus;
   1.658 +	}
   1.659 +
   1.660 +
   1.661 +void CSerialDesc::ReadCancel()
   1.662 +	{
   1.663 +	iCommPort.ReadCancel();
   1.664 +	}
   1.665 +
   1.666 +
   1.667 +void CSerialDesc::IoctlCancel()
   1.668 +	{
   1.669 +	//stop the ioctl if in progress
   1.670 +	CancelNotifiers(NULL);
   1.671 +
   1.672 +	if (iNotifyStatus)
   1.673 +		{
   1.674 +		iNotifyParamPtr[0] = 0;
   1.675 +		Complete(*iNotifyStatus, -3);
   1.676 +		}
   1.677 +
   1.678 +	}
   1.679 +
   1.680 +TInt CSerialDesc::ReadCompletion (TDes8& /*aBuf*/, TInt aStatus)
   1.681 +	{
   1.682 +	//The read has completed.  
   1.683 +	//See if we need to signal 'cos it completed with an error and someone is waiting 
   1.684 +	//on a notification.  In which case we need to complete the request with the correct results.
   1.685 +	
   1.686 +	if ((aStatus < 0) && (iRequestedSignals&(KNotifyFramingError|KNotifyOverrunError|KNotifyParityError)))	//we have a signal outstanding we can deal with here
   1.687 +		{
   1.688 +		switch (aStatus)
   1.689 +			{
   1.690 +			case KErrCommsFrame:	//comms framing error
   1.691 +				if (iRequestedSignals&KNotifyFramingError)
   1.692 +					Notify(KNotifyFramingError);
   1.693 +				break;
   1.694 +
   1.695 +			case KErrCommsOverrun:	//comms overrrun error
   1.696 + 				if (iRequestedSignals&KNotifyOverrunError)
   1.697 +					Notify(KNotifyOverrunError);
   1.698 +				break;
   1.699 +
   1.700 +			case KErrCommsParity:	//comms parity error
   1.701 + 				if (iRequestedSignals&KNotifyParityError)
   1.702 +					Notify(KNotifyParityError);
   1.703 +				break;
   1.704 +			
   1.705 +			default:
   1.706 +				//an error we don't signal
   1.707 +				break;
   1.708 +
   1.709 +			}
   1.710 +		}
   1.711 +	
   1.712 +	return aStatus;
   1.713 +	}
   1.714 +
   1.715 +TBool CSerialDesc::RequestedNotifiesSupported(TInt aRequested)
   1.716 +	{
   1.717 +	//return true if these notifies are OK.  0 if any of them are illegal
   1.718 +
   1.719 +	TInt mask = ~(NotifiesSupported());
   1.720 +	return !(aRequested&mask);
   1.721 +	}
   1.722 +
   1.723 +TInt CSerialDesc::NotifiesSupported()
   1.724 +	{
   1.725 +	//return which notifies are supported.
   1.726 +	//looks like the driver/server is going to have to be interrogated here
   1.727 +
   1.728 +	//start with the ones we can fake
   1.729 +	TInt supported = KNotifyFramingError|KNotifyOverrunError|KNotifyParityError;
   1.730 +	
   1.731 +#ifndef ER5U_NOTIFICATION_SUPPORT_ONLY
   1.732 +	//get the supported ones from C32
   1.733 +	TCommCaps2 devCap;
   1.734 +	TCommCapsV02& deviceCapabilities = devCap();
   1.735 +	deviceCapabilities.iNotificationCaps = 0;
   1.736 +	iCommPort.Caps(devCap);
   1.737 +
   1.738 +
   1.739 +	//signals
   1.740 +	if (deviceCapabilities.iNotificationCaps & KNotifySignalsChangeSupported)
   1.741 +		supported |= (KNotifyCD|KNotifyCTS|KNotifyDSR|KNotifyRI);
   1.742 +
   1.743 +	//break interrupt
   1.744 +	if (deviceCapabilities.iNotificationCaps & KNotifyBreakSupported)
   1.745 +		supported |= KNotifyBreakInt;
   1.746 +
   1.747 +
   1.748 +	//Data Available
   1.749 +	if (deviceCapabilities.iNotificationCaps & KNotifyDataAvailableSupported)
   1.750 +		supported |= KNotifyDataAvailable;
   1.751 +
   1.752 +	//Output Empty
   1.753 +	if (deviceCapabilities.iNotificationCaps & KNotifyOutputEmptySupported)
   1.754 +		supported |= KNotifyOutputEmpty;
   1.755 +
   1.756 +#endif  //ER5U_NOTIFICATION_SUPPORT_ONLY
   1.757 +
   1.758 +	return supported;
   1.759 +	}
   1.760 +
   1.761 +void CSerialDesc::Notify(TInt aVal)
   1.762 +	{
   1.763 +	if (iErrorsNotifier)
   1.764 +		{
   1.765 +//		iNotifyParamPtr[0] = aVal;
   1.766 +		*iRequestDataPtr = aVal;
   1.767 +		iErrorsNotifier->Complete(0);
   1.768 +		}
   1.769 +	}
   1.770 +
   1.771 +
   1.772 +#ifndef ER5U_NOTIFICATION_SUPPORT_ONLY
   1.773 +void CSerialDesc::NotifyDataAvailable(TRequestStatus& aStatus)
   1.774 +	{
   1.775 +	iCommPort.NotifyDataAvailable(aStatus);
   1.776 +	}
   1.777 +
   1.778 +void CSerialDesc::NotifyDataAvailableCancel()
   1.779 +	{
   1.780 +	iCommPort.NotifyDataAvailableCancel();
   1.781 +	}
   1.782 +
   1.783 +void CSerialDesc::NotifyOutputEmpty(TRequestStatus& aStatus)
   1.784 +	{
   1.785 +	iCommPort.NotifyOutputEmpty(aStatus);
   1.786 +	}
   1.787 +
   1.788 +void CSerialDesc::NotifyOutputEmptyCancel()
   1.789 +	{
   1.790 +	iCommPort.NotifyOutputEmptyCancel();
   1.791 +	}
   1.792 +
   1.793 +void CSerialDesc::NotifyBreak(TRequestStatus& aStatus)
   1.794 +	{
   1.795 +	iCommPort.NotifyBreak(aStatus);
   1.796 +	}
   1.797 +
   1.798 +void CSerialDesc::NotifyBreakCancel()
   1.799 +	{
   1.800 +	iCommPort.NotifyBreakCancel();
   1.801 +	}
   1.802 +
   1.803 +void CSerialDesc::NotifySignalChange(TRequestStatus& aStatus, TUint& aRequestData, TUint aSignalsMask)
   1.804 +	{
   1.805 +	iCommPort.NotifySignalChange(aStatus, aRequestData, aSignalsMask);
   1.806 +	}
   1.807 +
   1.808 +void CSerialDesc::NotifySignalChangeCancel()
   1.809 +	{
   1.810 +	iCommPort.NotifySignalChangeCancel();
   1.811 +	}
   1.812 +#endif  //ER5U_NOTIFICATION_SUPPORT_ONLY
   1.813 +
   1.814 +void CSerialDesc::NotifyWriteErrors(TRequestStatus& aStatus, TUint* aRequestData, TUint aSignalsMask)
   1.815 +	{
   1.816 +	iRequestedSignals = aSignalsMask;
   1.817 +	iRequestDataPtr = aRequestData;
   1.818 +//	iNotifyParamPtr = aRequestData;
   1.819 +	aStatus = KRequestPending;
   1.820 +	}
   1.821 +
   1.822 +void CSerialDesc::NotifyWriteErrorsCancel()
   1.823 +	{
   1.824 +	iErrorsNotifier->Complete(KErrCancel);
   1.825 +	}
   1.826 +
   1.827 +TUint CSerialDesc::Signals()
   1.828 +	{
   1.829 +	return iCommPort.Signals();
   1.830 +	}
   1.831 +
   1.832 +
   1.833 +void CSerialDesc::CancelNotifiers(const CNotifier* aCompletedNotifier)
   1.834 +	{
   1.835 +#ifndef ER5U_NOTIFICATION_SUPPORT_ONLY
   1.836 +	if (iDataAvailableNotifier && (aCompletedNotifier != iDataAvailableNotifier))
   1.837 +		{
   1.838 +		iDataAvailableNotifier->Cancel();
   1.839 +		delete iDataAvailableNotifier;
   1.840 +		iDataAvailableNotifier = NULL;
   1.841 +		}
   1.842 +
   1.843 +	if (iOutputEmptyNotifier && (aCompletedNotifier != iOutputEmptyNotifier))
   1.844 +		{
   1.845 +		iOutputEmptyNotifier->Cancel();
   1.846 +		delete iOutputEmptyNotifier;
   1.847 +		iOutputEmptyNotifier = NULL;
   1.848 +		}
   1.849 +	
   1.850 +	if (iBreakNotifier && (aCompletedNotifier != iBreakNotifier))
   1.851 +		{
   1.852 +		iBreakNotifier->Cancel();
   1.853 +		delete iBreakNotifier;
   1.854 +		iBreakNotifier = NULL;
   1.855 +		}
   1.856 +
   1.857 +
   1.858 +	if (iSignalsNotifier && (aCompletedNotifier != iSignalsNotifier))
   1.859 +		{
   1.860 +		iSignalsNotifier->Cancel();
   1.861 +		delete iSignalsNotifier;
   1.862 +		iSignalsNotifier = NULL;
   1.863 +		}
   1.864 +#endif //ER5U_NOTIFICATION_SUPPORT_ONLY
   1.865 +	if (iErrorsNotifier && (aCompletedNotifier != iErrorsNotifier))
   1.866 +		{
   1.867 +		iErrorsNotifier->Cancel();
   1.868 +		delete iErrorsNotifier;
   1.869 +		iErrorsNotifier = NULL;
   1.870 +		}
   1.871 +	}
   1.872 +