📄 poll.c
字号:
for( timeIdx = axisMask; timeIdx<= portMask; timeIdx=(timeIdx+1) | axisMask )
{
if( BeforeTimes[timeIdx] > beforeThresholdTime )
{
beforeThresholdTime = BeforeTimes[timeIdx];
afterThresholdTime = AfterTimes[timeIdx];
}
}
/*
* Convert the CPU specific timing values into 'wall clock'
* values so that they can be compared with the previous
* poll values and so that the range will be dependent on
* the gamecard/joystick characteristics, not the CPU
* and counter implementation.
* Use a ULONGLONG temp to avoid overflow.
*/
{
ULONGLONG u64Temp;
u64Temp = beforeThresholdTime * Global.CounterScale;
beforeThresholdTime = (ULONG)(u64Temp >> SCALE_SHIFT);
u64Temp = afterThresholdTime * Global.CounterScale;
afterThresholdTime = (ULONG)(u64Temp >> SCALE_SHIFT);
}
delta = afterThresholdTime - beforeThresholdTime;
if( delta > DeviceExtension->ScaledThreshold )
{
/*
* We took an unacceptable hit so only change the value
* if we know the last value is no longer correct
* Since the real time is somewhere between the before and
* after, take the value closer to the last value.
*/
if( fApproximate )
{
/*
* Be careful not to turn a failure into a success
*/
if( NT_SUCCESS(ntStatus) )
{
ntStatus = STATUS_TIMEOUT;
}
}
else
{
ntStatus = STATUS_DEVICE_NOT_CONNECTED;
}
if( Axis[axisIdx] >= AXIS_FULL_SCALE )
{
/*
* The previous poll was a timeout
*/
if( afterThresholdTime < AXIS_FULL_SCALE )
{
/*
* This poll is not a timeout so split the
* difference since there is nothing else
* to use for an estimate.
* Since these values are scaled, it would
* be perfectly legitimate for their sum to
* be greater than 32 bits.
*/
Axis[axisIdx] = (beforeThresholdTime>>1)
+ (afterThresholdTime>>1);
HGM_DBGPRINT( FILE_POLL | HGM_BABBLE2, \
("HGM_AnalogPoll:Axis=%d, using glitch average %04x",\
axisIdx, Axis[axisIdx] ) ) ;
}
else
{
/*
* Since the previous poll was a timeout and
* there is no evidence that this is not, call
* this a timeout.
*/
ntStatus = STATUS_DEVICE_NOT_CONNECTED;
HGM_DBGPRINT( FILE_POLL | HGM_BABBLE2, \
("HGM_AnalogPoll:Axis=%d, repeating timeout on glitch",\
axisIdx ) ) ;
}
}
else if( beforeThresholdTime > Axis[axisIdx] )
{
Axis[axisIdx] = beforeThresholdTime;
HGM_DBGPRINT( FILE_POLL | HGM_BABBLE2, \
("HGM_AnalogPoll:Axis=%d, using smaller glitch limit %04x",\
axisIdx, Axis[axisIdx] ) ) ;
}
else if( afterThresholdTime < Axis[axisIdx] )
{
Axis[axisIdx] = afterThresholdTime;
HGM_DBGPRINT( FILE_POLL | HGM_BABBLE2, \
("HGM_AnalogPoll:Axis=%d, using larger glitch limit %04x",\
axisIdx, Axis[axisIdx] ) ) ;
}
else
{
HGM_DBGPRINT( FILE_POLL | HGM_BABBLE2, \
("HGM_AnalogPoll:Axis=%d, repeating previous on glitch %04x",\
axisIdx, Axis[axisIdx] ) ) ;
}
}
else
{
if( (delta <<= 1) < DeviceExtension->ScaledThreshold )
{
HGM_DBGPRINT( FILE_POLL | HGM_BABBLE2, \
("HGM_AnalogPoll: Updating ScaledThreshold from %d to %d",\
DeviceExtension->ScaledThreshold, delta ) ) ;
/*
* Fastest change yet, update
*/
DeviceExtension->ScaledThreshold = delta;
}
/*
* It is possible that afterThresholdTime is greater
* than the timeout limit but since the purpose of
* the timeout is to prevent excessive sampling of
* the gameport, the success or failure of an
* uninterrupted poll around this limit is not
* important.
* Since these values are scaled, it would be
* perfectly legitimate for their sum to be greater
* than 32 bits and the 1 bit of lost resolution is
* utterly negligable.
*/
Axis[axisIdx] = (beforeThresholdTime>>1)
+ (afterThresholdTime>>1);
}
}
}
}
}
HGM_DBGPRINT( FILE_POLL | HGM_BABBLE2, \
("HGM_AnalogPoll:X=%d, Y=%d, R=%d, Z=%d Buttons=%d,%d,%d,%d",\
Axis[0], Axis[1], Axis[2], Axis[3],\
Button[0],Button[1],Button[2],Button[3] ) ) ;
HGM_EXITPROC(FILE_POLL|HGM_FEXIT, "HGM_AnalogPoll", ntStatus);
return ntStatus;
} /* HGM_AnalogPoll */
#pragma warning( default:4701 )
#pragma optimize( "", on )
/*****************************************************************************
*
* @doc EXTERNAL
*
* @func NTSTATUS | HGM_UpdateLatestPollData |
*
* Do whatever polling is required and possible to update the
* LastGoodAxis and LastGoodButton arrays in the DeviceExtension.
* Handles synchronization and non-fatal errors.
* <nl>This routine cannot be pageable as HID can make reads at
* dispatch-level.
*
* @parm IN OUT PDEVICE_EXTENSION | DeviceExtension |
*
* Pointer to the device extension containing the data to be updated
* and the functions and to use.
*
* @rvalue STATUS_SUCCESS | success
* @rvalue STATUS_DEVICE_CONFIGURATION_ERROR | Invalid configuration specified
*
*****************************************************************************/
#define APPROXIMATE_FAILS TRUE
NTSTATUS
HGM_UpdateLatestPollData
(
IN OUT PDEVICE_EXTENSION DeviceExtension
)
{
NTSTATUS ntStatus;
KIRQL oldIrql;
LONG axisIdx;
/*
* Acquire the global spinlock
* Read / Writes are made at dispatch level.
*/
KeAcquireSpinLock(&Global.SpinLock, &oldIrql );
/*
* First gain exclusive access to the hardware
*/
ntStatus = (*DeviceExtension->AcquirePort)( DeviceExtension->PortContext );
if( NT_SUCCESS(ntStatus) )
{
/*
* If it's available, let the hardware do the work
*/
if( DeviceExtension->ReadAccessorDigital )
{
ntStatus = (*DeviceExtension->ReadAccessorDigital)(DeviceExtension->GameContext,
DeviceExtension->resistiveInputMask,
APPROXIMATE_FAILS,
&DeviceExtension->LastGoodAxis[0],
&DeviceExtension->LastGoodButton[0]);
}
else
{
ntStatus = HGM_AnalogPoll(DeviceExtension,
DeviceExtension->resistiveInputMask,
APPROXIMATE_FAILS,
&DeviceExtension->LastGoodAxis[0],
&DeviceExtension->LastGoodButton[0]);
}
/*
* Either way, release the hardware ASAP
*/
(*DeviceExtension->ReleasePort)( DeviceExtension->PortContext );
}
/*
* Release the global spinlock and return to previous IRQL
*/
KeReleaseSpinLock(&Global.SpinLock, oldIrql);
if( ( ntStatus == STATUS_DEVICE_BUSY ) && APPROXIMATE_FAILS )
{
/*
* Clashed trying to access the gameport. So work with the same
* data as last time unless all failures must be reported or the
* last data was a failure for these axes.
*/
for( axisIdx=3; axisIdx>=0; axisIdx-- )
{
if( ( ( 1 << axisIdx ) & DeviceExtension->resistiveInputMask )
&&( DeviceExtension->LastGoodAxis[axisIdx]
>= DeviceExtension->ScaledTimeout ) )
{
break;
}
}
if( axisIdx<0 )
{
ntStatus = STATUS_TIMEOUT;
}
}
if( !NT_SUCCESS( ntStatus ) )
{
HGM_DBGPRINT(FILE_IOCTL | HGM_WARN,\
("HGM_UpdateLatestPollData Failed 0x%x", ntStatus));
}
return( ntStatus );
} /* HGM_UpdateLatestPollData */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -