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