📄 iodev.cpp
字号:
// IODEV.CPP
//
// Copyright (c) 1997-2002 Symbian Ltd. All rights reserved.
#include "iodev.h"
#include "iodef.h"
#include "oplutil.h"
#include "serial.h"
#include "module.h"
/*
* Arm THUMB requires alignment on the 16bit boundary.
*/
#if defined(__CW32__)
#define __LEAVE_IF_UNALIGNED(aPtr,aLeaveError)\
if((TUint32)(aPtr)&1)\
User::Leave((aLeaveError));
#else // Not CodeWarrior
#define __LEAVE_IF_UNALIGNED(aPtr,aLeaveError)\
if((TUint16)(aPtr)&1)\
User::Leave((aLeaveError));
#endif
_LIT(KOplrIODEV,"OplrIODEV");
//
// Class COplIOTimer
//
COplIOTimer::COplIOTimer(TInt16 aHandle)
:COplIO(aHandle)
{
}
void COplIOTimer::ConstructL(TBuf<256>& /*aDevName*/, TInt16 /*aMode*/)
{
User::LeaveIfError(iTimer.CreateLocal());
}
COplIOTimer::~COplIOTimer()
{
iTimer.Cancel(); // eb205: is any consumption of signals necessary here?
iTimer.Close();
}
void COplIOTimer::RunFunctionL(TInt aFuncNo,TIORequest*& aIOStatus,TOplReqStatus* aOplStatusPtr,TAny* aParam1,TAny* /*aParam2*/)
// eb205: I've replaced calls to "User::Leave(KOplErrInvalidIO)" with calls
// to "User::RequestComplete(statusPtr,KErrArgument)"
{
aIOStatus=new(ELeave) TOplIORequest(aOplStatusPtr,EActivePriorityWsEvents+3);
TRequestStatus* statusPtr=&aIOStatus->Status();
switch (aFuncNo)
{
case (FRELATIVE):
{
TInt32 time=OplUtil::GetLong(aParam1); // maybe should check range
iTimer.After(*statusPtr,TTimeIntervalMicroSeconds32(time*100000));
break;
}
case (FABSOLUTE):
{
TDateTime date(1970,TMonth(0),0,0,0,0,0);
TTime time(date);
TTimeIntervalSeconds secs=(TUint32)OplUtil::GetLong(aParam1);
iTimer.At(*statusPtr,(time+secs));
break;
}
case (FCLOSE):
{
(TheRuntime()->IOCollection()).RemoveObject(iHandle);
User::RequestComplete(statusPtr,KErrNone);
break;
}
case (FCANCEL):
{
iTimer.Cancel();
User::RequestComplete(statusPtr,KErrNone);
break;
}
default:
{
User::RequestComplete(statusPtr,KErrArgument);
return; // return here as there's been an error
}
}
}
//
// Class COplIOComm
//
_LIT(KCommPortName,"COMM::");
_LIT(KUartCsyName,"ECUART");
COplIOComm::COplIOComm(TInt16 aHandle)
:COplIO(aHandle)
{
}
void COplIOComm::ConstructL(TBuf<256>& aDevName,TInt16 aMode)
{
if (aDevName.Length()==5)
{
TChar port=aDevName[4];
port.UpperCase();
if (port.IsAlpha())
{
port-='A'-'0'; // TTY:A is COMM0, TTY:B is COMM1 etc.
User::LeaveIfError(iSession.Connect());
User::LeaveIfError(iSession.LoadCommModule(KUartCsyName));
TBuf<16> commPort=KCommPortName();
commPort.Append(port);
User::LeaveIfError(iPort.Open(iSession,commPort,ECommExclusive));
if (aMode==-1) // then try to set OPL1993 defaults
{
TCommConfig cBuf;
TCommConfigV01 &c=cBuf();
iPort.Config(cBuf);
c.iRate=EBps9600;
c.iDataBits=EData8;
c.iStopBits=EStop1;
c.iParity=EParityNone;
c.iHandshake=KConfigObeyCTS;
c.iParityError=KConfigParityErrorFail;
c.iFifo=EFifoDisable;
c.iTerminatorCount=0;
c.iXonChar=0x11;
c.iXoffChar=0x13;
c.iSIREnable=ESIRDisable;
User::LeaveIfError(iPort.SetConfig(cBuf));
}
return;
}
}
User::Leave(KOplErrInvalidIO);
}
void COplIOComm::RunFunctionL(TInt aFuncNo,TIORequest*& aIOStatus,TOplReqStatus* aOplStatusPtr, TAny* aParam1, TAny* aParam2)
// eb205: I've replaced calls to "User::Leave(KOplErrInvalidIO)" with calls
// to "User::RequestComplete(statusPtr,KErrArgument)"
{
if (aFuncNo==FREAD)
{
__LEAVE_IF_UNALIGNED(aParam1,KOplErrBadAlignment); // No statusPtr to RequestComplete against, at this point.
aIOStatus=new(ELeave) TOplIOReadRequest(aOplStatusPtr,EActivePriorityWsEvents+5,(TUint8*)aParam1,aParam2);
iPort.Read(aIOStatus->Status(),((TOplIOReadRequest*)aIOStatus)->iPtr8);
}
else if (aFuncNo==FWRITE)
{
__LEAVE_IF_UNALIGNED(aParam1,KOplErrBadAlignment); // No statusPtr to RequestComplete against, at this point.
aIOStatus=new(ELeave) TOplIOPtrRequest(aOplStatusPtr,EActivePriorityWsEvents+5,(TUint8*)aParam1,aParam2);
iPort.Write(aIOStatus->Status(),((TOplIOPtrRequest*)aIOStatus)->iPtr8);
}
else
{
aIOStatus=new(ELeave) TOplIORequest(aOplStatusPtr,EActivePriorityWsEvents+5);
TRequestStatus* statusPtr=&aIOStatus->Status();
switch (aFuncNo)
{
case (FCLOSE):
(TheRuntime()->IOCollection()).RemoveObject(iHandle);
User::RequestComplete(statusPtr,KErrNone);
break;
case (FCANCEL):
iPort.ReadCancel();
iPort.WriteCancel();
iPort.Cancel();
User::RequestComplete(statusPtr,KErrNone);
break;
case (FFLUSH):
iPort.ResetBuffers();
User::RequestComplete(statusPtr,KErrNone); // eb205: I've added this
break;
case (FSET):
{
TCommConfig configBuf;
TCommConfigV01& config=configBuf();
iPort.Config(configBuf);
P_SRCHAR& newConfig=*(P_SRCHAR*)aParam1;
config.iRate=(TBps)(Max(newConfig.tbaud,newConfig.rbaud)-1);
config.iDataBits=(TDataBits)(P_DATA_MASK&newConfig.frame);
config.iStopBits=(newConfig.frame&P_TWOSTOP)?EStop2:EStop1;
config.iParity=(newConfig.frame&P_PARITY)?((TParity)newConfig.parity):EParityNone;
config.iHandshake=Handshake(newConfig.hand);
config.iParityError=(newConfig.flags&P_IGNORE_PARITY)?KConfigParityErrorIgnore:KConfigParityErrorFail;
config.iXonChar=newConfig.xon;
config.iXoffChar=newConfig.xoff;
const TInt returnValue=Terminators(OplUtil::GetLong(&newConfig.tmask),config.iTerminator);
if (returnValue<0)
{
User::RequestComplete(statusPtr,returnValue);
return; // return here as there's been an error
}
config.iTerminatorCount=returnValue;
User::RequestComplete(statusPtr,iPort.SetConfig(configBuf));
break;
}
case (FSENSE):
{
TCommConfig configBuf;
TCommConfigV01& config=configBuf();
iPort.Config(configBuf);
P_SRCHAR& out=*(P_SRCHAR*)aParam1;
out.tbaud=out.rbaud=(TUint8)((config.iRate==EBpsSpecial)?0:(config.iRate+1)); // EBpsSpecial returned as zero
out.frame=(TUint8)(config.iDataBits|((config.iStopBits==EStop2)?P_TWOSTOP:0)|((config.iParity==0)?0:P_PARITY));
out.parity=(TUint8)config.iParity;
out.hand=Handshake(config.iHandshake);
out.xon=config.iXonChar;
out.xoff=config.iXoffChar;
out.flags=(TUint8)((config.iParityError==KConfigParityErrorIgnore)?P_IGNORE_PARITY:0);
TUint32 terminatorMask=0;
for (TInt i=0; i<config.iTerminatorCount; ++i)
{
TInt pos=config.iTerminator[i];
if (pos<0 || pos>31)
{
User::RequestComplete(statusPtr,KErrGeneral); // eb205: this was User::Leave(KOplErrInvalidIO)
return; // return here as there's been an error
}
terminatorMask|=(0x1<<pos);
}
OplUtil::PutLong(&out.tmask,terminatorMask);
User::RequestComplete(statusPtr,KErrNone);
break;
}
case (FTEST):
OplUtil::PutWord((TUint16*)aParam1,(TUint16)iPort.QueryReceiveBuffer());
User::RequestComplete(statusPtr,KErrNone);
break;
case (FINQ):
{
TCommCaps capsBuf;
TCommCapsV01& caps=capsBuf();
iPort.Caps(capsBuf);
OplUtil::PutLong(aParam1,(TInt32)caps.iRate);
TUint flags=caps.iDataBits;
if (caps.iStopBits&KCapsStop2)
flags|=P_SRINQ_STOP2;
flags|=((caps.iParity&~KCapsParityNone)<<4);
if (caps.iSignals&KCapsSignalDTRSupported)
flags|=P_SRINQ_SETDTR;
if ((caps.iHandshake&KCapsObeyXoffSupported) && (caps.iHandshake&KCapsSendXoffSupported))
flags|=P_SRINQ_XONXOFF;
OplUtil::PutWord((TUint16*)aParam1+2,(TUint16)flags);
User::RequestComplete(statusPtr,KErrNone);
break;
}
case (FCTRL):
{
TUint signals=iPort.Signals(KSignalCTS|KSignalDSR|KSignalDCD);
*(TUint8*)aParam1=(TUint8)signals;
TUint8 setDTR=*((TUint8*)aParam1+1);
if (setDTR==1)
iPort.SetSignalsToMark(KSignalDTR);
else if (setDTR==2)
iPort.SetSignalsToSpace(KSignalDTR);
User::RequestComplete(statusPtr,KErrNone);
break;
}
case (FXSET):
{
TCommConfig cBuf;
Mem::Copy(&cBuf(),aParam1,sizeof(TCommConfigV01));
User::RequestComplete(statusPtr,iPort.SetConfig(cBuf));
break;
}
case (FXSENSE):
{
TCommConfig cBuf;
iPort.Config(cBuf);
Mem::Copy(aParam1,&cBuf(),sizeof(TCommConfigV01));
User::RequestComplete(statusPtr,KErrNone);
break;
}
case (FXINQ):
{
TCommCaps caps;
iPort.Caps(caps);
Mem::Copy(aParam1,&caps(),sizeof(TCommCapsV01));
User::RequestComplete(statusPtr,KErrNone);
break;
}
case (FXCTRL):
{
OplUtil::PutWord((TUint16*)aParam1,(TUint16)iPort.Signals(KSignalCTS|KSignalDSR|KSignalDCD|KSignalRNG|KSignalRTS|KSignalDTR));
TUint set=OplUtil::GetWord((TUint16*)aParam1+1);
TUint clear=OplUtil::GetWord((TUint16*)aParam1+2);
iPort.SetSignalsToMark(set&~clear);
iPort.SetSignalsToSpace(clear&~set);
User::RequestComplete(statusPtr,KErrNone);
break;
}
default:
User::RequestComplete(statusPtr,KErrArgument);
return; // return here as there's been an error
}
}
}
TUint COplIOComm::Handshake(TUint8 aOpl1993Handshake)
{
TUint opler1Handshake;
if (aOpl1993Handshake&P_IGN_CTS)
opler1Handshake=0;
else
opler1Handshake=KConfigObeyCTS;
opler1Handshake|=(aOpl1993Handshake&0x3); // Obey/Send Xoff
return opler1Handshake|((aOpl1993Handshake&0x78)<<1);
}
TUint8 COplIOComm::Handshake(TUint aOpler1Handshake)
{
TUint opl1993Handshake=0;
if (!(aOpler1Handshake&KConfigObeyCTS))
opl1993Handshake=P_IGN_CTS;
opl1993Handshake|=(aOpler1Handshake&0x3);
return (TUint8)(opl1993Handshake|((aOpler1Handshake>>1)&0x78));
}
TInt COplIOComm::Terminators(TUint32 aMask,TText8* charPtr)
{
TInt count=0;
for (TInt ii=0;ii<32;ii++)
{
if ((aMask>>ii)&0x1)
{
count++;
if (count>KConfigMaxTerminators)
{
return KErrNotSupported;
}
*charPtr++=(TUint8)ii;
}
}
return count;
}
COplIOComm::~COplIOComm()
{
if (iPort.IsOpen())
{
iPort.ReadCancel();
iPort.WriteCancel();
iPort.Cancel();
// eb205: is any consumption of signals necessary here?
}
iPort.Close();
iSession.Close();
}
//
// Class COplIOFile
//
COplIOFile::COplIOFile(TInt16 aHandle)
:COplIO(aHandle)
{
}
void COplIOFile::DoOpenFileL(RFs& aRFs,TBuf<256>& aFileName,TUint aMode)
{
User::LeaveIfError(iFile.Open(aRFs,aFileName,aMode));
// If we're in text mode, check whether we have opened a Unicode text file or not
if (aMode&EFileStreamText)
{
// Read the first two bytes of the file
HBufC8* tempBuf=HBufC8::NewLC(2);
TPtr8 ptr(tempBuf->Des());
User::LeaveIfError(iFile.Read(ptr,2));
if (!(ptr[0]==0xFF && ptr[1]==0xFE) && !(ptr[0]==0xFE && ptr[1]==0xFF)) // Not Unicode
iUnicodeTextFile=EFalse;
CleanupStack::PopAndDestroy(); //tempBuf
// Reset the file to the start for any future use
TInt currentPos=0;
User::LeaveIfError(iFile.Seek(ESeekStart,currentPos));
}
}
void COplIOFile::ConstructL(TBuf<256>& aFileName,TInt16 aMode)
{
RFs& fs=TheRuntime()->ConEnv()->FsSession();
iMode=aMode;
const TUint mode=GetModeL();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -