AN00136 libusb (v3) Descriptor Request Error

If you have a simple question and just want an answer.
kyle123
Member++
Posts: 25
Joined: Tue May 19, 2015 8:17 pm

AN00136 libusb (v3) Descriptor Request Error

Post by kyle123 »

Hello,

I'm trying to run the USB example described in AN00136 using the XP-SKC-U16 development board. At this point, I have been able to compile and run the example on the device. However, the device does not enumerate properly and Windows7 generates a "Device Descriptor Request Failed" error. To verify that the hardware is functional, I have used the version1.0 USB libraries and XMOS provided .cpp testbench to provide hardware verification.

I have also reviewed and compared the original and new USB libraries and can't spot anything wrong with the device descriptors or the configuration files. So far, I have been operating under the assumption that the host drivers are only loaded after successful enumeration of the device since Windows must have basic information available to know what driver is appropriate for the device.

Perhaps there is an issue with the high speed vs full speed descriptors used by the new xud() method? Is it also possible that the new lib_logging(2.0.1) lib_xassert(2.0.1) and lib_gpio have now violated the timing requirements specified by USB 2.0 standard?

Has anyone else had similar issues with the new library or have debugging suggestions? For completeness, I've posted the code that I have put onto the device. Keep in mind that the main.xc and endpoint.xc files have been combined in the code viewer below.

Regards,

Kyle

Code: Select all

// Copyright (c) 2016, XMOS Ltd, All rights reserved

#include "usb.h"
#include <platform.h>

#define XUD_EP_COUNT_OUT   2
#define XUD_EP_COUNT_IN    2

/* Prototype for Endpoint0 function in endpoint0.xc */
void Endpoint0(chanend c_ep0_out, chanend c_ep0_in);

#define BCD_DEVICE              0x1000
#define VENDOR_ID               0x20B1
#define PRODUCT_ID              0x00B1
#define MANUFACTURER_STR_INDEX  0x0001
#define PRODUCT_STR_INDEX       0x0002

/* Vendor specific class defines */
#define VENDOR_SPECIFIC_CLASS    0xFF
#define VENDOR_SPECIFIC_SUBCLASS 0xFF
#define VENDOR_SPECIFIC_PROTOCOL 0xFF

/* Device Descriptor */
static unsigned char devDesc[] =
{
    0x12,                     /* 0  bLength */
    USB_DESCTYPE_DEVICE,      /* 1  bdescriptorType */
    0x00,                     /* 2  bcdUSB */
    0x02,                     /* 3  bcdUSB */
    VENDOR_SPECIFIC_CLASS,    /* 4  bDeviceClass */
    VENDOR_SPECIFIC_SUBCLASS, /* 5  bDeviceSubClass */
    VENDOR_SPECIFIC_PROTOCOL, /* 6  bDeviceProtocol */
    0x40,                     /* 7  bMaxPacketSize */
    (VENDOR_ID & 0xFF),       /* 8  idVendor */
    (VENDOR_ID >> 8),         /* 9  idVendor */
    (PRODUCT_ID & 0xFF),      /* 10 idProduct */
    (PRODUCT_ID >> 8),        /* 11 idProduct */
    (BCD_DEVICE & 0xFF),      /* 12 bcdDevice */
    (BCD_DEVICE >> 8),        /* 13 bcdDevice */
    MANUFACTURER_STR_INDEX,   /* 14 iManufacturer */
    PRODUCT_STR_INDEX,        /* 15 iProduct */
    0x00,                     /* 16 iSerialNumber */
    0x01                      /* 17 bNumConfigurations */
};

