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

📄 hidjoy.c

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

        /* 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, Set to polled POV", Idx ) ) ;
        Idx++;
    }

    /*
     *  Now fill in any remaining axis values as dummys
     */
    while( Idx < MAX_AXES )
    {
        /* Constant Field */
        NEXT_BYTE(pucReport,    HIDP_MAIN_INPUT_1);
        NEXT_BYTE(pucReport,    ITEM_PADDING);

        HGM_DBGPRINT( FILE_HIDJOY |  HGM_GEN_REPORT, \
                        ("HGM_GenerateReport:Idx=%d, Set to constant field", Idx ) ) ;
        Idx++;
    }
        

    /*
     *  Now move on to the byte sized fields
     */


    if( dwFlags & JOY_HWS_POVISBUTTONCOMBOS )
    {
        /*
         *  Redefine the logical and physical ranges from now on 
         *  A digital POV has a NULL value (a value outside the logical range) 
         *  when the POV is centered.  To make life easier call the NULL value 
         *  zero, so the logical range is from 1 to 4.

        /* Logical Min */
        NEXT_BYTE(pucReport,    HIDP_GLOBAL_LOG_MIN_1);
        NEXT_BYTE(pucReport,    1 );

        /* Logical Max */
        NEXT_BYTE(pucReport,    HIDP_GLOBAL_LOG_MAX_1);
        NEXT_BYTE(pucReport,    4 );

        /* 
         *  report for digital POV is 3 bits data plus 5 constant bits to fill 
         *  the byte.  
         */
        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);

        /* Data Field */
        NEXT_BYTE(pucReport,    HIDP_GLOBAL_REPORT_SIZE);
        NEXT_BYTE(pucReport,    0x3);
        NEXT_BYTE(pucReport,    HIDP_MAIN_INPUT_1);
        NEXT_BYTE(pucReport,    ITEM_DIGITAL_POV);

        /* top 5 bits constant */
        NEXT_BYTE(pucReport,    HIDP_GLOBAL_REPORT_SIZE);
        NEXT_BYTE(pucReport,    0x5);
        NEXT_BYTE(pucReport,    HIDP_MAIN_INPUT_1);
        NEXT_BYTE(pucReport,    ITEM_PADDING);

        HGM_DBGPRINT( FILE_HIDJOY |  HGM_GEN_REPORT, \
                        ("HGM_GenerateReport:First button combo POV is on" ) ) ;

        if( dwFlags & JOY_HWS_HASPOV2 )
        {
            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);

            /* Data Field */
            NEXT_BYTE(pucReport,    HIDP_GLOBAL_REPORT_SIZE);
            NEXT_BYTE(pucReport,    0x3);
            NEXT_BYTE(pucReport,    HIDP_MAIN_INPUT_1);
            NEXT_BYTE(pucReport,    ITEM_DIGITAL_POV);

            /* top 5 bits constant */
            NEXT_BYTE(pucReport,    HIDP_GLOBAL_REPORT_SIZE);
            NEXT_BYTE(pucReport,    0x5);
            NEXT_BYTE(pucReport,    HIDP_MAIN_INPUT_1);
            NEXT_BYTE(pucReport,    ITEM_PADDING);

            HGM_DBGPRINT( FILE_HIDJOY |  HGM_GEN_REPORT, \
                            ("HGM_GenerateReport:Second button combo POV is on" ) ) ;
        }
        else
        {
            /* 8 bits of constant data instead of second POV */
            NEXT_BYTE(pucReport,    HIDP_GLOBAL_REPORT_SIZE);
            NEXT_BYTE(pucReport,    0x8);

            /* Constant Field */
            NEXT_BYTE(pucReport,    HIDP_MAIN_INPUT_1);
            NEXT_BYTE(pucReport,    ITEM_PADDING);

            HGM_DBGPRINT( FILE_HIDJOY |  HGM_GEN_REPORT, \
                            ("HGM_GenerateReport:No second button combo POV" ) ) ;
        }
    } 
    else
    {
        /* 16 bits of constant data instead of button combo POVs */
        NEXT_BYTE(pucReport,    HIDP_GLOBAL_REPORT_SIZE);
        NEXT_BYTE(pucReport,    0x10);

        /* Constant Field */
        NEXT_BYTE(pucReport,    HIDP_MAIN_INPUT_1);
        NEXT_BYTE(pucReport,    ITEM_PADDING);

        HGM_DBGPRINT( FILE_HIDJOY |  HGM_GEN_REPORT, \
                        ("HGM_GenerateReport:Button combo POV are off" ) ) ;
    }


    /* 
     * Now the buttons 
     */
    for( Idx = 0x0; Idx < DeviceExtension->nButtons; Idx++ )
    {
        /* Report size is 1 bit for button */
        NEXT_BYTE(pucReport,    HIDP_GLOBAL_REPORT_SIZE);
        NEXT_BYTE(pucReport,    0x1);

        NEXT_BYTE(pucReport,    HIDP_LOCAL_USAGE_4);
        NEXT_BYTE(pucReport,    (UCHAR)(Idx + 1) );
        NEXT_BYTE(pucReport,    0x0);
        NEXT_BYTE(pucReport,    HID_USAGE_PAGE_BUTTON);
        NEXT_BYTE(pucReport,    0x0);

        /* Data field */
        NEXT_BYTE(pucReport,    HIDP_MAIN_INPUT_1);
        NEXT_BYTE(pucReport,    ITEM_BUTTON);

        /* 7 bits of constant data */
        NEXT_BYTE(pucReport,    HIDP_GLOBAL_REPORT_SIZE);
        NEXT_BYTE(pucReport,    0x7);
        NEXT_BYTE(pucReport,    HIDP_MAIN_INPUT_1);
        NEXT_BYTE(pucReport,    ITEM_PADDING);

        HGM_DBGPRINT( FILE_HIDJOY | HGM_GEN_REPORT, \
                        ("HGM_GenerateReport:Button %u on",Idx ) ) ;
    } 

    if( Idx < MAX_BUTTONS )
    {
        /* Constant report for 8 * unused buttons bits */
        NEXT_BYTE(pucReport,    HIDP_GLOBAL_REPORT_SIZE);
        NEXT_BYTE(pucReport,    (UCHAR)((MAX_BUTTONS-Idx)*8) );

        /* Constant Field */
        NEXT_BYTE(pucReport,    HIDP_MAIN_INPUT_1);
        NEXT_BYTE(pucReport,    ITEM_PADDING);

        HGM_DBGPRINT( FILE_HIDJOY | HGM_GEN_REPORT, \
                        ("HGM_GenerateReport:Last %u buttons off",MAX_BUTTONS-Idx ) ) ;
    }

    /* End of collection,  We're done ! */
    NEXT_BYTE(pucReport,  HIDP_MAIN_ENDCOLLECTION); 


