📄 vhidmini.c
字号:
/*++
Routine Description:
Handles all the internal ioctls
Arguments:
DeviceObject - Pointer to the device object.
Irp - Pointer to the request packet.
Return Value:
NT Status code
--*/
{
NTSTATUS ntStatus = STATUS_SUCCESS;
PIO_STACK_LOCATION IrpStack;
DebugPrint(("Enter InternalIoctl (DO=0x%x,Irp=0x%x)\n",
DeviceObject, Irp));
IrpStack = IoGetCurrentIrpStackLocation(Irp);
switch(IrpStack->Parameters.DeviceIoControl.IoControlCode)
{
case IOCTL_HID_GET_DEVICE_DESCRIPTOR:
//
// Retrieves the device's HID descriptor.
//
DebugPrint(("IOCTL_HID_GET_DEVICE_DESCRIPTOR\n"));
ntStatus = GetHidDescriptor(DeviceObject, Irp);
break;
case IOCTL_HID_GET_REPORT_DESCRIPTOR:
//
//Obtains the report descriptor for the HID device.
//
DebugPrint(("IOCTL_HID_GET_REPORT_DESCRIPTOR\n"));
ntStatus = GetReportDescriptor(DeviceObject, Irp);
break;
case IOCTL_HID_READ_REPORT:
//
//Return a report from the device into a class driver-supplied buffer.
//
DebugPrint(("IOCTL_HID_READ_REPORT\n"));
ntStatus = ReadReport(DeviceObject, Irp);
return ntStatus;
case IOCTL_HID_GET_DEVICE_ATTRIBUTES:
//
//Retrieves a device's attributes in a HID_DEVICE_ATTRIBUTES structure.
//
DebugPrint(("IOCTL_HID_GET_DEVICE_ATTRIBUTES\n"));
ntStatus = GetDeviceAttributes(DeviceObject, Irp);
break;
case IOCTL_HID_WRITE_REPORT:
//
//Transmits a class driver-supplied report to the device.
//
DebugPrint(("IOCTL_HID_WRITE_REPORT\n"));
ntStatus = STATUS_NOT_SUPPORTED;
break;
case IOCTL_HID_SET_FEATURE:
//
// This sends a HID class feature report to a top-level collection of
// a HID class device.
//
DebugPrint(("IOCTL_HID_SET_FEATURE\n"));
ntStatus = GetSetFeature(DeviceObject, Irp);
break;
case IOCTL_HID_GET_FEATURE:
//
// returns a feature report associated with a top-level collection
//
DebugPrint(("IOCTL_HID_GET_FEATURE\n"));
ntStatus = GetSetFeature(DeviceObject, Irp);
break;
/* Following two ioctls are not defined in the Win2K HIDCLASS.H headerfile
case IOCTL_HID_GET_INPUT_REPORT:
//
// returns a HID class input report associated with a top-level
// collection of a HID class device.
//
DebugPrint(("IOCTL_HID_GET_INPUT_REPORT\n"));
ntStatus = STATUS_NOT_SUPPORTED;
break;
case IOCTL_HID_SET_OUTPUT_REPORT:
//
// sends a HID class output report to a top-level collection of a HID
// class device.
//
DebugPrint(("IOCTL_HID_SET_OUTPUT_REPORT\n"));
ntStatus = STATUS_NOT_SUPPORTED;
break;
*/
case IOCTL_HID_GET_STRING:
//
//Requests that the HID minidriver retrieve a human-readable string
//for either the manufacturer ID, the product ID, or the serial number
//from the string descriptor of the device. The minidriver must send
//a Get String Descriptor request to the device, in order to retrieve
//the string descriptor, then it must extract the string at the
//appropriate index from the string descriptor and return it in the
//output buffer indicated by the IRP. Before sending the Get String
//Descriptor request, the minidriver must retrieve the appropriate
//index for the manufacturer ID, the product ID or the serial number
//from the device extension of a top level collection associated with
//the device.
//
DebugPrint(("IOCTL_HID_GET_STRING\n"));
ntStatus = STATUS_NOT_SUPPORTED;
break;
case IOCTL_HID_ACTIVATE_DEVICE:
//
//Makes the device ready for I/O operations.
//
DebugPrint(("IOCTL_HID_ACTIVATE_DEVICE\n"));
ntStatus = STATUS_NOT_SUPPORTED;
break;
case IOCTL_HID_DEACTIVATE_DEVICE:
//
//Causes the device to cease operations and terminate all outstanding
//I/O requests.
//
DebugPrint(("IOCTL_HID_DEACTIVATE_DEVICE\n"));
ntStatus = STATUS_NOT_SUPPORTED;
break;
//case IOCTL_HID_SEND_IDLE_NOTIFICATION_REQUEST:
// DebugPrint(("IOCTL_HID_SEND_IDLE_NOTIFICATION_REQUEST\n"));
// ntStatus = STATUS_NOT_SUPPORTED;
// break;
default:
DebugPrint(("Unknown or unsupported IOCTL (%x)\n",
IrpStack->Parameters.DeviceIoControl.IoControlCode));
ntStatus = STATUS_NOT_SUPPORTED;
break;
}
//
//Set real return status in Irp
//
Irp->IoStatus.Status = ntStatus;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
ntStatus = STATUS_SUCCESS;
return ntStatus;
}
NTSTATUS
GetSetFeature(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
Handles Ioctls for Get and Set feature for all the collection.
For control collection (custom defined collection) it handles
the user-defined control codes for sideband communication
Arguments:
DeviceObject - pointer to a device object.
Irp - Pointer to Interrupt Request Packet.
Return Value:
NT status code.
--*/
{
NTSTATUS ntStatus = STATUS_SUCCESS;
PIO_STACK_LOCATION IrpStack;
PHID_XFER_PACKET transferPacket = NULL;
IrpStack = IoGetCurrentIrpStackLocation(Irp);
transferPacket = (PHID_XFER_PACKET)Irp->UserBuffer;
if(!transferPacket->reportBufferLen){
ntStatus = STATUS_BUFFER_TOO_SMALL;
return ntStatus;
}
switch(IrpStack->Parameters.DeviceIoControl.IoControlCode)
{
case IOCTL_HID_GET_FEATURE:
//
// IOCTL_HID_GET_FEATURE is being used to send user-defined
// HIDMINI_CONTROL_CODE_Xxxx request to a custom collection
// defined especially for this purpose
//
if(CONTROL_COLLECTION_REPORT_ID == transferPacket->reportId){
//
//This is a special HIDMINI_CONTROL_CODE_Xxxx Type request
//
ntStatus = HandleControlRequests(transferPacket);
break;
}
//
// If collection ID is not for control collection then handle
// this request just as you would for a regular collection.
//
// fall thru
//
case IOCTL_HID_SET_FEATURE:
//
// not handled, fall thru
//
default:
ntStatus = STATUS_NOT_SUPPORTED;
break;
}
return ntStatus;
}
NTSTATUS
HandleControlRequests(
PHID_XFER_PACKET TransferPacket
)
/*++
Routine Description:
Handles HIDMINI_CONTROLCODE_Xxxx type requests
Arguments:
TransferPacket - pointer to HID_XFER_PACKET.
Return Value:
NT status code.
--*/
{
NTSTATUS ntStatus = STATUS_SUCCESS;
PHIDMINI_CONTROL_INFO controlInfo = NULL;
PHID_DEVICE_ATTRIBUTES deviceAttributes = NULL;
if(TransferPacket->reportBufferLen < sizeof(HIDMINI_CONTROL_INFO))
{
ntStatus = STATUS_BUFFER_TOO_SMALL;
return ntStatus;
}
controlInfo = (PHIDMINI_CONTROL_INFO)TransferPacket->reportBuffer;
switch(controlInfo->ControlCode)
{
case HIDMINI_CONTROL_CODE_GET_ATTRIBUTES:
DebugPrint(("Control Code HIDMINI_CONTROL_CODE_GET_ATTRIBUTES\n"));
if(TransferPacket->reportBufferLen
< (sizeof(HID_DEVICE_ATTRIBUTES)
+ sizeof(HIDMINI_CONTROL_INFO)))
{
ntStatus = STATUS_BUFFER_TOO_SMALL;
return ntStatus;
}
deviceAttributes = (PHID_DEVICE_ATTRIBUTES) controlInfo->ControlBuffer;
deviceAttributes->Size = sizeof (HID_DEVICE_ATTRIBUTES);
deviceAttributes->VendorID = HIDMINI_VID;
deviceAttributes->ProductID = HIDMINI_PID;
deviceAttributes->VersionNumber = HIDMINI_VERSION;
break;
case HIDMINI_CONTROL_CODE_DUMMY1:
DebugPrint(("Control Code HIDMINI_CONTROL_CODE_DUMMY1\n"));
ntStatus = STATUS_NOT_SUPPORTED;
break;
case HIDMINI_CONTROL_CODE_DUMMY2:
DebugPrint(("Control Code HIDMINI_CONTROL_CODE_DUMMY2\n"));
ntStatus = STATUS_NOT_SUPPORTED;
break;
default:
DebugPrint(("Unknown control Code\n"));
ntStatus = STATUS_NOT_SUPPORTED;
break;
}
return ntStatus;
}
NTSTATUS
GetHidDescriptor(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
Finds the HID descriptor and copies it into the buffer provided by the Irp.
Arguments:
DeviceObject - pointer to a device object.
Irp - Pointer to Interrupt Request Packet.
Return Value:
NT status code.
--*/
{
NTSTATUS ntStatus = STATUS_SUCCESS;
PDEVICE_EXTENSION deviceInfo;
PIO_STACK_LOCATION IrpStack;
ULONG bytesToCopy;
DebugPrint(("GetHIDDescriptor Entry\n"));
//
// Get a pointer to the current location in the Irp
//
IrpStack = IoGetCurrentIrpStackLocation(Irp);
//
// Get a pointer to the device extension
//
deviceInfo = GET_MINIDRIVER_DEVICE_EXTENSION(DeviceObject);
//
// Copy device descriptor to HIDCLASS buffer
//
DebugPrint(("HIDCLASS Buffer = 0x%x, Buffer length = 0x%x\n",
Irp->UserBuffer,
IrpStack->Parameters.DeviceIoControl.OutputBufferLength));
//
// Copy MIN (OutputBufferLength, DeviceExtension->HidDescriptor->bLength)
//
bytesToCopy = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
if(!bytesToCopy) {
return STATUS_BUFFER_TOO_SMALL;
}
//
// Since HidDescriptor.bLength could be >= sizeof(HID_DESCRIPTOR) we
// just check for HidDescriptor.bLength and
// copy MIN (OutputBufferLength, DeviceExtension->HidDescriptor->bLength)
//
if (bytesToCopy > deviceInfo->HidDescriptor.bLength) {
bytesToCopy = deviceInfo->HidDescriptor.bLength;
}
DebugPrint(("Copying %d bytes to HIDCLASS buffer\n",
bytesToCopy));
RtlCopyMemory((PUCHAR) Irp->UserBuffer,
(PUCHAR) &deviceInfo->HidDescriptor,
bytesToCopy);
DebugPrint((" bLength: 0x%x \n"
" bDescriptorType: 0x%x \n"
" bcdHID: 0x%x \n"
" bCountry: 0x%x \n"
" bNumDescriptors: 0x%x \n"
" bReportType: 0x%x \n"
" wReportLength: 0x%x \n",
deviceInfo->HidDescriptor.bLength,
deviceInfo->HidDescriptor.bDescriptorType,
deviceInfo->HidDescriptor.bcdHID,
deviceInfo->HidDescriptor.bCountry,
deviceInfo->HidDescriptor.bNumDescriptors,
deviceInfo->HidDescriptor.DescriptorList[0].bReportType,
deviceInfo->HidDescriptor.DescriptorList[0].wReportLength
));
//
// Report how many bytes were copied
//
Irp->IoStatus.Information = bytesToCopy;
DebugPrint(("HidMiniGetHIDDescriptor Exit = 0x%x\n", ntStatus));
return ntStatus;
}
NTSTATUS
ReadReport(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
Creates reports and sends it back to the requester.
Arguments:
DeviceObject - pointer to a device object.
Irp - Pointer to Interrupt Request Packet.
Return Value:
NT status code.
--*/
{
NTSTATUS ntStatus = STATUS_PENDING;
PDEVICE_EXTENSION deviceInfo;
PIO_STACK_LOCATION IrpStack;
LARGE_INTEGER timeout;
PREAD_TIMER readTimerStruct;
DebugPrint(("ReadReport Entry\n"));
//
// Get a pointer to the device extension
//
deviceInfo = GET_MINIDRIVER_DEVICE_EXTENSION(DeviceObject);
//
// Allocate the Timer structure
//
readTimerStruct = ExAllocatePoolWithTag(NonPagedPool,
sizeof(READ_TIMER),
VHID_POOL_TAG
);
if(!readTimerStruct){
DebugPrint(("Mem allocation for readTimerStruct failed\n"));
Irp->IoStatus.Status = ntStatus = STATUS_INSUFFICIENT_RESOURCES;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
else{
RtlZeroMemory(readTimerStruct, sizeof(READ_TIMER));
//
// Since the IRP will be completed later in the DPC,
// mark the IRP pending and return STATUS_PENDING.
//
IoMarkIrpPending(Irp);
//
//remember the Irp
//
readTimerStruct->Irp = Irp;
//
// Initialize the DPC structure and Timer
//
KeInitializeDpc(&readTimerStruct->ReadTimerDpc,
ReadTimerDpcRoutine,
(PVOID)readTimerStruct
);
KeInitializeTimer(&readTimerStruct->ReadTimer);
//
// Queue the timer DPC
//
timeout.HighPart = -1;
timeout.LowPart = -(LONG)(10*1000*5000); //in 100 ns.total 5 sec
KeSetTimer(&readTimerStruct->ReadTimer,
timeout,
&readTimerStruct->ReadTimerDpc
);
}
DebugPrint(("ReadReport Exit = 0x%x\n", ntStatus));
return ntStatus;
}
VOID
ReadTimerDpcRoutine(
IN PKDPC Dpc,
IN PVOID DeferredContext,
IN PVOID SystemArgument1,
IN PVOID SystemArgument2
)
{
NTSTATUS ntStatus = STATUS_SUCCESS;
PDEVICE_EXTENSION deviceInfo;
PIRP Irp;
PIO_STACK_LOCATION IrpStack;
PREAD_TIMER readTimerStruct;
ULONG bytesToCopy = INPUT_REPORT_BYTES + 1;
UCHAR readReport[INPUT_REPORT_BYTES + 1];
DebugPrint(("ReadTimerDpcRoutine Entry\n"));
//
// Get the Irp from context
//
readTimerStruct = (PREAD_TIMER)DeferredContext;
Irp = readTimerStruct->Irp;
//
// Get a pointer to the current location in the Irp
//
IrpStack = IoGetCurrentIrpStackLocation(Irp);
//
//First check the size of the output buffer (there is no input buffer)
//
if( IrpStack->Parameters.DeviceIoControl.OutputBufferLength < bytesToCopy)
{
DebugPrint(("ReadReport: Buffer too small, output=0x%x need=0x%x\n",
IrpStack->Parameters.DeviceIoControl.OutputBufferLength,
bytesToCopy
));
ntStatus = STATUS_BUFFER_TOO_SMALL;
}
else
{
//
//Create input report
//
readReport[0] = CONTROL_FEATURE_REPORT_ID;
readReport[1] = 'K';
//
// Copy input report to the Irp buffer
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -