Charles Lepple
2017-Mar-19 22:49 UTC
[Nut-upsdev] [nut-upsuser] Copeland Engineering Dockmaster
On Mar 19, 2017, at 10:56 AM, Drew from Zhrodague <drewzhrodague at 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 BitfieldThis 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=noneThis 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 10Exact 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.
Charles Lepple
2017-Mar-20 13:42 UTC
[Nut-upsdev] [nut-upsuser] Copeland Engineering Dockmaster
Drew, Another thing to consider is the NUT driver documentation. This is the template, but since it originally predated the USB drivers, feel free to draw on the other man pages for inspiration: https://github.com/networkupstools/nut/blob/master/docs/man/skel.txt - Charles
Drew from Zhrodague
2017-Mar-20 14:18 UTC
[Nut-upsdev] [nut-upsuser] Copeland Engineering Dockmaster
On 3/20/17 9:42 AM, Charles Lepple wrote:> Drew, > > Another thing to consider is the NUT driver documentation. This is the template, but since it originally predated the USB drivers, feel free to draw on the other man pages for inspiration: > > https://github.com/networkupstools/nut/blob/master/docs/man/skel.txtThanks, Charles, I'll take a look at this tonite. I've been using a Windows program on my thin-client to monitor the traffic. Still wrapping my head around reports and features. -- Drew from Zhrodague drew at zhrodague.net "Yeah, yeah, yeah!" - Rob Zombie
Charles Lepple
2017-Apr-26 12:35 UTC
[Nut-upsdev] [nut-upsuser] Copeland Engineering Dockmaster
On Mar 19, 2017, at 6:49 PM, Charles Lepple wrote:> > 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.Drew, any updates on what to write? I would still like to try and find the sequence of bytes that we would write with libusb, but if that isn't feasible, we can try to build something around the hidraw API. -- Charles Lepple clepple at gmail