📄 ioctl.c
字号:
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN BOOLEAN bWrite
)
/*++
Routine Description:
This function is called for IOCTLs to Read or Write.
For WRITEs, the data is retrieved from the SystemBuffer and sent to the device.
Arguments:
DeviceObject - pointer to the device object for this instance of the D12 device.
Irp - pointer to IRP
Read - if TRUE this is a Device-to-Host (Read from device) transfer
if FALSE this is a Host-to-Device (Write to device) transfer
Return Value:
NT status code
STATUS_SUCCESS: Read was done successfully
STATUS_INVALID_PARAMETER_3: The Endpoint Index does not specify an IN pipe
STATUS_NO_MEMORY: Insufficient data memory was supplied to perform the READ
This routine fills the status code into the Irp
--*/
{
USBD_INTERFACE_INFORMATION * pInterfaceInfo;
PIO_STACK_LOCATION irpStack;
PDEVICE_EXTENSION deviceExtension;
NTSTATUS ntStatus;
PVOID ioBuffer;
ULONG length;
ULONG inputBufferLength;
ULONG outputBufferLength;
ULONG siz;
PURB urb;
USHORT wValue, wIndex;
PIO_BLOCK ioBlock;
D12_KdPrint(("D12TEST.SYS: enter D12_ReadWriteRegister\n"));
irpStack = IoGetCurrentIrpStackLocation (Irp);
ASSERT (irpStack != NULL);
deviceExtension = DeviceObject->DeviceExtension;
ASSERT (deviceExtension != NULL);
ioBuffer = Irp->AssociatedIrp.SystemBuffer;
ioBlock = (PIO_BLOCK) ioBuffer;
inputBufferLength = irpStack->Parameters.DeviceIoControl.InputBufferLength;
outputBufferLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
//DEBUG ONLY
if ((ioBuffer == NULL) || (inputBufferLength == 0) ){
D12_KdPrint (("D12TEST.SYS: ERROR! ioBuffer %X | inBufLen: %d | outBufLen %d\n",
ioBuffer, inputBufferLength, outputBufferLength));
Irp->IoStatus.Information = 0;
return (STATUS_NO_MEMORY);
} //DEBUG ONLY
siz = sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST);
// allocate urb
urb = ExAllocatePool(NonPagedPool, siz);
// By convention, the first byte of the buffer is reserved for the ReportID, so
// skip over the first Byte when specifying the transferbuffer
length = ioBlock->uLength;
wValue = (USHORT)ioBlock->uOffset;
wIndex = (USHORT)ioBlock->uIndex;
D12_KdPrint (("D12TEST.SYS: ReadWriteRegister: ioBuffer = %p, wIndex = %x, wLength = %lx, wValue = %x.\n",
ioBlock->pbyData, wIndex, length, wValue));
if (bWrite) {
// A WRITE operation implies that the data is gotten from the User's Input Data Buffer
UsbBuildVendorRequest(urb, //ptr to urb
URB_FUNCTION_VENDOR_DEVICE,
(USHORT) siz, //siz of urb
0,
0x0, //reservedbits=bmRequestType
0x0C, //request = USBSCAN IOCTL_WRITE_REGISTER
wValue,
wIndex,
ioBlock->pbyData, //TransferBuffer
NULL, //mdl (unused)
length, //bufferlength
NULL); //link
} else {
// A READ operation implies that the data is placed in the User's Output Data Buffer
UsbBuildVendorRequest(urb, //ptr to urb
URB_FUNCTION_VENDOR_DEVICE,
(USHORT) siz, //siz of urb
USBD_TRANSFER_DIRECTION_IN,
0x0, //reservedbits=bmRequestType
0x0C, //request = USBSCAN IOCTL_READ_REGISTER
wValue,
wIndex,
ioBuffer, //TransferBuffer
NULL, //mdl (unused)
length, //bufferlength
NULL); //link
}/* else */
/*
/*
// Call the USB Stack. This call blocks until the device returns data. Note that if the
// device NAKs forever, this call will not return and this thread will hang. To correct
// this, a timeout value can be specified and a Kernel-Mode timer used to wake
// up the driver and then cancel this transfer. Future versions of this sample
// driver will demonstrate that capability, or consult the Windows NT DDK for
// further details on the Kernel Timer functionality as well as the
// IoCancelIrp functionality.
*/
ntStatus = D12_CallUSBD(DeviceObject, urb);
// The Information field tells IOM how much to copy back into the
// usermode buffer in the BUFFERED method
if (NT_SUCCESS(ntStatus) && bWrite) {
Irp->IoStatus.Information =length; //sizeof (ULONG);
}else if (NT_SUCCESS(ntStatus)) {
D12_KdPrint (("D12TEST.SYS: Sucessfully Transferred %d Bytes\n", urb->UrbControlVendorClassRequest.TransferBufferLength));
Irp->IoStatus.Information = (urb->UrbControlVendorClassRequest.TransferBufferLength); // + sizeof(UCHAR));
}
Irp->IoStatus.Status = ntStatus;
// free allocated urb
ExFreePool(urb);
D12_KdPrint(("D12TEST.SYS: exit D12_ReadWriteRegister\n"));
return (ntStatus);
}
NTSTATUS
D12_ProcessIOCTL(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
Arguments:
DeviceObject - pointer to the device object for this instance of the 82930
devcice.
Return Value:
NT status code
--*/
{
PIO_STACK_LOCATION irpStack;
PVOID ioBuffer;
ULONG inputBufferLength;
ULONG outputBufferLength;
PDEVICE_EXTENSION deviceExtension;
ULONG ioControlCode;
NTSTATUS ntStatus;
ULONG length;
PUCHAR pch;
PUSB_CONFIGURATION_DESCRIPTOR configurationDescriptor;
PUSB_DEVICE_DESCRIPTOR deviceDescriptor;
D12_KdPrint (("D12TEST.SYS: IRP_MJ_DEVICE_CONTROL\n"));
D12_IncrementIoCount(DeviceObject);
//
// Get a pointer to the current location in the Irp. This is where
// the function codes and parameters are located.
//
deviceExtension = DeviceObject->DeviceExtension;
if (deviceExtension->AcceptingRequests == FALSE) {
ntStatus = STATUS_DEVICE_DATA_ERROR;
Irp->IoStatus.Status = ntStatus;
Irp->IoStatus.Information = 0;
IoCompleteRequest (Irp,
IO_NO_INCREMENT
);
D12_DecrementIoCount(DeviceObject);
return ntStatus;
}
irpStack = IoGetCurrentIrpStackLocation (Irp);
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
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 IOCTL_D12_RESET_PIPE:
{
PD12_PIPE pipe;
PFILE_OBJECT fileObject;
// get our context and see if it is a pipe
fileObject = irpStack->FileObject;
pipe = (PD12_PIPE) fileObject->FsContext;
if(pipe == NULL) {
// error, this is not a pipe
ntStatus =
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
} else {
D12_ResetPipe(DeviceObject, pipe, TRUE);
ntStatus = Irp->IoStatus.Status = STATUS_SUCCESS;
}
}
break;
case IOCTL_D12_GET_CONFIG_DESCRIPTOR:
//
// This api returns a copy of the configuration descriptor
// and all endpoint/interface descriptors.
//
//
// inputs - none
// outputs - configuration descriptor plus interface
// and endpoint descriptors
//
pch = (PUCHAR) ioBuffer;
configurationDescriptor =
D12_GetConfigDescriptor(DeviceObject);
if (configurationDescriptor) {
length = configurationDescriptor->wTotalLength;
RtlCopyMemory(pch,
(PUCHAR) configurationDescriptor,
length);
ExFreePool(configurationDescriptor);
Irp->IoStatus.Information = length;
ntStatus = Irp->IoStatus.Status = STATUS_SUCCESS;
}
else {
Irp->IoStatus.Information = 0;
ntStatus = Irp->IoStatus.Status = STATUS_DEVICE_DATA_ERROR;
}
break;
case IOCTL_D12_RESET_DEVICE:
{
NTSTATUS ntStatus;
ULONG portStatus;
D12_KdPrint (("D12TEST.SYS: Reset Device Test\n"));
TRAP(); // test this
//
// Check the port state, if it is disabled we will need
// to re-enable it
//
ntStatus = D12_GetPortStatus(DeviceObject, &portStatus);
if (NT_SUCCESS(ntStatus) && !(portStatus & USBD_PORT_ENABLED) &&
portStatus & USBD_PORT_CONNECTED) {
//
// port is disabled, attempt reset
//
//D12_EnableParentPort(DeviceObject);
D12_ResetParentPort(DeviceObject);
}
}
break;
case IOCTL_D12_GET_DEVICE_DESCRIPTOR:
pch = (PUCHAR) ioBuffer;
deviceDescriptor =
deviceExtension->DeviceDescriptor;
if (deviceDescriptor) {
length = deviceDescriptor->bLength;
RtlCopyMemory(pch,
(PUCHAR) deviceDescriptor,
length);
Irp->IoStatus.Information = length;
ntStatus = Irp->IoStatus.Status = STATUS_SUCCESS;
}
else {
Irp->IoStatus.Information = 0;
ntStatus = Irp->IoStatus.Status = STATUS_DEVICE_DATA_ERROR;
}
break;
case IOCTL_READ_REGISTERS:
D12_ReadWriteRegister(DeviceObject, Irp, FALSE);
ntStatus = Irp->IoStatus.Status;
break;
case IOCTL_WRITE_REGISTERS:
D12_ReadWriteRegister(DeviceObject, Irp, TRUE);
ntStatus = Irp->IoStatus.Status;
break;
default:
ntStatus =
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
}
IoCompleteRequest (Irp,
IO_NO_INCREMENT
);
D12_DecrementIoCount(DeviceObject);
return ntStatus;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -