Continuing my quest to enumerate the path between the HCD and my usb device,
I’m stuck at the last step in the process.
I am using the device serial number to determine whether the device attached
to the port
I’m currently enumerating is actually the device for my device object.
When I detect a usb device, I create an Irp to send a
IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION to request the serial number
of the device attached to the port on the hub being enumerated.
If my device is connected to a port on an external hub, everything goes
great
and I am able to get the serial number string descriptor.
However, if my device is connected directly to a port on the root hub for an
HCD, IoCallDriver returns STATUS_CANCELLED.
Any idea why my irp would be cancelled in this case?
Here’s the relevant code I use to build the Irp:
// Build the string descriptor request
ULONG ulBytesRequested = sizeof(USB_DESCRIPTOR_REQUEST)
- sizeof(USB_STRING_DESCRIPTOR)
- MAXIMUM_USB_STRING_LENGTH;
PUSB_DESCRIPTOR_REQUEST pstStringDescRequest = (PUSB_DESCRIPTOR_REQUEST)
ExAllocatePool ( NonPagedPool, ulBytesRequested );
RtlZeroMemory ( pstStringDescRequest, ulBytesRequested );
pstStringDescRequest->ConnectionIndex = ulConnectionIndex_;
pstStringDescRequest->SetupPacket.wValue = (USB_STRING_DESCRIPTOR_TYPE
<< 8)
| iSerialNumberIndex_;
pstStringDescRequest->SetupPacket.wIndex = usLanguageId_;
pstStringDescRequest->SetupPacket.wLength = (USHORT)
MAXIMUM_USB_STRING_LENGTH;
// Build the IRP
KeInitializeEvent ( &event, NotificationEvent, FALSE );
Irp = IoBuildDeviceIoControlRequest
IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, // ioctl
pHubFdo_, // target device object
pstStringDescRequest, ulBytesRequested, // input buffer and
length
pstStringDescRequest, ulBytesRequested, // output buffer and
length
FALSE, // not an internal
device control
&event, // event to signal
completion
&iostatus ); // completion status
// Send it and wait for a response
NTSTATUS status = IoCallDriver ( pHubFdo_, Irp );
if ( status == STATUS_PENDING )
{
KeWaitForSingleObject ( &event, Executive, KernelMode, FALSE, NULL );
status = iostatus.Status;
}