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

📄 intrwr.c

📁 学习usb编程很好的例子 自己学习用的。
💻 C
📖 第 1 页 / 共 2 页
字号:
 /*++


Module Name:

    intrwr.c

Abstract:

    This file has routines to perform reads and writes.
    The read and writes are for int transfers.

Environment:

    Kernel mode

Notes:

    
--*/

#include "intusb.h"
#include "intpnp.h"
#include "intpwr.h"
#include "intdev.h"
#include "intrwr.h"
#include "intwmi.h"
#include "intusr.h"


///////////////////////////////////////////////////////////////////////////////

//#pragma PAGEDCODE
#pragma LOCKEDCODE

NTSTATUS 
CreateInterruptUrbIN(
	IN PDEVICE_OBJECT DeviceObject
	)
/*++
 
Routine Description:

    Create the input URB Polling Interrupt.

Arguments:

    DeviceObject - pointer to DeviceObject
    
Return Value:

    NT status value

--*/
	{							// CreateInterruptUrb
	PIRP IrpIN;
	PURB urbIN;
	PDEVICE_EXTENSION      deviceExtension;
	KdPrint( (DRIVERNAME " - CreateInterruptUrbIN - begins %8.8lX\n"));

	deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
	ASSERT(deviceExtension->PollingIrpIN == NULL);
	ASSERT(deviceExtension->PollingUrbIN == NULL);

	IrpIN = IoAllocateIrp(deviceExtension->TopOfStackDeviceObject->StackSize, FALSE);
	if (!IrpIN)
		{
		KdPrint((DRIVERNAME " - Unable to create IRP for interrupt polling\n"));
		return STATUS_INSUFFICIENT_RESOURCES;
		}

	urbIN = (PURB) ExAllocatePool(NonPagedPool, sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER));
	if (!urbIN)
		{
		KdPrint((DRIVERNAME " - Unable to allocate interrupt polling URB\n"));
		IoFreeIrp(IrpIN);
		return STATUS_INSUFFICIENT_RESOURCES;
		}
	
	deviceExtension->PollingIrpIN = IrpIN;
	deviceExtension->PollingUrbIN = urbIN;
	
	return STATUS_SUCCESS;
	}							// CreateInterruptUrb


///////////////////////////////////////////////////////////////////////////////

#pragma PAGEDCODE

VOID 
DeleteInterruptUrbIN(
	IN PDEVICE_OBJECT DeviceObject
	)
/*++
 
Routine Description:

    Delete the input URB Polling Interrupt.

Arguments:

    DeviceObject - pointer to DeviceObject
    
Return Value:

    NT status value

--*/
	{							// DeleteInterruptUrb
	PDEVICE_EXTENSION deviceExtension;

	KdPrint( (DRIVERNAME " - DeleteInterruptUrbIN - begins %8.8lX\n"));

	deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
	ASSERT(deviceExtension->PollingIrpIN != NULL);
	ASSERT(deviceExtension->PollingUrbIN != NULL);
	
	ExFreePool(deviceExtension->PollingUrbIN);
	IoFreeIrp(deviceExtension->PollingIrpIN);
	deviceExtension->PollingIrpIN = NULL;
	deviceExtension->PollingUrbIN = NULL;
	
	}							// DeleteInterruptUrb


///////////////////////////////////////////////////////////////////////////////

#pragma LOCKEDCODE

NTSTATUS 
StartInterruptUrbIN(
	IN PDEVICE_EXTENSION deviceExtension
	)
/*++
 
Routine Description:

    Submit the Polling IRP with associated URB to the bus driver.
	The URB is formatted for an MAX_TRANSFER_SIZE byte transfer on the interrupt 
	intput pipe with the USBD_SHORT_TRANSFER_OK flag set so any transfer
	from 0 to MAX_TRANSFER_SIZE bytes may be used.

Arguments:

    deviceExtension - Pointer to the device Extension

Return Value:

    NT status value

--*/
	{							// StartInterruptUrb

	NTSTATUS ReturnStatus;
	BOOLEAN startirp;
	KIRQL oldirql;
	PIRP IrpIN;
	PURB urbIN;
	NTSTATUS status;
	PIO_STACK_LOCATION stackIN;

	//KdPrint( (DRIVERNAME " - StartInterruptUrbIN - begins %8.8lX\n"));
	
	// Check to see if a Poll is already pending before submitting 
	// request to the bus.

	KeAcquireSpinLock(&deviceExtension->polllock, &oldirql);
	if (deviceExtension->pollpending)
		startirp = FALSE;
	else
		startirp = TRUE, deviceExtension->pollpending = TRUE;
	KeReleaseSpinLock(&deviceExtension->polllock, oldirql);

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

	IrpIN = deviceExtension->PollingIrpIN;
	urbIN = deviceExtension->PollingUrbIN;
	ASSERT(IrpIN && urbIN);
	
	// Acquire the remove lock the device cannot be removed while the IRP
	// is active.

	status = IoAcquireRemoveLock(&deviceExtension->RemoveLock, IrpIN);
	if (!NT_SUCCESS(status))
		{
		deviceExtension->pollpending = 0;
		return status;
		}

	// Initialize the URB we use for reading the interrupt pipe

	deviceExtension->hintpipeIN = deviceExtension->UsbInterface->Pipes[0].PipeHandle;

	UsbBuildInterruptOrBulkTransferRequest(urbIN, sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
		deviceExtension->hintpipeIN, &deviceExtension->intdataIN, NULL, MAX_TRANSFER_SIZE, USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK, NULL);

	// Install "OnInterruptIN" as the completion routine for the polling IRP.
	
	IoSetCompletionRoutine(IrpIN, (PIO_COMPLETION_ROUTINE) OnInterruptIN, deviceExtension, TRUE, TRUE, TRUE);

	// Initialize the IRP for an internal control request

	stackIN = IoGetNextIrpStackLocation(IrpIN);
	stackIN->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
	stackIN->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
	stackIN->Parameters.Others.Argument1 = urbIN;

	// Make sure the Cancel Flag is cleared

	IrpIN->Cancel = FALSE;

	status = IoCallDriver(deviceExtension->TopOfStackDeviceObject, IrpIN);
	
	return status;
	}							// StartInterruptUrb


