IntergatedCircuits / HidSharp

HIDSharp is a multiplatform C# library for USB HID devices by James F. Bellinger
https://www.zer7.com/software/hidsharp
Other
121 stars 34 forks source link

Bug in EncodedItem when creating instance and setting DataValueSigned #22

Open DBuergin opened 1 year ago

DBuergin commented 1 year ago

TL;DR

When creating instance of EncodedItem

if DataValueSigned = X where

(X > Int16.MinValue && X < 0) || (X > Int16.MaxValue)

Then DataValueSigned cannot be round tripped and later accessed DataItems have a wrong value.

Use case

I'm trying to get Logical min and max values from a USB device under Windows. The logical minimum in the hid descriptor is -512. The later accessed DataItem contains a logical minimum of 0.

I've managed to narrow it down to EncodedItem.cs, line 162

But I cannot for the life of me understand the logic behind EncodedItem.Data.

Steps to reproduce with VS 2022:

  1. Open HidSharp project

  2. In Visual Studio Menu, go to View > Other Windows > C# Interactive

  3. In Solution Explorer, right click HidSharp Project and choose Initialize Interactive with Project

  4. In Interactive Console, enter the following:

> using HidSharp.Reports.Encodings;
> var item = new EncodedItem() { ItemType = ItemType.Global, TagForGlobal = GlobalItemTag.LogicalMinimum, DataValueSigned = -32768 };
> item.DataValueSigned

EncodedItem.DataValueSigned = 0

Observations

In       Out
-32769 = -32769
-32768 = 0
-1     = 0
1      = 1
32767  = 32767
32768  = -32768

If anyone has an Idea how to correct this without breaking anything else, I would appreciate the help.

Diego

DBuergin commented 1 year ago

Changing the following two lines fixes the round-trip problem, but probably breaks reconstruction of the HID descriptor:

EncodedItem.cs : L160 change { DataValue = (uint)(sbyte)value; if (value < 0) { Data.Add(0); } } to { DataValue = (uint)(sbyte)value; }

and EncodedItem:L162 change { DataValue = (uint)(short)value; if (value < 0) { Data.Add(0); Data.Add(0); } } to { DataValue = (uint)(short)value; }