/* Configuration Descriptor */
static unsigned char cfgDesc[] =
{
    0x09,                     /* 0  bLength */
    0x02,                     /* 1  bDescriptortype */
    0x20, 0x00,               /* 2  wTotalLength */
    0x01,                     /* 4  bNumInterfaces */
    0x01,                     /* 5  bConfigurationValue */
    0x00,                     /* 6  iConfiguration */
    0x80,                     /* 7  bmAttributes */
    0xFA,                     /* 8  bMaxPower */

    0x09,                     /* 0  bLength */
    0x04,                     /* 1  bDescriptorType */
    0x00,                     /* 2  bInterfacecNumber */
    0x00,                     /* 3  bAlternateSetting */
    0x02,                     /* 4: bNumEndpoints */
    0xFF,                     /* 5: bInterfaceClass */
    0xFF,                     /* 6: bInterfaceSubClass */
    0xFF,                     /* 7: bInterfaceProtocol*/
    0x03,                     /* 8  iInterface */

    0x07,                     /* 0  bLength */
    0x05,                     /* 1  bDescriptorType */
    0x01,                     /* 2  bEndpointAddress */
    0x02,                     /* 3  bmAttributes */
    0x00,                     /* 4  wMaxPacketSize */
    0x02,                     /* 5  wMaxPacketSize */
    0x01,                     /* 6  bInterval */

    0x07,                     /* 0  bLength */
    0x05,                     /* 1  bDescriptorType */
    0x81,                     /* 2  bEndpointAddress */
    0x02,                     /* 3  bmAttributes */
    0x00,                     /* 4  wMaxPacketSize */
    0x02,                     /* 5  wMaxPacketSize */
    0x01                      /* 6  bInterval */
};

/* Set language string to US English */
#define STR_USENG 0x0409

/* String table */
unsafe
{
static char * unsafe stringDescriptors[] =
{
    "\x09\x04",                             // Language ID string (US English)
    "XMOS",                                 // iManufacturer
    "XMOS Custom Bulk Transfer Device",     // iProduct
    "Custom Interface",                     // iInterface
    "Config"                               // iConfiguration
};
}

/* Endpoint 0 Task */
void Endpoint0(chanend chan_ep0_out, chanend chan_ep0_in)
{
    USB_SetupPacket_t sp;
    XUD_BusSpeed_t usbBusSpeed;
    XUD_ep ep0_out = XUD_InitEp(chan_ep0_out, XUD_EPTYPE_CTL | XUD_STATUS_ENABLE);
    XUD_ep ep0_in  = XUD_InitEp(chan_ep0_in, XUD_EPTYPE_CTL | XUD_STATUS_ENABLE);

    while(1)
    {
        /* Returns XUD_RES_OKAY on success */
        XUD_Result_t result = USB_GetSetupPacket(ep0_out, ep0_in, sp);

        if(result == XUD_RES_OKAY)
        {
            /* Returns  XUD_RES_OKAY if handled okay,
             *          XUD_RES_ERR if request was not handled (i.e. STALLed),
             *          XUD_RES_RST if USB Reset */
            result = USB_StandardRequests(ep0_out, ep0_in, devDesc,
                        sizeof(devDesc), cfgDesc, sizeof(cfgDesc),
                        null, 0,
                        null, 0,
                        stringDescriptors, sizeof(stringDescriptors)/sizeof(stringDescriptors[0]),
                        sp, usbBusSpeed);
        }

        /* USB bus reset detected, reset EP and get new bus speed */
        if(result == XUD_RES_RST)
        {
            usbBusSpeed = XUD_ResetEndpoint(ep0_out, ep0_in);
        }
    }
}
#define BUFFER_SIZE 128


/* A basic endpoint function that receives 512-byte packets of data, processes
 * them and sends them back to the host. If at any point an error is detected
 * (return value < 0) then the process needs to be started again so that
 * both host and device stay in sync.
 */
void bulk_endpoint(chanend chan_ep_from_host, chanend chan_ep_to_host)
{
    int host_transfer_buf[BUFFER_SIZE];
    unsigned host_transfer_length = 0;
    XUD_Result_t result;

    XUD_ep ep_from_host = XUD_InitEp(chan_ep_from_host, XUD_EPTYPE_BUL | XUD_STATUS_ENABLE);
    XUD_ep ep_to_host = XUD_InitEp(chan_ep_to_host, XUD_EPTYPE_BUL | XUD_STATUS_ENABLE);

    while(1)
    {
        /* Receive a buffer (512-bytes) of data from the host */
        if((result = XUD_GetBuffer(ep_from_host, (host_transfer_buf, char[BUFFER_SIZE * 4]), host_transfer_length)) == XUD_RES_RST)
        {
            XUD_ResetEndpoint(ep_from_host, ep_to_host);
            continue;
        }

        /* Perform basic processing (increment data) */
        for (int i = 0; i < host_transfer_length/4; i++)
            host_transfer_buf[i]++;

        /* Send the modified buffer back to the host */
        if((result = XUD_SetBuffer(ep_to_host, (host_transfer_buf, char[BUFFER_SIZE * 4]), host_transfer_length)) == XUD_RES_RST)
        {
            XUD_ResetEndpoint(ep_from_host, ep_to_host);
        }
    }
}