#undef NEXT_BYTE
#undef NEXT_LONG

    if( pucReport - rgGameReport > MAXBYTES_GAME_REPORT)
    {
        ntStatus   = STATUS_BUFFER_TOO_SMALL;
        *pCbReport = 0x0;
        RtlZeroMemory(rgGameReport, sizeof(rgGameReport));
    } else
    {
        *pCbReport = (USHORT) (pucReport - rgGameReport);
        ntStatus = STATUS_SUCCESS;
    }

    HGM_DBGPRINT( FILE_HIDJOY | HGM_GEN_REPORT,\
                    ("HGM_GenerateReport: ReportSize=0x%x",\
                     *pCbReport) );

    HGM_EXITPROC(FILE_HIDJOY | HGM_FEXIT_STATUSOK, "HGM_GenerateReport", ntStatus);

    return ( ntStatus );
} /* HGM_GenerateReport */



/*****************************************************************************
 *
 *  @doc    EXTERNAL
 *
 *  @func   NTSTATUS  | HGM_JoystickConfig |
 *
 *          Check that the configuration is valid whilst there is still time 
 *          to refuse it.
 *          <nl>HGM_GenerateReport uses the results generated here if the 
 *          settings are OK.
 *
 *  @parm   IN PDEVICE_OBJECT | DeviceObject |
 *
 *          Pointer to the device object
 *
 *  @rvalue   STATUS_SUCCESS  | success
 *  @rvalue   STATUS_DEVICE_CONFIGURATION_ERROR  | Invalid configuration specified
 *
 *****************************************************************************/
