📄 hidjoy.c
字号:
/* 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 + -