⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 poll.c

📁 一个简单实现windows游戏杆的驱动示例-hidgame
💻 C
📖 第 1 页 / 共 2 页
字号:
                    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 + -