NTSTATUS INTERNAL
    HGM_JoystickConfig 
    (
    IN PDEVICE_OBJECT         DeviceObject
    )
{
    PDEVICE_EXTENSION   DeviceExtension;
    POEMDATA            OemData;
    NTSTATUS            ntStatus;
    int                 Idx;

    PAGED_CODE();

    HGM_DBGPRINT( FILE_HIDJOY | HGM_FENTRY,\
                    ("HGM_JoystickConfig(DeviceObject=0x%x)",\
                     DeviceObject) );


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

    DeviceExtension = GET_MINIDRIVER_DEVICE_EXTENSION(DeviceObject);

    ntStatus = HGM_MapAxesFromDevExt( DeviceExtension );

    if( DeviceExtension->ReadAccessorDigital )
    {
        DeviceExtension->ScaledTimeout = AXIS_TIMEOUT;
    }
    else
    {
        /*
         * Calculate time thresholds for analog device
         */
        if( ( DeviceExtension->HidGameOemData.OemData[0].Timeout < ANALOG_POLL_TIMEOUT_MIN )
          ||( DeviceExtension->HidGameOemData.OemData[0].Timeout > ANALOG_POLL_TIMEOUT_MAX ) )
        {
            HGM_DBGPRINT(FILE_HIDJOY | HGM_BABBLE,\
                           ("Ignoring out of range timeout: %u uSecs",\
                            DeviceExtension->HidGameOemData.OemData[0].Timeout));

            DeviceExtension->ScaledTimeout = (ULONG)( ( (ULONGLONG)ANALOG_POLL_TIMEOUT_DFT
                                                      * (ULONGLONG)(AXIS_FULL_SCALE<<SCALE_SHIFT) )
                                                    / (ULONGLONG)ANALOG_POLL_TIMEOUT_MAX );
        }
        else
        {
            DeviceExtension->ScaledTimeout = (ULONG)( ( (ULONGLONG)DeviceExtension->HidGameOemData.OemData[0].Timeout
                                                      * (ULONGLONG)(AXIS_FULL_SCALE<<SCALE_SHIFT) )
                                                    / (ULONGLONG)ANALOG_POLL_TIMEOUT_MAX );
        }

        HGM_DBGPRINT(FILE_HIDJOY | HGM_BABBLE,\
                       ("ScaledTimeout: %u",\
                        DeviceExtension->ScaledTimeout));

        /*
         *  Use one quarter of the minimum poll timeout as a starting value 
         *  for the time between two polls which will be considered to have 
         *  been interrupted.
         */
        DeviceExtension->ScaledThreshold = (ULONG)( ( (ULONGLONG)ANALOG_POLL_TIMEOUT_MIN
                                                    * (ULONGLONG)AXIS_FULL_SCALE )
                                                  / (ULONGLONG)ANALOG_POLL_TIMEOUT_MAX )>>2;
    }


    /*
     *  Set initial values of LastGoodAxis so that the device will not show
     *  up as present until we get at least one valid poll.
     */
    for( Idx = MAX_AXES; Idx >= 0; Idx-- )
    {
        DeviceExtension->LastGoodAxis[Idx] = AXIS_TIMEOUT;
    }

    HGM_EXITPROC(FILE_HIDJOY | HGM_FEXIT_STATUSOK, "HGM_JoystickConfig", ntStatus);

    return ntStatus;
} /* HGM_JoystickConfig */


/*****************************************************************************
 *
 *  @doc    EXTERNAL
 *
 *  @func   NTSTATUS  | HGM_InitAnalog |
 *
 *          Check that the configuration is valid whilst there is still time 
 *          to refuse it.  
 *          <nl>Detect and validate sibling relationships and call 
 *          HGM_JoystickConfig for the rest of the work.
 *
 *  @parm   IN PDEVICE_OBJECT | DeviceObject |
 *
 *          Pointer to the device object
 *
 *  @rvalue   STATUS_SUCCESS  | success
 *  @rvalue   STATUS_DEVICE_CONFIGURATION_ERROR  | Invalid configuration specified
 *
 *****************************************************************************/
