📄 tchmain.c
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
/*++
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.
@doc EX_TOUCH_DDI INTERNAL DRIVERS MDD TOUCH_PANEL
Module Name:
@module mdd.c
Abstract:
This module contains the DDI implementation and the supporting administriva.
if DBGCAL is defined, the results of the calibration calculations are
displayed following the setting of calibration data. <nl>
Functions:
TouchPanelpDetach
TouchPanelpAttach
TouchPanelpISR
TouchPanelGetDeviceCaps
TouchPanelSetMode
TouchPanelPowerHandler
TouchPanelEnable
TouchPanelDisable
TouchPanelReadCalibrationPoint
TouchPanelReadCalibrationAbort
Notes:
--*/
#include <windows.h>
#include <types.h>
#include <memory.h>
#include <nkintr.h>
#include <tchddi.h>
#include <tchddsi.h>
extern PFN_TOUCH_PANEL_CALLBACK v_pfnCgrPointCallback;
extern PFN_TOUCH_PANEL_CALLBACK v_pfnCgrCallback;
// To track if we are in OOM state.
BOOL _bTchThreadHighPriority = FALSE;
//
// Run at high priority so that we can service our interrupts quickly.
//
#define DEFAULT_THREAD_PRIORITY 109
#define DEFAULT_THREAD_HIGH_PRIORITY 109
#define CAL_DELTA_RESET 20
#define CAL_HOLD_STEADY_TIME 1500
// If we are a DLL, we can define our dpCurSettings
#ifdef DEBUG
DBGPARAM dpCurSettings = {
TEXT("Touch"), {
TEXT("Samples"),TEXT("Calibrate"),TEXT("Stats"),TEXT("Thread"),
TEXT("TipState"),TEXT("Init"),TEXT(""),TEXT(""),
TEXT(""),TEXT("Misc"),TEXT("Delays"),TEXT("Timing"),
TEXT("Alloc"),TEXT("Function"),TEXT("Warning"),TEXT("Error") },
0xC020 // warning, error, init
};
#endif
//
// Calibration State defintions
//
// @const LONG | CalibrationAvailable |
// Indicates that calibration is not in progress and is available for use.
//
// @const LONG | CalibrationActive |
// Indicates that calibration is active.
//
// @const LONG | CalibrationInactive |
// Indicates that calibration is inactive and waiting for completion.
//
// @const LONG | CalibrationAborted |
// Indicates that calibration is in the process of aborting via user request.
//
#define CalibrationInactive 0x00
#define CalibrationWaiting 0x01
#define CalibrationDown 0x02
#define CalibrationValid 0x03
#define CalibrationAborted 0x04
// Scale factor to support sub-pixel resolutions
#define X_SCALE_FACTOR 4
#define Y_SCALE_FACTOR 4
//
// Macro for absolute value.
//
#define ABS(x) ((x) >= 0 ? (x) : (-(x)))
//
// Internal Function Prototypes
//
static ULONG
TouchPanelpISR(
PVOID Reserved
);
ULONG culReferenceCount; //@globalvar ULONG | culReferenceCount | Count of attached threads
HANDLE hThread; //@globalvar HANDLE | hThread | Handle of attached thread
CRITICAL_SECTION csMutex; //@globalvar CRITICAL_SECTION | csMutex | Critical section
HANDLE hTouchPanelEvent; //@globalvar HANDLE | hTouchPanelEvent | Holds the event handle for
// touch panel event notification.
HANDLE hCalibrationSampleAvailable; //@globalvar HANDLE | hCalibrationSampleAvailable | Holds the event handle for
// notification that a calibration
// mapping point is available.
INT CalibrationState; //@globalvar INT | CalibrationState | Flag which indicates the
// state of calibration: Available,
// Active or Inactive.
static DWORD gThreadPriority; //@globalvar DWORD | gThreadPriority | Interrupt thread normal priority
static DWORD gThreadHighPriority; //@globalvar DWORD | gThreadHighPriority | Interrupt thread high priority
// The MIN_CAL_COUNT is defined in the PDD, since each touch panel
// has different characteristics. The value should be high enough
// to prevent spurious touches, but low enough that the user doesn't
// have to hold the pen on each crosshair too long.
extern int MIN_CAL_COUNT;
LONG lCalibrationXCoord; //@globalvar LONG | lCalibrationXCoord | Holds the X coordinate
// corresponding to the touch.
LONG lCalibrationYCoord; //@globalvar LONG | lCalibrationYCoord | Holds the Y coordinate
// corresponding to the touch.
INT32 DisplayWidth;
INT32 DisplayHeight;
DWORD gdwTouchIstTimeout = INFINITE; // hold csMutex when accessing this
//
//@globalvar PFN_TOUCH_PANEL_CALLBACK | v_pfnPointCallback |
// Pointer to the application supplied function for receiving points.
//
PFN_TOUCH_PANEL_CALLBACK v_pfnPointCallback;
//**********************************************************************
// The following routines are internal helpers, and are not visible to
// the DDI layer.
// @doc IN_TOUCH_DDI INTERNAL DRIVERS MDD TOUCH_PANEL
//**********************************************************************
/*++
Autodoc Information:
@func VOID | TouchPanelpDetach |
Performs cleanup and frees memory when owning process detaches.
@devnote
We let ExitProcess handle the shutting down of the ISR thread.
--*/
static VOID
TouchPanelpDetach(
VOID
)
{
}
/*++
Autodoc Information:
@func BOOL | TouchPanelpAttach |
This routine performs the initialization for the touch panel.
@rdesc
If the function succeeds the return value is TRUE, otherwise, it is FALSE.
--*/
static BOOL
TouchPanelpAttach(
VOID
)
{
//
// Create the event for touch panel events.
// If creation fails, return failure.
//
hTouchPanelEvent = CreateEvent( NULL,
FALSE, // Not manual reset
FALSE, // Not signalled
NULL
);
if ( !hTouchPanelEvent )
return ( FALSE );
//
// Create the event for signaling when a calibration sample has been sent.
//
hCalibrationSampleAvailable =
CreateEvent( NULL,
FALSE, // Not manual reset
FALSE, // Not signalled
NULL
);
if ( !hCalibrationSampleAvailable )
return ( FALSE );
DdsiTouchPanelDisable(); // Insure the device is disabled
//
// Initialize the critical section, flags, callbacks, reference count,
// sample rate.
//
InitializeCriticalSection( &csMutex );
CalibrationState = CalibrationInactive;
v_pfnPointCallback = NULL;
culReferenceCount = 0;
//
// Initialize calibration info used to convert uncalibrated to calibrated
// points so that function is a noop.
//
TouchPanelSetCalibration( 0, NULL, NULL, NULL, NULL );
return ( TRUE );
}
/*++
Autodoc Information:
@func ULONG | TouchPanelpISR |
This routine is the thread which handles touch panel events.
The event that this thread synchronizes on is signaled by the PDD based on
the sampling rate, typically 10ms.
@rdesc
Never returns.
--*/
static ULONG
TouchPanelpISR(
PVOID Reserved //@parm Reserved, not used.
)
{
TOUCH_PANEL_SAMPLE_FLAGS SampleFlags = 0;
INT32 RawX, CalX;
INT32 RawY, CalY;
UINT32 MaxX = DisplayWidth * X_SCALE_FACTOR;
UINT32 MaxY = DisplayHeight * Y_SCALE_FACTOR;
UINT32 CurrentDown = 0;
static LONG CX;
static LONG CY;
static LONG XBase;
static LONG YBase;
static int CalibrationSampleCount;
static BOOL fSetBase;
static DWORD BaseTime;
static BOOL fGotSample;
PFN_TOUCH_PANEL_CALLBACK pfnCallback;
for ( ; ; )
{
wait_for_event:
WaitForSingleObject( hTouchPanelEvent, gdwTouchIstTimeout );
EnterCriticalSection( &csMutex );
DEBUGMSG(ZONE_THREAD, (TEXT("TCH_INTR\r\n")) );
// Give the pdd the down state of the previous sample
if ( CurrentDown )
SampleFlags |= TouchSamplePreviousDownFlag;
else
SampleFlags &= ~TouchSamplePreviousDownFlag;
DdsiTouchPanelGetPoint( &SampleFlags, &RawX, &RawY ); // Get the point info
if ( SampleFlags & TouchSampleIgnore )
{
// do nothing, not a valid sample
LeaveCriticalSection( &csMutex );
goto wait_for_event;
}
if ( SampleFlags & TouchSampleValidFlag )
{
// Set the previous down state for our use, since the pdd may not
// have preserved it.
if ( CurrentDown )
SampleFlags |= TouchSamplePreviousDownFlag;
else
SampleFlags &= ~TouchSamplePreviousDownFlag;
CurrentDown = SampleFlags & TouchSampleDownFlag;
}
if ( CalibrationState )
{
//
// At this point we know that calibration is active.
//
// Typically, the user touches the panel then converges to the
// displayed crosshair. When the tip state transitions to
// the up state, we forward the last valid point to the callback
// function.
//
DEBUGMSG(ZONE_SAMPLES, (TEXT("**** Calibration point (%d, %d), flags 0x%4.4X\r\n"),
RawX, RawY, SampleFlags) );
// Skip if not valid.
if ( !(SampleFlags & TouchSampleValidFlag) )
{
LeaveCriticalSection( &csMutex );
goto wait_for_event;
}
// Must see down transition.
if ( (SampleFlags & (TouchSampleDownFlag|TouchSamplePreviousDownFlag)) ==
TouchSampleDownFlag )
{
CalibrationState = CalibrationDown;
fSetBase = TRUE;
CalibrationSampleCount = 0;
fGotSample = FALSE;
}
// Only look at stuff if we saw a down transition.
if ( (CalibrationState == CalibrationDown) && !fGotSample )
{
if ( SampleFlags & TouchSampleDownFlag )
{
long DeltaX, DeltaY;
CalibrationSampleCount++;
CX = RawX;
CY = RawY;
if ( fSetBase )
{
XBase = CX;
YBase = CY;
BaseTime = GetTickCount();
fSetBase = FALSE;
}
DeltaX = CX - XBase;
DeltaY = CY - YBase;
if ( (GetTickCount() - BaseTime) > CAL_HOLD_STEADY_TIME )
{
fGotSample = TRUE;
}
else if ( ( ABS(DeltaX) > CAL_DELTA_RESET ) ||
( ABS(DeltaY) > CAL_DELTA_RESET ) )
{
RETAILMSG(1, (TEXT("M %ld,%ld %ld,%ld %ld,%ld"),
XBase,YBase, CX,CY, DeltaX,DeltaY));
fSetBase = TRUE;
}
}
else
{
// They lifted the pen, see if we will accept coordinate.
if ( CalibrationSampleCount >= MIN_CAL_COUNT )
{
fGotSample = TRUE;
}
else
{
CalibrationState = CalibrationWaiting;
}
}
if ( fGotSample )
{
CalibrationState = CalibrationValid;
lCalibrationXCoord = CX;
lCalibrationYCoord = CY;
SetEvent(hCalibrationSampleAvailable);
}
}
LeaveCriticalSection( &csMutex );
}
else
{
pfnCallback = v_pfnPointCallback;
if ( pfnCallback != NULL )
{
if( SampleFlags & TouchSampleIsCalibratedFlag )
{ // Sample already calibrated by PDD
CalX = RawX;
CalY = RawY;
}
else
{ // Not previously calibrated, do it now.
TouchPanelCalibrateAPoint( RawX, RawY, &CalX, &CalY );
SampleFlags |= TouchSampleIsCalibratedFlag;
}
LeaveCriticalSection( &csMutex );
// Bounds check this value
if( CalX < 0 )
CalX = 0;
else if( MaxX && ((UINT32)CalX >= MaxX) )
CalX = MaxX - X_SCALE_FACTOR;
if( CalY < 0 )
CalY = 0;
else if( MaxY && ((UINT32)CalY >= MaxY) )
CalY = MaxY - Y_SCALE_FACTOR ;
DEBUGMSG( ZONE_SAMPLES,
(TEXT("**** Queuing point (%d, %d), flags 0x%4.4X\r\n"),
CalX, CalY, SampleFlags) );
#ifdef DEBUG
{
static DWORD SampleCt;
if( SampleFlags & TouchSampleDownFlag )
SampleCt++;
else
{
DEBUGMSG( ZONE_TIMING,
(TEXT("%d down samples queued\r\n"),
SampleCt) );
SampleCt = 0;
}
}
#endif
(pfnCallback)( SampleFlags, CalX, CalY);
}
else
{
LeaveCriticalSection( &csMutex );
}
}
}
return ( TRUE );
}
#define KEYNAME_TOUCH_DRIVER TEXT("\\Drivers\\BuiltIn\\Touch")
#define VALNAME_THREAD_PRIO TEXT("Priority256")
#define VALNAME_THREAD_HIGH_PRIO TEXT("HighPriority256")
/*++
Autodoc Information:
@func DWORD | TouchPanelpGetPriority |
This routine reads the TouchPanelpISR thread priority from the registry.
--*/
static VOID TouchPanelpGetPriority(DWORD *ThrdPrio, DWORD *ThrdHighPrio)
{
HKEY hKey;
DWORD dwType;
DWORD dwSize;
DWORD dwStatus;
dwStatus = RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
KEYNAME_TOUCH_DRIVER,
0,
0,
&hKey
);
if (dwStatus)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -