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

📄 hidjoy.c

📁 一个简单实现windows游戏杆的驱动示例-hidgame
💻 C
📖 第 1 页 / 共 4 页
字号:

/*++

Copyright (c) 1998 - 1999  Microsoft Corporation

Module Name:

    pnp.c

Abstract: This module contains routines Generate the HID report and
    configure the joystick.

Environment:

    Kernel mode


--*/

#include "hidgame.h"


#ifdef ALLOC_PRAGMA
    #pragma alloc_text (INIT, HGM_DriverInit)
    #pragma alloc_text (PAGE, HGM_SetupButtons)
    #pragma alloc_text (PAGE, HGM_MapAxesFromDevExt)
    #pragma alloc_text (PAGE, HGM_GenerateReport)
    #pragma alloc_text (PAGE, HGM_JoystickConfig)
    #pragma alloc_text (PAGE, HGM_InitAnalog)
/*  Sample only functions */
#ifdef CHANGE_DEVICE 
    #pragma alloc_text (PAGE, HGM_ChangeHandler)
    #pragma alloc_text (PAGE, HGM_DeviceChanged)
#endif /* CHANGE_DEVICE */
#endif





/*
 *  A few look up tables to translate the JOY_HWS_* flags into axis masks.
 *  These flags allow any axis to be polled on any of the four axis bits in 
 *  the gameport.  For example, the X axis on a standard joystick is found on 
 *  bit 0 (LSB) and the Y axis is on bit 1; however many steering wheel/pedal 
 *  controllers have X on bit 0 but Y on bit 2.  Although very few of these
 *  combinations are known to be used, supporting all the flags only causes a 
 *  little extra work on setup.  For each axis, there are three flags, one for 
 *  each of the possible non-standard bit masks.  Since it is possible that 
 *  more than one of these may be set the invalid combinations are marked so 
 *  that they can be refused.
 */



#define NA ( 0x80 )

/*
 *  Short versions of bit masks for axes
 */
#define X1 AXIS_X
#define Y1 AXIS_Y
#define X2 AXIS_R
#define Y2 AXIS_Z

/*
 *  Per axis flag masks and look up tables.
 *  In each case, combinations with more than one bit set are invalid
 */
#define XMAPBITS    (JOY_HWS_XISJ2Y |   JOY_HWS_XISJ2X |   JOY_HWS_XISJ1Y)
/*
 *                          0                   0                   0           0001
 *                          0                   0                   1           0010
 *                          0                   1                   0           0100
 *                          1                   0                   0           1000
 */
static const unsigned char XLU[8] = { X1,Y1,X2,NA,Y2,NA,NA,NA };
#define XMAPSHFT 7

#define YMAPBITS    (JOY_HWS_YISJ2Y |   JOY_HWS_YISJ2X |   JOY_HWS_YISJ1X)
/*                          0                   0                   0           0010
 *                          0                   0                   1           0001
 *                          0                   1                   0           0100
 *                          1                   0                   0           1000
 */
static const unsigned char YLU[8] = { Y1,X1,X2,NA,Y2,NA,NA,NA };
#define YMAPSHFT 10

#define RMAPBITS    (JOY_HWS_RISJ2Y |   JOY_HWS_RISJ1X |   JOY_HWS_RISJ1Y)
/*                          0                   0                   0           0100
 *                          0                   0                   1           0010
 *                          0                   1                   0           0001
 *                          1                   0                   0           1000
 */
static const unsigned char RLU[8] = { X2,Y1,X1,NA,Y2,NA,NA,NA };
#define RMAPSHFT 20

#define ZMAPBITS    (JOY_HWS_ZISJ2X |   JOY_HWS_ZISJ1X |   JOY_HWS_ZISJ1Y)
/*                          0                   0                   0           1000
 *                          0                   0                   1           0010
 *                          0                   1                   0           0001
 *                          1                   0                   0           0100
 */
