📄 xbcd_control.c
字号:
/*
Copyright 2003 Helder Acevedo
This file is part of XBCD.
XBCD is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
XBCD is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Foobar; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "XBCD_driver.h"
#include "XBCD_report.h"
ULONG _fltused = 0;
#pragma LOCKEDCODE
NTSTATUS XBCDDispatchIntDevice(IN PDEVICE_OBJECT pFdo, IN PIRP pIrp)
{
PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(pIrp);
NTSTATUS Status = STATUS_SUCCESS;
PDEVICE_EXTENSION pDevExt = GET_MINIDRIVER_DEVICE_EXTENSION(pFdo);
switch (stack->Parameters.DeviceIoControl.IoControlCode)
{
case IOCTL_HID_GET_DEVICE_ATTRIBUTES:
{
PHID_DEVICE_ATTRIBUTES pHidAttributes;
pHidAttributes = (PHID_DEVICE_ATTRIBUTES) pIrp->UserBuffer;
KdPrint(("XBCDDispatchIntDevice - sending device attributes"));
if (stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(HID_DEVICE_ATTRIBUTES))
{
Status = STATUS_BUFFER_TOO_SMALL;
KdPrint(("Buffer for Device Attributes is too small"));
}
else
{
RtlZeroMemory(pHidAttributes, sizeof(HID_DEVICE_ATTRIBUTES));
pHidAttributes->Size = sizeof(HID_DEVICE_ATTRIBUTES);
pHidAttributes->VendorID = 0x0738;//pDevExt->dd.idVendor;
pHidAttributes->ProductID = 0x4516;//pDevExt->dd.idProduct;
pHidAttributes->VersionNumber = 0x0001;//pDevExt->dd.bcdDevice;
pIrp->IoStatus.Information = sizeof(HID_DEVICE_ATTRIBUTES);
KdPrint(("XBCDDispatchIntDevice - Sent Device Attributes"));
}
break;
}
case IOCTL_HID_GET_DEVICE_DESCRIPTOR:
{
PHID_DESCRIPTOR pHidDescriptor;
pHidDescriptor = (PHID_DESCRIPTOR) pIrp->UserBuffer;
KdPrint(("XBCDDispatchIntDevice - sending device descriptor"));
if (stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(HID_DESCRIPTOR))
{
Status = STATUS_BUFFER_TOO_SMALL;
KdPrint(("Buffer for Device Descriptor is too small"));
}
else
{
RtlZeroMemory(pHidDescriptor, sizeof(HID_DESCRIPTOR));
pHidDescriptor->bLength = sizeof(HID_DESCRIPTOR);
pHidDescriptor->bDescriptorType = HID_HID_DESCRIPTOR_TYPE;
pHidDescriptor->bcdHID = HID_REVISION;
pHidDescriptor->bCountry = 0;
pHidDescriptor->bNumDescriptors = 1;
pHidDescriptor->DescriptorList[0].bReportType = HID_REPORT_DESCRIPTOR_TYPE;
pHidDescriptor->DescriptorList[0].wReportLength = sizeof(ReportDescriptor);
pIrp->IoStatus.Information = sizeof(HID_DESCRIPTOR);
KdPrint(("XBCDDispatchIntDevice - Sent Device Descriptor"));
}
break;
}
case IOCTL_HID_GET_REPORT_DESCRIPTOR:
{
KdPrint(("XBCDDispatchIntDevice - sending report descriptor"));
if (stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(ReportDescriptor))
{
Status = STATUS_BUFFER_TOO_SMALL;
KdPrint(("Buffer for Report Descriptor is too small"));
}
else
{
RtlCopyMemory(pIrp->UserBuffer, ReportDescriptor, sizeof(ReportDescriptor));
pIrp->IoStatus.Information = sizeof(ReportDescriptor);
KdPrint(("XBCDDispatchIntDevice - Sent Report Descriptor"));
}
break;
}
case IOCTL_HID_READ_REPORT:
{
KIRQL oldirql;
LARGE_INTEGER timeout;
KdPrint(("XBCDDispatchIntDevice - IOCTL_HID_READ_REPORT entry"));
Status = XBCDReadData(pDevExt, pIrp);
//Set a timer to keep reading data for another 5 seconds
//Fixes problems with button configuration in games
timeout.QuadPart = -50000000;
KeSetTimer(&pDevExt->timer, timeout, &pDevExt->timeDPC);
pDevExt->timerEnabled = TRUE;
Status = StartInterruptUrb(pDevExt);
KdPrint(("XBCDDispatchIntDevice - IOCTL_HID_READ_REPORT exit"));
return Status;
}
case IOCTL_HID_WRITE_REPORT:
{
PHID_XFER_PACKET temp = (PHID_XFER_PACKET)pIrp->UserBuffer;
KdPrint(("XBCDDispatchIntDevice - IOCTL_HID_WRITE_REPORT"));
if (temp->reportBuffer && temp->reportBufferLen)
{
int iTemp;
pDevExt->intoutdata[0] = 0x00;
pDevExt->intoutdata[1] = 0x06;
pDevExt->intoutdata[2] = 0x00;
iTemp = temp->reportBuffer[1];
iTemp = iTemp * pDevExt->LAFactor/100;
pDevExt->intoutdata[3] = iTemp;
pDevExt->intoutdata[4] = 0x00;
iTemp = temp->reportBuffer[2];
iTemp = iTemp * pDevExt->RAFactor/100;
pDevExt->intoutdata[5] = iTemp;
Status = SendInterruptUrb(pDevExt);
if(temp->reportBuffer[0] == 1)
{
XBCDReadButtonConfig(pFdo);
}
}
else
{
KdPrint(("HIDMINI.SYS: Write report ID 0x%x w/o buffer\n",
(unsigned)temp->reportId ));
}
Status = STATUS_SUCCESS;
pIrp->IoStatus.Information = 0;
break;
}
default:
{
KdPrint(("XBCDDispatchIntDevice - Irp not implemented"));
Status = STATUS_NOT_SUPPORTED;
break;
}
}
pIrp->IoStatus.Status = Status;
if(Status != STATUS_PENDING)
{
KdPrint(("XBCDDispatchIntDevice - irp status not pending"));
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
Status = STATUS_SUCCESS;
}
else
{
KdPrint(("XBCDDispatchIntDevice - mark the irp as pending"));
IoMarkIrpPending(pIrp);
}
KdPrint(("XBCDDispatchIntDevice - returning"));
return Status;
}
#pragma PAGEDCODE
NTSTATUS XBCDDispatchDevice(IN PDEVICE_OBJECT pFdo, IN PIRP pIrp)
{
PDEVICE_EXTENSION pDevExt = GET_MINIDRIVER_DEVICE_EXTENSION(pFdo);
NTSTATUS status;
PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(pIrp);
IoSkipCurrentIrpStackLocation(pIrp);
status = IoCallDriver(pDevExt->pLowerPdo, pIrp);
return status;
}
#pragma PAGEDCODE
NTSTATUS XBCDDispatchSystem(IN PDEVICE_OBJECT pFdo, IN PIRP pIrp)
{
PDEVICE_EXTENSION pDevExt = GET_MINIDRIVER_DEVICE_EXTENSION(pFdo);
NTSTATUS status;
PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(pIrp);
IoSkipCurrentIrpStackLocation(pIrp);
status = IoCallDriver(pDevExt->pLowerPdo, pIrp);
return status;
}
#pragma LOCKEDCODE
double sqrt2(double x)
{ // sqrt
double result;
_asm
{
fld x
fsqrt
fstp result
}
return result;
}
int ftoi(float f)
{
int rv;
_asm {
fld f
fistp rv
//fwait /* not sure if this is necessary on newer processors... */
}
return rv ;
}
void CalcAxes(short *xdatain, short *ydatain, int iDeadZone, PDEVICE_EXTENSION pDevExt)
{
short xdata = *xdatain;
short ydata = *ydatain;
if(!pDevExt->bFPCalc)
{
//Floating Point disabled
//Use simple deadzone calculations
if(xdata >= 0)
{
if(xdata < iDeadZone)
{
xdata = 0;
}
else
{
xdata = 32767 * (xdata - iDeadZone)/(32767 - iDeadZone);
}
}
else
{
if(xdata > -(iDeadZone))
{
xdata = 0;
}
else
{
xdata = -32767 * (xdata + iDeadZone)/(-32768 + iDeadZone);
}
}
if(ydata >= 0)
{
if(ydata < iDeadZone)
{
ydata = 0;
}
else
{
ydata = 32767 * (ydata - iDeadZone)/(32767 - iDeadZone);
}
}
else
{
if(ydata > -(iDeadZone))
{
ydata = 0;
}
else
{
ydata = -32767 * (ydata + iDeadZone)/(-32768 + iDeadZone);
}
}
}
else
{
//Floating Point enabled
NTSTATUS Status;
KFLOATING_SAVE saveData;
double radius;
double xdata2;
double ydata2;
Status = KeSaveFloatingPointState(&saveData);
if(NT_SUCCESS(Status))
{
radius = (double)(xdata * xdata) + (double)(ydata * ydata);
radius = sqrt2(radius);
if(radius > 32767)
radius = 32767;
if(radius >= iDeadZone)
{
radius = 32767 * (radius - iDeadZone)/(32767 - iDeadZone);
xdata2 = xdata/(radius * 0.7071);
ydata2 = ydata/(radius * 0.7071);
if(xdata2 > 1)
xdata2 = 1;
if(xdata2 < -1)
xdata2 = -1;
if(ydata2 > 1)
ydata2 = 1;
if(ydata2 < -1)
ydata2 = -1;
xdata2 = xdata2 * radius;
ydata2 = ydata2 * radius;
xdata = ftoi(xdata2);
ydata = ftoi(ydata2);
}
else
{
xdata = 0;
ydata = 0;
}
KeRestoreFloatingPointState(&saveData);
}
}
*xdatain = xdata;
*ydatain = ydata;
}
NTSTATUS XBCDReadData(PDEVICE_EXTENSION pDevExt, PIRP pIrp)
{
unsigned char xbdata[11]; //Holds output data
short btndata;
short xdata;
short ydata;
int iTBuffer; //Temporary buffer for analog button data
int iTest;
NTSTATUS Status;
RtlZeroMemory(&btndata, sizeof(btndata));
RtlZeroMemory(&xbdata, sizeof(xbdata));
RtlZeroMemory(&xdata, sizeof(xdata));
RtlZeroMemory(&ydata, sizeof(ydata));
if(pDevExt->btnset)
{
//Button A
iTBuffer = pDevExt->intdata[4] & 255; //Pass the value of button A to iTBuffer
//If value of button is higher than the threshold value then button is active
if (iTBuffer >= pDevExt->BThreshold)
{
btndata |= pDevExt->buttons[0];
}
//Button B
iTBuffer = pDevExt->intdata[5] & 255;
if (iTBuffer >= pDevExt->BThreshold)
{
btndata |= pDevExt->buttons[1];
}
//Button X
iTBuffer = pDevExt->intdata[6] & 255;
if (iTBuffer >= pDevExt->BThreshold)
{
btndata |= pDevExt->buttons[2];
}
//Button Y
iTBuffer = pDevExt->intdata[7] & 255;
if (iTBuffer >= pDevExt->BThreshold)
{
btndata |= pDevExt->buttons[3];
}
//Black Button
iTBuffer = pDevExt->intdata[8] & 255;
if (iTBuffer >= pDevExt->BThreshold)
{
btndata |= pDevExt->buttons[4];
}
//White Button
iTBuffer = pDevExt->intdata[9] & 255;
if (iTBuffer >= pDevExt->BThreshold)
{
btndata |= pDevExt->buttons[5];
}
//Start Button
if (pDevExt->intdata[2] & 16)
{
btndata |= pDevExt->buttons[6];
}
//Back Button
if (pDevExt->intdata[2] & 32)
{
btndata |= pDevExt->buttons[7];
}
//L-Stick Press
if (pDevExt->intdata[2] & 64)
{
btndata |= pDevExt->buttons[8];
}
//R-Stick Press
if (pDevExt->intdata[2] & 128)
{
btndata |= pDevExt->buttons[9];
}
if(!pDevExt->bTThrottle)
{
//L-Trigger Button
iTBuffer = pDevExt->intdata[10] & 255;
if (iTBuffer >= pDevExt->TThreshold)
{
btndata |= pDevExt->buttons[10];
}
//R-Trigger Button
iTBuffer = pDevExt->intdata[11] & 255;
if (iTBuffer >= pDevExt->TThreshold)
{
btndata |= pDevExt->buttons[11];
}
}
}
else
{
//Button A
iTBuffer = pDevExt->intdata[4] & 255; //Pass the value of button A to iTBuffer
//If value of button is higher than the threshold value then button is active
if (iTBuffer >= pDevExt->BThreshold)
{
xbdata[0] |= 1;
}
//Button B
iTBuffer = pDevExt->intdata[5] & 255;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -