Author Topic: StringDescriptor displays ASCII  (Read 12144 times)

gi

  • Member
  • ***
  • Posts: 27
StringDescriptor displays ASCII
« on: July 05, 2011, 05:57:54 am »
Hello guys,
I have almost completed my USB code and about to run and it was successfully enumerated by my XP OS as HID device.
The problem is that the Manufacturer string shows an ASCII in my desktop application.

Here is my string descriptor:
Code: [Select]
#define STR1LEN sizeof("HELLO CORP") * 2

unsigned char code String1Desc [STR1LEN] =
{
    STR1LEN,
DESCRIPTORTYPE_STRING,
'H', 0,
'E', 0,
'L', 0,
'L', 0,
'O', 0,
' ', 0,
'C', 0,
'O', 0,
'R', 0,
'P', 0
}; // End of String1Desc

#define STR2LEN sizeof("MyDevice") * 2

unsigned char code String2Desc [STR2LEN] =
{
   STR2LEN,
DESCRIPTORTYPE_STRING,
'M', 0,
'y', 0,
'D', 0,
'e', 0,
'v', 0,
'i', 0,
'c', 0,
'e', 0
}; // End of String2Desc

#define STR3LEN sizeof("0001") * 2

unsigned char code String3Desc[STR3LEN] =
{
STR3LEN,
DESCRIPTORTYPE_STRING,
'0', 0,
'0', 0,
'0', 0,
'1', 0
};//End of String3Desc

unsigned char code * STRINGDESCTABLE [] =
{
   String0Desc,
   String1Desc, //iManufacturer
   String2Desc //iProduct
   String3Desc //iSerialNumber
};

And my device descriptor:
Code: [Select]
const device_descriptor code DEVICEDESC =
{
   18,                                 // bLength
   0x01,                               // bDescriptorType
   0x1001,                             // bcdUSB
   0x00,                               // bDeviceClass
   0x00,                               // bDeviceSubClass
   0x00,                               // bDeviceProtocol
   EP0_PACKET_SIZE,                    // bMaxPacketSize0
   0x10C4,                             // idVendor
   0x0004,                             // idProduct
   0x0000,                             // bcdDevice
   0x02,                               // iManufacturer
   0x01,                               // iProduct
   0x03,                               // iSerialNumber
   0x01                                // bNumConfigurations
}; //end of DEVICEDESC

I tried to attach the screen shot here but I can't see it during preview so I just put it in google docs and just share the link.
You can find the screenshot at the link below:
http://goo.gl/uXteq

Also, the serial number did not display in the desktop application.
May I know how to display the string correctly as well as the serial number?

BTW, my mcu is Silabs C8051f340 w/ C51 Keil compiler.

thanks and regards
gi

Guido Koerber

  • Frequent Contributor
  • ****
  • Posts: 72
Re: StringDescriptor displays ASCII
« Reply #1 on: July 05, 2011, 07:39:50 am »
Not sure why your manufacturer string does not get displayed, it would possibly be necessary to see the complete descriptor to uderstand this.

The serial number needs to be a unicode string too.

Pat Crowe

  • Member
  • ***
  • Posts: 39
Re: StringDescriptor displays ASCII
« Reply #2 on: July 05, 2011, 08:16:49 am »
It looks as though you may have the indexes for manufacturer and product strings back to front in the device descriptor.

Try changing the PID to one which you haven't used before.

gi

  • Member
  • ***
  • Posts: 27
Re: StringDescriptor displays ASCII
« Reply #3 on: July 05, 2011, 08:46:03 pm »
Hi Guido and Pat,
Thanks for your reply.
I looked at the Get_Descriptor request and found out that it was hard coded as
Code: [Select]
if(SETUP.wValue.c[LSB] > 2) Stall();
under string descriptor type, which set the STSTL whenever the request exceeds 2(indexed 0), in my string descriptor table I have 3 because of the serial number added.

Now I changed it to 3
Code: [Select]
if(SETUP.wValue.c[LSB] > 3) Stall();
 
I tried to changed also what Pat suggested and here is the result in my desktop application:
Link: http://goo.gl/rdFFe

Now, the serial gets displayed but in unreadable characters as well as the Product name string.

I noticed also in the desktop app, that the Product name was interchanged with the Manufacturer name:
Product name supposedly is "MyDevice" and Manufacturer is "HELLO CORP", I am sure it was set in order in my Device descriptor.

