[libhid-discuss] Misunderstanding input and output paths
Charles Lepple
clepple at ghz.cc
Fri Apr 23 12:09:25 UTC 2010
On Apr 23, 2010, at 1:17 AM, Gary Briggs wrote:
> On Tue, Apr 20, 2010 at 07:49:50AM -0400, Charles Lepple wrote:
>>> I've written some code [mainly copied outright from the libhid test
>>> example], here:
>>> http://icculus.org/~chunky/stuff/dcdcusb/main.c
>>>
>>> The output from that program is:
>>> http://icculus.org/~chunky/stuff/dcdcusb/
>>> set_output_report_output.txt
>>
>> The only thing to note is that there is a bug in the printing
>> routine,
>> and if you see a "0x00000000" path element, it is just the 2nd or
>> later element of a range. The parser knows what to do internally,
>> though.
>
> I'm still just having a hard time understanding the overall "how to
> get a
> path out, given a lsusb listing".
You're not the first :-)
Based on a quick read of the Windows source code, I don't know if the
paths will really matter. Note that the hid_interrupt_read() and
hid_interrupt_write() calls do not worry about paths - they just take
an endpoint number, and require you to figure out the packet size
yourself.
But for completeness, here's how the first element in the dump is
computed.
> parse tree of HIDInterface 003/015[0]:
> path: 0x00010080.0x00010081; type: 0x80
The first part of the report descriptor:
> Report Descriptor: (length is 200)
> Item(Global): Usage Page, data= [ 0x01 ] 1
> Generic Desktop Controls
> Item(Local ): Usage, data= [ 0x80 ] 128
> System Control
"Usage Page...= 0x01" is shorthand, and gets translated to "0x0001 <<
16", or 0x00010000. "Usage...=0x80" gets OR'd with that, to produce
"0x00010080". That full 32-bit Usage is the first element of the path
("root directory", if you will).
The next element in the report descriptor is a collection:
> Item(Main ): Collection, data= [ 0x01 ] 1
> Application
The notion of a collection is similar to a directory on a filesystem;
hence, the full Usage calculated above will be the first elements of
all the paths until the collection ends.
> Item(Global): Report ID, data= [ 0x01 ] 1
Report IDs are sort of another dimension to the data - they allow the
information to be broken up into chunks that can be requested
separately (keyed by the Report ID). They are "sticky" until the next
Report ID.
> Item(Local ): Usage, data= [ 0x81 ] 129
> System Power Down
This Usage ID is inside the collection, and it inherits the last Usage
Page which was set (0x0001 => 0x00010000). So its full 32-bit Usage is
(0x0001 << 16) | 0x0081, or 0x00010081, which is the second element of
the path (shown in the first line of the dump).
> Item(Global): Logical Minimum, data= [ 0x00 ] 0
> Item(Global): Logical Maximum, data= [ 0x01 ] 1
> Item(Global): Report Size, data= [ 0x01 ] 1
> Item(Global): Report Count, data= [ 0x01 ] 1
> Item(Main ): Input, data= [ 0x06 ] 6
> Data Variable Relative No_Wrap Linear
> Preferred_State No_Null_Position
> Non_Volatile Bitfield
This portion from the lsusb listing basically says that the path
represents one bit of input data. The "0x80" at the end of the libhid
dump is the internal libhid direction flag (Input, which is Device-to-
Host).
> Item(Global): Report Count, data= [ 0x07 ] 7
> Item(Main ): Input, data= [ 0x01 ] 1
> Constant Array Absolute No_Wrap Linear
> Preferred_State No_Null_Position
> Non_Volatile Bitfield
The single bit of data is padded out with 7 bits of "don't care" (the
Constant/Absolute flags above).
If we look up the Usage in that Usage Page (which lsusb has done for
us), it appears as though the PSU is synthesizing a "System Power
Down" keypress.
After that, the collection is closed, which is sort of like "cd ..":
> Item(Main ): End Collection, data=none
So the next Usage Page and Usage pair will specify the first element
in the path.
> I started reading this:
> http://www.networkupstools.org/doc/2.2.0/hid-subdrivers.html
> Is this actually relevant to me? It seems that if someone else has
> done
> most of the work for HID power supplies, I'll have more luck beginning
> with that?
Unfortunately, that particular driver is looking for the standard HID
Power Device Class (PDC) Usage numbers (0x0084 and 0x0085).
Here's a sample libhid dump from the kind of UPS that NUT works with
out-of-the-box:
http://boxster.ghz.cc/projects/libhid/browser/trunk/ref/test_libhid_output/MGE_Pulsar_Evolution_500
>>> Overall, I'm just confused as to what's going on or how to progress
>>> and
>>> make this work. If anyone has any suggestions as to what I should do
>>> from here, I'd greatly appreciate it.
>>
>> What are your goals? Shutting down the power supply? Monitoring
>> certain parameters? If possible, I would start with something
>> innocuous like changing the state of an LED, but if you can power the
>> test machine from another power source, that would be best.
>
> At least to start, I just want to read the current state of the PSU.
> Saliently, at least to start, I just want to be able to figure out
> whether the ignition is connected or not, and if not, how long until
> it
> actually shuts the whole system down.
You may be in luck if it's rainy this weekend - I'll have more time to
look into the Windows code.
> I figure that once I see *something* everything else is in the realm
> of
> figuring out the device-specific hoojimajiggery. I'm still just at the
> point where I want to see *something*.
>
> Thank-you so much for your time and explanations, they've really been
> helping me.
You're welcome. You have evidently spent a lot of time researching
this, so I figure it's the least I can do.
Oh, OK - I admit it - I think this device would be cool to support in
Network UPS Tools :-)
More information about the libhid-discuss
mailing list