About the HID_DEVICE_EXTENSION

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

Is this a HID miniport or a driver that sits on top of the HID enumerated stack? If you are on top of HID, using HID_DEVICE_EXTENSION in the way you are doing (to get the underlying USB PDO to send URBs) is completely undocumented and not supported

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@hotmail.com
Sent: Sunday, January 15, 2017 9:49 PM
To: Windows System Software Devs Interest List
Subject: [ntdev] About the HID_DEVICE_EXTENSION

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


NTDEV is sponsored by OSR

Visit the list online at: http:

MONTHLY seminars on crash dump analysis, WDF, Windows internals and software drivers!
Details at http:

To unsubscribe, visit the List Server section of OSR Online at http:</http:></http:></http:>

Thanks, Doron. It’s on top of the HID enumerated stack. That’s the legacy code that I would like to change. Is there any way to use the documented APIs to do that?

Thanks again,
Marshall

No, when you are on the hid enumerated stack you use hid related io requests. There is no documented or supported way to skip down a level

Bent from my phone


From: xxxxx@lists.osr.com on behalf of xxxxx@hotmail.com
Sent: Sunday, January 15, 2017 11:38:57 PM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] About the HID_DEVICE_EXTENSION

Thanks, Doron. It’s on top of the HID enumerated stack. That’s the legacy code that I would like to change. Is there any way to use the documented APIs to do that?

Thanks again,
Marshall


NTDEV is sponsored by OSR

Visit the list online at: http:

MONTHLY seminars on crash dump analysis, WDF, Windows internals and software drivers!
Details at http:

To unsubscribe, visit the List Server section of OSR Online at http:</http:></http:></http:>

Hi Doron,

Would it be workable if I have a HIDUSB lower filter driver which exposes a RAW PDO?

The HID driver talks to the RAW PDO and sends the data to the lower filter driver. The lower filter driver sends the URB to the USB stack.

Regards,
Marshall

Yes, that would work

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@hotmail.com
Sent: Sunday, February 12, 2017 10:16 PM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] About the HID_DEVICE_EXTENSION

Hi Doron,

Would it be workable if I have a HIDUSB lower filter driver which exposes a RAW PDO?

The HID driver talks to the RAW PDO and sends the data to the lower filter driver. The lower filter driver sends the URB to the USB stack.

Regards,
Marshall


NTDEV is sponsored by OSR

Visit the list online at: http:

MONTHLY seminars on crash dump analysis, WDF, Windows internals and software drivers!
Details at http:

To unsubscribe, visit the List Server section of OSR Online at http:</http:></http:></http:>