Hi All,
I have an HID function driver on a USB HID device. It uses the following code to retrieve the device object of its USB Input device to send URB. The following code is called in the handler of the EvtDevicePrepareHardware.
PDEVICE_OBJECT pdo = WdfDeviceWdmGetPhysicalDevice(hDevice);
if (pdo)
{
// pdo is HidUsb!
HID_DEVICE_EXTENSION* pHidExtension = (HID_DEVICE_EXTENSION*)pdo->DeviceExtension;
if (pHidExtension)
{
m_pimp->SetUSBDeviceObject( pHidExtension->PhysicalDeviceObject);
}
}
After caching the device object of the USB Input Device, it builds the URB and sends it down to that device object using the following code:
bool CModule_Commands_Impl::SendWriteRequest( SVendorRequestKnl &vendorRequest)
{
SaiTrace(TRACE_LEVEL_VERBOSE, SAI_COMMAND, “%s - called.”, FUNCTION);
bool retval(false);
PURB urb = (PURB)ExAllocatePoolWithTag(NonPagedPool, sizeof(_URB) + 512, s_PoolTag);
if (urb)
{
UsbBuildVendorRequest(urb, URB_FUNCTION_VENDOR_DEVICE, (USHORT)sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST),
USBD_TRANSFER_DIRECTION_OUT, 0, vendorRequest.userRequest.request, vendorRequest.userRequest.value, vendorRequest.userRequest.index, vendorRequest.data, 0, vendorRequest.dataLength, NULL);
urb->UrbHeader.Length = sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST);
urb->UrbHeader.Function = URB_FUNCTION_VENDOR_DEVICE;
urb->UrbHeader.Status = USBD_STATUS_SUCCESS;
// send this urb
retval = SendUrb(urb);
ExFreePool(urb);
}
SaiTrace(TRACE_LEVEL_VERBOSE, SAI_COMMAND, “<<%s -%!BOOLEAN!”, FUNCTION, retval);
return retval;
}
bool CModule_Commands_Impl::SendUrb(void* Urb)
{
NTSTATUS status( STATUS_INSUFFICIENT_RESOURCES );
ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
PDEVICE_OBJECT pUsbDeviceObject = GetUSBDeviceObject();
if (pUsbDeviceObject != NULL)
{
KEVENT evt;
KeInitializeEvent(&evt, NotificationEvent, FALSE);
IO_STATUS_BLOCK iostatus;
PIRP Irp = IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_USB_SUBMIT_URB, pUsbDeviceObject, NULL, 0, NULL, 0, TRUE, &evt, &iostatus);
if(Irp)
{
SaiTrace(TRACE_LEVEL_VERBOSE, SAI_COMMAND, “%s - IoBuildDeviceIoControlRequest suceeded”, FUNCTION);
PIO_STACK_LOCATION stack = IoGetNextIrpStackLocation(Irp);
stack->Parameters.Others.Argument1 = Urb;
status = IoCallDriver( pUsbDeviceObject, Irp);
if (NT_SUCCESS(status))
{
SaiTrace(TRACE_LEVEL_VERBOSE, SAI_COMMAND, “%s - IoCallDriver suceeded %!STATUS!”, FUNCTION, status);
}
else
{
SaiTrace(TRACE_LEVEL_ERROR, SAI_COMMAND, “%s - IoCallDriver failed - status = %!STATUS!”, FUNCTION, status);
}
if(status == STATUS_PENDING)
{
status = KeWaitForSingleObject(&evt, Executive, KernelMode, FALSE, NULL);
if (status == STATUS_SUCCESS)
The code works fine on Win7 x86, Win8.1 X64 and Win10 X64. But it hangs the send thread on Win7 x64 after several successful sending. The USB analyzer shows that the URB doesn’t get sent down to the device when the issue happens. Does anyone know why? Is it a right way to send the URB from the HID function driver?
Thanks,
Marshall