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

📄 xbcd_control.c

📁 xbox game joystick driver.
💻 C
📖 第 1 页 / 共 2 页
字号:
/*	
    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 + -