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

📄 hidjoy.c

📁 一个简单实现windows游戏杆的驱动示例-hidgame
💻 C
📖 第 1 页 / 共 4 页
字号:
                DeviceExtension->AxisMap[RIS] = cAxisIndexTable[AxisMask];
            }
        }
    }


    if( dwFlags & JOY_HWS_HASPOV )
    {
        switch( dwFlags & ( JOY_HWS_POVISPOLL | JOY_HWS_POVISBUTTONCOMBOS ) )
        {
        case 0:
            HGM_DBGPRINT(FILE_HIDJOY | HGM_ERROR,\
                           ("HGM_MapAxesFromDevExt: POV is not polled or button combo"));
            ntStatus = STATUS_DEVICE_CONFIGURATION_ERROR;
            break;

        case JOY_HWS_POVISBUTTONCOMBOS:
            break;

        case JOY_HWS_POVISPOLL:
            AxisMask = ZLU[(dwFlags & POVMAPBITS) >> POVMAPSHFT];
            if( AxisMask >= NA )
            {
                HGM_DBGPRINT( FILE_HIDJOY | HGM_ERROR,\
                                ("HGM_MapAxesFromDevExt: POV 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: POV axis mapped to same as Z or R axis") );
                    ntStatus = STATUS_DEVICE_CONFIGURATION_ERROR ; 
                }
                else
                {
                    DeviceExtension->resistiveInputMask |= AxisMask;
                    DeviceExtension->povMap = cAxisIndexTable[AxisMask];
                }
            }
            break;

        case JOY_HWS_POVISPOLL | JOY_HWS_POVISBUTTONCOMBOS:
            HGM_DBGPRINT(FILE_HIDJOY | HGM_ERROR,\
                           ("HGM_MapAxesFromDevExt: POV reports button combo and polled"));
            ntStatus = STATUS_DEVICE_CONFIGURATION_ERROR;
            break;
        }
    }
    else if( dwFlags & ( JOY_HWS_POVISPOLL | JOY_HWS_POVISBUTTONCOMBOS ) )
    {
        HGM_DBGPRINT(FILE_HIDJOY | HGM_ERROR,\
                       ("HGM_MapAxesFromDevExt: non-existant POV is polled or button combo"));
        ntStatus = STATUS_DEVICE_CONFIGURATION_ERROR ;
    }


    AxisMask = XLU[( dwFlags & XMAPBITS ) >> XMAPSHFT];
    if( AxisMask >= NA )
    {
        HGM_DBGPRINT( FILE_HIDJOY | HGM_ERROR,\
                        ("HGM_MapAxesFromDevExt: X axis mapping error dwFlags=0x%x",\
                         dwFlags));
        ntStatus = STATUS_DEVICE_CONFIGURATION_ERROR ; 
    }
    else
    {
        if( DeviceExtension->resistiveInputMask & AxisMask )
        {
            HGM_DBGPRINT( FILE_HIDJOY | HGM_WARN,\
                            ("HGM_MapAxesFromDevExt: X axis mapped to same as another axis") );
        }
        else
        {
            nAxis++;
            DeviceExtension->resistiveInputMask |= AxisMask;
            DeviceExtension->AxisMap[XIS] = cAxisIndexTable[AxisMask];
        }
    }


    AxisMask = YLU[( dwFlags & YMAPBITS ) >> YMAPSHFT];
    if( AxisMask >= NA )
    {
        HGM_DBGPRINT( FILE_HIDJOY | HGM_ERROR,\
                        ("HGM_MapAxesFromDevExt: Y axis mapping error dwFlags=0x%x",\
                         dwFlags));
        ntStatus = STATUS_DEVICE_CONFIGURATION_ERROR ; 
    }
    else
    {
        if( DeviceExtension->resistiveInputMask & AxisMask )
        {
            HGM_DBGPRINT( FILE_HIDJOY | HGM_WARN,\
                            ("HGM_MapAxesFromDevExt: Y axis mapped to same as another axis") );
        }
        else
        {
            nAxis++;
            DeviceExtension->resistiveInputMask |= AxisMask;
            DeviceExtension->AxisMap[YIS] = cAxisIndexTable[AxisMask];
        }
    }

#undef XIS
#undef YIS
#undef ZIS
#undef RIS

#undef NA

    /*
     *  Don't fail for this if CHANGE_DEVICE is defined because an exposed 
     *  sibling will always have an nAxis of zero.
     */