///////////////////////////////////////////////////////////////////////////////

#pragma LOCKEDCODE
	
VOID 
StopInterruptUrbIN(
	IN PDEVICE_EXTENSION deviceExtension
	)
/*++
 
Routine Description:

    This routine cancels the Polling IRP

Arguments:

    deviceExtension - Pointer to the device Extension


--*/
	{							// StopInterruptUrb

	KdPrint( (DRIVERNAME " - StopInterruptUrbIN - begins %8.8lX\n"));
	
	if (deviceExtension->pollpending)
		IoCancelIrp(deviceExtension->PollingIrpIN);
	}							// StopInterruptUrb

///////////////////////////////////////////////////////////////////////////////



#pragma LOCKEDCODE

NTSTATUS 
OnInterruptIN(
	IN PDEVICE_OBJECT junk, 
	IN PIRP IrpIN, 
	IN PDEVICE_EXTENSION deviceExtension
	)
/*++
 
Routine Description:

    This routine is the completion routine for the Polling IRP submitted in
	the StartInterruptIN routine. If the IRP was successful this routine will
	transfer the input data to the Application by means of an IO Control request.
	An the IO Control request must already be submitted and outstanding before this 
	routine is called in order to be serviced.

Arguments:

    DeviceObject - pointer to DeviceObject
    IrpIN - Polling input pipe Irp to be serviced.
	deviceExtension - Pointer to the device Extension

Return Value:

    NT status value

--*/
	{							// OnInterrupt

	KIRQL oldirql;
	PVOID powercontext;
	PIRP intirpIN;
	IO_REMOVE_LOCK localRemoveLock;
	
	//KdPrint( (DRIVERNAME " - OnInterruptIN - begins %8.8lX\n"));
	
	KeAcquireSpinLock(&deviceExtension->polllock, &oldirql);
	deviceExtension->pollpending = FALSE;		// allow another poll to be started
	powercontext = deviceExtension->powercontext;
	deviceExtension->powercontext = NULL;
	KeReleaseSpinLock(&deviceExtension->polllock, oldirql);

	// If the poll completed successfully,answer the IOCTL request sent by the Windows
	// application and reissue the read. We're trying to have a read outstanding on the
	// interrupt pipe when the device is running.

	if (NT_SUCCESS(IrpIN->IoStatus.Status))
		{						// an interrupt has occurred
		//KdPrint((DRIVERNAME " - Interrupt IN!\n"));
		// Get the length of the transfer from the URB we used for this request
		InterlockedExchange(&(deviceExtension->intdataLength),deviceExtension->PollingUrbIN->UrbBulkOrInterruptTransfer.TransferBufferLength);  
		
		intirpIN = UncacheReadRequest(deviceExtension, &deviceExtension->InterruptIrp);
		if (intirpIN)
		{
			// Exchange data between the Polling URB and the Servicing IRP
			RtlCopyMemory(intirpIN->AssociatedIrp.SystemBuffer,&deviceExtension->intdataIN,deviceExtension->intdataLength);
			RtlZeroMemory(&deviceExtension->intdataIN, MAX_TRANSFER_SIZE);
			
			// Complete the request and indicate the length
			// in the information field.
			
        	CompleteRequest(intirpIN, STATUS_SUCCESS, deviceExtension->intdataLength);
		}
		else
			// Interrupt occurred but was not serviced
			InterlockedIncrement(&deviceExtension->numintsIN);

		// Reissue the polling IRP. 
		StartInterruptUrbIN(deviceExtension); // issue next polling request
		}						// device signalled an interrupt
#if DBG	
	else
		{
		KdPrint((DRIVERNAME " - Interrupt polling IRP IN %X failed - %X (USBD status %X)\n",
			IrpIN, IrpIN->IoStatus.Status, URB_STATUS(deviceExtension->PollingUrbIN)));
		}
#endif

	// Release RemoveLock which was acquired in StartInterruptUrbIN
	IoReleaseRemoveLock(&deviceExtension->RemoveLock, IrpIN); 

	return STATUS_MORE_PROCESSING_REQUIRED;
	}							// OnInterrupt