static const unsigned char ZLU[8] = { Y2,Y1,X1,NA,X2,NA,NA,NA };
#define ZMAPSHFT 13
#define POVMAPBITS  (JOY_HWS_POVISJ2X | JOY_HWS_POVISJ1X | JOY_HWS_POVISJ1Y)
/*
 *  POV is the same as Z but with a larger shift
 */
#define POVMAPSHFT 16

#undef X1
#undef Y1
#undef X2
#undef Y2

/*
 *  This translates from an axis bitmask to an axis value index.  The elements 
 *  used should be as follows (X marks unsed)   { X, 0, 1, X, 2, X, X, X, 3 }.
 */
static const unsigned char cAxisIndexTable[9] = { 0, 0, 1, 0, 2, 0, 0, 0, 3 };


typedef enum _POV1
{
    P1_NULL = 0x80,
    P1_0,
    P1_90,
    P1_180,
    P1_270    
} POV1;

typedef enum _POV2
{
    P2_NULL = 0xc0,
    P2_0,
    P2_90,
    P2_180,
    P2_270    
} POV2;

#define POV_MASK ((unsigned char)(~(P1_NULL | P2_NULL)))
/*
 *  Look up tables for button combos
 *  Buttons are zero based so use P1_NULL for a zero input so we don't have to 
 *  special case it as a do nothing button.
 *  The 7th Button can be mapped either from it's unique combination or as 
 *  foreward on a second POV being read as buttons 7 - 10.
 */
static const unsigned char c1PComboLU[] =   {   P1_NULL,0,      1,      P1_270,
                                                2,      4,      8,      P1_180,
                                                3,      5,      7,      P1_90,
                                                9,      6,      6,      P1_0 };

static const unsigned char c2PComboLU[] =   {   P1_NULL,0,      1,      P1_270,
                                                2,      4,      P2_180, P1_180,
                                                3,      5,      P2_90,  P1_90,
                                                P2_270, 6,      P2_0,   P1_0 };


/*****************************************************************************
 *
 *  @doc    EXTERNAL
 *
 *  @func   NTSTATUS | HGM_DriverInit |
 *
 *          Perform global initialization.
 *          <nl>This is called from DriverEntry.  Try to initialize a CPU 
 *          specific timer but if it fails set up default
 *
 *  @rvalue   STATUS_SUCCESS | success
 *  @rvalue   STATUS_UNSUCCESSFUL | not success
 *
 *****************************************************************************/
NTSTATUS EXTERNAL
    HGM_DriverInit()
{
    NTSTATUS ntStatus = STATUS_SUCCESS;

    if( !HGM_CPUCounterInit() )
    {
        LARGE_INTEGER QPCFrequency;

        KeQueryPerformanceCounter( &QPCFrequency );

        if( ( QPCFrequency.HighPart == 0 )
         && ( QPCFrequency.LowPart <= 10000 ) )
        {
            ntStatus = STATUS_UNSUCCESSFUL;

            HGM_DBGPRINT(FILE_HIDJOY | HGM_ERROR,\
                           ("QPC at %I64u Hz is unusable", 
                           QPCFrequency.QuadPart ));
        }
        else
        {
            Global.CounterScale = CALCULATE_SCALE( QPCFrequency.QuadPart );
            Global.ReadCounter = (COUNTER_FUNCTION)&KeQueryPerformanceCounter;

            HGM_DBGPRINT(FILE_HIDJOY | HGM_BABBLE,\
                           ("QPC at %I64u Hz used with scale %d", 
                           QPCFrequency.QuadPart, Global.CounterScale ));
        }
    }

    return ntStatus;
}

