Re: [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@gmail ___ Nut-upsdev mailing list Nut-upsdev@lists.alioth.debian.org http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/nut-upsdev
Re: [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.txt Thanks, 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 d...@zhrodague.net "Yeah, yeah, yeah!" - Rob Zombie ___ Nut-upsdev mailing list Nut-upsdev@lists.alioth.debian.org http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/nut-upsdev
Re: [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 ___ Nut-upsdev mailing list Nut-upsdev@lists.alioth.debian.org http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/nut-upsdev
Re: [Nut-upsdev] [nut-upsuser] Copeland Engineering Dockmaster
On Mar 19, 2017, at 10:56 AM, Drew from Zhrodaguewrote: > > [] 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 >bmAttributes3 > Transfer TypeInterrupt > 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
Re: [Nut-upsdev] [nut-upsuser] Copeland Engineering Dockmaster
On 3/11/17 9:15 AM, Charles Lepple wrote: [moved to nut-upsdev while we figure out the protocol] On Mar 9, 2017, at 11:22 AM, Drew from Zhrodaguewrote: I'm able to cat /dev/usb/hiddev0 and /dev/hidraw0 - I pipe this through hexdump and I get different types of data from each: I was trying to reconcile this with your earlier information from usbhid-dump, and it looks like hexdump is swapping bytes: Couple of updates: [] 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. [] 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. [] 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 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 Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x81 EP 1 IN bmAttributes3 Transfer TypeInterrupt Synch Type None Usage Type Data wMaxPacketSize 0x0008 1x 8 bytes bInterval 10 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 welcome any advice or assistance - ideally I'd like to use a proper UPS software, rather than my own egregious use of bash. Thanks! -- Drew from Zhrodague d...@zhrodague.net ___ Nut-upsdev mailing list Nut-upsdev@lists.alioth.debian.org http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/nut-upsdev
Re: [Nut-upsdev] [nut-upsuser] Copeland Engineering Dockmaster
[moved to nut-upsdev while we figure out the protocol] > On Mar 9, 2017, at 11:22 AM, Drew from Zhrodague >wrote: > > I'm able to cat /dev/usb/hiddev0 and /dev/hidraw0 - I pipe this through > hexdump and I get different types of data from each: > > > hiddev: > > 0002420 00a7 ffa0 00ff 00a7 ffa0 00ff > 0002430 00a7 ffa0 00a3 00a7 ffa0 0001 > 0002440 00a6 ffa0 0080 00a7 ffa0 0011 > 0002450 00a7 ffa0 00bd 00a7 ffa0 0057 > 0002460 00a7 ffa0 00ff 00a7 ffa0 00ff > 0002470 00a7 ffa0 00a3 00a7 ffa0 0001 > > > hidraw: > > 000 1180 59e1 01a3 1180 59e2 01a3 > 010 1180 5ae3 01a3 1180 5ae4 01a3 > 020 1180 5ae5 01a3 1180 5ae6 01a3 > 030 1180 5ae7 01a3 1180 5ae8 01a3 > 040 1180 5ae9 01a3 1180 5aea 01a3 > 050 1180 5aeb 01a3 1180 5aec 01a3 I was trying to reconcile this with your earlier information from usbhid-dump, and it looks like hexdump is swapping bytes: $ printf 12345678|hexdump 000 3231 3433 3635 3837 008 You can do one of the following to get the natural order, plus an ASCII dump: $ printf 12345678|hexdump -C 31 32 33 34 35 36 37 38 |12345678| 0008 $ printf 12345678|hd 31 32 33 34 35 36 37 38 |12345678| 0008 > I haven't been able to figure out what the differences between hiddev > and hidraw are, but the first one has the state (0001), and the second one > has the timers (59e2). It also looks like there are two sentences per line. > > I have put together a bash script to fetch a few lines from the hiddev, > and look for a key/value - sometimes what I'm using as a key changes between > boots. It may not be a key/value pair. Here's the kernel documentation: https://www.kernel.org/doc/Documentation/hid/hiddev.txt https://www.kernel.org/doc/Documentation/hid/hidraw.txt In both cases, "cat" is triggering the "read()" operation in each driver. > In its basic mode, the hiddev will make these individual > usage changes available to the reader using a struct hiddev_event: > >struct hiddev_event { >unsigned hid; >signed int value; >}; I think the "hid" value in the hiddev output is one of "ffa000a6" or "ffa000a7", but byte-swapped (still i686, right?) and hexdump-swapped to "00a6 ffa0" and "00a7 ffa0". The next four bytes are the zero-padded version of each byte that shows up in the hidraw output. I'm not sure what the difference between the ...a6 and ...a7 parts are -- the HID Report Descriptor is not well-formed. It does look like the a6 part comes right before the 80, which seems to be at the beginning of the message. For hidraw, it looks like we could just read 8 bytes at once, and be done. >> If you are interested in taking a look at related code, these two drivers >> are probably good starting points: >> >> * >> https://github.com/networkupstools/nut/blob/libusb-1.0/drivers/nutdrv_atcl_usb.c >> >> * >> https://github.com/networkupstools/nut/blob/libusb-1.0/drivers/richcomm_usb.c I mention these two drivers because, as I recall, they are also for non-PDC HID devices. For portability, NUT tends to use libusb rather than the Linux-specific hiddev/hidraw APIs. We have a few options: * Use hidraw, which is only available on Linux, but is known to work with this device. This would require a bit of autoconf plumbing in order to prevent other platforms from building the new driver. * Use HIDAPI, a portability library written by Alan Ott (author of the hidraw.txt kernel documentation). Adds another dependency that we haven't used yet. * 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. NUT developers: anyone else want to weigh in here? I'm leaning towards the third option, but I'm open to suggestions. ___ Nut-upsdev mailing list Nut-upsdev@lists.alioth.debian.org http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/nut-upsdev