genericopenlibs/cstdlib/USTLIB/USERIAL.CPP
changeset 31 ce057bb09d0b
parent 0 e4d67989cc36
equal deleted inserted replaced
30:e20de85af2ee 31:ce057bb09d0b
       
     1 // Copyright (c) 1997-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 // Implementation of STDLIB serialports.
       
    15 // 
       
    16 //
       
    17 
       
    18 #include "FDESC.H"
       
    19 #include <sys/types.h>
       
    20 #include <string.h>		// for memcpy
       
    21 #include <sys/errno.h>		// for ENOTSOCK
       
    22 #include <sys/socket.h>
       
    23 #include <sys/ioctl.h>
       
    24 #include <sys/serial.h>
       
    25 #include <c32comm.h>
       
    26 
       
    27 
       
    28 //define this to allow the code to be built for ER5U without most of the notifications
       
    29 //leave commented for all notifications
       
    30 //#define ER5U_NOTIFICATION_SUPPORT_ONLY
       
    31 #ifdef _DEBUG
       
    32 _LIT(KCSerialDescPanic, "CSerialDesc");
       
    33 #endif
       
    34 
       
    35 //
       
    36 //
       
    37 // -----> CSerialTimer (implementation)
       
    38 //
       
    39 //
       
    40 CSerialTimer::CSerialTimer()
       
    41 	: CTimer(CActive::EPriorityHigh)
       
    42 	  // Construct standard-priority active object
       
    43 	{};
       
    44 
       
    45 CSerialTimer* CSerialTimer::NewLC(CFileDescBase* aFile)
       
    46 	{
       
    47 	CSerialTimer* self=new (ELeave) CSerialTimer;
       
    48 	CleanupStack::PushL(self);
       
    49 	self->ConstructL(aFile);
       
    50 	return self;
       
    51 	}
       
    52 
       
    53 CSerialTimer* CSerialTimer::NewL(CFileDescBase* aFile)
       
    54 	{
       
    55 	CSerialTimer* self = NewLC(aFile);
       
    56 	CleanupStack::Pop();
       
    57 	return self;
       
    58 	}
       
    59 
       
    60 void CSerialTimer::ConstructL(CFileDescBase* aFile)
       
    61 	{
       
    62 	  // Base class second-phase construction.
       
    63 	CTimer::ConstructL();
       
    64 	iFile = aFile;
       
    65 	  // Add active object to active scheduler
       
    66 	CActiveScheduler::Add(this); 
       
    67 	}
       
    68 
       
    69 
       
    70 CSerialTimer::~CSerialTimer()
       
    71 	{
       
    72 	  // Make sure we're cancelled
       
    73 	Cancel();
       
    74 	}
       
    75 
       
    76 void CSerialTimer::DoCancel()
       
    77 	{
       
    78 	  // Base class
       
    79 	CTimer::DoCancel(); 
       
    80 	}
       
    81 
       
    82 void CSerialTimer::IssueRequest()
       
    83 	{
       
    84 	  // There should never be an outstanding request at this point.
       
    85 	__ASSERT_DEBUG(!IsActive(),User::Panic(KCSerialDescPanic,1));
       
    86 
       
    87 	  // Request
       
    88 	CTimer::After(iFile->TimeoutValue()*1000);
       
    89 	}
       
    90 
       
    91 void CSerialTimer::RunL()
       
    92 	{
       
    93 		//the timer has gone off.
       
    94 	iFile->ReadCancel();
       
    95 	iFile->TimedMessage = NULL;
       
    96 	iFile->ReadIsTimed = EFalse;
       
    97 	iFile->ReadWasCancelled = ETrue;
       
    98 	delete this;
       
    99 	}
       
   100 
       
   101 
       
   102 
       
   103 /****/
       
   104 NONSHARABLE_CLASS(CNotifier) : public CActive
       
   105 	{
       
   106 	public:
       
   107 		CNotifier();
       
   108 		~CNotifier();
       
   109 		void IssueRequest(TInt aRequest, TInt* aRequestParams=NULL);
       
   110 		static CNotifier* NewLC(CSerialDesc* aPort);
       
   111 		static CNotifier* NewL(CSerialDesc* aPort);
       
   112 		void Construct(CSerialDesc* aPort);
       
   113 		void Complete(TInt aVal);
       
   114 
       
   115 	private:
       
   116 		enum RequestTypes {None, DataAvailable, OutputEmpty, Break, Signals, WriteErrors};
       
   117 		void DoCancel();
       
   118 		void RunL();
       
   119 		CSerialDesc * iSerialPort;
       
   120 		enum RequestTypes iRequest;
       
   121 		TUint iRequestData;
       
   122 		TInt* iRequestParams;
       
   123 
       
   124 } ;
       
   125 
       
   126 CNotifier::CNotifier() : CActive(CActive::EPriorityStandard), iRequest(None), iRequestData(0), iRequestParams(NULL)
       
   127 	{
       
   128 	}
       
   129 
       
   130 
       
   131 void CNotifier::IssueRequest(TInt aRequest, TInt* aRequestParams)
       
   132 	{
       
   133 	iRequestParams = aRequestParams;
       
   134 	
       
   135 #ifndef ER5U_NOTIFICATION_SUPPORT_ONLY
       
   136 	if (KNotifyDataAvailable == aRequest)
       
   137 		{
       
   138 		iRequest = DataAvailable;
       
   139 		iSerialPort->NotifyDataAvailable(iStatus);
       
   140 		}
       
   141 
       
   142 	else if (KNotifyOutputEmpty == aRequest)
       
   143 		{
       
   144 		iRequest = OutputEmpty;
       
   145 		iSerialPort->NotifyOutputEmpty(iStatus);
       
   146 		}
       
   147 	
       
   148 	else if (KNotifyBreakInt == aRequest)
       
   149 		{
       
   150 		iRequest = Break;
       
   151 		iSerialPort->NotifyBreak(iStatus);
       
   152 		}
       
   153 	
       
   154 	else if (aRequest & (KNotifyCD|KNotifyCTS|KNotifyDSR|KNotifyRI))	//signals
       
   155 		{
       
   156 		TUint signalsRequested = 0;
       
   157 
       
   158 		//build up the mask of signals to request
       
   159 		if (aRequest & KNotifyCD) signalsRequested |=  KSignalDCD;
       
   160 		if (aRequest & KNotifyCTS) signalsRequested |=  KSignalCTS;
       
   161 		if (aRequest & KNotifyDSR) signalsRequested |=  KSignalDSR;
       
   162 		if (aRequest & KNotifyRI) signalsRequested |=  KSignalRNG;
       
   163 		iRequest = Signals;
       
   164 		iSerialPort->NotifySignalChange(iStatus, iRequestData, signalsRequested);
       
   165 		}
       
   166 	
       
   167 	else 
       
   168 #endif	//ER5U_NOTIFICATION_SUPPORT_ONLY
       
   169 		if (aRequest & (KNotifyFramingError|KNotifyOverrunError|KNotifyParityError))
       
   170 		{
       
   171 		iRequest = WriteErrors;
       
   172 		iSerialPort->NotifyWriteErrors(iStatus, &iRequestData, aRequest);
       
   173 		}
       
   174 		
       
   175 	SetActive();
       
   176 	}
       
   177 
       
   178 void CNotifier::RunL()
       
   179 	{
       
   180 	//now what!
       
   181 	//cancel all the others
       
   182 	//use iRequest to determine what we are doing here
       
   183 
       
   184 	CNotifier** ppn = NULL;
       
   185 	switch (iRequest)
       
   186 		{
       
   187 #ifndef ER5U_NOTIFICATION_SUPPORT_ONLY
       
   188 
       
   189 		case DataAvailable:
       
   190 			iSerialPort->iNotifyParamPtr[0] = KNotifyDataAvailable;
       
   191 			ppn = &iSerialPort->iDataAvailableNotifier;
       
   192 			break;
       
   193 
       
   194 		case OutputEmpty:
       
   195 			iSerialPort->iNotifyParamPtr[0] = KNotifyOutputEmpty;
       
   196 			ppn = &iSerialPort->iOutputEmptyNotifier;
       
   197 			break;
       
   198 
       
   199 		case Break:
       
   200 			iSerialPort->iNotifyParamPtr[0] = KNotifyBreakInt;
       
   201 			ppn = &iSerialPort->iBreakNotifier;
       
   202 			break;
       
   203 
       
   204 		case Signals:
       
   205 			{
       
   206 			ppn = &iSerialPort->iSignalsNotifier;
       
   207 			iSerialPort->iNotifyParamPtr[0] = 0;
       
   208 			iSerialPort->iNotifyParamPtr[1] = 0;
       
   209 			if (iRequestData & KDCDChanged)
       
   210 				{
       
   211 				iSerialPort->iNotifyParamPtr[0] |=  KNotifyCD;
       
   212 				iSerialPort->iNotifyParamPtr[1] |=  (iRequestData & KSignalDCD);
       
   213 				}
       
   214 
       
   215 			if (iRequestData & KCTSChanged)
       
   216 				{
       
   217 				iSerialPort->iNotifyParamPtr[0] |=  KNotifyCTS;
       
   218 				iSerialPort->iNotifyParamPtr[1] |=  (iRequestData & KSignalCTS);
       
   219 				}
       
   220 
       
   221 			if (iRequestData & KDSRChanged)
       
   222 				{
       
   223 				iSerialPort->iNotifyParamPtr[0] |=  KNotifyDSR;
       
   224 				iSerialPort->iNotifyParamPtr[1] |=  (iRequestData & KSignalDSR);
       
   225 				}
       
   226 
       
   227 			if (iRequestData & KRNGChanged)
       
   228 				{
       
   229 				iSerialPort->iNotifyParamPtr[0] |=  KNotifyRI;
       
   230 				iSerialPort->iNotifyParamPtr[1] |=  (iRequestData & KSignalRNG);
       
   231 				}
       
   232 
       
   233 			}
       
   234 			break;
       
   235 #endif //ER5U_NOTIFICATION_SUPPORT_ONLY
       
   236 		case WriteErrors:
       
   237 			{
       
   238 			iSerialPort->iNotifyParamPtr[0] = iRequestData;
       
   239 			iSerialPort->iNotifyParamPtr[1] = 0;
       
   240 			ppn = &iSerialPort->iErrorsNotifier;
       
   241 			}
       
   242 			break;
       
   243 
       
   244 		default:
       
   245 			__ASSERT_DEBUG(EFalse, User::Panic(KCSerialDescPanic, 1));
       
   246 			break;
       
   247 		}
       
   248 
       
   249 	//cancel all the others
       
   250 	iSerialPort->CancelNotifiers(this);	//telling it who we are.
       
   251 
       
   252 	//and complete the outstanding user request
       
   253 	User::RequestComplete(iSerialPort->iNotifyStatus, iStatus.Int());
       
   254 	delete this;
       
   255 	if (ppn) *ppn = NULL;
       
   256 	}
       
   257 
       
   258 void CNotifier::DoCancel()
       
   259 	{
       
   260 	switch (iRequest)
       
   261 		{
       
   262 #ifndef ER5U_NOTIFICATION_SUPPORT_ONLY
       
   263 
       
   264 		case DataAvailable:
       
   265 			iSerialPort->NotifyDataAvailableCancel();
       
   266 			break;
       
   267 
       
   268 		case OutputEmpty:
       
   269 			iSerialPort->NotifyOutputEmptyCancel();
       
   270 			break;
       
   271 
       
   272 		case Break:
       
   273 			iSerialPort->NotifyBreakCancel();
       
   274 			break;
       
   275 
       
   276 		case Signals:
       
   277 			iSerialPort->NotifySignalChangeCancel();
       
   278 			break;
       
   279 #endif //ER5U_NOTIFICATION_SUPPORT_ONLY
       
   280 		case WriteErrors:
       
   281 			iSerialPort->NotifyWriteErrorsCancel();
       
   282 			break;
       
   283 
       
   284 		default:
       
   285 			break;
       
   286 		}
       
   287 
       
   288 
       
   289 	}
       
   290 
       
   291 
       
   292 void CNotifier::Complete(TInt aVal)
       
   293 	{
       
   294 	TRequestStatus* ps = &iStatus;
       
   295 	User::RequestComplete(ps, aVal);
       
   296 	}
       
   297 
       
   298 
       
   299 CNotifier* CNotifier::NewLC(CSerialDesc* aPort)
       
   300 	{
       
   301 	CNotifier* self=new (ELeave) CNotifier;
       
   302 	CleanupStack::PushL(self);
       
   303 	self->Construct(aPort);
       
   304 	return self;
       
   305 	}
       
   306 
       
   307 CNotifier* CNotifier::NewL(CSerialDesc* aPort)
       
   308 	{
       
   309 	CNotifier* self = NewLC(aPort);
       
   310 	CleanupStack::Pop();
       
   311 	return self;
       
   312 	}
       
   313 
       
   314 void CNotifier::Construct(CSerialDesc* aPort)
       
   315 	{
       
   316 	iSerialPort = aPort;
       
   317 	CActiveScheduler::Add(this) ;  // add to active scheduler
       
   318 	}
       
   319 
       
   320 CNotifier::~CNotifier()
       
   321 	{
       
   322 	Cancel();
       
   323 	}
       
   324 
       
   325 
       
   326 /****/
       
   327 
       
   328 
       
   329 
       
   330 // The Serial descriptor class
       
   331 
       
   332 TInt CSerialDesc::Open(RCommServ& aSession, const wchar_t* name, int mode, int /*perms*/)
       
   333 	{
       
   334 	//the name will be a wide version of COM?: or IRCOM?: where ? is a number 1 to 9.
       
   335 	//this has already been checked in the call to CFileDescBase open.
       
   336 
       
   337 	
       
   338 	
       
   339 	TInt err = KErrArgument;
       
   340 	if (L'C' == name[0])
       
   341 		{
       
   342 		//serial port
       
   343 		//load the comms module we require
       
   344 		err = aSession.LoadCommModule(_L("ECUART"));
       
   345 		if (KErrAlreadyExists != err && KErrNone != err)	//problem
       
   346 			return err;
       
   347 		//convert the name into an epoc port name
       
   348 		//eg COMM::0
       
   349 		TBuf<7> epocName(_L("COMM::0"));
       
   350 		epocName[6] = (TText)(name[3] - 1);
       
   351 
       
   352 		//try opening as a dte or a dce
       
   353 		err = iCommPort.Open(aSession, epocName, (enum TCommAccess)mode, ECommRoleDTE);
       
   354 		if (err) 			
       
   355 			err = iCommPort.Open(aSession, epocName, (enum TCommAccess)mode, ECommRoleDCE);
       
   356 		}
       
   357 	else
       
   358 		{
       
   359 		//IR port
       
   360 		err = aSession.LoadCommModule(_L("IrCOMM"));
       
   361 		if (KErrAlreadyExists != err && KErrNone != err)	//problem
       
   362 			return err;
       
   363 		//convert the name into an epoc port name
       
   364 		//eg COMM::0
       
   365 		TBuf<9> epocName(_L("IrCOMM::0"));
       
   366 		epocName[8] = (TText)(name[5] - 1);
       
   367 
       
   368 		//try opening as a dte or a dce
       
   369 		err = iCommPort.Open(aSession, epocName, (enum TCommAccess)mode, ECommRoleDTE);
       
   370 		if (err) 			
       
   371 			err = iCommPort.Open(aSession, epocName, (enum TCommAccess)mode, ECommRoleDCE);
       
   372 		}
       
   373 	return err;
       
   374 	}
       
   375 
       
   376 void CSerialDesc::UserClose()
       
   377 	{
       
   378 	IoctlCancel();
       
   379 	}
       
   380 
       
   381 TInt CSerialDesc::FinalClose()
       
   382 	{
       
   383 	iCommPort.Close();
       
   384 	return 0;
       
   385 	}
       
   386 
       
   387 
       
   388 
       
   389 
       
   390 TBool CSerialDesc::TimedRead()
       
   391 	{
       
   392 		//if we have a timeout without a threshold we need an external timer
       
   393 		return (-1 != iReadTimeout && -1 == iReadThreshold);
       
   394 	}
       
   395 
       
   396 
       
   397 void CSerialDesc::Read(TDes8& aBuf, TRequestStatus& aStatus)
       
   398 	{
       
   399 	//do a read..
       
   400 	//4 different ones
       
   401 	if (-1 == iReadThreshold)
       
   402 		{
       
   403 		iCommPort.ReadOneOrMore(aStatus, aBuf);
       
   404 		}
       
   405 	else
       
   406 		{
       
   407 		TInt len = (iReadThreshold < aBuf.MaxLength() ? iReadThreshold : aBuf.MaxLength());
       
   408 		if (-1 == iReadTimeout)
       
   409 			{
       
   410 			//read threshold with no timeout
       
   411 			iCommPort.Read(aStatus, aBuf, len);
       
   412 			}
       
   413 		else
       
   414 			{
       
   415 			//read threshold and timeout
       
   416 			TTimeIntervalMicroSeconds32 timeout(iReadTimeout*1000);
       
   417 			iCommPort.Read(aStatus, timeout, aBuf, len);
       
   418 			}
       
   419 		}
       
   420 
       
   421 	}
       
   422 
       
   423 
       
   424 void CSerialDesc::Write (TDes8& aBuf, TRequestStatus& aStatus)
       
   425 	{
       
   426 	iCommPort.Write(aStatus, aBuf);
       
   427 	}
       
   428 
       
   429 
       
   430 void CSerialDesc::Ioctl(int aCmd, void* aParam, TRequestStatus& aStatus)
       
   431 	{
       
   432 	TInt ret=KErrNone;
       
   433 	if (aParam)
       
   434 		{
       
   435 		
       
   436 		aCmd &= ~0x4000;	//mask off the queue bit!
       
   437 
       
   438 		switch (aCmd)
       
   439 			{
       
   440 			case COMMIOCTL_SETSIGNALS:
       
   441 				{
       
   442 				int* param =REINTERPRET_CAST(int*,aParam);
       
   443 				TUint setMask = (TUint)param[0];
       
   444 				TUint clearMask = (TUint)param[1];
       
   445 				iCommPort.SetSignals(setMask, clearMask);
       
   446 				}
       
   447 				break;
       
   448 
       
   449 			case COMMIOCTL_GETSIGNALS:
       
   450 				{
       
   451 				int* param =REINTERPRET_CAST(int*,aParam);
       
   452 				TUint signals = iCommPort.Signals();
       
   453 				*param = (int)signals;
       
   454 				}
       
   455 				break;
       
   456 
       
   457 			case COMMIOCTL_SETCONFIG:	
       
   458 				{
       
   459 				SerialConfig * param =REINTERPRET_CAST(SerialConfig *,aParam);
       
   460 				TCommConfig cfg;
       
   461 
       
   462 				TCommConfigV01& cfg01 =cfg();
       
   463 				
       
   464 				cfg01.iRate = (enum TBps)param->iRate; 
       
   465 				cfg01.iDataBits = (enum TDataBits)param->iDataBits;
       
   466 				cfg01.iStopBits = (enum TStopBits)param->iStopBits; 
       
   467 				cfg01.iParity = (enum TParity)param->iParity; 
       
   468 				cfg01.iHandshake = param->iHandshake;
       
   469 				cfg01.iParityError = param->iParityError;
       
   470 				cfg01.iFifo = param->iFifo;
       
   471 				cfg01.iSpecialRate = param->iSpecialRate;
       
   472 				cfg01.iTerminatorCount = param->iTerminatorCount;
       
   473 				cfg01.iXonChar = param->iXonChar; 
       
   474 				cfg01.iXoffChar = param->iXoffChar; 
       
   475 				cfg01.iParityErrorChar = param->iParityErrorChar; 
       
   476 				cfg01.iSIREnable = (enum TSir)param->iSIREnable; 
       
   477 				cfg01.iSIRSettings = param->iSIRSettings;
       
   478 
       
   479 				for (int i =0; i < ConfigMaxTerminators; i++)
       
   480 					cfg01.iTerminator[i] = param->iTerminator[i];
       
   481 
       
   482 				iCommPort.SetConfig(cfg);
       
   483 				}
       
   484 				break;
       
   485 
       
   486 			case COMMIOCTL_GETCONFIG:	
       
   487 				{
       
   488 				SerialConfig * param =REINTERPRET_CAST(SerialConfig *,aParam);
       
   489 				TCommConfig cfg;
       
   490 				iCommPort.Config(cfg);
       
   491 				TCommConfigV01& cfg01 =cfg();
       
   492 				
       
   493 				param->iRate = (enum Bps)cfg01.iRate;
       
   494 				param->iDataBits = (enum DataBits)cfg01.iDataBits;
       
   495 				param->iStopBits = (enum StopBits)cfg01.iStopBits;
       
   496 				param->iParity = (enum Parity)cfg01.iParity;
       
   497 				param->iHandshake = cfg01.iHandshake;
       
   498 				param->iParityError = cfg01.iParityError;
       
   499 				param->iFifo = cfg01.iFifo;
       
   500 				param->iSpecialRate = cfg01.iSpecialRate;
       
   501 				param->iTerminatorCount = cfg01.iTerminatorCount;
       
   502 				for (int i =0; i < ConfigMaxTerminators; i++)
       
   503 					param->iTerminator[i] = cfg01.iTerminator[i];
       
   504 				param->iXonChar = cfg01.iXonChar;
       
   505 				param->iXoffChar = cfg01.iXoffChar;
       
   506 				param->iParityErrorChar = cfg01.iParityErrorChar;
       
   507 				param->iSIREnable = (enum Sir)cfg01.iSIREnable;
       
   508 				param->iSIRSettings = cfg01.iSIRSettings;
       
   509 				}
       
   510 				break;
       
   511 
       
   512 			case COMMIOCTL_BREAK:	
       
   513 				{
       
   514 				int* param =REINTERPRET_CAST(int*,aParam);
       
   515 				TTimeIntervalMicroSeconds32 time(*param);
       
   516 				iCommPort.Break(aStatus, time);
       
   517 				return;
       
   518 				}
       
   519 
       
   520 			case COMMIOCTL_SETREADTIMEOUT:
       
   521 				{
       
   522 				int* param =REINTERPRET_CAST(int*,aParam);
       
   523 				iReadTimeout = *param;
       
   524 				}
       
   525 				break;
       
   526 
       
   527 			case COMMIOCTL_GETREADTIMEOUT:
       
   528 				{
       
   529 				int* param =REINTERPRET_CAST(int*,aParam);
       
   530 				*param = iReadTimeout;
       
   531 				}
       
   532 				break;
       
   533 
       
   534 			case COMMIOCTL_SETREADTHRESHOLD:
       
   535 				{
       
   536 				int* param =REINTERPRET_CAST(int*,aParam);
       
   537 				iReadThreshold = *param;
       
   538 				}
       
   539 				break;
       
   540 
       
   541 			case COMMIOCTL_GETREADTHRESHOLD:
       
   542 				{
       
   543 				int* param =REINTERPRET_CAST(int*,aParam);
       
   544 				*param = iReadThreshold;
       
   545 				}
       
   546 				break;
       
   547 
       
   548 			case COMMIOCTL_SETBUFFERLENGTH:
       
   549 				{
       
   550 				int* param =REINTERPRET_CAST(int*,aParam);
       
   551 				iCommPort.SetReceiveBufferLength(TInt(*param));
       
   552 				}
       
   553 				break;
       
   554 
       
   555 			case COMMIOCTL_GETBUFFERLENGTH:
       
   556 				{
       
   557 				int* param =REINTERPRET_CAST(int*,aParam);
       
   558 				*param = iCommPort.ReceiveBufferLength();
       
   559 				}
       
   560 				break;
       
   561 
       
   562 			case COMMIOCTL_NOTIFYSUPPORTED:
       
   563 				{
       
   564 				int* param =REINTERPRET_CAST(int*,aParam);
       
   565 				*param = NotifiesSupported();
       
   566 				}
       
   567 				break;
       
   568 
       
   569 			case REAL_COMMIOCTL_NOTIFY:
       
   570 				{
       
   571 				int* param =REINTERPRET_CAST(int*,aParam);
       
   572 				//if they are supported
       
   573 				if (RequestedNotifiesSupported(*param))
       
   574 					{
       
   575 					//see if we need real notifications or we are to fake them
       
   576 					//always use aStatus for the final thing
       
   577 					TBool wantDataAvailable = *param & KNotifyDataAvailable;
       
   578 					TBool wantOutputEmpty = *param & KNotifyOutputEmpty;
       
   579 					TBool wantBreakInt = *param & KNotifyBreakInt;
       
   580 					TBool wantSignals = *param & (KNotifyCD|KNotifyCTS|KNotifyDSR|KNotifyRI);
       
   581 					TBool wantErrors = *param & (KNotifyFramingError|KNotifyOverrunError|KNotifyParityError);
       
   582 
       
   583 					iDataAvailableNotifier = NULL;
       
   584 					iOutputEmptyNotifier = NULL;
       
   585 					iBreakNotifier = NULL;
       
   586 					iSignalsNotifier = NULL;
       
   587 					iErrorsNotifier = NULL;
       
   588 
       
   589 					TRAPD(tRes,
       
   590 						{
       
   591 						if (wantDataAvailable) iDataAvailableNotifier = CNotifier::NewL(this);
       
   592 						if (wantOutputEmpty) iOutputEmptyNotifier = CNotifier::NewL(this);
       
   593 						if (wantBreakInt) iBreakNotifier = CNotifier::NewL(this);
       
   594 						if (wantSignals) iSignalsNotifier = CNotifier::NewL(this);
       
   595 						if (wantErrors) iErrorsNotifier = CNotifier::NewL(this);
       
   596 						});
       
   597 					
       
   598 					if (KErrNone == tRes)
       
   599 						{
       
   600 						//smashing, no failure, request those events
       
   601 						if (wantDataAvailable) iDataAvailableNotifier->IssueRequest(KNotifyDataAvailable);
       
   602 						if (wantOutputEmpty) iOutputEmptyNotifier->IssueRequest(KNotifyOutputEmpty);
       
   603 						if (wantBreakInt) iBreakNotifier->IssueRequest(KNotifyBreakInt);
       
   604 						if (wantSignals) iSignalsNotifier->IssueRequest(*param & (KNotifyCD|KNotifyCTS|KNotifyDSR|KNotifyRI));
       
   605 						if (wantErrors) iErrorsNotifier->IssueRequest(*param & (KNotifyFramingError|KNotifyOverrunError|KNotifyParityError));
       
   606 
       
   607 						iRequestedSignals = *param;
       
   608 						iNotifyParamPtr = REINTERPRET_CAST(unsigned int*,aParam);
       
   609 						iNotifyStatus = &aStatus;
       
   610 						aStatus = KRequestPending;
       
   611 						return;			//on an async call here
       
   612 						}
       
   613 					else
       
   614 						{
       
   615 						//deal with the problem
       
   616 						//we're going to have to tidy up, delete things etc
       
   617 						delete iDataAvailableNotifier;
       
   618 						delete iOutputEmptyNotifier;
       
   619 						delete iBreakNotifier;
       
   620 						delete iSignalsNotifier;
       
   621 						delete iErrorsNotifier;
       
   622 						iDataAvailableNotifier = NULL;
       
   623 						iOutputEmptyNotifier = NULL;
       
   624 						iBreakNotifier = NULL;
       
   625 						iSignalsNotifier = NULL;
       
   626 						iErrorsNotifier = NULL;
       
   627 						ret = tRes;
       
   628 						}
       
   629 
       
   630 					}
       
   631 				else
       
   632 					{
       
   633 					ret = KErrNotSupported;
       
   634 					*param &=~NotifiesSupported();
       
   635 					}
       
   636 				}
       
   637 				break;
       
   638 
       
   639 				
       
   640 			default:
       
   641 				ret=KErrNotSupported;
       
   642 				break;
       
   643 			}
       
   644 		}
       
   645 		else
       
   646 			ret = KErrArgument;
       
   647  
       
   648 	Complete(aStatus,ret);
       
   649 	}
       
   650 
       
   651 
       
   652 TInt CSerialDesc::IoctlCompletion(int /*aCmd*/, void* /*aParam*/, TInt aStatus)
       
   653 	{
       
   654 	return aStatus;
       
   655 	}
       
   656 
       
   657 
       
   658 void CSerialDesc::ReadCancel()
       
   659 	{
       
   660 	iCommPort.ReadCancel();
       
   661 	}
       
   662 
       
   663 
       
   664 void CSerialDesc::IoctlCancel()
       
   665 	{
       
   666 	//stop the ioctl if in progress
       
   667 	CancelNotifiers(NULL);
       
   668 
       
   669 	if (iNotifyStatus)
       
   670 		{
       
   671 		iNotifyParamPtr[0] = 0;
       
   672 		Complete(*iNotifyStatus, -3);
       
   673 		}
       
   674 
       
   675 	}
       
   676 
       
   677 TInt CSerialDesc::ReadCompletion (TDes8& /*aBuf*/, TInt aStatus)
       
   678 	{
       
   679 	//The read has completed.  
       
   680 	//See if we need to signal 'cos it completed with an error and someone is waiting 
       
   681 	//on a notification.  In which case we need to complete the request with the correct results.
       
   682 	
       
   683 	if ((aStatus < 0) && (iRequestedSignals&(KNotifyFramingError|KNotifyOverrunError|KNotifyParityError)))	//we have a signal outstanding we can deal with here
       
   684 		{
       
   685 		switch (aStatus)
       
   686 			{
       
   687 			case KErrCommsFrame:	//comms framing error
       
   688 				if (iRequestedSignals&KNotifyFramingError)
       
   689 					Notify(KNotifyFramingError);
       
   690 				break;
       
   691 
       
   692 			case KErrCommsOverrun:	//comms overrrun error
       
   693  				if (iRequestedSignals&KNotifyOverrunError)
       
   694 					Notify(KNotifyOverrunError);
       
   695 				break;
       
   696 
       
   697 			case KErrCommsParity:	//comms parity error
       
   698  				if (iRequestedSignals&KNotifyParityError)
       
   699 					Notify(KNotifyParityError);
       
   700 				break;
       
   701 			
       
   702 			default:
       
   703 				//an error we don't signal
       
   704 				break;
       
   705 
       
   706 			}
       
   707 		}
       
   708 	
       
   709 	return aStatus;
       
   710 	}
       
   711 
       
   712 TBool CSerialDesc::RequestedNotifiesSupported(TInt aRequested)
       
   713 	{
       
   714 	//return true if these notifies are OK.  0 if any of them are illegal
       
   715 
       
   716 	TInt mask = ~(NotifiesSupported());
       
   717 	return !(aRequested&mask);
       
   718 	}
       
   719 
       
   720 TInt CSerialDesc::NotifiesSupported()
       
   721 	{
       
   722 	//return which notifies are supported.
       
   723 	//looks like the driver/server is going to have to be interrogated here
       
   724 
       
   725 	//start with the ones we can fake
       
   726 	TInt supported = KNotifyFramingError|KNotifyOverrunError|KNotifyParityError;
       
   727 	
       
   728 #ifndef ER5U_NOTIFICATION_SUPPORT_ONLY
       
   729 	//get the supported ones from C32
       
   730 	TCommCaps2 devCap;
       
   731 	TCommCapsV02& deviceCapabilities = devCap();
       
   732 	deviceCapabilities.iNotificationCaps = 0;
       
   733 	iCommPort.Caps(devCap);
       
   734 
       
   735 
       
   736 	//signals
       
   737 	if (deviceCapabilities.iNotificationCaps & KNotifySignalsChangeSupported)
       
   738 		supported |= (KNotifyCD|KNotifyCTS|KNotifyDSR|KNotifyRI);
       
   739 
       
   740 	//break interrupt
       
   741 	if (deviceCapabilities.iNotificationCaps & KNotifyBreakSupported)
       
   742 		supported |= KNotifyBreakInt;
       
   743 
       
   744 
       
   745 	//Data Available
       
   746 	if (deviceCapabilities.iNotificationCaps & KNotifyDataAvailableSupported)
       
   747 		supported |= KNotifyDataAvailable;
       
   748 
       
   749 	//Output Empty
       
   750 	if (deviceCapabilities.iNotificationCaps & KNotifyOutputEmptySupported)
       
   751 		supported |= KNotifyOutputEmpty;
       
   752 
       
   753 #endif  //ER5U_NOTIFICATION_SUPPORT_ONLY
       
   754 
       
   755 	return supported;
       
   756 	}
       
   757 
       
   758 void CSerialDesc::Notify(TInt aVal)
       
   759 	{
       
   760 	if (iErrorsNotifier)
       
   761 		{
       
   762 //		iNotifyParamPtr[0] = aVal;
       
   763 		*iRequestDataPtr = aVal;
       
   764 		iErrorsNotifier->Complete(0);
       
   765 		}
       
   766 	}
       
   767 
       
   768 
       
   769 #ifndef ER5U_NOTIFICATION_SUPPORT_ONLY
       
   770 void CSerialDesc::NotifyDataAvailable(TRequestStatus& aStatus)
       
   771 	{
       
   772 	iCommPort.NotifyDataAvailable(aStatus);
       
   773 	}
       
   774 
       
   775 void CSerialDesc::NotifyDataAvailableCancel()
       
   776 	{
       
   777 	iCommPort.NotifyDataAvailableCancel();
       
   778 	}
       
   779 
       
   780 void CSerialDesc::NotifyOutputEmpty(TRequestStatus& aStatus)
       
   781 	{
       
   782 	iCommPort.NotifyOutputEmpty(aStatus);
       
   783 	}
       
   784 
       
   785 void CSerialDesc::NotifyOutputEmptyCancel()
       
   786 	{
       
   787 	iCommPort.NotifyOutputEmptyCancel();
       
   788 	}
       
   789 
       
   790 void CSerialDesc::NotifyBreak(TRequestStatus& aStatus)
       
   791 	{
       
   792 	iCommPort.NotifyBreak(aStatus);
       
   793 	}
       
   794 
       
   795 void CSerialDesc::NotifyBreakCancel()
       
   796 	{
       
   797 	iCommPort.NotifyBreakCancel();
       
   798 	}
       
   799 
       
   800 void CSerialDesc::NotifySignalChange(TRequestStatus& aStatus, TUint& aRequestData, TUint aSignalsMask)
       
   801 	{
       
   802 	iCommPort.NotifySignalChange(aStatus, aRequestData, aSignalsMask);
       
   803 	}
       
   804 
       
   805 void CSerialDesc::NotifySignalChangeCancel()
       
   806 	{
       
   807 	iCommPort.NotifySignalChangeCancel();
       
   808 	}
       
   809 #endif  //ER5U_NOTIFICATION_SUPPORT_ONLY
       
   810 
       
   811 void CSerialDesc::NotifyWriteErrors(TRequestStatus& aStatus, TUint* aRequestData, TUint aSignalsMask)
       
   812 	{
       
   813 	iRequestedSignals = aSignalsMask;
       
   814 	iRequestDataPtr = aRequestData;
       
   815 //	iNotifyParamPtr = aRequestData;
       
   816 	aStatus = KRequestPending;
       
   817 	}
       
   818 
       
   819 void CSerialDesc::NotifyWriteErrorsCancel()
       
   820 	{
       
   821 	iErrorsNotifier->Complete(KErrCancel);
       
   822 	}
       
   823 
       
   824 TUint CSerialDesc::Signals()
       
   825 	{
       
   826 	return iCommPort.Signals();
       
   827 	}
       
   828 
       
   829 
       
   830 void CSerialDesc::CancelNotifiers(const CNotifier* aCompletedNotifier)
       
   831 	{
       
   832 #ifndef ER5U_NOTIFICATION_SUPPORT_ONLY
       
   833 	if (iDataAvailableNotifier && (aCompletedNotifier != iDataAvailableNotifier))
       
   834 		{
       
   835 		iDataAvailableNotifier->Cancel();
       
   836 		delete iDataAvailableNotifier;
       
   837 		iDataAvailableNotifier = NULL;
       
   838 		}
       
   839 
       
   840 	if (iOutputEmptyNotifier && (aCompletedNotifier != iOutputEmptyNotifier))
       
   841 		{
       
   842 		iOutputEmptyNotifier->Cancel();
       
   843 		delete iOutputEmptyNotifier;
       
   844 		iOutputEmptyNotifier = NULL;
       
   845 		}
       
   846 	
       
   847 	if (iBreakNotifier && (aCompletedNotifier != iBreakNotifier))
       
   848 		{
       
   849 		iBreakNotifier->Cancel();
       
   850 		delete iBreakNotifier;
       
   851 		iBreakNotifier = NULL;
       
   852 		}
       
   853 
       
   854 
       
   855 	if (iSignalsNotifier && (aCompletedNotifier != iSignalsNotifier))
       
   856 		{
       
   857 		iSignalsNotifier->Cancel();
       
   858 		delete iSignalsNotifier;
       
   859 		iSignalsNotifier = NULL;
       
   860 		}
       
   861 #endif //ER5U_NOTIFICATION_SUPPORT_ONLY
       
   862 	if (iErrorsNotifier && (aCompletedNotifier != iErrorsNotifier))
       
   863 		{
       
   864 		iErrorsNotifier->Cancel();
       
   865 		delete iErrorsNotifier;
       
   866 		iErrorsNotifier = NULL;
       
   867 		}
       
   868 	}
       
   869