/*****************************************************************************
 *
 *  @doc    EXTERNAL
 *
 *  @func   NTSTATUS | HGM_SetupButtons |
 *
 *          Use the flags in the DeviceExtension to check and set up buttons.
 *          <nl>This is called both from HGM_JoystickConfig to validate the 
 *          configuration and HGM_GenerateReport to prepare for polling.
 *
 *  @parm   IN OUT PDEVICE_EXTENSION | DeviceExtension |
 *
 *          Pointer to the minidriver device extension
 *
 *  @rvalue   STATUS_SUCCESS | success
 *  @rvalue   STATUS_DEVICE_CONFIGURATION_ERROR | The configuration is invalid
 *
 *****************************************************************************/
NTSTATUS INTERNAL
    HGM_SetupButtons
    (
    IN OUT PDEVICE_EXTENSION DeviceExtension 
    )
{
    NTSTATUS    ntStatus = STATUS_SUCCESS;

    if( DeviceExtension->fSiblingFound )
    {
        if( DeviceExtension->nButtons > 2 )
        {
            ntStatus = STATUS_DEVICE_CONFIGURATION_ERROR;
            HGM_DBGPRINT( FILE_HIDJOY | HGM_ERROR,\
                            ("HGM_SetupButtons: failing config of sibling device with %u buttons",\
                             DeviceExtension->nButtons));
        }
        if( DeviceExtension->HidGameOemData.OemData[1].joy_hws_dwFlags & JOY_HWS_POVISBUTTONCOMBOS )
        {
            ntStatus = STATUS_DEVICE_CONFIGURATION_ERROR;
            HGM_DBGPRINT( FILE_HIDJOY | HGM_ERROR,\
                            ("HGM_SetupButtons: failing config of sibling device with combo buttons" ));
        }
    }
    else
    {
        if( DeviceExtension->HidGameOemData.OemData[0].joy_hws_dwFlags & JOY_HWS_POVISBUTTONCOMBOS )
        {
            if( DeviceExtension->nButtons > MAX_BUTTONS )
            {
                ntStatus = STATUS_DEVICE_CONFIGURATION_ERROR;
                HGM_DBGPRINT( FILE_HIDJOY | HGM_ERROR,\
                                ("HGM_SetupButtons: failing config of button combo device with %u buttons",\
                                 DeviceExtension->nButtons));
            }
        }
        else
        {
            if( DeviceExtension->nButtons > 4 )
            {
                if( DeviceExtension->resistiveInputMask & AXIS_R )
                {
                    ntStatus = STATUS_DEVICE_CONFIGURATION_ERROR;
                    HGM_DBGPRINT( FILE_HIDJOY | HGM_ERROR,\
                                    ("HGM_SetupButtons: failing config of device with R axis and %u buttons",\
                                     DeviceExtension->nButtons));
                }
                else
                {
                    /*
                     *  5th button always read from R axis.
                     *  Set the inital on/off boundary low
                     */
                    DeviceExtension->resistiveInputMask |= AXIS_R;
                    DeviceExtension->button5limit = 2;
                }

                if( DeviceExtension->nButtons > 5 )
                {
                    if( DeviceExtension->resistiveInputMask & AXIS_Z )
                    {
                        ntStatus = STATUS_DEVICE_CONFIGURATION_ERROR;
                        HGM_DBGPRINT( FILE_HIDJOY | HGM_ERROR,\
                                        ("HGM_SetupButtons: failing config of device with Z axis and %u buttons",\
                                         DeviceExtension->nButtons));
                    }
                    else
                    {
                        /*
                         *  6th button always read from Z axis.
                         *  Set the inital on/off boundary low
                         */
                        DeviceExtension->resistiveInputMask |= AXIS_Z;
                        DeviceExtension->button6limit = 2;
                    }

                    if( DeviceExtension->nButtons > 6 )
                    {
                        ntStatus = STATUS_DEVICE_CONFIGURATION_ERROR;
                        HGM_DBGPRINT( FILE_HIDJOY | HGM_ERROR,\
                                        ("HGM_SetupButtons: failing config of device with %u buttons",\
                                         DeviceExtension->nButtons));
                    }
                }
            }
        }
    }

    return( ntStatus );
} /* HGM_SetupButtons */



