This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Mistake found in RTL version of "usbcore.c" in USB_ReqGetDescriptor()

Hello!
I have recently decided to try a newer version of USB for RTL and detected a mistake in file "usbcore.c":

__inline BOOL USB_ReqGetDescriptor (void) {
  U8  *pD;
  U32 len, n;

  switch (SetupPacket.bmRequestType.BM.Recipient) {
    case REQUEST_TO_DEVICE:
      switch (SetupPacket.wValue.WB.H) {

          ...

        case USB_STRING_DESCRIPTOR_TYPE:
          pD = (U8 *)USB_StringDescriptor;
          for (n = 0; n != SetupPacket.wValue.WB.L; n++) {
            if (((USB_STRING_DESCRIPTOR *)pD)->bLength != 0) {
              pD += ((USB_STRING_DESCRIPTOR *)pD)->bLength;
            }
          }
          if (((USB_STRING_DESCRIPTOR *)pD)->bLength == 0) {
            return (__FALSE);
          }
          EP0Data.pData = pD;
          len = ((USB_STRING_DESCRIPTOR *)pD)->bLength;
         break;

         ...

      }
      break;

      ...
}

Selected code part which is responsible for sending the string descriptor to the host, doesn't work correctly. In previous versions of USB sources, al least in version V1.10 of USB Core Module it worked well and it looked like this:

        case USB_STRING_DESCRIPTOR_TYPE:
          EP0Data.pData = (U8 *)USB_StringDescriptor + SetupPacket.wValue.WB.L;
          len = ((USB_STRING_DESCRIPTOR *)EP0Data.pData)->bLength;
          break;

Please correct the issue if I am right, or explain the situation if not.
Thanks in advance.

  • I will discribe the issue a little more detailed.

    I've been using USB stack for LPC2148 microcontrollers for a couple of years and there were no problems until I decided to update Keil IDE and RTX from old version 3.22 to the newest 4.13. The first thing that stopped working after that was getting the serial number from USB string descriptor. The descriptor is defined in file "USBDESC.C" and contains strings such as Manufacturer, Product Name, Serial Number and so on.

    When I try to read out the Serial Number of the USB device, host driver sends the appropriate packet to the device in which SetupPacket.wValue.WB.L field contains the byte offset of the beginning of the specified string in the descriptor.

    The old implementation of USB sources works well, it simply returns the address of string beginning and its length:

              EP0Data.pData = (U8 *)USB_StringDescriptor + SetupPacket.wValue.WB.L;
              len = ((USB_STRING_DESCRIPTOR *)EP0Data.pData)->bLength;
    

    In the new implementation the for(;;n++) loop is used to "calculate" the string address, but the calculation algorithm is incorrect: n increments as many times as the offset value is. So the algorithm jumps though strings in the descriptor a number of times equal to string offset value! Obviously someone has mixed up "string offset" and "number of jumps through strings".

    Has anyone noticed any problems using USB like me?

  • Well.... I've just realized what the issue was. It was not actually a source code mistake, as the Device Descriptor has also been modified in the new version of sources. The Device Descriptor includes bytes which previously (in the old version) held string offsets, but now they hold string indices (0x01, 0x02, e.t.c). Taking this into account, I see that the string descriptor processing algorithm is correct.

    Recompiling my projects I have copy-pasted my old USB descriptors into a new USB sources without changing and it wasn't right. So be careful with that.

    Now the problem is solved,
    Thank you.

  • Hello Alexey Kozyrev,

    The reason for using indices rather than offset was that the USB Compliance test threw an error/warning for the older version which used the offset to address the string.

    Best Regards, Martin Guenther