/* The main function runs three tasks: the XUD manager, Endpoint 0, and bulk
 * endpoint. An array of channels is used for both IN and OUT endpoints,
 * endpoint zero requires both, bulk endpoint requires an IN and an OUT endpoint
 * to receive and send a data buffer to the host.
 */
int main()
{
    chan c_ep_out[XUD_EP_COUNT_OUT], c_ep_in[XUD_EP_COUNT_IN];

    par
    {
        on USB_TILE: xud(c_ep_out, XUD_EP_COUNT_OUT, c_ep_in, XUD_EP_COUNT_IN, null, XUD_SPEED_HS, XUD_PWR_BUS);
        on USB_TILE: Endpoint0(c_ep_out[0], c_ep_in[0]);
        on USB_TILE: bulk_endpoint(c_ep_out[1], c_ep_in[1]);
    }
    return 0;
}


User avatar
mon2
XCore Legend
Posts: 1913
Joined: Thu Jun 10, 2010 11:43 am
Contact:

Post by mon2 »

While we did not test your specific combination of tools and example, we did test a few others with success last year (ie. HID, USB mouse, etc.). Back then we recall that the supplied device drivers were not yet signed for 64 bit OS use. Suspecting your issue is different but can you try the following and report back ?

Change the following line to be self powered and be sure to apply a local power adapter:

Code: Select all

on USB_TILE: xud(c_ep_out, XUD_EP_COUNT_OUT, c_ep_in, XUD_EP_COUNT_IN,
null, XUD_SPEED_HS, XUD_PWR_SELF);
The last parameter is different in the actual application note as compared to your posted code.

Have you tested the HID example ? USB Mouse example ?

Is your OS 32 or 64 bit ?

https://www.xmos.com/node/17007?page=5

Try the following appnote and post your results:

http://www.xmos.com/support/appnotes/AN00129

Or a CDC model example - if you are on a 64 bit OS, you may need this work around::

http://www.xcore.com/forum/viewtopic.ph ... =microchip
kyle123
Member++
Posts: 25
Joined: Tue May 19, 2015 8:17 pm

Post by kyle123 »

Thanks for the suggestions and will run the tests later this weekend. To answer your hardware questions:
  1. I have also tried using the vendor specific application note and eventually made my way back to this example to try to make some sense of the USB errors. I have not yet tried the HID mouse example.
  2. My OS is 64 bit.
  3. Thanks for the workaround suggestion. I did get a windows error stating that the driver was not a 64bit driver. But I figured that would be the next task after enumerating the device.
Regards,

Kyle
kyle123
Member++
Posts: 25
Joined: Tue May 19, 2015 8:17 pm

Post by kyle123 »

For reference. I have checked the legacy usb module main.xc code and the device (with working example) is configured as a bus powered application. However, the new application note specifies that it should use SELF power on the same hardware. In either case that doesn't solve my particular issue, I just want to make users aware of this particular inconsistency.

Question:

The xud() method specifies whether the device should be SELF powered or BUS powered. Isn't this redundant information that is specified by the configuration descriptor bmAttributes of cfgConfig[]? I believe that bus powered applications should set the bmAtrributes to 0x80 and SELF power should be 0xC0.

Regards,

Kyle
User avatar
mon2
XCore Legend
Posts: 1913
Joined: Thu Jun 10, 2010 11:43 am
Contact:

Post by mon2 »

Kyle you noted that your OS is 64 bit. Is the device driver package for your project that is supplied by XMOS featuring a CAT file ? The CAT file is the Microsoft signed approval file that is necessary to permit the related device driver to install on 64 bit operating systems. Without this file, the driver will not install on your 64 bit box. Not sure if this is your root cause but worth reviewing.

