Author Topic: GenericHID Reading Indexed Strings  (Read 16705 times)

Haldor

  • Member
  • ***
  • Posts: 4
GenericHID Reading Indexed Strings
« on: July 12, 2011, 10:50:35 am »
Hello Jan,

I found your example GenericHid C# program to be most helpful in writing host software in dot.net (everything I have done in the past on the PC side was written in VB6).  One thing that was not supported in GenericHID that I wanted to be able to do is to read the indexed string descriptors (Vendor Name, Serial Number etc.).  I have added this to GenericHid and as a way of saying thanks I am posting how I did it in case anyone else needs to do the same.

First you have to add the following code to the HidDeclarations.cs file

[ DllImport( "hid.dll", SetLastError=true ) ]       
internal static extern Boolean HidD_GetIndexedString(SafeFileHandle HidDeviceObject, Int32 StringIdex, Byte[] StringBuffer, Int32 StringBufferLength );

Next add a function to the Hid.cs file to handle the API call.  The line "using System.Text;" is required to use the Encoding function which I used to convert the C unicode string returned by the API call into a C# string.

using System.Text;

        internal Boolean GetIndexedString(SafeFileHandle hidHandle, Int32 StringIndex, ref string Destination, Int32 MaxLength)
        {
            Boolean success;
            Byte[] Buffer;
            Buffer = new Byte[MaxLength * 2];
            try
            {
                 //  ***
                 //  API function: HidD_GetIndexedString
                 //  Attempts to read a requested indexed string from the device.

                 //  Requires:
                 //  A handle to a HID
                 //  The index to the string
                 //  A pointer to a string to store the response in
                 //  The max length of string you are willing to accept

                 //  Returns: true on success, false on failure.
                 //  ***                   

                 success = HidD_GetIndexedString(hidHandle, StringIndex, Buffer, Buffer.Length);
                 if (success == true)
                 {
                     Destination = Encoding.Unicode.GetString(Buffer);
                 }
                 else
                 {
                     Destination = null;
                 }
            }
            catch (Exception ex)
            {
                 DisplayException(MODULE_NAME, ex);
                 throw;
            }
        }


Finally here is an example that uses the GetIndexedString function to read the Vendor Name String (Index = 1) and store it to a text box.

        private void cmdGetStringbtn_Click(object sender, EventArgs e)
        {
            Boolean success = false;
            string Result = null;
            Int32 Index = 1;
            Int32 MaxLength = 20;
            success = MyHid.GetIndexedString(hidHandle, Index, ref Result, MaxLength);
            if (success == true)
            {
                IndexedStringtxb.Text = Result;
            }
        }

Thanks very much for the help you given me in the past Jan.  I used your first edition "USB Complete" while I was developing my first USB devices back in 2000 and found it to be very helpful also.  I am just getting my feet wet in the C# world (I am primarily an embedded developer), but so far I really like it.


« Last Edit: July 12, 2011, 10:55:58 am by Haldor »

Jan Axelson

  • Administrator
  • Frequent Contributor
  • *****
  • Posts: 3033
    • Lakeview Research
Re: GenericHID Reading Indexed Strings
« Reply #1 on: July 12, 2011, 06:10:01 pm »
Thanks so much for posting this.

Jan

Haldor

  • Member
  • ***
  • Posts: 4
Re: GenericHID Reading Indexed Strings
« Reply #2 on: July 12, 2011, 07:46:16 pm »
My pleasure.

Do you have any recommendations on how to read the Report Descriptor? I would like to be able to calculate the individual report lengths (so I don't have to hard code them in my application). I can calculate each report length from the Report Descriptor, I'm just not sure what the best way is to read it  in.  I have never used the HID format decoder capability (previously I just manually parsed the report data).  Do you know of a good tutorial on using the Report Descriptor to automatically parse the data (assuming the HID device driver supplies this capability)?

Haldor

  • Member
  • ***
  • Posts: 4
Re: GenericHID Reading Indexed Strings
« Reply #3 on: July 13, 2011, 04:43:44 pm »
Minor update.

I discovered that this get indexed string works a lot better if you trim any extra nulls from the end.  This way if you wish to concatenate the indexed strings together you can.  I ran into this problem while I was trying to build up a list of connected HID devices.  When I tried to combine the Manufacture, Product and Serial Number strings into a single string, I only got the first one.

Please modify the above example to use this line of code instead.

Destination = Encoding.Unicode.GetString(Buffer).TrimEnd('\0');

F.Y.I.  Normal USB usage for indexed strings are as follows:

String Index 0 = Language ID
String Index 1 = Manufacturer Name String
String Index 2 = Product Name String
String Index 3 = Serial Number String

You can also read get the string indexes from the Device Descriptor.  There are also dedicated functions in HID.dll to read each of these strings directly (so you don't have to know the string index values).  The work exactly the same as the indexed version except you have one less parameter to pass.


        [ DllImport( "hid.dll", SetLastError=true ) ]       
        internal static extern Boolean HidD_GetManufacturerString(SafeFileHandle HidDeviceObject, Byte[] StringBuffer, Int32 StringBufferLength );

        [DllImport("hid.dll", SetLastError = true)]
        internal static extern Boolean HidD_GetProductString(SafeFileHandle HidDeviceObject, Byte[] StringBuffer, Int32 StringBufferLength);

        [DllImport("hid.dll", SetLastError = true)]
        internal static extern Boolean HidD_GetSerialNumberString(SafeFileHandle HidDeviceObject, Byte[] StringBuffer, Int32 StringBufferLength);


« Last Edit: July 13, 2011, 04:47:21 pm by Haldor »

Jan Axelson

  • Administrator
  • Frequent Contributor
  • *****
  • Posts: 3033
    • Lakeview Research
Re: GenericHID Reading Indexed Strings
« Reply #4 on: July 14, 2011, 09:15:59 am »
Start with the HIDP_CAPS structure retrieved by HidP_GetCaps. From there you can use the other HID parser functions documented here:

http://msdn.microsoft.com/en-us/library/ms894897.aspx

You may have to write the C# declarations, using the ones you have as a model.

Jan