📄 testusb.c
字号:
// ===================================================================
//
// testusb.c
//
// rev 1.0 beta
//
// this module handles USB IOCTL/IRP calls
//
// USB device driver for USB Device Example
// kernel mode driver
//
//
// ===================================================================
#define DRIVER
// Include files needed for WDM driver support; from NT DDK
#include "wdm.h"
#include "stdarg.h"
#include "stdio.h"
// Include files needed for USB support; from USB DDK
#include "usbdi.h"
#include "usbdlib.h"
#include "usb.h"
#include "Testdrv.h" // headers specified to this driver
#include "test98.h"
// ===================================================================
NTSTATUS
Test_CallUSBD(
IN PDEVICE_OBJECT DeviceObject,
IN PURB Urb
)
/*
Passes a Usb Request Block (URB) to the USB class driver (USBD)
Note that we create our own IRP here and use it to send the request to
the USB software subsystem. This means that this routine is essentially
independent of the IRP that caused this driver to be called in the first
place. The IRP for this transfer is created, used, and then destroyed
in this routine.
DiviceObject - pointer to the device object for this instance of a Test Device
Urb - pointer to Urb request block
Return Value:
STATUS_SUCCESS if successful,
STATUS_UNSUCCESSFUL otherwise
*/
{
NTSTATUS ntStatus, status = STATUS_SUCCESS;
PFDO_DEVICE_DATA deviceData;
PIRP irp;
KEVENT event;
IO_STATUS_BLOCK ioStatus;
PIO_STACK_LOCATION nextStack;
deviceData = (PFDO_DEVICE_DATA) DeviceObject->DeviceExtension;
// issue a synchronous request (see notes above)
KeInitializeEvent(&event, NotificationEvent, FALSE);
irp = IoBuildDeviceIoControlRequest(
IOCTL_INTERNAL_USB_SUBMIT_URB,
deviceData->UnderlyingPDO,
NULL,
0,
NULL,
0,
TRUE, /* INTERNAL */
&event,
&ioStatus);
// Prepare for calling the USB driver stack
nextStack = IoGetNextIrpStackLocation(irp);
ASSERT(nextStack != NULL);
// Set up the URB ptr to pass to the USB driver stack
nextStack->Parameters.Others.Argument1 = Urb;
// Call the USB class driver to perform the operation. If the returned status
// is PENDING, wait for the request to complete.
ntStatus = IoCallDriver(deviceData->UnderlyingPDO,
irp);
if (ntStatus == STATUS_PENDING) {
status = KeWaitForSingleObject(
&event,
Suspended,
KernelMode,
FALSE,
NULL);
} else {
ioStatus.Status = ntStatus;
}
// USBD maps the error code for us. USBD uses error codes in its URB
// structure that are more insightful into USB behavior. To allow more insight into
// the specific USB error that occurred, your driver may wish to examine the
// URB's status code (Urb->UrbHeader.Status) as well.
ntStatus = ioStatus.Status;
return ntStatus;
}
// ===================================================================
NTSTATUS
Test_ProcessIOCTL(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*
This where all the DeviceIoControl codes are handled. You can expand and add more code
here to handle IOCTL/IRP codes that are specific to your device driver.
DeviceObject - pointer to the device object for this instance of the test device.
Return Value: NT status
*/
{
PIO_STACK_LOCATION irpStack;
PVOID ioBuffer;
ULONG inputBufferLength;
ULONG outputBufferLength;
// PDEVICE_EXTENSION deviceExtension;
PFDO_DEVICE_DATA deviceData;
ULONG ioControlCode;
NTSTATUS ntStatus;
ULONG length;
PUCHAR pch;
// Get a pointer to the current location in the Irp. This is where
// the function codes and parameters are located.
irpStack = IoGetCurrentIrpStackLocation (Irp);
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
// Get a pointer to the device extension
deviceData = (PFDO_DEVICE_DATA) DeviceObject->DeviceExtension;
// ***
Test98_IncIoCount (deviceData);
ioBuffer = Irp->AssociatedIrp.SystemBuffer;
inputBufferLength = irpStack->Parameters.DeviceIoControl.InputBufferLength;
outputBufferLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
ioControlCode = irpStack->Parameters.DeviceIoControl.IoControlCode;
// Handle Ioctls from User mode
switch (ioControlCode) {
case IRP_Test_GET_PIPE_INFO:
// inputs - none
// outputs - we copy the interface information structure that we have
// stored in our device extension area to the output buffer which
// will be reflected to the user mode application by the IOS.
length = 0;
pch = (PUCHAR) ioBuffer;
Irp->IoStatus.Information = length;
Irp->IoStatus.Status = STATUS_SUCCESS;
break;
case IRP_Test_GET_DEVICE_DESCRIPTOR:
// inputs - pointer to a buffer in which to place descriptor data
// outputs - we put the device descriptor data, if any is returned by the device
// in the system buffer and then we set the length inthe Information field
// in the Irp, which will then cause the system to copy the buffer back
// to the user's buffer
length = Test_GetDeviceDescriptor (DeviceObject, ioBuffer);
Irp->IoStatus.Information = length;
Irp->IoStatus.Status = STATUS_SUCCESS;
break;
case IRP_Test_GET_CONFIGURATION_DESCRIPTOR:
// inputs - pointer to a buffer in which to place descriptor data
// outputs - we put the configuration descriptor data, if any is returned by the device
// in the system buffer and then we set the length in the Information field
// in the Irp, which will then cause the system to copy the buffer back
// to the user's buffer
length = Test_GetConfigDescriptor (DeviceObject, ioBuffer, outputBufferLength);
Irp->IoStatus.Information = length;
Irp->IoStatus.Status = STATUS_SUCCESS;
break;
default:
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
}// switch on ioControlCode
ntStatus = Irp->IoStatus.Status;
IoCompleteRequest (Irp,
IO_NO_INCREMENT
);
Test98_DecIoCount (deviceData);
return ntStatus;
}
// ===================================================================
ULONG
Test_GetDeviceDescriptor(
IN PDEVICE_OBJECT DeviceObject,
PVOID pvOutputBuffer
)
/*
Gets a device descriptor from the given device object
DeviceObject - pointer to the test device object
Return Value: Number of valid bytes in data buffer
*/
{
PFDO_DEVICE_DATA deviceData = NULL;
NTSTATUS ntStatus = STATUS_SUCCESS;
PURB urb = NULL;
ULONG length = 0;
deviceData = (PFDO_DEVICE_DATA) DeviceObject->DeviceExtension;
urb = ExAllocatePool(NonPagedPool,
sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST));
if (urb) {
if (pvOutputBuffer) {
UsbBuildGetDescriptorRequest(urb,
(USHORT) sizeof (struct _URB_CONTROL_DESCRIPTOR_REQUEST),
USB_DEVICE_DESCRIPTOR_TYPE, //descriptor type
0, //index
0, //language ID
pvOutputBuffer, //transfer buffer
NULL, //MDL
sizeof(USB_DEVICE_DESCRIPTOR), //buffer length
NULL); //link
ntStatus = Test_CallUSBD(DeviceObject, urb);
} else {
ntStatus = STATUS_NO_MEMORY;
}
// Get the length from the Urb
length = urb->UrbControlDescriptorRequest.TransferBufferLength;
ExFreePool(urb);
} else {
ntStatus = STATUS_NO_MEMORY;
}
return length;
}
// ===================================================================
/* not tested it yet
NTSTATUS SetOne(IN PDEVICE_OBJECT pDeviceObject, PUSBTESTCTRLDESC pTestCtrlDesc)
// perform a "set" setup packet
//
// Return Value: ntstatus
{
NTSTATUS ntStatus;
PURB pUrb;
pTemp=ExAllocatePool(NonPagedPool, sizeof(USBDISPDESC));
pUrb=ExAllocatePool(NonPagedPool, sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST));
if (pUrb) {
RtlCopyMemory(pTemp, pTestCtrlDesc, sizeof(USBTESTDESC));
UsbBuildVendorRequest(pUrb,
URB_FUNCTION_CLASS_DEVICE, //Command
sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST),
!(USBD_TRANSFER_DIRECTION_IN),// Direction Bit: OUT
0, // Reserved Bits !
0x04, // Request (0xF1)
pTestCtrlDesc->usControlCode, // Value (0xF0)
0x0, // Index (0x00)
pTemp, // Transfer Buffer
NULL, // Transfer Buffer MDL
0x08, // Transfer buffer length: Size of display
// descriptor.
NULL) ;
ntStatus=MakeUSBDCall(pDeviceObject, pUrb);
ExFreePool(pUrb);
}
ExFreePool(pTemp);
return ntStatus;
}
*/
// ===================================================================
ULONG
Test_GetConfigDescriptor(
IN PDEVICE_OBJECT DeviceObject,
PVOID pvOutputBuffer,
ULONG ulLength
)
/*
Gets configuration descriptors from the given device object
DeviceObject - pointer to the test device object
pvOutputBuffer - pointer to the buffer where the data is to be placed
ulLength - length of the buffer
Return Value: Number of valid bytes in data buffer
*/
{
PFDO_DEVICE_DATA deviceData = NULL;
NTSTATUS ntStatus = STATUS_SUCCESS;
PURB urb = NULL;
ULONG length = 0;
deviceData = (PFDO_DEVICE_DATA) DeviceObject->DeviceExtension;
urb = ExAllocatePool(NonPagedPool,
sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST));
if (urb) {
if (pvOutputBuffer) {
UsbBuildGetDescriptorRequest(urb,
(USHORT) sizeof (struct _URB_CONTROL_DESCRIPTOR_REQUEST),
USB_CONFIGURATION_DESCRIPTOR_TYPE, //descriptor type
0, //index
0, //language ID
pvOutputBuffer, //transfer buffer
NULL, //MDL
ulLength, //buffer length
NULL); //link
ntStatus = Test_CallUSBD(DeviceObject, urb);
} else {
ntStatus = STATUS_NO_MEMORY;
}
// Get the length from the Urb
length = urb->UrbControlDescriptorRequest.TransferBufferLength;
ExFreePool(urb);
} else {
ntStatus = STATUS_NO_MEMORY;
}
return length;
}
// ===================================================================
NTSTATUS
Test_Read(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*
This function is called for a IRP_MJ_READ.
TODO: Add functionality here for your device driver if it handles that IRP code.
DeviceObject - pointer to the device object for this instance of the Test device.
Irp - pointer to IRP
Return Value: NT status
*/
{
NTSTATUS ntStatus = STATUS_SUCCESS;
UNREFERENCED_PARAMETER (DeviceObject);
UNREFERENCED_PARAMETER (Irp);
return (ntStatus);
}
// ===================================================================
NTSTATUS
Test_Write(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*
This function is called for a IRP_MJ_WRITE.
TODO: Add functionality here for your device driver if it handles that IRP code.
DeviceObject - pointer to the device object for this instance of the Test device.
Irp - pointer to IRP
Return Value: NT status
*/
{
NTSTATUS ntStatus = STATUS_SUCCESS;
UNREFERENCED_PARAMETER (DeviceObject);
UNREFERENCED_PARAMETER (Irp);
return (ntStatus);
}
// ===================================================================
NTSTATUS
Test_Create(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
NTSTATUS ntStatus;
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
// Create all the symbolic links here
ntStatus = Irp->IoStatus.Status;
IoCompleteRequest (Irp,IO_NO_INCREMENT);
UNREFERENCED_PARAMETER (DeviceObject);
return ntStatus;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -