Luckily reverse engineering funky binary protocols is one of my specialities, so, let's see …
Data seems to arrive in 8-byte packets always. Indeed, this appears to be a property of what they did with the HID spec (more on that in a moment). The timing between 8-byte packets is irregular. In each packet there seem to be two groups of 4 byte each. The second byte of each group is always the same.
Getting more data by re-starting the Windows software makes things more confusing: The second byte of each group is still constant, but different now. It's numerically close though, so, time-based? This sucks.
Maybe I can learn something more from the USB HID device descriptor… (Intermission music playing while I google how to get the HID descriptor under Linux)
# echo 1-1.2:1.0 > /sys/bus/usb/drivers/usbhid/unbind
# lsusb -vd 04d9:a052
Bus 001 Device 014: ID 04d9:a052 Holtek Semiconductor, Inc.
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 1.10
bDeviceClass 0 (Defined at Interface level)
bDeviceSubClass 0
bDeviceProtocol 0
bMaxPacketSize0 8
idVendor 0x04d9 Holtek Semiconductor, Inc.
idProduct 0xa052
bcdDevice 1.00
iManufacturer 1 Holtek
iProduct 2 USB-zyTemp
iSerial 3 1.40
bNumConfigurations 1
Configuration Descriptor:
bLength 9
bDescriptorType 2
wTotalLength 34
bNumInterfaces 1
bConfigurationValue 1
iConfiguration 0
bmAttributes 0x80
(Bus Powered)
MaxPower 100mA
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 0
bAlternateSetting 0
bNumEndpoints 1
bInterfaceClass 3 Human Interface Device
bInterfaceSubClass 0 No Subclass
bInterfaceProtocol 0 None
iInterface 0
HID Device Descriptor:
bLength 9
bDescriptorType 33
bcdHID 1.10
bCountryCode 0 Not supported
bNumDescriptors 1
bDescriptorType 34 Report
wDescriptorLength 53
Report Descriptor: (length is 53)
Item(Global): Usage Page, data= [ 0x00 0xff ] 65280
(null)
Item(Local ): Usage, data= [ 0x01 ] 1
(null)
Item(Main ): Collection, data= [ 0x01 ] 1
Application
Item(Global): Logical Minimum, data= [ 0x00 ] 0
Item(Global): Logical Maximum, data= [ 0xff 0x00 ] 255
Item(Local ): Usage Minimum, data= [ 0x00 ] 0
(null)
Item(Local ): Usage Maximum, data= [ 0xff ] 255
(null)
Item(Global): Report Count, data= [ 0x08 ] 8
Item(Global): Report Size, data= [ 0x08 ] 8
Item(Main ): Feature, data= [ 0x02 ] 2
Data Variable Absolute No_Wrap Linear
Preferred_State No_Null_Position Non_Volatile Bitfield
Item(Global): Logical Minimum, data= [ 0x00 ] 0
Item(Global): Logical Maximum, data= [ 0xff 0x00 ] 255
Item(Local ): Usage Minimum, data= [ 0x00 ] 0
(null)
Item(Local ): Usage Maximum, data= [ 0xff ] 255
(null)
Item(Global): Report Count, data= [ 0x08 ] 8
Item(Global): Report Size, data= [ 0x08 ] 8
Item(Main ): Input, data= [ 0x02 ] 2
Data Variable Absolute No_Wrap Linear
Preferred_State No_Null_Position Non_Volatile Bitfield
Item(Global): Logical Minimum, data= [ 0x00 ] 0
Item(Global): Logical Maximum, data= [ 0xff 0x00 ] 255
Item(Local ): Usage Minimum, data= [ 0x00 ] 0
(null)
Item(Local ): Usage Maximum, data= [ 0xff ] 255
(null)
Item(Global): Report Count, data= [ 0x08 ] 8
Item(Global): Report Size, 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
bmAttributes 3
Transfer Type Interrupt
Synch Type None
Usage Type Data
wMaxPacketSize 0x0008 1x 8 bytes
bInterval 10
Device Status: 0x0000
(Bus Powered)
Now, that's just patently unhelpful. All it says is that there's report types that contain 8 items of values 0 through 255 each. In other words: 8 bytes. Yeah, I could have guessed that.Okay, maybe looking more closely what the Windows software does will help me:
# modprobe usbmon
# wireshark -i usbmon1will let me record (on the VM host) what the software does (in the VM guest) when started. And at least that's mildly enlightening:
which is an outgoing HID SET_REPORT with 8 bytes of data, after which the device starts sending reports of 8 bytes of data using INTERRUPT IN:

These 8-byte packets are then what I was seeing in the output of /dev/hidrawX.
Repeating different captures shows: The SET_REPORT generated by the windows software is different each time (though the DF byte at the end is constant). Also note that the device won't send anything before receiving this packet, so in order to gather data for analyzing on my Linux box I have to use the Windows software at least once after plugging the device in.
Henryk Plötz
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.
Personally, I would go a more hardware-centric route for reverse engineering. If you check out that Russian link, there are two ICs that look sort of interesting. There's the big one, no datasheet available online, from my very brief searching. It'll be the brains. Then there's a small IC right near the USB port. It's very likely that that's just a bridge.
On the end of that bridge chip (pins 3 & 4), there are two lines that look like they might be going to the big IC. If you tap those with a logic analyser or BusPirate or similar, I would bet that it's an I2C, SPI, UART signal, something similar. And it will be a lot easier to decode the protocol there instead of dealing with USB junk, too.
That would be my strategy, anyway.
Are you sure? yes | no