sl@0: // Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // Implementation of STDLIB serialports. sl@0: // sl@0: // sl@0: sl@0: #include "FDESC.H" sl@0: #include sl@0: #include // for memcpy sl@0: #include // for ENOTSOCK sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: sl@0: sl@0: //define this to allow the code to be built for ER5U without most of the notifications sl@0: //leave commented for all notifications sl@0: //#define ER5U_NOTIFICATION_SUPPORT_ONLY sl@0: #ifdef _DEBUG sl@0: _LIT(KCSerialDescPanic, "CSerialDesc"); sl@0: #endif sl@0: sl@0: // sl@0: // sl@0: // -----> CSerialTimer (implementation) sl@0: // sl@0: // sl@0: CSerialTimer::CSerialTimer() sl@0: : CTimer(CActive::EPriorityHigh) sl@0: // Construct standard-priority active object sl@0: {}; sl@0: sl@0: CSerialTimer* CSerialTimer::NewLC(CFileDescBase* aFile) sl@0: { sl@0: CSerialTimer* self=new (ELeave) CSerialTimer; sl@0: CleanupStack::PushL(self); sl@0: self->ConstructL(aFile); sl@0: return self; sl@0: } sl@0: sl@0: CSerialTimer* CSerialTimer::NewL(CFileDescBase* aFile) sl@0: { sl@0: CSerialTimer* self = NewLC(aFile); sl@0: CleanupStack::Pop(); sl@0: return self; sl@0: } sl@0: sl@0: void CSerialTimer::ConstructL(CFileDescBase* aFile) sl@0: { sl@0: // Base class second-phase construction. sl@0: CTimer::ConstructL(); sl@0: iFile = aFile; sl@0: // Add active object to active scheduler sl@0: CActiveScheduler::Add(this); sl@0: } sl@0: sl@0: sl@0: CSerialTimer::~CSerialTimer() sl@0: { sl@0: // Make sure we're cancelled sl@0: Cancel(); sl@0: } sl@0: sl@0: void CSerialTimer::DoCancel() sl@0: { sl@0: // Base class sl@0: CTimer::DoCancel(); sl@0: } sl@0: sl@0: void CSerialTimer::IssueRequest() sl@0: { sl@0: // There should never be an outstanding request at this point. sl@0: __ASSERT_DEBUG(!IsActive(),User::Panic(KCSerialDescPanic,1)); sl@0: sl@0: // Request sl@0: CTimer::After(iFile->TimeoutValue()*1000); sl@0: } sl@0: sl@0: void CSerialTimer::RunL() sl@0: { sl@0: //the timer has gone off. sl@0: iFile->ReadCancel(); sl@0: iFile->TimedMessage = NULL; sl@0: iFile->ReadIsTimed = EFalse; sl@0: iFile->ReadWasCancelled = ETrue; sl@0: delete this; sl@0: } sl@0: sl@0: sl@0: sl@0: /****/ sl@0: NONSHARABLE_CLASS(CNotifier) : public CActive sl@0: { sl@0: public: sl@0: CNotifier(); sl@0: ~CNotifier(); sl@0: void IssueRequest(TInt aRequest, TInt* aRequestParams=NULL); sl@0: static CNotifier* NewLC(CSerialDesc* aPort); sl@0: static CNotifier* NewL(CSerialDesc* aPort); sl@0: void Construct(CSerialDesc* aPort); sl@0: void Complete(TInt aVal); sl@0: sl@0: private: sl@0: enum RequestTypes {None, DataAvailable, OutputEmpty, Break, Signals, WriteErrors}; sl@0: void DoCancel(); sl@0: void RunL(); sl@0: CSerialDesc * iSerialPort; sl@0: enum RequestTypes iRequest; sl@0: TUint iRequestData; sl@0: TInt* iRequestParams; sl@0: sl@0: } ; sl@0: sl@0: CNotifier::CNotifier() : CActive(CActive::EPriorityStandard), iRequest(None), iRequestData(0), iRequestParams(NULL) sl@0: { sl@0: } sl@0: sl@0: sl@0: void CNotifier::IssueRequest(TInt aRequest, TInt* aRequestParams) sl@0: { sl@0: iRequestParams = aRequestParams; sl@0: sl@0: #ifndef ER5U_NOTIFICATION_SUPPORT_ONLY sl@0: if (KNotifyDataAvailable == aRequest) sl@0: { sl@0: iRequest = DataAvailable; sl@0: iSerialPort->NotifyDataAvailable(iStatus); sl@0: } sl@0: sl@0: else if (KNotifyOutputEmpty == aRequest) sl@0: { sl@0: iRequest = OutputEmpty; sl@0: iSerialPort->NotifyOutputEmpty(iStatus); sl@0: } sl@0: sl@0: else if (KNotifyBreakInt == aRequest) sl@0: { sl@0: iRequest = Break; sl@0: iSerialPort->NotifyBreak(iStatus); sl@0: } sl@0: sl@0: else if (aRequest & (KNotifyCD|KNotifyCTS|KNotifyDSR|KNotifyRI)) //signals sl@0: { sl@0: TUint signalsRequested = 0; sl@0: sl@0: //build up the mask of signals to request sl@0: if (aRequest & KNotifyCD) signalsRequested |= KSignalDCD; sl@0: if (aRequest & KNotifyCTS) signalsRequested |= KSignalCTS; sl@0: if (aRequest & KNotifyDSR) signalsRequested |= KSignalDSR; sl@0: if (aRequest & KNotifyRI) signalsRequested |= KSignalRNG; sl@0: iRequest = Signals; sl@0: iSerialPort->NotifySignalChange(iStatus, iRequestData, signalsRequested); sl@0: } sl@0: sl@0: else sl@0: #endif //ER5U_NOTIFICATION_SUPPORT_ONLY sl@0: if (aRequest & (KNotifyFramingError|KNotifyOverrunError|KNotifyParityError)) sl@0: { sl@0: iRequest = WriteErrors; sl@0: iSerialPort->NotifyWriteErrors(iStatus, &iRequestData, aRequest); sl@0: } sl@0: sl@0: SetActive(); sl@0: } sl@0: sl@0: void CNotifier::RunL() sl@0: { sl@0: //now what! sl@0: //cancel all the others sl@0: //use iRequest to determine what we are doing here sl@0: sl@0: CNotifier** ppn = NULL; sl@0: switch (iRequest) sl@0: { sl@0: #ifndef ER5U_NOTIFICATION_SUPPORT_ONLY sl@0: sl@0: case DataAvailable: sl@0: iSerialPort->iNotifyParamPtr[0] = KNotifyDataAvailable; sl@0: ppn = &iSerialPort->iDataAvailableNotifier; sl@0: break; sl@0: sl@0: case OutputEmpty: sl@0: iSerialPort->iNotifyParamPtr[0] = KNotifyOutputEmpty; sl@0: ppn = &iSerialPort->iOutputEmptyNotifier; sl@0: break; sl@0: sl@0: case Break: sl@0: iSerialPort->iNotifyParamPtr[0] = KNotifyBreakInt; sl@0: ppn = &iSerialPort->iBreakNotifier; sl@0: break; sl@0: sl@0: case Signals: sl@0: { sl@0: ppn = &iSerialPort->iSignalsNotifier; sl@0: iSerialPort->iNotifyParamPtr[0] = 0; sl@0: iSerialPort->iNotifyParamPtr[1] = 0; sl@0: if (iRequestData & KDCDChanged) sl@0: { sl@0: iSerialPort->iNotifyParamPtr[0] |= KNotifyCD; sl@0: iSerialPort->iNotifyParamPtr[1] |= (iRequestData & KSignalDCD); sl@0: } sl@0: sl@0: if (iRequestData & KCTSChanged) sl@0: { sl@0: iSerialPort->iNotifyParamPtr[0] |= KNotifyCTS; sl@0: iSerialPort->iNotifyParamPtr[1] |= (iRequestData & KSignalCTS); sl@0: } sl@0: sl@0: if (iRequestData & KDSRChanged) sl@0: { sl@0: iSerialPort->iNotifyParamPtr[0] |= KNotifyDSR; sl@0: iSerialPort->iNotifyParamPtr[1] |= (iRequestData & KSignalDSR); sl@0: } sl@0: sl@0: if (iRequestData & KRNGChanged) sl@0: { sl@0: iSerialPort->iNotifyParamPtr[0] |= KNotifyRI; sl@0: iSerialPort->iNotifyParamPtr[1] |= (iRequestData & KSignalRNG); sl@0: } sl@0: sl@0: } sl@0: break; sl@0: #endif //ER5U_NOTIFICATION_SUPPORT_ONLY sl@0: case WriteErrors: sl@0: { sl@0: iSerialPort->iNotifyParamPtr[0] = iRequestData; sl@0: iSerialPort->iNotifyParamPtr[1] = 0; sl@0: ppn = &iSerialPort->iErrorsNotifier; sl@0: } sl@0: break; sl@0: sl@0: default: sl@0: __ASSERT_DEBUG(EFalse, User::Panic(KCSerialDescPanic, 1)); sl@0: break; sl@0: } sl@0: sl@0: //cancel all the others sl@0: iSerialPort->CancelNotifiers(this); //telling it who we are. sl@0: sl@0: //and complete the outstanding user request sl@0: User::RequestComplete(iSerialPort->iNotifyStatus, iStatus.Int()); sl@0: delete this; sl@0: if (ppn) *ppn = NULL; sl@0: } sl@0: sl@0: void CNotifier::DoCancel() sl@0: { sl@0: switch (iRequest) sl@0: { sl@0: #ifndef ER5U_NOTIFICATION_SUPPORT_ONLY sl@0: sl@0: case DataAvailable: sl@0: iSerialPort->NotifyDataAvailableCancel(); sl@0: break; sl@0: sl@0: case OutputEmpty: sl@0: iSerialPort->NotifyOutputEmptyCancel(); sl@0: break; sl@0: sl@0: case Break: sl@0: iSerialPort->NotifyBreakCancel(); sl@0: break; sl@0: sl@0: case Signals: sl@0: iSerialPort->NotifySignalChangeCancel(); sl@0: break; sl@0: #endif //ER5U_NOTIFICATION_SUPPORT_ONLY sl@0: case WriteErrors: sl@0: iSerialPort->NotifyWriteErrorsCancel(); sl@0: break; sl@0: sl@0: default: sl@0: break; sl@0: } sl@0: sl@0: sl@0: } sl@0: sl@0: sl@0: void CNotifier::Complete(TInt aVal) sl@0: { sl@0: TRequestStatus* ps = &iStatus; sl@0: User::RequestComplete(ps, aVal); sl@0: } sl@0: sl@0: sl@0: CNotifier* CNotifier::NewLC(CSerialDesc* aPort) sl@0: { sl@0: CNotifier* self=new (ELeave) CNotifier; sl@0: CleanupStack::PushL(self); sl@0: self->Construct(aPort); sl@0: return self; sl@0: } sl@0: sl@0: CNotifier* CNotifier::NewL(CSerialDesc* aPort) sl@0: { sl@0: CNotifier* self = NewLC(aPort); sl@0: CleanupStack::Pop(); sl@0: return self; sl@0: } sl@0: sl@0: void CNotifier::Construct(CSerialDesc* aPort) sl@0: { sl@0: iSerialPort = aPort; sl@0: CActiveScheduler::Add(this) ; // add to active scheduler sl@0: } sl@0: sl@0: CNotifier::~CNotifier() sl@0: { sl@0: Cancel(); sl@0: } sl@0: sl@0: sl@0: /****/ sl@0: sl@0: sl@0: sl@0: // The Serial descriptor class sl@0: sl@0: TInt CSerialDesc::Open(RCommServ& aSession, const wchar_t* name, int mode, int /*perms*/) sl@0: { sl@0: //the name will be a wide version of COM?: or IRCOM?: where ? is a number 1 to 9. sl@0: //this has already been checked in the call to CFileDescBase open. sl@0: sl@0: sl@0: sl@0: TInt err = KErrArgument; sl@0: if (L'C' == name[0]) sl@0: { sl@0: //serial port sl@0: //load the comms module we require sl@0: err = aSession.LoadCommModule(_L("ECUART")); sl@0: if (KErrAlreadyExists != err && KErrNone != err) //problem sl@0: return err; sl@0: //convert the name into an epoc port name sl@0: //eg COMM::0 sl@0: TBuf<7> epocName(_L("COMM::0")); sl@0: epocName[6] = (TText)(name[3] - 1); sl@0: sl@0: //try opening as a dte or a dce sl@0: err = iCommPort.Open(aSession, epocName, (enum TCommAccess)mode, ECommRoleDTE); sl@0: if (err) sl@0: err = iCommPort.Open(aSession, epocName, (enum TCommAccess)mode, ECommRoleDCE); sl@0: } sl@0: else sl@0: { sl@0: //IR port sl@0: err = aSession.LoadCommModule(_L("IrCOMM")); sl@0: if (KErrAlreadyExists != err && KErrNone != err) //problem sl@0: return err; sl@0: //convert the name into an epoc port name sl@0: //eg COMM::0 sl@0: TBuf<9> epocName(_L("IrCOMM::0")); sl@0: epocName[8] = (TText)(name[5] - 1); sl@0: sl@0: //try opening as a dte or a dce sl@0: err = iCommPort.Open(aSession, epocName, (enum TCommAccess)mode, ECommRoleDTE); sl@0: if (err) sl@0: err = iCommPort.Open(aSession, epocName, (enum TCommAccess)mode, ECommRoleDCE); sl@0: } sl@0: return err; sl@0: } sl@0: sl@0: void CSerialDesc::UserClose() sl@0: { sl@0: IoctlCancel(); sl@0: } sl@0: sl@0: TInt CSerialDesc::FinalClose() sl@0: { sl@0: iCommPort.Close(); sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: TBool CSerialDesc::TimedRead() sl@0: { sl@0: //if we have a timeout without a threshold we need an external timer sl@0: return (-1 != iReadTimeout && -1 == iReadThreshold); sl@0: } sl@0: sl@0: sl@0: void CSerialDesc::Read(TDes8& aBuf, TRequestStatus& aStatus) sl@0: { sl@0: //do a read.. sl@0: //4 different ones sl@0: if (-1 == iReadThreshold) sl@0: { sl@0: iCommPort.ReadOneOrMore(aStatus, aBuf); sl@0: } sl@0: else sl@0: { sl@0: TInt len = (iReadThreshold < aBuf.MaxLength() ? iReadThreshold : aBuf.MaxLength()); sl@0: if (-1 == iReadTimeout) sl@0: { sl@0: //read threshold with no timeout sl@0: iCommPort.Read(aStatus, aBuf, len); sl@0: } sl@0: else sl@0: { sl@0: //read threshold and timeout sl@0: TTimeIntervalMicroSeconds32 timeout(iReadTimeout*1000); sl@0: iCommPort.Read(aStatus, timeout, aBuf, len); sl@0: } sl@0: } sl@0: sl@0: } sl@0: sl@0: sl@0: void CSerialDesc::Write (TDes8& aBuf, TRequestStatus& aStatus) sl@0: { sl@0: iCommPort.Write(aStatus, aBuf); sl@0: } sl@0: sl@0: sl@0: void CSerialDesc::Ioctl(int aCmd, void* aParam, TRequestStatus& aStatus) sl@0: { sl@0: TInt ret=KErrNone; sl@0: if (aParam) sl@0: { sl@0: sl@0: aCmd &= ~0x4000; //mask off the queue bit! sl@0: sl@0: switch (aCmd) sl@0: { sl@0: case COMMIOCTL_SETSIGNALS: sl@0: { sl@0: int* param =REINTERPRET_CAST(int*,aParam); sl@0: TUint setMask = (TUint)param[0]; sl@0: TUint clearMask = (TUint)param[1]; sl@0: iCommPort.SetSignals(setMask, clearMask); sl@0: } sl@0: break; sl@0: sl@0: case COMMIOCTL_GETSIGNALS: sl@0: { sl@0: int* param =REINTERPRET_CAST(int*,aParam); sl@0: TUint signals = iCommPort.Signals(); sl@0: *param = (int)signals; sl@0: } sl@0: break; sl@0: sl@0: case COMMIOCTL_SETCONFIG: sl@0: { sl@0: SerialConfig * param =REINTERPRET_CAST(SerialConfig *,aParam); sl@0: TCommConfig cfg; sl@0: sl@0: TCommConfigV01& cfg01 =cfg(); sl@0: sl@0: cfg01.iRate = (enum TBps)param->iRate; sl@0: cfg01.iDataBits = (enum TDataBits)param->iDataBits; sl@0: cfg01.iStopBits = (enum TStopBits)param->iStopBits; sl@0: cfg01.iParity = (enum TParity)param->iParity; sl@0: cfg01.iHandshake = param->iHandshake; sl@0: cfg01.iParityError = param->iParityError; sl@0: cfg01.iFifo = param->iFifo; sl@0: cfg01.iSpecialRate = param->iSpecialRate; sl@0: cfg01.iTerminatorCount = param->iTerminatorCount; sl@0: cfg01.iXonChar = param->iXonChar; sl@0: cfg01.iXoffChar = param->iXoffChar; sl@0: cfg01.iParityErrorChar = param->iParityErrorChar; sl@0: cfg01.iSIREnable = (enum TSir)param->iSIREnable; sl@0: cfg01.iSIRSettings = param->iSIRSettings; sl@0: sl@0: for (int i =0; i < ConfigMaxTerminators; i++) sl@0: cfg01.iTerminator[i] = param->iTerminator[i]; sl@0: sl@0: iCommPort.SetConfig(cfg); sl@0: } sl@0: break; sl@0: sl@0: case COMMIOCTL_GETCONFIG: sl@0: { sl@0: SerialConfig * param =REINTERPRET_CAST(SerialConfig *,aParam); sl@0: TCommConfig cfg; sl@0: iCommPort.Config(cfg); sl@0: TCommConfigV01& cfg01 =cfg(); sl@0: sl@0: param->iRate = (enum Bps)cfg01.iRate; sl@0: param->iDataBits = (enum DataBits)cfg01.iDataBits; sl@0: param->iStopBits = (enum StopBits)cfg01.iStopBits; sl@0: param->iParity = (enum Parity)cfg01.iParity; sl@0: param->iHandshake = cfg01.iHandshake; sl@0: param->iParityError = cfg01.iParityError; sl@0: param->iFifo = cfg01.iFifo; sl@0: param->iSpecialRate = cfg01.iSpecialRate; sl@0: param->iTerminatorCount = cfg01.iTerminatorCount; sl@0: for (int i =0; i < ConfigMaxTerminators; i++) sl@0: param->iTerminator[i] = cfg01.iTerminator[i]; sl@0: param->iXonChar = cfg01.iXonChar; sl@0: param->iXoffChar = cfg01.iXoffChar; sl@0: param->iParityErrorChar = cfg01.iParityErrorChar; sl@0: param->iSIREnable = (enum Sir)cfg01.iSIREnable; sl@0: param->iSIRSettings = cfg01.iSIRSettings; sl@0: } sl@0: break; sl@0: sl@0: case COMMIOCTL_BREAK: sl@0: { sl@0: int* param =REINTERPRET_CAST(int*,aParam); sl@0: TTimeIntervalMicroSeconds32 time(*param); sl@0: iCommPort.Break(aStatus, time); sl@0: return; sl@0: } sl@0: sl@0: case COMMIOCTL_SETREADTIMEOUT: sl@0: { sl@0: int* param =REINTERPRET_CAST(int*,aParam); sl@0: iReadTimeout = *param; sl@0: } sl@0: break; sl@0: sl@0: case COMMIOCTL_GETREADTIMEOUT: sl@0: { sl@0: int* param =REINTERPRET_CAST(int*,aParam); sl@0: *param = iReadTimeout; sl@0: } sl@0: break; sl@0: sl@0: case COMMIOCTL_SETREADTHRESHOLD: sl@0: { sl@0: int* param =REINTERPRET_CAST(int*,aParam); sl@0: iReadThreshold = *param; sl@0: } sl@0: break; sl@0: sl@0: case COMMIOCTL_GETREADTHRESHOLD: sl@0: { sl@0: int* param =REINTERPRET_CAST(int*,aParam); sl@0: *param = iReadThreshold; sl@0: } sl@0: break; sl@0: sl@0: case COMMIOCTL_SETBUFFERLENGTH: sl@0: { sl@0: int* param =REINTERPRET_CAST(int*,aParam); sl@0: iCommPort.SetReceiveBufferLength(TInt(*param)); sl@0: } sl@0: break; sl@0: sl@0: case COMMIOCTL_GETBUFFERLENGTH: sl@0: { sl@0: int* param =REINTERPRET_CAST(int*,aParam); sl@0: *param = iCommPort.ReceiveBufferLength(); sl@0: } sl@0: break; sl@0: sl@0: case COMMIOCTL_NOTIFYSUPPORTED: sl@0: { sl@0: int* param =REINTERPRET_CAST(int*,aParam); sl@0: *param = NotifiesSupported(); sl@0: } sl@0: break; sl@0: sl@0: case REAL_COMMIOCTL_NOTIFY: sl@0: { sl@0: int* param =REINTERPRET_CAST(int*,aParam); sl@0: //if they are supported sl@0: if (RequestedNotifiesSupported(*param)) sl@0: { sl@0: //see if we need real notifications or we are to fake them sl@0: //always use aStatus for the final thing sl@0: TBool wantDataAvailable = *param & KNotifyDataAvailable; sl@0: TBool wantOutputEmpty = *param & KNotifyOutputEmpty; sl@0: TBool wantBreakInt = *param & KNotifyBreakInt; sl@0: TBool wantSignals = *param & (KNotifyCD|KNotifyCTS|KNotifyDSR|KNotifyRI); sl@0: TBool wantErrors = *param & (KNotifyFramingError|KNotifyOverrunError|KNotifyParityError); sl@0: sl@0: iDataAvailableNotifier = NULL; sl@0: iOutputEmptyNotifier = NULL; sl@0: iBreakNotifier = NULL; sl@0: iSignalsNotifier = NULL; sl@0: iErrorsNotifier = NULL; sl@0: sl@0: TRAPD(tRes, sl@0: { sl@0: if (wantDataAvailable) iDataAvailableNotifier = CNotifier::NewL(this); sl@0: if (wantOutputEmpty) iOutputEmptyNotifier = CNotifier::NewL(this); sl@0: if (wantBreakInt) iBreakNotifier = CNotifier::NewL(this); sl@0: if (wantSignals) iSignalsNotifier = CNotifier::NewL(this); sl@0: if (wantErrors) iErrorsNotifier = CNotifier::NewL(this); sl@0: }); sl@0: sl@0: if (KErrNone == tRes) sl@0: { sl@0: //smashing, no failure, request those events sl@0: if (wantDataAvailable) iDataAvailableNotifier->IssueRequest(KNotifyDataAvailable); sl@0: if (wantOutputEmpty) iOutputEmptyNotifier->IssueRequest(KNotifyOutputEmpty); sl@0: if (wantBreakInt) iBreakNotifier->IssueRequest(KNotifyBreakInt); sl@0: if (wantSignals) iSignalsNotifier->IssueRequest(*param & (KNotifyCD|KNotifyCTS|KNotifyDSR|KNotifyRI)); sl@0: if (wantErrors) iErrorsNotifier->IssueRequest(*param & (KNotifyFramingError|KNotifyOverrunError|KNotifyParityError)); sl@0: sl@0: iRequestedSignals = *param; sl@0: iNotifyParamPtr = REINTERPRET_CAST(unsigned int*,aParam); sl@0: iNotifyStatus = &aStatus; sl@0: aStatus = KRequestPending; sl@0: return; //on an async call here sl@0: } sl@0: else sl@0: { sl@0: //deal with the problem sl@0: //we're going to have to tidy up, delete things etc sl@0: delete iDataAvailableNotifier; sl@0: delete iOutputEmptyNotifier; sl@0: delete iBreakNotifier; sl@0: delete iSignalsNotifier; sl@0: delete iErrorsNotifier; sl@0: iDataAvailableNotifier = NULL; sl@0: iOutputEmptyNotifier = NULL; sl@0: iBreakNotifier = NULL; sl@0: iSignalsNotifier = NULL; sl@0: iErrorsNotifier = NULL; sl@0: ret = tRes; sl@0: } sl@0: sl@0: } sl@0: else sl@0: { sl@0: ret = KErrNotSupported; sl@0: *param &=~NotifiesSupported(); sl@0: } sl@0: } sl@0: break; sl@0: sl@0: sl@0: default: sl@0: ret=KErrNotSupported; sl@0: break; sl@0: } sl@0: } sl@0: else sl@0: ret = KErrArgument; sl@0: sl@0: Complete(aStatus,ret); sl@0: } sl@0: sl@0: sl@0: TInt CSerialDesc::IoctlCompletion(int /*aCmd*/, void* /*aParam*/, TInt aStatus) sl@0: { sl@0: return aStatus; sl@0: } sl@0: sl@0: sl@0: void CSerialDesc::ReadCancel() sl@0: { sl@0: iCommPort.ReadCancel(); sl@0: } sl@0: sl@0: sl@0: void CSerialDesc::IoctlCancel() sl@0: { sl@0: //stop the ioctl if in progress sl@0: CancelNotifiers(NULL); sl@0: sl@0: if (iNotifyStatus) sl@0: { sl@0: iNotifyParamPtr[0] = 0; sl@0: Complete(*iNotifyStatus, -3); sl@0: } sl@0: sl@0: } sl@0: sl@0: TInt CSerialDesc::ReadCompletion (TDes8& /*aBuf*/, TInt aStatus) sl@0: { sl@0: //The read has completed. sl@0: //See if we need to signal 'cos it completed with an error and someone is waiting sl@0: //on a notification. In which case we need to complete the request with the correct results. sl@0: sl@0: if ((aStatus < 0) && (iRequestedSignals&(KNotifyFramingError|KNotifyOverrunError|KNotifyParityError))) //we have a signal outstanding we can deal with here sl@0: { sl@0: switch (aStatus) sl@0: { sl@0: case KErrCommsFrame: //comms framing error sl@0: if (iRequestedSignals&KNotifyFramingError) sl@0: Notify(KNotifyFramingError); sl@0: break; sl@0: sl@0: case KErrCommsOverrun: //comms overrrun error sl@0: if (iRequestedSignals&KNotifyOverrunError) sl@0: Notify(KNotifyOverrunError); sl@0: break; sl@0: sl@0: case KErrCommsParity: //comms parity error sl@0: if (iRequestedSignals&KNotifyParityError) sl@0: Notify(KNotifyParityError); sl@0: break; sl@0: sl@0: default: sl@0: //an error we don't signal sl@0: break; sl@0: sl@0: } sl@0: } sl@0: sl@0: return aStatus; sl@0: } sl@0: sl@0: TBool CSerialDesc::RequestedNotifiesSupported(TInt aRequested) sl@0: { sl@0: //return true if these notifies are OK. 0 if any of them are illegal sl@0: sl@0: TInt mask = ~(NotifiesSupported()); sl@0: return !(aRequested&mask); sl@0: } sl@0: sl@0: TInt CSerialDesc::NotifiesSupported() sl@0: { sl@0: //return which notifies are supported. sl@0: //looks like the driver/server is going to have to be interrogated here sl@0: sl@0: //start with the ones we can fake sl@0: TInt supported = KNotifyFramingError|KNotifyOverrunError|KNotifyParityError; sl@0: sl@0: #ifndef ER5U_NOTIFICATION_SUPPORT_ONLY sl@0: //get the supported ones from C32 sl@0: TCommCaps2 devCap; sl@0: TCommCapsV02& deviceCapabilities = devCap(); sl@0: deviceCapabilities.iNotificationCaps = 0; sl@0: iCommPort.Caps(devCap); sl@0: sl@0: sl@0: //signals sl@0: if (deviceCapabilities.iNotificationCaps & KNotifySignalsChangeSupported) sl@0: supported |= (KNotifyCD|KNotifyCTS|KNotifyDSR|KNotifyRI); sl@0: sl@0: //break interrupt sl@0: if (deviceCapabilities.iNotificationCaps & KNotifyBreakSupported) sl@0: supported |= KNotifyBreakInt; sl@0: sl@0: sl@0: //Data Available sl@0: if (deviceCapabilities.iNotificationCaps & KNotifyDataAvailableSupported) sl@0: supported |= KNotifyDataAvailable; sl@0: sl@0: //Output Empty sl@0: if (deviceCapabilities.iNotificationCaps & KNotifyOutputEmptySupported) sl@0: supported |= KNotifyOutputEmpty; sl@0: sl@0: #endif //ER5U_NOTIFICATION_SUPPORT_ONLY sl@0: sl@0: return supported; sl@0: } sl@0: sl@0: void CSerialDesc::Notify(TInt aVal) sl@0: { sl@0: if (iErrorsNotifier) sl@0: { sl@0: // iNotifyParamPtr[0] = aVal; sl@0: *iRequestDataPtr = aVal; sl@0: iErrorsNotifier->Complete(0); sl@0: } sl@0: } sl@0: sl@0: sl@0: #ifndef ER5U_NOTIFICATION_SUPPORT_ONLY sl@0: void CSerialDesc::NotifyDataAvailable(TRequestStatus& aStatus) sl@0: { sl@0: iCommPort.NotifyDataAvailable(aStatus); sl@0: } sl@0: sl@0: void CSerialDesc::NotifyDataAvailableCancel() sl@0: { sl@0: iCommPort.NotifyDataAvailableCancel(); sl@0: } sl@0: sl@0: void CSerialDesc::NotifyOutputEmpty(TRequestStatus& aStatus) sl@0: { sl@0: iCommPort.NotifyOutputEmpty(aStatus); sl@0: } sl@0: sl@0: void CSerialDesc::NotifyOutputEmptyCancel() sl@0: { sl@0: iCommPort.NotifyOutputEmptyCancel(); sl@0: } sl@0: sl@0: void CSerialDesc::NotifyBreak(TRequestStatus& aStatus) sl@0: { sl@0: iCommPort.NotifyBreak(aStatus); sl@0: } sl@0: sl@0: void CSerialDesc::NotifyBreakCancel() sl@0: { sl@0: iCommPort.NotifyBreakCancel(); sl@0: } sl@0: sl@0: void CSerialDesc::NotifySignalChange(TRequestStatus& aStatus, TUint& aRequestData, TUint aSignalsMask) sl@0: { sl@0: iCommPort.NotifySignalChange(aStatus, aRequestData, aSignalsMask); sl@0: } sl@0: sl@0: void CSerialDesc::NotifySignalChangeCancel() sl@0: { sl@0: iCommPort.NotifySignalChangeCancel(); sl@0: } sl@0: #endif //ER5U_NOTIFICATION_SUPPORT_ONLY sl@0: sl@0: void CSerialDesc::NotifyWriteErrors(TRequestStatus& aStatus, TUint* aRequestData, TUint aSignalsMask) sl@0: { sl@0: iRequestedSignals = aSignalsMask; sl@0: iRequestDataPtr = aRequestData; sl@0: // iNotifyParamPtr = aRequestData; sl@0: aStatus = KRequestPending; sl@0: } sl@0: sl@0: void CSerialDesc::NotifyWriteErrorsCancel() sl@0: { sl@0: iErrorsNotifier->Complete(KErrCancel); sl@0: } sl@0: sl@0: TUint CSerialDesc::Signals() sl@0: { sl@0: return iCommPort.Signals(); sl@0: } sl@0: sl@0: sl@0: void CSerialDesc::CancelNotifiers(const CNotifier* aCompletedNotifier) sl@0: { sl@0: #ifndef ER5U_NOTIFICATION_SUPPORT_ONLY sl@0: if (iDataAvailableNotifier && (aCompletedNotifier != iDataAvailableNotifier)) sl@0: { sl@0: iDataAvailableNotifier->Cancel(); sl@0: delete iDataAvailableNotifier; sl@0: iDataAvailableNotifier = NULL; sl@0: } sl@0: sl@0: if (iOutputEmptyNotifier && (aCompletedNotifier != iOutputEmptyNotifier)) sl@0: { sl@0: iOutputEmptyNotifier->Cancel(); sl@0: delete iOutputEmptyNotifier; sl@0: iOutputEmptyNotifier = NULL; sl@0: } sl@0: sl@0: if (iBreakNotifier && (aCompletedNotifier != iBreakNotifier)) sl@0: { sl@0: iBreakNotifier->Cancel(); sl@0: delete iBreakNotifier; sl@0: iBreakNotifier = NULL; sl@0: } sl@0: sl@0: sl@0: if (iSignalsNotifier && (aCompletedNotifier != iSignalsNotifier)) sl@0: { sl@0: iSignalsNotifier->Cancel(); sl@0: delete iSignalsNotifier; sl@0: iSignalsNotifier = NULL; sl@0: } sl@0: #endif //ER5U_NOTIFICATION_SUPPORT_ONLY sl@0: if (iErrorsNotifier && (aCompletedNotifier != iErrorsNotifier)) sl@0: { sl@0: iErrorsNotifier->Cancel(); sl@0: delete iErrorsNotifier; sl@0: iErrorsNotifier = NULL; sl@0: } sl@0: } sl@0: