Hi
I have a unique serial number saved in EEPROM for each PCB, I want to assign that serial number string to the USB descriptor, so on windows, I can see that serial number. How can I do this? I see the USB descriptor serial number is defined as macro, can't be changed in run-time.
Thanks Wang
USB device returns serial number string, when host requests it using Get_Descriptor request. In the handler of Get_Descriptor on a stack, your firmware gets chance to read serial number from an EEPROM.
What is a USB example you are working on?
Tsuneo
I am using "C:\Keil\ARM\Boards\Keil\MCB1700\RL\USB\Device\Memory", seems need to change "usb_lib.c"?
Thanks.
String descriptor structure on RAM
On RL-USB library, USBD_StringDescriptor structure, defined on usb_lib.c, gives the all string descriptors on the device, including the serial number string. As the default, this structure is assigned to ROM by "const" modifier. Deleting "const" modifier, this structure is placed on RAM, so that it can be modified at run time.
1) Copy C:\Keil\ARM\RV31\INC\usb_lib.c to your project folder, and rename it. 2) Change usb_lib.c reference in usb_config.c at the bottom of this file.
usb_config.c #ifndef __NO_USB_LIB_C #include <usb_lib.c> // <--- change to "renamed_usb_lib.c" #endif
Now that you may customize renamed usb_lib.c as you like.
3) Near the bottom of usb_lib.c, USBD_StringDescriptor is defined. Delete "const" from this definition.
usb_lib.c __weak \ const struct { // <--- delete "const" of this line struct { U8 len; U8 type; U16 langid; } desc_langid; USBD_STR_DEF(STRDESC_MAN); USBD_STR_DEF(STRDESC_PROD); #if (USBD_STRDESC_SER_ENABLE) USBD_STR_DEF(STRDESC_SER); #endif ... ... } USBD_StringDescriptor
4) At the start-up initialization in main(), before "usbd_connect(__TRUE);" is called, the string descriptor for serial number is replaced to those read out from EEPROM.
USBD_StringDescriptor.descSTRDESC_SER.len (U8 variable) - length of custom string + 2 USBD_StringDescriptor.descSTRDESC_SER.str[] (U16 array) - body of custom string in UNICODE
Ah, you have to assign dummy string of enough length to USBD_STRDESC_SER
usb_config.c #define USBD_STRDESC_SER L"0001A0000000" // <--- assign dummy string of enough length
USB_ReqGetDescriptor() routine may be overridden, but it isn't safe without original source code of this routine.
Great! Thanks Tsuneo! Will try it now.
An interesting thing here is this part:
__weak \ <==== weak linkage, so another file can contain a symbol of same name to replace this. const struct { struct { U8 len; U8 type; U16 langid; } desc_langid;
So in case this file contains lots of other things that a user do not want to change, then another source file should be able to redeclare USBD_StringDescriptor.
Aha, I know how how "__week" works. But in this case, USBD_StringDescriptor definition uses bunch of #define macros and conditional compilation, which are defined in usb_lib.c and usb_config.c. To extract USBD_StringDescriptor definition, we have to make these macros referable. It's so troublesome. In this reason, above method is easier and safer, just to delete "const" modifier.