diff -r 000000000000 -r a41df078684a kernel/eka/drivers/xyin/d_xyin.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kernel/eka/drivers/xyin/d_xyin.cpp Mon Oct 19 15:55:17 2009 +0100 @@ -0,0 +1,417 @@ +// Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of the License "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// e32\drivers\xyin\d_xyin.cpp +// Generic digitiser driver +// +// + + +#include +#include + +_LIT(KLitDigitiser,"Digitiser"); + +LOCAL_C void sampleDfc(TAny* aPtr) + { + ((DDigitiser*)aPtr)->ProcessRawSample(); + } + +LOCAL_C void penUpDfc(TAny* aPtr) + { + ((DDigitiser*)aPtr)->ProcessPenUp(); + } + +LOCAL_C TInt halFunction(TAny* aPtr, TInt aFunction, TAny* a1, TAny* a2) + { + DDigitiser* pH=(DDigitiser*)aPtr; + return pH->HalFunction(aFunction,a1,a2); + } + +LOCAL_C void rxMsg(TAny* aPtr) + { + DDigitiser& h=*(DDigitiser*)aPtr; + TMessageBase* pM=h.iMsgQ.iMessage; + if (pM) + h.HandleMsg(pM); + } + +DDigitiser::DDigitiser() + : DPowerHandler(KLitDigitiser), + iMsgQ(rxMsg,this,NULL,1), + iSampleDfc(sampleDfc,this,5), + iPenUpDfc(penUpDfc,this,5) + { +// iBufferIndex=0; +// iLastPos=TPoint(0,0); +// iState=EIdle; +// iCount=0; +// iPointerOn=EFalse + } + +TInt DDigitiser::Create() + { + TInt r=DoCreate(); // do hardware-dependent initialisation + + if (r!=KErrNone) + return r; + + __ASSERT_DEBUG(iDfcQ, Kern::Fault("DDigitiser::Create iDfcQ not set", __LINE__)); + iMsgQ.SetDfcQ(iDfcQ); + iSampleDfc.SetDfcQ(iDfcQ); + iPenUpDfc.SetDfcQ(iDfcQ); + + TInt n=iCfg.iPenUpDiscard; // number of samples to delay + iBuffer=(TPoint*)Kern::Alloc(n*sizeof(TPoint)); + if (!iBuffer) + return KErrNoMemory; + + // install the HAL function + r=Kern::AddHalEntry(EHalGroupDigitiser,halFunction,this); + if (r!=KErrNone) + return r; + + iMsgQ.Receive(); + + // wait for pen down + WaitForPenDown(); + + return r; + } + +void DDigitiser::RawSampleValid() +// +// Called by hardware-dependent code when a raw sample is available +// + { + iSampleDfc.Add(); + } + +void DDigitiser::PenUp() +// +// Called by hardware-dependent code when the pen goes up +// + { + iPenUpDfc.Add(); + } + +void DDigitiser::ProcessRawSample() +// +// DFC to process a raw sample +// + { + TPoint p; + TInt r; + TBool ok=SamplesToPoint(p); + if (!ok) + { + // wait for pen to stabilise + __KTRACE_XY2(Kern::Printf("BS")); + WaitForPenUpDebounce(); + return; + } + __KTRACE_XY2(Kern::Printf("GS (%d,%d) %d",p.iX,p.iY,iState)); + switch (iState) + { + case EIdle: + // pen has just gone down + iCount=iCfg.iPenDownDiscard; + iState=EDiscardOnPenDown; + // fall through + case EDiscardOnPenDown: + if (iCount) + { + // still discarding + iCount--; + break; + } + iState=EBufferFilling; + iBufferIndex=0; + iCount=iCfg.iPenUpDiscard; + // fall through + case EBufferFilling: + if (iCount) + { + // buffer still filling + iCount--; + iBuffer[iBufferIndex++]=p; + if (iBufferIndex==iCfg.iPenUpDiscard) + iBufferIndex=0; + break; + } + iState=EBufferFull; + // fall through + case EBufferFull: + r=DelayAndConvertSample(p,iLastPos); + if (r!=KErrNone) + break; // off the screen, so don't issue Pen Down Event + iState=EPenDown; + ResetPenMoveFilter(); + IssuePenDownEvent(); + break; + case EPenDown: + r=DelayAndConvertSample(p,p); + if (r!=KErrNone) + { + iState=EIdle; // off the screen, so treat as pen-up + IssuePenUpEvent(); + break; + } + FilterPenMove(p); + break; + }; + WaitForPenUp(); // request another sample from the hardware + } + +void DDigitiser::ProcessPenUp() +// +// DFC to process pen-up events +// + { + __KTRACE_XY2(Kern::Printf("up %d",iState)); + switch (iState) + { + case EIdle: + case EDiscardOnPenDown: + case EBufferFilling: + case EBufferFull: + iState=EIdle; + break; + case EPenDown: + iState=EIdle; + IssuePenUpEvent(); + break; + } + WaitForPenDown(); // tell the hardware to watch for another pen-down + } + +TBool DDigitiser::SamplesToPoint(TPoint& aPoint) +// +// Average and validate the raw samples from the hardware +// + { +#if defined(__DIGITISER_DEBUG2__) + TBuf<80> buf; +#endif + TInt i; + TInt minx=KMaxTInt; + TInt miny=KMaxTInt; + TInt maxx=KMinTInt; + TInt maxy=KMinTInt; + TInt sumx=0; + TInt sumy=0; + TInt n=iCfg.iNumXYSamples; + for (i=0; imaxx) + maxx=x; + sumx+=x; + TInt y=iY[i]; + if (ymaxy) + maxy=y; + sumy+=y; +// __KTRACE_XY2(buf.AppendFormat(_L("(%d,%d) "),x,y)); + __KTRACE_XY2(Kern::Printf("(%d,%d) ",x,y)); + } +// __KTRACE_XY2(Kern::Printf("%S", buf)); + + TInt spreadx=maxx-minx; + TInt spready=maxy-miny; + if (iCfg.iDisregardMinMax) + { + sumx-=minx; // disregard extremal values in average + sumx-=maxx; + sumy-=miny; + sumy-=maxy; + n-=2; + } + sumx/=n; // average the values + sumy/=n; + if (spreadx=iCfg.iMinX && sumx<=iCfg.iMaxX && sumy>=iCfg.iMinY && sumy<=iCfg.iMaxY) + { + // samples are OK + aPoint.iX=sumx; + aPoint.iY=sumy; + return ETrue; + } + // samples are dodgy + return EFalse; + } + +TInt DDigitiser::DelayAndConvertSample(const TPoint& aSample, TPoint& aScreenPoint) +// +// Pass a sample through the delay line and convert to screen coordinates +// + { + if (iCfg.iPenUpDiscard != 0) + { + TPoint p=iBuffer[iBufferIndex]; // sample leaving delay line + iBuffer[iBufferIndex++]=aSample; // sample entering delay line + if (iBufferIndex==iCfg.iPenUpDiscard) + iBufferIndex=0; + return DigitiserToScreen(p,aScreenPoint); + } + return DigitiserToScreen(aSample,aScreenPoint); + } + +void DDigitiser::IssuePenDownEvent() + { + TRawEvent e; + e.Set(TRawEvent::EButton1Down,iLastPos.iX,iLastPos.iY); + Kern::AddEvent(e); + __KTRACE_XY2(Kern::Printf("D %d,%d",e.Pos().iX,e.Pos().iY)); + } + +void DDigitiser::IssuePenUpEvent() + { + TRawEvent e; + e.Set(TRawEvent::EButton1Up,iLastPos.iX,iLastPos.iY); + Kern::AddEvent(e); + __KTRACE_XY2(Kern::Printf("U %d,%d",e.Pos().iX,e.Pos().iY)); + } + +void DDigitiser::IssuePenMoveEvent(const TPoint& aPoint) + { + TRawEvent e; + e.Set(TRawEvent::EPointerMove,aPoint.iX,aPoint.iY); + Kern::AddEvent(e); + __KTRACE_XY2(Kern::Printf("M %d,%d",e.Pos().iX,e.Pos().iY)); + } + +void DDigitiser::HandleMsg(TMessageBase* aMsg) + { + if (aMsg->iValue) + DigitiserOn(); + else + DigitiserOff(); + aMsg->Complete(KErrNone,ETrue); + } + +TInt DDigitiser::HalFunction(TInt aFunction, TAny* a1, TAny* a2) + { + TInt r=KErrNone; +__KTRACE_OPT(KEXTENSION,Kern::Printf("HalFunction %d", aFunction)); + switch(aFunction) + { + case EDigitiserHalXYInfo: + { + TPckgBuf vPckg; + DigitiserInfo(vPckg()); + Kern::InfoCopy(*(TDes8*)a1,vPckg); + break; + } + case EDigitiserHalSetXYInputCalibration: + { + if(!Kern::CurrentThreadHasCapability(ECapabilityWriteDeviceData,__PLATSEC_DIAGNOSTIC_STRING("Checked by Hal function EDigitiserHalSetXYInputCalibration"))) + return KErrPermissionDenied; + TDigitizerCalibration cal; + kumemget32(&cal,a1,sizeof(TDigitizerCalibration)); + r=SetXYInputCalibration(cal); + break; + } + case EDigitiserHalCalibrationPoints: + TDigitizerCalibration cal; + r=CalibrationPoints(cal); + kumemput32(a1,&cal,sizeof(TDigitizerCalibration)); + break; + case EDigitiserHalSaveXYInputCalibration: + r=SaveXYInputCalibration(); + break; + case EDigitiserHalRestoreXYInputCalibration: + if(!Kern::CurrentThreadHasCapability(ECapabilityWriteDeviceData,__PLATSEC_DIAGNOSTIC_STRING("Checked by Hal function EDigitiserHalRestoreXYInputCalibration"))) + return KErrPermissionDenied; + r=RestoreXYInputCalibration((TDigitizerCalibrationType)(TInt)a1); + break; + case EDigitiserHalSetXYState: + { + if(!Kern::CurrentThreadHasCapability(ECapabilityPowerMgmt,__PLATSEC_DIAGNOSTIC_STRING("Checked by Hal function EDigitiserHalSetXYState"))) + return KErrPermissionDenied; + if ((TBool)a1) + { + TThreadMessage& m=Kern::Message(); + m.iValue = ETrue; + m.SendReceive(&iMsgQ); + } + else + { + TThreadMessage& m=Kern::Message(); + m.iValue = EFalse; + m.SendReceive(&iMsgQ); + } + } + break; + case EDigitiserHalXYState: + kumemput32(a1, (TBool*)&iPointerOn, sizeof(TBool)); + break; + default: + r=KErrNotSupported; + break; + } + return r; + } + +DECLARE_STANDARD_EXTENSION() + { + __KTRACE_OPT(KEXTENSION,Kern::Printf("Starting digitiser driver")); + if (Kern::SuperPage().iCpuId & KCpuIdISS) + return KErrNone; // no digitiser on ARMULATOR + DDigitiser* pD=DDigitiser::New(); + TInt r=KErrNoMemory; + if (pD) + r=pD->Create(); + __KTRACE_OPT(KEXTENSION,Kern::Printf("Returning %d",r)); + return r; + } + +#ifdef __BUILD_DEVICE_DRIVER__ +class DDigitiserPdd : public DPhysicalDevice + { +public: + virtual TInt Install(); + virtual void GetCaps(TDes8& aDes) const; + virtual TInt Create(DBase*& aChannel, TInt aUnit, const TDesC8* anInfo, const TVersion& aVer); + virtual TInt Validate(TInt aUnit, const TDesC8* anInfo, const TVersion& aVer); + }; + +_LIT(KPddName,"XYInput"); + +TInt DDigitiserPdd::Install() + { + return SetName(&KPddName); + } + +void DDigitiserPdd::GetCaps(TDes8&) const + { + } + +TInt DDigitiserPdd::Create(DBase*& aChannel, TInt, const TDesC8*, const TVersion&) + { + aChannel=NULL; + return KErrNone; + } + +TInt DDigitiserPdd::Validate(TInt, const TDesC8*, const TVersion&) + { + return KErrNotSupported; + } + +DECLARE_EXTENSION_PDD() + { + return new DDigitiserPdd; + } +#endif