Here is my device descriptor:
Code: [Select]
const device_descriptor code DEVICEDESC =
{
   18,                                 // bLength
   0x01,                               // bDescriptorType
   0x1001,                             // bcdUSB
   0x00,                               // bDeviceClass
   0x00,                               // bDeviceSubClass
   0x00,                               // bDeviceProtocol
   EP0_PACKET_SIZE,                    // bMaxPacketSize0
   0xC410,                             // idVendor
   0x0100,                             // idProduct
   0x0000,                             // bcdDevice
   0x01,                               // iManufacturer
   0x02,                               // iProduct
   0x03,                               // iSerialNumber
   0x01                                // bNumConfigurations
}; //end of DEVICEDESC

Here is my the Get_Descriptor request:
Code: [Select]
void Get_Descriptor (void)             // This routine sets the data pointer
{                                      // and size to correct descriptor and
                                       // sets the endpoint status to transmit

   switch(SETUP.wValue.c[MSB])         // Determine which type of descriptor
   {                                   // was requested, and set data ptr and
      case DSC_DEVICE:                 // size accordingly
         DATAPTR = (unsigned char*) &DEVICEDESC;
         DATASIZE = DEVICEDESC.bLength;
         break;

      case DSC_CONFIG:
         DATAPTR = (unsigned char*) &ConfigDesc;
                                       // Compiler Specific - The next statement
                                       // reverses the bytes in the configuration
                                       // descriptor for the compiler
         DATASIZE = ConfigDesc.wTotalLength.c[MSB] +
                    256*ConfigDesc.wTotalLength.c[LSB];
         break;

  case DSC_STRING:
//  NOTE: if strings are added to this project, the hard-coded
         // value of 2 will need to be increased
         if (SETUP.wValue.c[LSB] > 3)   // If asking for string that's N/A
         {
            Force_Stall();
         }
         else
         {
            DATAPTR = STRINGDESCTABLE[SETUP.wValue.c[LSB]];
                               // Can have a maximum of 255 strings
            DATASIZE = *DATAPTR;
         }
         break;

      case DSC_INTERFACE:
         DATAPTR = (unsigned char*) &InterfaceDesc;
         DATASIZE = InterfaceDesc.bLength;
         break;

      case DSC_ENDPOINT:
         // This example splits endpoint 1 into an
         // IN endpoint and an OUT endpoint
         // In the ...Descriptor.c and ...Descriptor.h files,
         // OUT endpoint 1 is referred to as Endpoint 2.
         if ( (SETUP.wValue.c[LSB] == IN_EP1) )
         {
            DATAPTR = (unsigned char*) &Endpoint1Desc;
            DATASIZE = Endpoint1Desc.bLength;
         }
         else if ( (SETUP.wValue.c[LSB] == OUT_EP1) )
         {
            DATAPTR = (unsigned char*) &Endpoint2Desc;
            DATASIZE = Endpoint2Desc.bLength;
         }
         else
         {
            Force_Stall();
         }
         break;

   case DSC_HID:                       // HID Specific (HID class descriptor)
      DATAPTR = (unsigned char*)&HidDesc;
      DATASIZE = HidDesc.bLength;
      break;

   case DSC_HID_REPORT:                // HID Specific (HID report descriptor)
      DATAPTR = (unsigned char*)&HIDREPORTDESC;
      DATASIZE = HID_REPORT_DESCRIPTOR_SIZE;
      break;

      default:
         Force_Stall ();               // Send Stall if unsupported request
         break;
   }

   // Verify that the requested descriptor is valid
   if (SETUP.wValue.c[MSB] == DSC_DEVICE ||
   SETUP.wValue.c[MSB] == DSC_CONFIG     ||
   SETUP.wValue.c[MSB] == DSC_STRING     ||
   SETUP.wValue.c[MSB] == DSC_INTERFACE  ||
   SETUP.wValue.c[MSB] == DSC_ENDPOINT)
   {
      if ((SETUP.wLength.c[LSB] < DATASIZE) &&
      (SETUP.wLength.c[MSB] == 0))
      {
         DATASIZE = SETUP.wLength.i;   // Send only requested amount of data
      }
   }
   if (EP_STATUS[0] != EP_STALL)       // Make sure endpoint not in stall mode
   {
     POLL_WRITE_BYTE (E0CSR, rbSOPRDY);// Service SETUP Packet
     EP_STATUS[0] = EP_TX;             // Put endpoint in transmit mode
     DATASENT = 0;                     // Reset Data Sent counter
   }
}

thank you very much for your valuable help.

regards
gi