--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kernel/eka/drivers/xyin/d_xyin.cpp Thu Dec 17 09:24:54 2009 +0200
@@ -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 <drivers/xyin.h>
+#include <kernel/kern_priv.h>
+
+_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; i<n; i++)
+ {
+ TInt x=iX[i];
+ if (x<minx)
+ minx=x;
+ if (x>maxx)
+ maxx=x;
+ sumx+=x;
+ TInt y=iY[i];
+ if (y<miny)
+ miny=y;
+ if (y>maxy)
+ 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.iSpreadX && spready<iCfg.iSpreadY && sumx>=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<TDigitiserInfoV01> 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