/*
 *  Disable warning for variable used before set as it is hard for a compiler 
 *  to see that the use of DeviceExtension_Sibling is gated by a flag which 
 *  can only be set after DeviceExtension_Sibling is initialized.
 */
#pragma warning( disable:4701 )
NTSTATUS EXTERNAL
    HGM_InitAnalog
    (
    IN PDEVICE_OBJECT         DeviceObject
    )
{
    NTSTATUS            ntStatus;
    PDEVICE_EXTENSION   DeviceExtension;
    PDEVICE_EXTENSION   DeviceExtension_Sibling;
    PLIST_ENTRY         pEntry;

#define ARE_WE_RELATED(_x_, _y_)                                \
    (                                                           \
        (_x_)->GameContext     == (_y_)->GameContext      &&    \
        (_x_)->WriteAccessor   == (_y_)->WriteAccessor    &&    \
        (_x_)->ReadAccessor    == (_y_)->ReadAccessor           \
    )

    PAGED_CODE ();
    
    /*
     * Get a pointer to the device extension
     */
    DeviceExtension = GET_MINIDRIVER_DEVICE_EXTENSION(DeviceObject);
    

    /*
     *  No modifications to the Global List while we are looking at it
     */
    ExAcquireFastMutex (&Global.Mutex);

    /*
     *  For two joysticks interface two fdos are created to service them 
     *  but physically they both share the same port.
     *  For the second sibling certain extra rules must be applied so we 
     *  search our list of devices for another device using the same port 
     *  and if we find one mark this one as a sibling.
     */
    for(pEntry = Global.DeviceListHead.Flink;
       pEntry != &Global.DeviceListHead;
       pEntry = pEntry->Flink)
    {

        /*
         * Obtain the device Extension of the Sibling
         */
        DeviceExtension_Sibling = CONTAINING_RECORD(pEntry, DEVICE_EXTENSION, Link);

        if(       DeviceExtension_Sibling != DeviceExtension
               && TRUE == ARE_WE_RELATED(DeviceExtension, DeviceExtension_Sibling)
               && TRUE == DeviceExtension_Sibling->fStarted )
        {
#ifdef CHANGE_DEVICE
            if( DeviceExtension_Sibling->fReplaced )
            {
                HGM_DBGPRINT(FILE_HIDJOY | HGM_BABBLE, ("Outgoing Sibling found (0x%x)", DeviceExtension_Sibling));
            }
            else
            {
#endif /* CHANGE_DEVICE */
                HGM_DBGPRINT(FILE_HIDJOY | HGM_BABBLE, ("Sibling found (0x%x)", DeviceExtension_Sibling));

                DeviceExtension->fSiblingFound = TRUE;
#ifdef CHANGE_DEVICE
            }
#endif /* CHANGE_DEVICE */
            break;
        }
    }

    /*
     *  We are done, release the Mutex
     */
    ExReleaseFastMutex (&Global.Mutex);

    /*
     * check the axis and button configuration for the joystick
     */
    ntStatus = HGM_JoystickConfig(DeviceObject);

    if( NT_SUCCESS( ntStatus ) )
    {
        /*
         *  Make sure that sibling axes are not overlapped
         */
        if(  DeviceExtension->fSiblingFound &&
             (DeviceExtension_Sibling->resistiveInputMask & DeviceExtension->resistiveInputMask) != 0x0 )
        {

            HGM_DBGPRINT(FILE_HIDJOY |HGM_ERROR,\
                           ("HGM_InitDevice: OverLapping Resources ResisitiveInputMask(0x%x) Sibling(0x%x)",\
                            DeviceExtension->resistiveInputMask,DeviceExtension_Sibling->resistiveInputMask ));
            ntStatus = STATUS_DEVICE_CONFIGURATION_ERROR;

        }
    }
    else

⌨️ 快捷键说明

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