Reverse Engineering the Crivit Z31192 USB Pedometer to create Linux Support

Crivit Z31192 Pedometer

This is a simple dump of the thought processes, false trails and work done to get a Crivit USB Pedometer (Model Z31192) working with Linux. I'm dumping it here and linking search engines to it in case someone else gets one of these devices and searches the web for help.

After a week of work (of about 1 or 2 hours a day) I have got to the stage where I can dump the contents of the Pedometer in hex and make some sense of the data it is throwing out. At this point I started to write this blog so that others can pick up on it.

Day 1. July 13th 2012

Bought one of these gadgets from Lidl for the sum of £9.99. No mention on the packaging that the bundled software (Walknote) only works with Windows 2000, Vista and 7.

Waste several hours trying to find alternative software on WWW. Find nothing.

lsusb identifies the device thus ...

[mike@ceri ~]$ lsusb -vd C45:70c1

Bus 002 Device 014: ID 0c45:70c1 Microdia 
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               1.10
  bDeviceClass            0 (Defined at Interface level)
  bDeviceSubClass         0 
  bDeviceProtocol         0 
  bMaxPacketSize0         8
  idVendor           0x0c45 Microdia
  idProduct          0x70c1 
  bcdDevice            0.01
  iManufacturer           1 ----
  iProduct                2 USB Pedometer 
  iSerial                 0 
  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      27
         Report Descriptors: 
           ** UNAVAILABLE **
      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)
[mike@ceri ~]$ 

Day 2. July 14th 2012

Try to get the pedometer software Walknote working with wine. My version is 1.2.3, didn't work, so tried versions 1.4 and 1.4.1. Neither of these worked.

Day 3. July 15th 2012

Installed the Walknote software on a laptop running Windows Vista Home. It appears to work OK, and also seems to send basic configuration data - such as target number of steps, and step length; to the pedometer, so the device is programmable.
Although the software saves historical data, is doesn't seem possible to analyse the data without plugging in the pedometer. Why would that be ??

Day 4. July 16th 2012

Start to reverse engineer the pedometer. Install a USB Snoop program on the laptop that's running Windows Vista. Not knowing much about Windows, or USB, I end up with a 14 day free trial of HHD Software Device Monitoring Studio 6.41. Play around with various options and save copies of dumps which I print off. Can't make much sense of it.
Either there are extra packets containing data that the USB snoop program is not dumping, or the data being output is encrypted in some way. Can't see the point in encrypting the data, but maybe it is bit packed somehow. I need to perform more dumps, or just the written and read packets alongside each other to see what changes when data on the pedometer changes.

Day 5. July 17th 2012

Plugging the USB Pedometer into linux results in the following messages in the system log.

Jul 17 19:52:57 ceri kernel: [24644.558392] usb 2-7: new low-speed USB device number 14 using ohci_hcd
Jul 17 19:52:57 ceri kernel: [24644.749195] usb 2-7: New USB device found, idVendor=0c45, idProduct=70c1
Jul 17 19:52:57 ceri kernel: [24644.749207] usb 2-7: New USB device strings: Mfr=1, Product=2, SerialNumber=0
Jul 17 19:52:57 ceri kernel: [24644.749214] usb 2-7: Product: USB Pedometer
Jul 17 19:52:57 ceri kernel: [24644.749219] usb 2-7: Manufacturer: ----
Jul 17 19:52:57 ceri kernel: [24644.761365] generic-usb 0003:0C45:70C1.0005: hiddev0,hidraw0: USB HID v1.10 Device [---- USB Pedometer ] on usb-0000:00:02.0-7/input0

You will notice that the kernel loads a HID device driver for raw HID communication.

To use raw HID with linux from a normal user account, some extra udev rules are needed, to change the access rights, and also to set up a specific name "/dev/pedometer" we can access.
#
# Add a rule to allow read/write access to the Crivit Z31192 pedometer
#
SUBSYSTEMS=="usb", ACTION=="add", ATTRS{idVendor}=="0c45", ATTRS{idProduct}=="70c1", MODE="666", SYMLINK+="pedometer"
Alas, I couldn't get any info out of the pedometer, with a simple open() read() close() program.

