Send Hub class Request from host to USB device.

Hi!

I am trying to write a custom driver to send Commands to a USB device.
The USB device supports 3.0 version.
My intention here is to issue a SetPortFeature Command.

the setup packet details is as follows.
bmrequesttype : 00100011 (CLASS request, OTHER recepient)
bmrequest : SET_FEATURE
wvalue : BH_PORT_RESET
windex = 17 (port number)
wlength = 0

The spec says This command is a Hub class request command.

I am trying to send the command using URB.
I have tried the below steps to send the URB packet.

  1. Get the device object of our Driver (Functional Driver Object, FDO) using WdfDeviceWdmGetDeviceObject API.

  2. Get the Physical device object of USB Hub (USB Hub PDO) using WdfDeviceWdmGetPhysicalDevice API.

  3. Build IRP For the command using IoBuildDeviceIoControlRequest API. Internal IOCtl code is set to IOCTL_INTERNAL_USB_SUBMIT_URB.

  4. Creating URB Handle using USBD_CreateHandle API. (Driver’s FDO from Step 1 and Hub PDO from step 2 are given as arguments to this API.)

  5. Create a URB block using USBD_UrbAllocate API.

  6. Create a URB Header structure and assign function value to URB_FUNCTION_CLASS_OTHER and length field to sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST);
    //Create Header
    struct _URB_HEADER urb_header;
    urb_header.Function = URB_FUNCTION_CLASS_OTHER;
    urb_header.Length = sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST);

  7. Assign the following values to urb block as given below.
    //Assign header value.
    urb->UrbControlVendorClassRequest.Hdr = urb_header;

    //Assign request code to SET_FEATURE.
    urb->UrbControlVendorClassRequest.Request = 0x3;

    //Assign value to feature selector BH_PORT_RESET (0X28)
    urb->UrbControlVendorClassRequest.Value = 0x28;

    //Assign index value to Port number (Port no is 17).
    urb->UrbControlVendorClassRequest.Index = 0x11;

  8. Get next stack location of IRP and assign the urb block to that stack. Code snippet is given below.

    IoStack = IoGetNextIrpStackLocation(Irp);
    IoStack->Parameters.Others.Argument1 = urb;

  9. Send the IRP to the driver using IOCallDriver API. (Hubs PDO and IRP obtained in Step 3 are sent as Arguments to this API.)

I am doing the following steps above, but not getting the required status as SUCCESS in status field. The status code obtained is 0XC0000001 (STATUS_UNSUCCESSFUL)

I am not sure whether I am sending the command correctly… Can you please help me what could be the reason for this status? Am I missing anything here?

Regards,
Srihari.

The BH_PORT_RESET command is decimal 28, not hex 0x28.

Are you quite sure about the port number? A USB 3 hub is limited to at most 15 ports. Where did you find your value of 17?

I’m not convinced you can send a hub request that way. When you send an URB to your PDO, the hub driver is going to treat that as a command to your device, not a command to itself. I will go look that up. Will IOCTL_INTERNAL_USB_CYCLE_PORT not do what you need?

As an overly general rule, a device that requires a reset in order to operate correctly is broken. The bus resets you when you first plug in. If you’re getting hosed for some reason, then you have a device problem.

Hi Tim, Thanks for your reply. I had a couple of questions here.

  1. The BH_PORT_RESET command opcode is 0x1c in hexadecimal (28 in decimal). Actually it was a typing mistake. the wValue (feature_selector) field of setup packet is set to 0x1c itself. not 0x28.

  2. I found the port number 17 from the device manager properties. It mentioned Port_#0017.Hub_#0001 in properties of device. I found the device connected to same port number in usbview application also. thats why I gave this value as port number. Do we have to give a different number here??

  3. If the command is not targeted to the hub, is there a possible way to target any request to a hub port?

What are you hoping for this to do? BH_PORT_RESET is not well defined in the USB spec. What are you hoping for it to do?

You can send IOCTL_USB_HUB_CYCLE_PORT down to your PDO, and that should simulate an unplug/replug. Is that what you’re after?