///////////////////////////////////////////////////////////////////////////////

#pragma LOCKEDCODE

NTSTATUS 
CompleteRequest(
	IN PIRP Irp, 
	IN NTSTATUS status, 
	IN ULONG_PTR info
	)
/*++
 
Routine Description:

    Complete the Request with no priority boost since we are not waiting on IO.

Arguments:

    Irp - IRP to be completed
	status - IRP completion status
	info - information associated with the IRP

Return Value:

    NT status value

--*/
{							
	Irp->IoStatus.Status = status;
	Irp->IoStatus.Information = info;
	IoCompleteRequest(Irp, IO_NO_INCREMENT);
	return status;
}							


PINTUSB_PIPE_CONTEXT
IntUsb_PipeWithName(
    IN PDEVICE_OBJECT  DeviceObject,
    IN PUNICODE_STRING FileName
    )
/*++
 
Routine Description:

    This routine will pass the string pipe name and
    fetch the pipe number.

Arguments:

    DeviceObject - pointer to DeviceObject
    FileName - string pipe name

Return Value:

    The device extension maintains a pipe context for 
    the pipes on the board.
    This routine returns the pointer to this context in
    the device extension for the "FileName" pipe.

--*/
{
    LONG                  ix;
    ULONG                 uval; 
    ULONG                 nameLength;
    ULONG                 umultiplier;
    PDEVICE_EXTENSION     deviceExtension;
    PINTUSB_PIPE_CONTEXT pipeContext;

    //
    // initialize variables
    //
    pipeContext = NULL;
    //
    // typedef WCHAR *PWSTR;
    //
    nameLength = (FileName->Length / sizeof(WCHAR));
    deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;

    KdPrint( ("IntUsb_PipeWithName - begins\n"));

    if(nameLength != 0) {
    
        KdPrint( ("Filename = %ws nameLength = %d\n", FileName->Buffer, nameLength));

        //
        // Parse the pipe#
        //
        ix = nameLength - 1;

        // if last char isn't digit, decrement it.
        while((ix > -1) &&
              ((FileName->Buffer[ix] < (WCHAR) '0')  ||
               (FileName->Buffer[ix] > (WCHAR) '9')))             {

            ix--;
        }

        if(ix > -1) {

            uval = 0;
            umultiplier = 1;

            // traversing least to most significant digits.

            while((ix > -1) &&
                  (FileName->Buffer[ix] >= (WCHAR) '0') &&
                  (FileName->Buffer[ix] <= (WCHAR) '9'))          {
        
                uval += (umultiplier *
                         (ULONG) (FileName->Buffer[ix] - (WCHAR) '0'));

                ix--;
                umultiplier *= 10;
            }
        }

        if(uval < 6 && deviceExtension->PipeContext) {
        
            pipeContext = &deviceExtension->PipeContext[uval];
        }
    }

    KdPrint( ("IntUsb_PipeWithName - ends\n"));

    return pipeContext;
}

NTSTATUS
IntUsb_DispatchWrite(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP           Irp
    )
/*++
 
Routine Description:

    Dispatch routine for write.
    This routine creates a INTUSB_RW_CONTEXT for a write.
    
Arguments:

    DeviceObject - pointer to device object
    Irp - I/O request packet

Return Value:

    NT status value

--*/
{
    PURB                   urb;
    ULONG                  Length;
    ULONG                  urbFlags;
    BOOLEAN                read;
    NTSTATUS               ntStatus;
    PFILE_OBJECT           fileObject;
    PDEVICE_EXTENSION      deviceExtension;
    PIO_STACK_LOCATION     irpStack;
    PIO_STACK_LOCATION     nextStack;
    PINTUSB_RW_CONTEXT    rwContext;
    PUSBD_PIPE_INFORMATION pipeInformation;
	PIO_STACK_LOCATION		IrpStack;

    //
    // initialize variables
    //
    urb = NULL;
    rwContext = NULL;
    Length = 0;
    irpStack = IoGetCurrentIrpStackLocation(Irp);
    fileObject = irpStack->FileObject;
    read = (irpStack->MajorFunction == IRP_MJ_READ) ? TRUE : FALSE;
    deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
	IrpStack = IoGetCurrentIrpStackLocation(Irp);
	urbFlags = USBD_SHORT_TRANSFER_OK;
	

    KdPrint( ("IntUsb_DispatchWrite - begins\n"));
	
	

    if(deviceExtension->DeviceState != Working) {

        KdPrint( ("Invalid device state\n"));

        ntStatus = STATUS_INVALID_DEVICE_STATE;
        goto IntUsb_DispatchReadWrite_Exit;
    }

    //
    // It is true that the client driver cancelled the selective suspend
    // request in the dispatch routine for create Irps.
    // But there is no guarantee that it has indeed completed.
    // so wait on the NoIdleReqPendEvent and proceed only if this event
    // is signalled.
    //
    KdPrint( ("Waiting on the IdleReqPendEvent\n"));
    
    //
    // make sure that the selective suspend request has been completed.

⌨️ 快捷键说明

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