Day 6. July 18th 2012

Investigate the various USB libraries and APIs' available to Linux. I'm running Fedora 16 and have both libusb and libusb-1 installed. Sort out some symlinks so that I use libusb-1 in preference to the older libusb.

Day 7. July 19th 2012

With information from the USB snoop program, write a libusb based C++ program to write identical packets dumped by the USB snoop program to the pedometer, and to collect the replies. That way, I know that there is no missing data in the dumps that the USB snoop program appears to omit. The C++ program can be found here.

Output from the program is here.
11 Devices in list.
Device Opened
Claimed Interface
Sending ...: 00 00 00 00 00 00 c8 02    Post read ...: 00 07 20 85 05 f4 c8 12
Sending ...: 00 00 00 00 00 00 01 02    Post read ...: 00 07 20 85 05 f4 01 12
Sending ...: 06 00 00 00 00 00 02 02    Post read ...: 39 24 01 10 51 00 02 12
Sending ...: 0c 00 00 00 00 00 03 02    Post read ...: 20 03 33 01 78 10 03 12
Sending ...: 12 00 00 00 00 00 04 02    Post read ...: 14 93 77 92 00 03 04 12
Sending ...: 18 00 00 00 00 00 05 02    Post read ...: 00 32 50 32 07 17 05 12
Sending ...: 1e 00 00 00 00 00 06 02    Post read ...: 46 01 84 90 40 75 06 12
Sending ...: 24 00 00 00 00 00 07 02    Post read ...: 99 28 00 03 60 03 07 12
Sending ...: 2a 00 00 00 00 00 08 02    Post read ...: 80 08 43 04 50 60 08 12
Sending ...: 30 00 00 00 00 00 09 02    Post read ...: 04 10 44 98 00 08 09 12
Sending ...: 36 00 00 00 00 00 0a 02    Post read ...: 00 03 80 03 82 02 0a 12
Sending ...: 3c 00 00 00 00 00 0b 02    Post read ...: 51 01 87 50 41 32 0b 12
Sending ...: 42 00 00 00 00 00 0c 02    Post read ...: 88 05 00 03 70 03 0c 12
Sending ...: 48 00 00 00 00 00 0d 02    Post read ...: 70 07 48 03 99 70 0d 12
Sending ...: 4e 00 00 00 00 00 0e 02    Post read ...: 84 30 18 58 00 07 0e 12
Sending ...: 54 00 00 00 00 00 0f 02    Post read ...: 00 01 30 01 57 00 0f 12
Sending ...: 5a 00 00 00 00 00 10 02    Post read ...: 47 00 25 70 05 72 10 12
Sending ...: 60 00 00 00 00 00 11 02    Post read ...: ff ff 00 00 40 00 11 12
Sending ...: 00 00 00 00 00 00 00 02    Post read ...: 00 07 20 85 05 f4 00 12
Sending ...: 01 00 00 00 00 00 c9 02    Post read ...: 00 00 07 20 85 05 c9 12
Sending ...: 00 00 07 20 85 05 01 03    Post read ...: 07 00 00 00 00 00 01 13
Sending ...: 04 00 00 00 00 00 c9 02    Post read ...: 01 10 51 00 00 07 c9 12
Sending ...: 01 10 51 00 00 07 01 03    Post read ...: 0a 00 00 00 00 00 01 13
Released Interface

Now, the good thing here is that I can recognise some of the values being returned. Although the dump is in HEX, the values in the dump are BCD. So for example The pedometer shows 3924 steps so far today. That number appears at the start of the third line down.
I'm not sure the replies are in fixed format though because we're supposed to get up to 99,999 steps a day, and the total number of steps so far for me is 37,792, and that appears in line 5.
I can also see the number of steps, kcal, km, for each of my historical days in this data dump.
I need to let the pedometer collect more data, and perform more dumps, to see if or how the data moves around in the dump before going further.

Somehow I have also managed to reprogram the pedometer with a new time of day. Not sure how, and no other data has changed in the Pedometer.

Day 8. July 20th 2012