#ifdef CHANGE_DEVICE
    if( DeviceExtension->nAxes )
    {
#endif /* CHANGE_DEVICE */
        if( nAxis != DeviceExtension->nAxes )
        {
            ntStatus = STATUS_DEVICE_CONFIGURATION_ERROR ;
            HGM_DBGPRINT(FILE_HIDJOY | HGM_ERROR,\
                           ("HGM_MapAxesFromDevExt: nAxis(%d) != DeviceExtension->nAxes(%d)", \
                            nAxis, (int) DeviceExtension->nAxes));
        }
#ifdef CHANGE_DEVICE
    }
    else
    {
        /*
         *  This must be an exposed sibling so store the calculated nAxis and 
         *  a nButton just to look different.
         */
        DeviceExtension->nAxes = (USHORT)nAxis;
        DeviceExtension->nButtons = MAX_BUTTONS;
    }
#endif /* CHANGE_DEVICE */


    HGM_DBGPRINT( FILE_HIDJOY | HGM_BABBLE,\
                    ("HGM_MapAxesFromDevExt:  uResistiveInputMask=0x%x",\
                     DeviceExtension->resistiveInputMask) );


    if( NT_SUCCESS(ntStatus) )
    {
        ntStatus = HGM_SetupButtons( DeviceExtension );
    }

    return( ntStatus );
} /* HGM_MapAxesFromDevExt */


/*****************************************************************************
 *
 *  @doc    EXTERNAL
 *
 *  @func   NTSTATUS  | HGM_GenerateReport |
 *
 *          Generates a hid report descriptor for a n-axis, m-button joystick,
 *          depending on number of buttons and joy_hws_flags field.
 *
 *  @parm   IN PDEVICE_OBJECT | DeviceObject |
 *
 *          Pointer to the device object
 *
 *  @parm   IN OUT UCHAR * | rgGameReport[MAXBYTES_GAME_REPORT] |
 *
 *          Array that receives the HID report descriptor
 *
 *  @parm   OUT PUSHORT | pCbReport |
 *          
 *          Address of a short integer that receives size of 
 *          HID report descriptor. 
 *
 *  @rvalue   STATUS_SUCCESS  | success
 *  @rvalue   STATUS_BUFFER_TOO_SMALL  | Need more memory for HID descriptor
 *
 *****************************************************************************/
