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

📄 xbcd_usb.c

📁 xbox game joystick driver.
💻 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"

#pragma PAGEDCODE

//Send URB to the lower device object
NTSTATUS SendAwaitUrb(PDEVICE_OBJECT pFdo, PURB pUrb)
	{
	PDEVICE_EXTENSION pDevExt = GET_MINIDRIVER_DEVICE_EXTENSION(pFdo);
	KEVENT event;
	PIRP pIrp;
	IO_STATUS_BLOCK iostatus;
	PIO_STACK_LOCATION stack;
	NTSTATUS status;

	//PAGED_CODE();
	//ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);

	KeInitializeEvent(&event, NotificationEvent, FALSE);

	pIrp = IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_USB_SUBMIT_URB,
		pDevExt->pLowerPdo, NULL, 0, NULL, 0, TRUE, &event, &iostatus);

	if (!pIrp)
		{
			KdPrint(("SendAwaitUrb - Unable to allocate IRP for sending URB"));
			return STATUS_INSUFFICIENT_RESOURCES;
		}

	stack = IoGetNextIrpStackLocation(pIrp);
	stack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
	stack->Parameters.Others.Argument1 = pUrb;
	status = IoCallDriver(pDevExt->pLowerPdo, pIrp);
	if (status == STATUS_PENDING)
		{
			KdPrint(("SendAwaitUrb - status_pending"));
			KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
			status = iostatus.Status;
		}
	if(NT_SUCCESS(status))
	{
		KdPrint(("SendAwaitUrb - status success"));
	}
	else
	{
		KdPrint(("SendAwaitUrb - error %d", status));
	}
	KdPrint(("SendAwaitUrb - returning"));
	return status;
}

#pragma LOCKEDCODE

NTSTATUS StartInterruptUrb(PDEVICE_EXTENSION pDevExt)
	{

	NTSTATUS status;
	PIRP Irp;
	PURB urb;
	PIO_STACK_LOCATION stack;
	BOOLEAN bStartIrp;
	KIRQL oldirql;

	KeAcquireSpinLock(&pDevExt->polllock, &oldirql);

	// If the IRP is currently running, don't try to start it again.
	if (pDevExt->pollpending)
		bStartIrp = FALSE;
	else
		bStartIrp = TRUE, pDevExt->pollpending = TRUE;

	KeReleaseSpinLock(&pDevExt->polllock, oldirql);

	if (!bStartIrp)
		return STATUS_DEVICE_BUSY;	// already pending

	Irp = pDevExt->pIrp;
	urb = pDevExt->pUrb;
	if(!(Irp && urb))
	{
		KdPrint(("StartInterruptUrb - Could not get Irp and urb from Device Extension"));
	}

	// Acquire the remove lock so we can't remove the lower device while the IRP
	// is still active.
	status = AcquireRemoveLock(&pDevExt->RemoveLock, Irp);

	if (!NT_SUCCESS(status))
	{
		KdPrint(("StartInterruptUrb - Acquiring remove lock failed"));
		pDevExt->pollpending = FALSE;
		return status;
	}

	KdPrint(("StartInterruptUrb - Building urb"));
	UsbBuildInterruptOrBulkTransferRequest(urb, sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
		pDevExt->hintpipe, &pDevExt->intdata, NULL, 20, USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK, NULL);

	// Install "OnInterrupt" as the completion routine for the IRP.
	IoSetCompletionRoutine(Irp, (PIO_COMPLETION_ROUTINE) OnInterrupt, pDevExt, TRUE, TRUE, TRUE);

	// Initialize the IRP for an internal control request
	stack = IoGetNextIrpStackLocation(Irp);
	stack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
	stack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
	stack->Parameters.Others.Argument1 = urb;

	// Set the IRP Cancel flag to false.  It could have been canceled previously
	// and we need to reuse it.  IoReuseIrp is not available in Windows 9x.
	Irp->Cancel = FALSE;

	KdPrint(("StartInterruptUrb - Returning"));
	return IoCallDriver(pDevExt->pLowerPdo, Irp);
}

NTSTATUS SendInterruptUrb(PDEVICE_EXTENSION pDevExt)
	{

	NTSTATUS status;
	PIRP pIrp;
	IO_STATUS_BLOCK iostatus;
	PIO_STACK_LOCATION stack;
	KEVENT event;
	PURB urb = (PURB)ExAllocatePool(NonPagedPool, sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER));


	KdPrint(("SendInterruptUrb - Building urb"));
	UsbBuildInterruptOrBulkTransferRequest(urb, sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
		pDevExt->hintoutpipe, &pDevExt->intoutdata, NULL, 6, USBD_TRANSFER_DIRECTION_OUT | USBD_SHORT_TRANSFER_OK, NULL);

	//status = SendAwaitUrb(pDevExt->pPdo, urb);

	KeInitializeEvent(&event, NotificationEvent, FALSE);

	pIrp = IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_USB_SUBMIT_URB,
		pDevExt->pLowerPdo, NULL, 0, NULL, 0, TRUE, &event, &iostatus);

	if (!pIrp)
		{
			KdPrint(("SendInterruptUrb - Unable to allocate IRP for sending URB"));
			return STATUS_INSUFFICIENT_RESOURCES;
		}

	stack = IoGetNextIrpStackLocation(pIrp);
	stack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
	stack->Parameters.Others.Argument1 = urb;
	status = IoCallDriver(pDevExt->pLowerPdo, pIrp);
	if (status == STATUS_PENDING)
		{
			KdPrint(("SendAwaitUrb - status_pending"));
			KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
			status = iostatus.Status;
		}
	if(NT_SUCCESS(status))
	{
		KdPrint(("SendInterruptUrb - status success"));
	}
	else
	{
		KdPrint(("SendInterruptUrb - error %d", status));
	}
	KdPrint(("SendInterruptUrb - returning"));

	return status;
}

