cancel
Showing results for 
Search instead for 
Did you mean: 

USB Low-Full-High Speed Peripherals

New Contributor

Hello,

I'm curious to know if it should be possible to send an invalid vendor request code to the Default USB device on an FX2[LP]. I know that the request code 0xa0 is always recognized before and after renumeration. I attempted to send another code that is implemented in our firmware to the default USB device and I expected that it would simply reject the request and stall endpoint 0. In our Windows driver when I attempted to send a URB that packages that vendor request, USBD seems to block indefinitely. After seeing that, I put in logic to cancel the IRP after a timeout elapsed. However, when I went to continue through our usual process of downloading firmware, it seems to malfunction, as if it consumed part of my invalid vendor request and cached it before processing the subsequent 0xa0 vendor request.

Is this just something I should completely avoid doing [sending unrecognized vendor request codes to it]? I managed to move on to a different technique but my motivation was to try to discern between our device having renumerated with firmware and a fresh firmware-less enumeration state. Granted, one can use vendor, product, and device ID combinations to deduce this, but this was something of an academic exercise for me and I'm genuinely curious. I could not find anything in the TRM that would tell me what to expect under this scenario.

~Thanks

0 Likes
Reply
2 Replies
Moderator
Moderator

Hi,

Yes, invalid vendor commands can be sent to default USB device and device will stall the endpoint 0. This stall will be automatically cleared upon next setup packet arrival. therefore it should not be affecting the firmware download.

As per USB 2.0 spec "A protocol STALL is returned during the Data or Status stage of a control transfer, and the STALL condition terminates at the beginning of the next control transfer (Setup). " https://www.usb.org/document-library/usb-20-specification Page no. 207

Same is implemented and stated in the FX2LP TRM [Page no. 39] "If the firmware stalls endpoint zero (by setting the STALL and HSNAK bits to 1), the EZ-USB automatically clears the stall bit when the next SETUP token arrives."

Can you please clarify whether you are using CYUSB3 driver or any other custom driver?

 

Best regards,
Pranava
0 Likes
Reply
New Contributor

Hi Pranava,

Thank you for taking the time to respond. We have a custom WDM-based driver that we have deployed for many years, and I recently took over as the main developer for it, though I was familiar with many of its workings before that. 

Here is a slightly modified version of code I was attempting. Some of these are helper routines but they're broadly deployed with other parts of the code base and don't seem to have any known problems. The URB seems to block indefinitely when I call this before our firmware is running (or any has been downloaded), whereas I expected it to return almost immediately if endpoint 0 stalls. Hence why I added the timeout and cancellation of the IRP after some time. This code was intended to be called very shortly after the device enumerates and is noticed by Windows, and additionally on demand by way of a device IOCTL from a diagnostic application we have.

 

 

    NTSTATUS
    OurDriver_IsRenumerated
    (
        DEVICE_OBJECT * const p_do,
        BOOLEAN       * const p_response
    )
    {
        NTSTATUS r = STATUS_SUCCESS;
        
        // Clarification: underlying type is _URB_CONTROL_VENDOR_OR_CLASS_REQUEST
        URB * const urb = OurDriver_AllocateVendorRequestUrb
        (
            CUSTOM_VENDOR_REQUEST_TAG
        );
        
        // -----------------------------
        
        if(urb)
        {
            UCHAR xfer_buffer[2] = { 0 };
            
            // -----------------------------
            
            OurDriver_PrepareVendorRequestUrb
            (
                urb,
                (USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK),
                xfer_buffer,
                sizeof(xfer_buffer),
                VR_OURDRIVER_IS_RENUMERATED,
                0, // request's value
                0  // request's index
            );
            
            r = OurDriver_CallUSBD_WithTimeout
            (
                p_do,
                urb,
                (1000 * 1000) * 1 // (1 second, currently)
            );
            
            if( NT_SUCCESS(r) )
            {
                USHORT const magic_number = Get_LittleEndian_16Bit(xfer_buffer);
                
                // -----------------------------
                
                (*p_response) =
                (
                    (magic_number == OURDRIVER_MAGIC)
                  ? TRUE
                  : FALSE
                );
            }
        }
        else
        {
            r = STATUS_NO_MEMORY;
        }
        
        // Clean up.
        if(urb)
        {
            OurDriver_ExFreePoolWithTag
            (
                urb,
                CUSTOM_VENDOR_REQUEST_TAG
            );
        }
        
        return r;
    }

 

 

I'm not here to have everything spoon-fed to me so of course if you have a document or section of a document to point me to that would give me an idea of what to do I'd be just as happy. Of note is that this is an IN transfer, and the underlying vendor request code is 0xc2 [of no relation to a 0xc2 boot EEPROM load, it's just coincidence]. Currently we do not call this function upon enumeration (or renumeration) because it I couldn't get it to work the way I wanted. Are we supposed to do something on the host side to clear the stall? Is there something one must do in Windows drivers to detect that a stall has occurred? Notwithstanding this, I pondered for several weeks whether to even ask this question at all so I will have to re-enable it to remind myself of the exact way this seems to screw with firmware downloads.

At the risk of being a nuisance by asking an additional unrelated question, but for me it is a burning one for several months: Is it expected behavior that the 0xa0 vendor request seems to work properly regardless of whether the CPU is held in reset when the target RAM region is 0xe000 to 0xe1ff? A long time ago we accidentally noticed that it just seems to work but I couldn't find this documented in the TRM.

0 Likes
Reply