NTSTATUS INTERNAL
    HGM_GenerateReport
    (
    IN PDEVICE_OBJECT       DeviceObject, 
    OUT UCHAR               rgGameReport[MAXBYTES_GAME_REPORT],
    OUT PUSHORT             pCbReport
    )
{
    NTSTATUS    ntStatus;
    PDEVICE_EXTENSION DeviceExtension;
    UCHAR       *pucReport; 
    int         Idx;
    int         UsageIdx;
    ULONG       dwFlags; 
    POEMDATA    OemData;

    int         InitialAxisMappings[MAX_AXES];


    typedef struct _USAGES
    {
        UCHAR UsagePage;
        UCHAR Usage;
    } USAGES, *PUSAGE;

    typedef struct _JOYCLASSPARAMS
    {
        UCHAR   TopLevelUsage;
        USAGES  Usages[MAX_AXES];
    } JOYCLASSPARAMS, *PJOYCLASSPARAMS;
    
    PJOYCLASSPARAMS pJoyParams;

    /* 
     *  Canned parameters for devices
     *  The top-level usage must be either HID_USAGE_GENERIC_JOYSTICK or 
     *  HID_USAGE_GENERIC_GAMEPAD in order for the device to be treated as a 
     *  game controller.
     *  The poll limits are specified in uSecs so the value stored here is 1000000/x
     */

    JOYCLASSPARAMS JoystickParams =
    {   
        HID_USAGE_GENERIC_JOYSTICK,
        {   { HID_USAGE_PAGE_GENERIC, HID_USAGE_GENERIC_X} , 
            { HID_USAGE_PAGE_GENERIC, HID_USAGE_GENERIC_Y} , 
            { HID_USAGE_PAGE_SIMULATION, HID_USAGE_SIMULATION_THROTTLE} ,
            { HID_USAGE_PAGE_SIMULATION, HID_USAGE_SIMULATION_RUDDER} }
    };

    JOYCLASSPARAMS GamepadParams =
    {   
        HID_USAGE_GENERIC_GAMEPAD,
        {   { HID_USAGE_PAGE_GENERIC, HID_USAGE_GENERIC_X} , 
            { HID_USAGE_PAGE_GENERIC, HID_USAGE_GENERIC_Y} , 
            { HID_USAGE_PAGE_SIMULATION, HID_USAGE_SIMULATION_THROTTLE} ,
            { HID_USAGE_PAGE_SIMULATION, HID_USAGE_SIMULATION_RUDDER} }
    };

    JOYCLASSPARAMS CarCtrlParams =
    {   
        HID_USAGE_GENERIC_JOYSTICK,
        {   { HID_USAGE_PAGE_GENERIC, HID_USAGE_GENERIC_X} , 
            { HID_USAGE_PAGE_GENERIC, HID_USAGE_GENERIC_Y} , 
            { HID_USAGE_PAGE_SIMULATION, HID_USAGE_SIMULATION_THROTTLE} ,
            { HID_USAGE_PAGE_SIMULATION, HID_USAGE_SIMULATION_RUDDER} }
    };

    JOYCLASSPARAMS FlightYokeParams =
    {   
        HID_USAGE_GENERIC_JOYSTICK,
        {   { HID_USAGE_PAGE_GENERIC, HID_USAGE_GENERIC_X} , 
            { HID_USAGE_PAGE_GENERIC, HID_USAGE_GENERIC_Y} , 
            { HID_USAGE_PAGE_SIMULATION, HID_USAGE_SIMULATION_THROTTLE} ,
            { HID_USAGE_PAGE_SIMULATION, HID_USAGE_SIMULATION_RUDDER} }
    };


    PAGED_CODE();

    HGM_DBGPRINT( FILE_HIDJOY | HGM_FENTRY,\
                    ("HGM_GenerateReport(ucIn=0x%x,DeviceObject=0x%x)",\
                     rgGameReport, DeviceObject) );

    /*
     *  Get a pointer to the device extension
     */

    DeviceExtension = GET_MINIDRIVER_DEVICE_EXTENSION(DeviceObject);

    /*
     *  Although the axes have already been validated and mapped in 
     *  HGM_JoystickConfig this function destroys the mapping when it compacts 
     *  the axes towards the start of the descriptor report.  Since this 
     *  function will be called once to find the descriptor length and then 
     *  again to read the report, the mappings are regenerated again each 
     *  time through.  Although this results in the parameters being 
     *  interpreted three times (for validation, descriptor size and 
     *  descriptor content) it avoids the possibility of a discrepancy in 
     *  implementation of separate functions.
     */

    ntStatus = HGM_MapAxesFromDevExt( DeviceExtension );
    ASSERTMSG( "HGM_GenerateReport:", ntStatus == STATUS_SUCCESS );

    pucReport = rgGameReport;

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


    /* 
     *  What manner of beast have we ?
     */
    if( dwFlags & JOY_HWS_ISGAMEPAD )
    {
        pJoyParams = &GamepadParams;
    }
    else if( dwFlags & JOY_HWS_ISYOKE )
    {
        pJoyParams = &FlightYokeParams;
    }
    else if( dwFlags & JOY_HWS_ISCARCTRL )
    {
        pJoyParams = &CarCtrlParams;
    }
    else
    {
        pJoyParams = &JoystickParams;
    }

#define NEXT_BYTE( pReport, Data )   \
            ASSERTMSG( "HGM_GenerateReport:", pReport+sizeof(UCHAR)-rgGameReport < MAXBYTES_GAME_REPORT );  \
            *pReport++ = Data;    

#define NEXT_LONG( pReport, Data )   \
            ASSERTMSG( "HGM_GenerateReport:", pReport+sizeof(ULONG)-rgGameReport < MAXBYTES_GAME_REPORT);   \
            *(((LONG UNALIGNED*)(pReport))++) = Data;

#define ITEM_DEFAULT        0x00 /* Data, Array, Absolute, No Wrap, Linear, Preferred State, Has no NULL */
#define ITEM_VARIABLE       0x02 /* as ITEM_DEFAULT but value is a variable, not an array */
#define ITEM_HASNULL        0x40 /* as ITEM_DEFAULT but values out of range are considered NULL */
#define ITEM_ANALOG_AXIS    ITEM_VARIABLE
#define ITEM_DIGITAL_POV    (ITEM_VARIABLE|ITEM_HASNULL)
#define ITEM_BUTTON         ITEM_VARIABLE
#define ITEM_PADDING        0x01 /* Constant (nothing else applies) */


    /* USAGE_PAGE (Generic Desktop) */
    NEXT_BYTE(pucReport,    HIDP_GLOBAL_USAGE_PAGE_1);
    NEXT_BYTE(pucReport,    HID_USAGE_PAGE_GENERIC);

    /* USAGE (Joystick | GamePad ) */
    NEXT_BYTE(pucReport,    HIDP_LOCAL_USAGE_1);
    NEXT_BYTE(pucReport,    pJoyParams->TopLevelUsage);

    /* Logical Min is the smallest value that could be produced by a poll */
    NEXT_BYTE(pucReport,    HIDP_GLOBAL_LOG_MIN_4);
    NEXT_LONG(pucReport,    0 );

    /* Logical Max is the largest value that could be produced by a poll */
    NEXT_BYTE(pucReport,    HIDP_GLOBAL_LOG_MAX_4);
    NEXT_LONG(pucReport,    AXIS_FULL_SCALE );

    /* Start a Linked collection */
    /*
     *  Since this is a generic driver we know knothing about the physical 
     *  distribution of controls on the device so we put everything in a 
     *  single collection.  If, for instance, we knew that some buttons were 
     *  on the base and some on the stick we could better describe them by 
     *  reporting them in separate collections.
     */
    NEXT_BYTE(pucReport,    HIDP_MAIN_COLLECTION); 
    NEXT_BYTE(pucReport,    0x0 ); 

    /* Define one axis at a time */
    NEXT_BYTE(pucReport,    HIDP_GLOBAL_REPORT_COUNT_1);
    NEXT_BYTE(pucReport,    0x1);  

    /* Each axis is a 32 bits value */
    NEXT_BYTE(pucReport,    HIDP_GLOBAL_REPORT_SIZE);
    NEXT_BYTE(pucReport,    8 * sizeof(ULONG) );

    /* 
     *  Do the axis 
     *  Although HID could cope with the "active" axes being mixed with the 
     *  dummy ones, it makes life simpler to move them to the start.
     *  Pass through all the axis maps generated by HGM_JoystickConfig 
     *  and map all the active ones into the descriptor, copying the usages 
     *  appropriate for the type of device.
     *  Since a polled POV is nothing more than a different interpretation 
     *  of axis data, this is added after any axes.
     */
    C_ASSERT( sizeof( InitialAxisMappings ) == sizeof( DeviceExtension->AxisMap ) );
    RtlCopyMemory( InitialAxisMappings, DeviceExtension->AxisMap, sizeof( InitialAxisMappings ) );



    Idx = 0;
    for( UsageIdx = 0; UsageIdx < MAX_AXES; UsageIdx++ )
    {
        if( InitialAxisMappings[UsageIdx] >= INVALID_INDEX )
        {
            continue;
        }

        DeviceExtension->AxisMap[Idx] = InitialAxisMappings[UsageIdx];

        NEXT_BYTE(pucReport,    HIDP_LOCAL_USAGE_4);
        NEXT_BYTE(pucReport,    pJoyParams->Usages[UsageIdx].Usage);
        NEXT_BYTE(pucReport,    0x0);
        NEXT_BYTE(pucReport,    pJoyParams->Usages[UsageIdx].UsagePage);
        NEXT_BYTE(pucReport,    0x0);

        /* Data Field */
        NEXT_BYTE(pucReport,    HIDP_MAIN_INPUT_1);
        NEXT_BYTE(pucReport,    ITEM_ANALOG_AXIS);

        HGM_DBGPRINT( FILE_HIDJOY |  HGM_GEN_REPORT, \
                        ("HGM_GenerateReport:Idx=%d, UsageIdx=%d, Mapping=%d, Usage=%02x, Page=%02x",\
                         Idx, UsageIdx, DeviceExtension->AxisMap[UsageIdx], \
                         pJoyParams->Usages[UsageIdx].Usage, pJoyParams->Usages[UsageIdx].UsagePage ) ) ;
        Idx++;
    }

    if( dwFlags & JOY_HWS_POVISPOLL )
    {
        /*
         *  A polled POV is just the same as an axis.
         *  Note, we have already checked that there is an axis for use as the POV.
         *  Also, this type of POV can be distinguished from a digital POV by it's 
         *  lack of a NULL value.
         */
        NEXT_BYTE(pucReport,    HIDP_LOCAL_USAGE_4);
        NEXT_BYTE(pucReport,    HID_USAGE_GENERIC_HATSWITCH);
        NEXT_BYTE(pucReport,    0x0);
        NEXT_BYTE(pucReport,    HID_USAGE_PAGE_GENERIC);
        NEXT_BYTE(pucReport,    0x0);

⌨️ 快捷键说明

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