You should be able to test by searching on the net for articles on how to install unsigned driver files and see if that makes a difference for your project.

If you can, do consider to test the CDC (serial port) ref design by following our suggestion. By changing the IDs to those posted in my link, then you can proceed to actually install with signed INF files. This should allow for a positive verification in that something is working on your 64 bit OS and is based on the XMOS toolkit. We have confirmed that we could compile and install the CDC example fine but ran into the ID issue for which we posted the work around.
kyle123
Member++
Posts: 25
Joined: Tue May 19, 2015 8:17 pm

Post by kyle123 »

Hi,

Sorry for the long delay. I'm afraid that the proposed solution didn't help. I have tried to download the CDC drivers and change the VID/PID as suggested. However, the same Device Descriptor Request failed error appears. I'm confused as to the requirements for the driver. I have been able to run the demo example on the demo kit...Presumably this means that windows knows which driver to install for the device.

Where the does the windows driver get started in this process. Should the driver be running before enumeration or after the device descriptor is found? I'm trying to determine whether the issue is in hardware, software or somewhere in the middle:) For instance, should windows be able to at least recognize the PID and VID? Right now, it reads VID_0000&PID_0002 which is definitely not what was written in the firmware posted previously.

Thanks,

Kyle
kyle123
Member++
Posts: 25
Joined: Tue May 19, 2015 8:17 pm

Post by kyle123 »

Also backup plan / question:

What are the data/ speed limitations of the JTAG adapter? Is it possible to simply spit the data out over the debug adapter? I need a minimum of 64Mbit/s bandwidth. If this is not possible, then I can do processing on the spare tile and try to reduce bandwidth requirements.

Thanks again:)
User avatar
mon2
XCore Legend
Posts: 1913
Joined: Thu Jun 10, 2010 11:43 am
Contact:

Post by mon2 »

Hey Kyle. Both VID & PID are both messed up. I would not take place any bets on the proper workings of the balance of this code.

1) Are you using only the default XMOS supplied example code for this CDC example ?

2) Which tool chain version are you using for these tests ? Perhaps the issue is tool chain version related ?

3) Can you try the HID keyboard or mouse example ? Just to see if you can at least install the XMOS board as the respective USB function. That will provide you with a vote of confidence that the devkit is operating correctly.

https://www.xmos.com/published/hid-clas ... tart-guide

4) What is the history of your development board ? Is it new ? Known to be working otherwise ?

The XTAG interface is using a 2-wire XLINK to perform its tasks.

See 4.2 of this document:

https://www.xmos.com/download/private/X ... 1.0%29.pdf

and reviewing Section 2 of this document:

https://www.xmos.com/download/private/X ... 2.0%29.pdf

Image

sounds like you will be fine.

12.5 Mbyte/sec*8 = 100 Mbits/sec.
kyle123
Member++
Posts: 25
Joined: Tue May 19, 2015 8:17 pm

Post by kyle123 »

Hi mon2,

I was just relaying the Windows 7 response in regards to the PID and VID. I realize that it is completely messed up and does not make sense according to USB specifications. I have tried running the new library from my linux box to get around the potential windows driver issues. The same descriptor error occurred on that side as well. I've got a sneaking suspicion that it is related to USB_StandardRequests() although no firm proof.

However, I have managed to make a functional USB device and transfer data using the old USB library with xud_manager. This library works on both my custom hardware and the development kit XP-SKC-U16.

I am using:
  • XtimeComposer 14.1.2
  • Debugger/ XTAG2
Thanks for the info on the xlink data rates. For the time being I will proceed using the older library.

Regards,

Kyle
User avatar
mon2
XCore Legend
Posts: 1913
Joined: Thu Jun 10, 2010 11:43 am
Contact:

Post by mon2 »

Check it kyle123..XMOS has posted a fix that may resolve your issues with the v3 USB library:

http://www.xcore.com/forum/viewtopic.php?f=8&t=4420

Hope you can test and report your findings at your convenience.
Post Reply