/*****************************************************************************
 *
 *  @doc    EXTERNAL
 *
 *  @func   NTSTATUS  | HGM_MapAxesFromDevExt |
 *
 *          Use the flags in the DeviceExtension to generate mappings for each 
 *          axis.  
 *          <nl>This is called both from HGM_JoystickConfig to validate the 
 *          configuration and HGM_GenerateReport to use the axis maps.
 *          
 *
 *  @parm   IN OUT PDEVICE_EXTENSION | DeviceExtension |
 *
 *          Pointer to the minidriver device extension
 *
 *  @rvalue   STATUS_SUCCESS | success
 *  @rvalue   STATUS_DEVICE_CONFIGURATION_ERROR | The configuration is invalid
 *
 *****************************************************************************/
NTSTATUS EXTERNAL
    HGM_MapAxesFromDevExt
    (
    IN OUT PDEVICE_EXTENSION DeviceExtension 
    )
{
    NTSTATUS    ntStatus;
    ULONG       dwFlags;
    int         nAxis;
    UCHAR       AxisMask;

    ntStatus = STATUS_SUCCESS;



    dwFlags = DeviceExtension->HidGameOemData.OemData[(DeviceExtension->fSiblingFound!=0)].joy_hws_dwFlags;  

    HGM_DBGPRINT( FILE_HIDJOY | HGM_BABBLE2,\
                    ("HGM_MapAxesFromDevExt: - - - dwFlags=0x%x - - -", dwFlags));

#define XIS (0)
#define YIS (1)
#define ZIS (2)
#define RIS (3)

    /* 
     *  Check X and Y last as Z, R and POV must not overlap
     *  The are no flags to indicate the presence of X or Y so if they 
     *  overlap, this indicates that they are not used,
     */

    DeviceExtension->resistiveInputMask = 0;
    for( nAxis=MAX_AXES; nAxis>=0; nAxis-- )
    {
        DeviceExtension->AxisMap[nAxis] = INVALID_INDEX;
    }
    nAxis = 0;
    DeviceExtension->povMap = INVALID_INDEX;

    if( dwFlags & JOY_HWS_HASZ )
    {
        AxisMask = ZLU[(dwFlags & ZMAPBITS) >> ZMAPSHFT];
        if( AxisMask >= NA )
        {
            HGM_DBGPRINT( FILE_HIDJOY | HGM_ERROR,\
                            ("HGM_MapAxesFromDevExt: Z axis mapping error dwFlags=0x%x",\
                             dwFlags));
            ntStatus = STATUS_DEVICE_CONFIGURATION_ERROR; 
        }
        else
        {
            nAxis = 1;
            DeviceExtension->resistiveInputMask = AxisMask;
            DeviceExtension->AxisMap[ZIS] = cAxisIndexTable[AxisMask];
        }
    }


    if( dwFlags & JOY_HWS_HASR )
    {
        AxisMask = RLU[(dwFlags & RMAPBITS) >> RMAPSHFT];
        if( AxisMask >= NA )
        {
            HGM_DBGPRINT( FILE_HIDJOY | HGM_ERROR,\
                            ("HGM_MapAxesFromDevExt: R axis mapping error dwFlags=0x%x",\
                             dwFlags));
            ntStatus = STATUS_DEVICE_CONFIGURATION_ERROR; 
        }
        else
        {
            if( DeviceExtension->resistiveInputMask & AxisMask )
            {
                HGM_DBGPRINT( FILE_HIDJOY | HGM_ERROR, \
                                ("HGM_MapAxesFromDevExt: R axis mapped to same as Z axis"));
                ntStatus = STATUS_DEVICE_CONFIGURATION_ERROR ; 
            }
            else
            {
                nAxis++;
                DeviceExtension->resistiveInputMask |= AxisMask;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -