I implemented a HIDClass lower filter which filters some HID devices by parsing their HID descriptor. I save all relevant devices in a device list and then filter all HID reports that the system receives.
The filter works fine until I physically unplug (surprise remove) any HID device (it doesn’t matter if the HID device is registered in my list or not). This is a sign, that something goes wrong in the HID device stack…
If I remove one HID device (no matter which one) by calling “devcon remove HID*xxxx*” the operating system successful removes the device, but still HANGS after I try to physically remove the device. The system is really hanging (e.g. the clock is also not working).
No, I don’t call WdfDeviceInitSetFilter in EvtDriverDeviceAdd. Instead I call WdfFdoInitSetFilter (I don’t know if is the same thing)
I register a completion callback for every request that I receive. I the completion callback I read the data that the HID device send it to the OS.
VOID DispatchPassThrough(IN WDFREQUEST Request,
IN WDFIOTARGET IoTarget,
pfCompletionRequest Completion)
{
//
// Pass the IRP to the target
//
BOOLEAN ret;
NTSTATUS status = STATUS_SUCCESS;
//DbgPrint(“DispatchPassThrough”);
WdfRequestFormatRequestUsingCurrentType(Request);
WdfRequestSetCompletionRoutine(Request, Completion, WDF_NO_CONTEXT);
ret = WdfRequestSend(Request, IoTarget, WDF_NO_SEND_OPTIONS);
if (ret == FALSE)
{
status = WdfRequestGetStatus(Request);
#ifdef DEBUG
DbgPrint(“WdfRequestSend failed: 0x%x\n”, status);
#endif
WdfRequestComplete(Request, status);
}
return;
}
VOID EvtInterruptTransferCompletionRoutine(IN WDFREQUEST objRequest,
IN WDFIOTARGET objTarget,
IN PWDF_REQUEST_COMPLETION_PARAMS objReqComplnParams,
IN WDFCONTEXT objContext)
{
NTSTATUS status = STATUS_SUCCESS;
PURB pUrbBuffer = NULL;
WDF_REQUEST_PARAMETERS objRequestParameters;
UNREFERENCED_PARAMETER(objReqComplnParams);
UNREFERENCED_PARAMETER(objContext);
//DbgPrint(“TESTDRIVER: MESSAGE: —>EvtInterruptTransferCompletionRoutine\n”);
WDF_REQUEST_PARAMETERS_INIT(&objRequestParameters);
WdfRequestGetParameters(objRequest, &objRequestParameters);
pUrbBuffer = objRequestParameters.Parameters.Others.Arg1;
if (pUrbBuffer->UrbHeader.Function == URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER)
{
if (pUrbBuffer->UrbBulkOrInterruptTransfer.TransferBufferLength > 0 &&
pUrbBuffer->UrbBulkOrInterruptTransfer.TransferBuffer != NULL)
{
// read data here
}
}
WdfRequestComplete(objRequest, status);
}