Day of rest - or at least, walking to get more data.

Discover how I am resetting the time on the pedometer with the above program. It is all down to the last line.

01 10 51 00 00 07 01 03       sets the time to 11:05
01 94 51 00 00 07 01 03       sets the time to 19:45

Based on that, maybe the next 5 nibbles set the step target which is currently 10,000. Will investigate tomorrow.

Day 9. July 21st 2012

Yes, setting those 5 nibbles does alter the target step.

Also note that if you go into setup mode on the pedometer (using the buttons) and change the units from metric to imperial (or vice versa) then not only are the step length, weight and target wiped to default values, but all the recorded history is lost too.

Day 10. July 22nd 2012

It appears that just to update the pedometer with a new configuration it is only necessary to send the 1st and last 5 packets. I say "appears to" because I've managed to wipe the history the pedometer collected so I'm not sure now if just sending just these 6 packets did that, or if it was a programming error before.
Anyway, a new C++ program to program the pedometer with your weight, step length, step target, and correct time can be found here. Currently the values are hard-wired into the program.
Not sure if this is useful information or not, but the 01 10 51 after the 39 24 in the above dump represents the time the pedometer was last accessed via the USB. May be the time the configuration was written, or history read. Not sure yet. But it is a time field. When the pedometer is first plugged into the PC, the field reads zero, run the logger program, and on the 2nd and subsequent run it shows the time you previously ran the logger program. How mad it that ? What use is it ??

Set the project up on sourceforge.net

Day 11. July 23rd 2012

Wheee! Google now finds this sourceforge project, so anyone else out there scratching their heads can find the work I'm doing too.

I seem to be able to find most of the data in the dumps, but the "walking time" is completely fooling me. I can scribble out the data from the dump that corresponds to number of steps, distance and calories, but what is left doesn't seem to make much sense as a time. It doesn't appear to be minutes in BCD or binary. It may be held as seconds, then rounded to the nearest minute for display, but since I've lost all the accumulated data in the pedometer several times, I still need more data to be sure.

The 12/24hr clock setup choice is purely cosmetic. The time is sent to the pedometer in 24hr format, and the pedometer then displays a "P" alongside the time when it's pm.

Day 12. July 24th 2012

The pedometer will show the current day details, plus 7 further days of history, i.e. 8 days in total. The memory dump only appears to give the current day, plus 5 days of history, i.e. 6 days in total.
Also, as I am now tracking the history rippling through the memory dump each day, I can see that some BCD digits are not contiguous. Maybe this is why I cannot see the "walking time" at all. Also some of the "step" fields only appear to be 4 digits long. I need a day of at least 10,000 steps to see how this ripples through the dump each day.
Walk over 10,000 steps today, and I can confirm that the BCD numbers are not contiguous. A "1" has appeared where then was once a "0", I guess I need another 10,000 steps to see if that nibble changes to a "2". I'm getting fit if nothing else !!

Day 13. July 25th 2012

OK. Got this more or less sorted now. Finding all the data - including the "walking time". Just need a few more days of data to check I'm picking up all the data from the correct locations. And despite what I wrote yesterday, all 7 days worth of history are in the dump.

I should have a program that will dump the contents of the Crivit Z31192 USB pedometer in csv in a few days. It just needs testing with large numbers in the fields, and check the metric/imperial switching.

Day 14. July 26th 2012

Have a problem programming the pedometer with a weight. Until now I've been using my own weight of 72kg, but when I try to put in weight outside the 70's it just seems to program a weight of seventy something. If I program the pedometer to change mode to imperial, and send a new weight at the same time, it sort of works in that I can put in numbers outside the 70 range, but even then some numbers appear to be corrupted.
This is a little odd because I can re-program the step size OK, and the packets I'm writing appear to be exactly the same when compared to the packets Walknote writes.

Prepare to release a new version of the program. I can easily comment out the stuff dealing with weights, and it's not as if that sort of thing changes much. Once the weight and step size are in, and the user has chosen metric or imperial units, they are not likely to change, ever.

Day 15. July 27th 2012

Comment out the code dealing with weights and step lengths and release the code as version 0.0.2