[Nut-upsdev] USB HID Spec help (passing strings)

Charles Lepple clepple at gmail.com
Wed Sep 2 13:24:13 UTC 2015


On Sep 2, 2015, at 8:54 AM, Rob Groner <rgroner at RTD.com> wrote:
> 
>  
> No, just as a variable string descriptor.
>  
> By “variable string descriptor”, do you mean what is contained in the example in the App Note?  I’m just asking for clarification, in case variable string descriptor is something different than shown there.

By "variable" I mean "not const". Although they did not explicitly mark any of the structs "const", their code does not change any of the string descriptors at runtime.

>  
> The way they do the string descriptors in the example is how I have mine now.  They return a size and address, but it is to something that was defined at compile time.  I guess I’ve been fixated on that, so I don’t know if I can simply pass a different string that what was defined before.  And I don’t know how to handle something of an unknown size (though in my case, the MAX size of the serial number can be defined)
Because the structs are not const, you should be able to write new values into them at runtime. (It's up to you to do this before the string is actually requested, but since string descriptors are not requested often, you could do it in something like GetStringDescriptor() just before it returns.)

You would need to change the "sizeof()" to be the actual length of that struct at runtime. It's a little tricky, because the base struct is sizeof(USB_STRING_DESCRIPTOR), and then you need to add 2*strlen(serial_number) if your copy of the serial number from EEPROM is ASCII. (Note that the ['M', 'i', 'c', 'r', 'o'...] initialization is for a WORD[] rather than char[]. USB strings are 16-bit little-endian Unicode.)

Dragging in a copy of sprintf() might be overkill, but you could have a loop that reads in the bytes of the serial number, adds '0' (0x30) to each 4-bit hex digit, and writes that into the string descriptor.
>  
> That’s why I was asking about the variable string descriptor...it sounds more like something where you can pass a string of any size and address, which would definitely be what I’m looking for.
GetStringDescriptor() is returning a pointer via "return", and a length passed by reference ("*length = ..."), so as long as you construct the string descriptor to look the same as the statically-initialized ones, you should be all set.
>  
> Looking at the data being passed, I realized that battery.type is something else that I possibly won’t know until the code is running.  Our UPS can use different attached batteries, and will be able to discern what it is at runtime, and that’s when it would be able to report battery.type.
For returning one choice from a limited set, you might want to create one const string descriptor for each battery type string, and choose one pointer/length pair at runtime.
>  
> Thanks for the help Charles…that is a very good link to the Appnote considering you haven’t done PIC32 work.  J  My google skills failed me.
> 
No problem. Using the standard string descriptors means fewer special cases in our source code :-)

Note that you should be able to test reading the string descriptors by simply using "lsusb -v -d VID:" on your device (might need to be run as root, depending on permissions). Next to the iSerialNumber value, it will try to fetch the corresponding string descriptor and print it.

-- 
Charles Lepple
clepple at gmail



-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.alioth.debian.org/pipermail/nut-upsdev/attachments/20150902/6ea888c8/attachment-0001.html>


More information about the Nut-upsdev mailing list