📄 dpnp.c
字号:
// #define DRIVER
//
// Include files needed for WDM driver support
//
#include <wdm.h>
#include "stdarg.h"
#include "stdio.h"
//
// Include files needed for USB support
//
#include "usbdi.h"
#include "usbdlib.h"
//
// Include file for the Ezusb Device
//
#include "ezusbsys.h"
#ifdef DOWNLOAD_KEIL_MONITOR
extern INTEL_HEX_RECORD mon_ext_sio1_fx2[];
extern INTEL_HEX_RECORD loader[];
#endif // ifdef DOWNLOAD_KEIL_MONITOR
void d_DumpBuffer(PVOID pvBuffer, ULONG length);
NTSTATUS d_DispatchPnp(
IN PDEVICE_OBJECT fdo,
IN PIRP Irp
)
/*++
Routine Description:
Process Plug and Play IRPs sent to this device.
Arguments:
fdo - pointer to a device object
Irp - pointer to an I/O Request Packet
Return Value:
NTSTATUS
--*/
{
PIO_STACK_LOCATION irpStack;
PDEVICE_EXTENSION pdx = fdo->DeviceExtension;
ULONG fcn;
NTSTATUS ntStatus;
Ezusb_KdPrint (("Enter Ezusb_DispatchPnp\n"));
if (!LockDevice(fdo))
return CompleteRequest(Irp, STATUS_DELETE_PENDING, 0);
//
// Get a pointer to the current location in the Irp. This is where
// the function codes and parameters are located.
//
irpStack = IoGetCurrentIrpStackLocation (Irp);
ASSERT(irpStack->MajorFunction == IRP_MJ_PNP);
fcn = irpStack->MinorFunction;
switch (fcn)
{
case IRP_MN_START_DEVICE:
Ezusb_KdPrint (("IRP_MN_START_DEVICE\n"));
ntStatus = d_HandleStartDevice(fdo,Irp);
if (ntStatus == STATUS_SUCCESS)
{
pdx->Started = TRUE;
}
break; //IRP_MN_START_DEVICE
case IRP_MN_STOP_DEVICE:
Ezusb_KdPrint (("IRP_MN_STOP_DEVICE\n"));
//
// first pass the request down the stack
//
d_DefaultPnpHandler(fdo,Irp);
ntStatus = d_StopDevice(fdo);
break; //IRP_MN_STOP_DEVICE
case IRP_MN_REMOVE_DEVICE:
Ezusb_KdPrint (("IRP_MN_REMOVE_DEVICE\n"))
ntStatus = d_HandleRemoveDevice(fdo,Irp);
break; //IRP_MN_REMOVE_DEVICE
case IRP_MN_QUERY_CAPABILITIES:
{
//
// This code swiped from Walter Oney. Please buy his book!!
//
PDEVICE_CAPABILITIES pdc = irpStack->Parameters.DeviceCapabilities.Capabilities;
Ezusb_KdPrint (("IRP_MN_QUERY_CAPABILITIES\n"))
// Check to be sure we know how to handle this version of the capabilities structure
if (pdc->Version < 1)
{
ntStatus = d_DefaultPnpHandler(fdo, Irp);
break;
}
ntStatus = d_ForwardAndWait(fdo, Irp);
if (NT_SUCCESS(ntStatus))
{ // IRP succeeded
pdc = irpStack->Parameters.DeviceCapabilities.Capabilities;
// 用户删除设备时,阻止 NT5 发出警告.
pdc->SurpriseRemovalOK = 0;//TRUE;//1;//
} // IRP succeeded
ntStatus = CompleteRequest(Irp, ntStatus, Irp->IoStatus.Information);
//Irp->IoStatus.Status = ntStatus;
//Irp->IoStatus.Information = Irp->IoStatus.Information;
//IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
break; //IRP_MN_QUERY_CAPABILITIES
//
// All other PNP IRP's are just passed down the stack by the default handler
//
default:
Ezusb_KdPrint (("Passing down unhandled PnP IOCTL 0x%x\n", fcn));
ntStatus = d_DefaultPnpHandler(fdo, Irp);
} // switch MinorFunction
if (fcn != IRP_MN_REMOVE_DEVICE)
UnlockDevice(fdo);
Ezusb_KdPrint (("Exit Ezusb_DispatchPnp %x\n", ntStatus));
return ntStatus;
}//Ezusb_Dispatch
NTSTATUS d_HandleStartDevice(
IN PDEVICE_OBJECT fdo,
IN PIRP Irp
)
{
NTSTATUS ntStatus;
//
// First let all lower-level drivers handle this request.
//
ntStatus = d_ForwardAndWait(fdo, Irp);
if (!NT_SUCCESS(ntStatus))
return CompleteRequest(Irp, ntStatus, Irp->IoStatus.Information);
//
// now do whatever we need to do to start the device
//
ntStatus = d_StartDevice(fdo);
return CompleteRequest(Irp, ntStatus, 0);
}
NTSTATUS d_DefaultPnpHandler(
IN PDEVICE_OBJECT fdo,
IN PIRP Irp
)
{
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;
IoSkipCurrentIrpStackLocation(Irp);
return IoCallDriver(pdx->StackDeviceObject, Irp);
}
NTSTATUS d_HandleRemoveDevice(
IN PDEVICE_OBJECT fdo,
IN PIRP Irp
)
{
NTSTATUS ntStatus;
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;
ULONG i;
// set the removing flag to prevent any new I/O's
pdx->removing = TRUE;
// brute force - send an abort pipe message to all pipes to cancel any
// pending transfers. this should solve the problem of the driver blocking
// on a REMOVE message because there is a pending transfer.
for (i = 0; i < pdx->Interface->NumberOfPipes; i++)
{
c_AbortPipe(fdo,(USBD_PIPE_HANDLE) pdx->Interface->Pipes[i].PipeHandle);
}
UnlockDevice(fdo); // once for LockDevice at start of dispatch
UnlockDevice(fdo); // once for initialization during AddDevice
KeWaitForSingleObject(&pdx->evRemove, Executive, KernelMode, FALSE, NULL);
d_RemoveDevice(fdo);
ntStatus = d_DefaultPnpHandler(fdo, Irp);
return ntStatus; // lower-level completed IoStatus already
}
NTSTATUS d_StopDevice(
IN PDEVICE_OBJECT fdo
)
/*++
Routine Description:
Stops a given instance of a Ezusb Device device on USB.
Arguments:
fdo - pointer to the device object for this instance of a Ezusb Device
Return Value:
NT status code
--*/
{
PDEVICE_EXTENSION pdx;
NTSTATUS ntStatus = STATUS_SUCCESS;
PURB urb;
ULONG siz;
Ezusb_KdPrint (("enter Ezusb_StopDevice\n"));
pdx = fdo->DeviceExtension;
//
// Send the select configuration urb with a NULL pointer for the configuration
// handle, this closes the configuration and puts the device in the 'unconfigured'
// state.
//
siz = sizeof(struct _URB_SELECT_CONFIGURATION);
urb = ExAllocatePool(NonPagedPool,
siz);
if (urb)
{
NTSTATUS status;
UsbBuildSelectConfigurationRequest(urb,
(USHORT) siz,
NULL);
status = Ezusb_CallUSBD(fdo, urb);
Ezusb_KdPrint (("Device Configuration Closed status = %x usb status = %x.\n",
status, urb->UrbHeader.Status));
ExFreePool(urb);
}
else
{
ntStatus = STATUS_NO_MEMORY;
}
Ezusb_KdPrint (("exit Ezusb_StopDevice (%x)\n", ntStatus));
return ntStatus;
}
NTSTATUS d_ForwardAndWait(
IN PDEVICE_OBJECT fdo,
IN PIRP Irp
)
/*++
Routine Description:
Forward request to lower level and await completion
The only purpose of this routine in this particular driver is to pass down
IRP_MN_START_DEVICE requests and wait for the PDO to handle them.
The processor must be at PASSIVE IRQL because this function initializes
and waits for non-zero time on a kernel event object.
Arguments:
fdo - pointer to a device object
Irp - pointer to an I/O Request Packet
Return Value:
STATUS_SUCCESS if successful,
STATUS_UNSUCCESSFUL otherwise
--*/
{
KEVENT event;
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;
NTSTATUS ntStatus;
ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
//
// Initialize a kernel event object to use in waiting for the lower-level
// driver to finish processing the object.
//
KeInitializeEvent(&event, NotificationEvent, FALSE);
IoCopyCurrentIrpStackLocationToNext(Irp);
IoSetCompletionRoutine(Irp, (PIO_COMPLETION_ROUTINE) OnRequestComplete,
(PVOID) &event, TRUE, TRUE, TRUE);
ntStatus = IoCallDriver(pdx->StackDeviceObject, Irp);
if (ntStatus == STATUS_PENDING)
{
KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
ntStatus = Irp->IoStatus.Status;
}
return ntStatus;
}
NTSTATUS d_StartDevice(
IN PDEVICE_OBJECT fdo
)
/*++
Routine Description:
Initializes a given instance of the Ezusb Device on the USB.
Arguments:
fdo - pointer to the device object for this instance of a
Ezusb Device
Return Value:
NT status code
--*/
{
PDEVICE_EXTENSION pdx;
NTSTATUS ntStatus;
PUSB_DEVICE_DESCRIPTOR deviceDescriptor = NULL;
PURB urb;
ULONG siz;
Ezusb_KdPrint (("enter Ezusb_StartDevice\n"));
pdx = fdo->DeviceExtension;
pdx->NeedCleanup = TRUE;
/*
// Get some memory from then non paged pool (fixed, locked system memory)
// for use by the USB Request Block (urb) for the specific USB Request we
// will be performing below (a USB device request).
*/
urb = ExAllocatePool( NonPagedPool,
sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST));
if (urb) {
siz = sizeof(USB_DEVICE_DESCRIPTOR);
// Get some non paged memory for the device descriptor contents
deviceDescriptor = ExAllocatePool(NonPagedPool,
siz);
if (deviceDescriptor) {
// Use a macro in the standard USB header files to build the URB
UsbBuildGetDescriptorRequest(urb,
(USHORT) sizeof (struct _URB_CONTROL_DESCRIPTOR_REQUEST),
USB_DEVICE_DESCRIPTOR_TYPE,
0,
0,
deviceDescriptor,
NULL,
siz,
NULL);
// Get the device descriptor
ntStatus = Ezusb_CallUSBD(fdo, urb);
} else {
ntStatus = STATUS_NO_MEMORY;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -