On Mar 19, 2017, at 10:56 AM, Drew from Zhrodague <drewzhroda...@zhrodague.net> 
wrote:
> 
>       [] I've spoken with one of the developers, and he's offered to share 
> some technical documentation with me. I'll report here with whatever I can. 
> He's on vacation in China.

Hopefully this documentation will lead to fewer surprises down the road.

>       [] I found this hid-example.c program, which fetches the values from 
> the unit, including a timer, and a current state. However, this example 
> program pushes data into the unit (to test writing), which sets the timers to 
> astronomical values. I am not sure the format it wants, I'm unable to 
> actually set anything, and the timer seems to default to 'a3 minutes'. My C 
> is rusty, but commenting-out the writing portion makes the data collection 
> not work.

I keep finding the generic hid-example.c from the Linux kernel tree when 
searching - do you have one specifically for this device?
> 
>       [] After unloading the hid modules, I was able to get more details on 
> the USB format, and I am trying to read documentation to understand what's 
> going on. From lsusb -vvv:
> 
>    Report Descriptor: (length is 34)
>            Item(Global): Usage Page, data= [ 0xa0 0xff ] 65440
>                            (null)
>            Item(Local ): Usage, data= [ 0xa5 ] 165
>                            (null)
>            Item(Main  ): Collection, data= [ 0x01 ] 1
>                            Application
>            Item(Local ): Usage, data= [ 0xa6 ] 166
>                            (null)
>            Item(Local ): Usage, data= [ 0xa7 ] 167
>                            (null)
>            Item(Global): Logical Minimum, data= [ 0x00 ] 0
>            Item(Global): Logical Maximum, data= [ 0xff ] 255
>            Item(Global): Report Size, data= [ 0x08 ] 8
>            Item(Global): Report Count, data= [ 0x08 ] 8
>            Item(Main  ): Input, data= [ 0x02 ] 2
>                            Data Variable Absolute No_Wrap Linear
>                            Preferred_State No_Null_Position Non_Volatile 
> Bitfield

This is the decoded version of roughly the first half of the Report Descriptor 
bytes below. The HID Report Descriptor has an obscure stack-based approach to 
organizing data. Both collections and individual Input/Output/Feature items are 
"named" with Usage numbers, and the Usage Page is a way to set the top 16 bits 
of the Usage number.

The problem here is that the Usage Page is 0xFFA0, and IDs beginning with 0xFF 
are vendor-specific. (For an UPS, this would be something like 0x84 for the 
Power Device Page. See /usr/share/misc/usb.ids after the VID/PID section.)

I think this one byte (Report Size == 8 bits) for Usage 0xA6, and the other 
seven bytes (left over from Report Count == 8 x 8 bits) for usage 0xA7. Logical 
Minimum and Logical Maximum of 0 and 255 tell us that the bytes are unsigned, 
but that is typical for just passing things through the HID APIs. (A mouse 
would use signed values for the X and Y axes, for instance.)

>            Item(Local ): Usage, data= [ 0xa9 ] 169
>                            (null)
>            Item(Global): Logical Minimum, data= [ 0x00 ] 0
>            Item(Global): Logical Maximum, data= [ 0xff ] 255
>            Item(Global): Report Size, data= [ 0x08 ] 8
>            Item(Global): Report Count, data= [ 0x08 ] 8
>            Item(Main  ): Output, data= [ 0x02 ] 2
>                            Data Variable Absolute No_Wrap Linear
>                            Preferred_State No_Null_Position Non_Volatile 
> Bitfield
>            Item(Main  ): End Collection, data=none

This is the part that is being written to - 0xA9 is an 8-byte output field. As 
with the Input items earlier, the microcontroller is free to interpret these 
bytes in any way, so there might be fields within that.

>      Endpoint Descriptor:
>        bLength                 7
>        bDescriptorType         5
>        bEndpointAddress     0x81  EP 1 IN
>        bmAttributes            3
>          Transfer Type            Interrupt
>          Synch Type               None
>          Usage Type               Data
>        wMaxPacketSize     0x0008  1x 8 bytes
>        bInterval              10

Exact values usually don't matter here, but 8 bytes is a typical 
wMaxPacketSize, especially for lower-speed USB devices.

>       This is from the hid-example.c:
> 
> Report Descriptor:
> 6 a0 ff 9 a5 a1 1 9 a6 9 a7 15 0 25 ff 75 8 95 8 81 2 9 a9 15 0 25 ff 75 8 95 
> 8 91 2 c0
> 

I mistyped earlier:

> * Use libhid, which involves detaching the hiddev/hidraw driver from the 
> device. We do this all the time with PDC HID devices. It might take a little 
> more experimenting to find the libusb command to send.

should be "Use libusb..." - at one point, there was a libhid that used libusb, 
but part of that got absorbed into NUT.

I started modifying one of the drivers to do the reads, but it may not be of 
much use until we understand what needs to be written, as you mentioned here:

> but commenting-out the writing portion makes the data collection not work.



_______________________________________________
Nut-upsdev mailing list
Nut-upsdev@lists.alioth.debian.org
http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/nut-upsdev

Reply via email to