#pragma PAGEDCODE
//Create an Interrupt Urb
NTSTATUS CreateInterruptUrb(PDEVICE_OBJECT pFdo)
	{
	PDEVICE_EXTENSION pDevExt = GET_MINIDRIVER_DEVICE_EXTENSION(pFdo);
	PIRP pIrp;
	PURB pUrb;

	pIrp = IoAllocateIrp(pDevExt->pLowerPdo->StackSize, FALSE);
	if (!pIrp)
		{
		KdPrint(("CreateInterruptUrb - Unable to create IRP for interrupt polling"));
		return STATUS_INSUFFICIENT_RESOURCES;
		}

	pUrb = (PURB) ExAllocatePool(NonPagedPool, sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER));
	if (!pUrb)
		{
		KdPrint(("CreateInterruptUrb - Unable to allocate interrupt polling URB"));
		IoFreeIrp(pIrp);
		return STATUS_INSUFFICIENT_RESOURCES;
		}

	pDevExt->pIrp = pIrp;
	pDevExt->pUrb = pUrb;

	return STATUS_SUCCESS;
}

#pragma PAGEDCODE
//Delete the Interrup Urb
VOID DeleteInterruptUrb(PDEVICE_OBJECT pFdo)
{
	PDEVICE_EXTENSION pDevExt = GET_MINIDRIVER_DEVICE_EXTENSION(pFdo);

	//ASSERT(pDevExt->pIrp != NULL);
	//ASSERT(pDevExt->pUrb != NULL);

	ExFreePool(pDevExt->pUrb);
	IoFreeIrp(pDevExt->pIrp);
	pDevExt->pIrp = NULL;
	pDevExt->pUrb = NULL;
}

#pragma LOCKEDCODE

NTSTATUS OnInterrupt(PDEVICE_OBJECT junk, PIRP pIrp, PDEVICE_EXTENSION pDevExt)
	{
	KIRQL oldirql;
	NTSTATUS Status;

	KeAcquireSpinLock(&pDevExt->polllock, &oldirql);

	if (NT_SUCCESS(pIrp->IoStatus.Status))
	{						
		//Status = XBCDReadData(pDevExt, pDevExt->CurrentIrp);
		
		KdPrint(("OnInterrupt - Success reading report"));
	}
	else
	{
		KdPrint(("OnInterrupt - Failed to read report"));
	}

	pDevExt->pollpending = FALSE;	// allow another poll to be started
	KeReleaseSpinLock(&pDevExt->polllock, oldirql);

	KdPrint(("OnInterrupt - Releasing Removelock"));
	ReleaseRemoveLock(&pDevExt->RemoveLock, pDevExt->pIrp); // balances acquisition in StartInterruptUrb

	if(pDevExt->timerEnabled)
		Status = StartInterruptUrb(pDevExt);
	
	KdPrint(("OnInterrupt - Returning"));
	return STATUS_MORE_PROCESSING_REQUIRED;
}

#pragma LOCKEDCODE

VOID StopInterruptUrb(PDEVICE_EXTENSION pDevExt)
{	
	KdPrint(("StopInterruptUrb - Entered"));
	if (pDevExt->pollpending)
	{
		KdPrint(("StopInterruptUrb - Canceling pIrp"));
		IoCancelIrp(pDevExt->pIrp);
	}
	return;
}

/*++
 
Routine Description:

    This routine synchronously submits a URB_FUNCTION_RESET_PIPE
    request down the stack.

Arguments:

    DeviceObject - pointer to device object
    PipeInfo - pointer to PipeInformation structure
               to retrieve the pipe handle

Return Value:

    NT status value

--*/

/*NTSTATUS ResetPipe(IN PDEVICE_OBJECT DeviceObject, IN USBD_PIPE_HANDLE *PipeHandle)
{
    PURB              urb;
    NTSTATUS          ntStatus;
    PDEVICE_EXTENSION deviceExtension;

    //
    // initialize variables
    //

    urb = NULL;
    deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;


    urb = ExAllocatePool(NonPagedPool, 
                         sizeof(struct _URB_PIPE_REQUEST));

    if(urb) {

        urb->UrbHeader.Length = (USHORT) sizeof(struct _URB_PIPE_REQUEST);
        urb->UrbHeader.Function = URB_FUNCTION_RESET_PIPE;
        urb->UrbPipeRequest.PipeHandle = PipeHandle;

        ntStatus = SendAwaitUrb(DeviceObject, urb);

        ExFreePool(urb);
    }
    else {

        ntStatus = STATUS_INSUFFICIENT_RESOURCES;
    }

    if(NT_SUCCESS(ntStatus)) {
    
        KdPrint(("ResetPipe - success\n"));
        ntStatus = STATUS_SUCCESS;
    }
    else {

        KdPrint(("ResetPipe - failed\n"));
    }

    return ntStatus;
}*/

⌨️ 快捷键说明

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