We're going to go back and revisit the mysterious Read command 0x32 that we fuzzed with for a bit. Its also in the logs, be sure to set your filter to show both Host-to-Device and Device-to-Host since its a 'read' not a 'write'
We were pretty close with our commands, it looks like we should be reading only 10 bytes. It also looks like the data doesn't really change much except for a bit further down…

The 7'th byte changes a lot right after we send it that bRequest 0x31 (motor movement). That implies that this data read is somehow affected by the motor, possibly a motor feedback byte?

Checking out a tear-down of the device (from iFixit) we see that there is an 'inclinometer'/accelerometer (Kionix KXSD9). The datasheet indicates it is used for image stabilization, and it has 3 axes (X Y and Z) with 10 bits of data per axis.

Lets continuously read that data

import usb.core
import usb.util
import sys
import time
 
# find our device
dev = usb.core.find(idVendor=0x045e, idProduct=0x02B0)
 
# was it found?
if dev is None:
    raise ValueError('Device not found')
 
dev.set_configuration()
 
while True:
    # Get data from brequest 0x32
    ret = dev.ctrl_transfer(0xC0, 0x32, 0x0, 0x0, 10)
    print map(hex, ret)

Shaking the Kinect while running the script you'll see clearly that the data changes with movement.

To identify the accelerometer axes, rotate it only one way at a time and note what changes. You can also see how this data is in bytes but the accelerometer data should be a signed word because there are flips from 0xfff7 to 0x0007 which would indicate a negative to positive conversion.

We can cast two bytes to a signed value by 'hand' (in C this is a little easier, we know)
import usb.core
import usb.util
import sys
import time
 
# find our device
dev = usb.core.find(idVendor=0x045e, idProduct=0x02B0)
 
# was it found?
if dev is None:
    raise ValueError('Device not found')
 
dev.set_configuration()
 
while True:
    # Get data from brequest 0x32
    ret = dev.ctrl_transfer(0xC0, 0x32, 0x0, 0x0, 10)
    #print map(hex, ret)
 
    x = (ret[2] << 8) | ret[3]
    x = (x + 2 ** 15) % 2**16 - 2**15     # convert to signed 16b
    y = (ret[4] << 8) | ret[5]
    y = (y + 2 ** 15) % 2**16 - 2**15     # convert to signed 16b
    z = (ret[6] << 8) | ret[7]
    z = (z + 2 ** 15) % 2**16 - 2**15     # convert to signed 16b
 
    print x, "\t", y, "\t", z
Now when you run the script you'll see the signed data appear properly.

This guide was first published on Jul 29, 2012. It was last updated on Jun 13, 2012.

This page (Bonus Accelerometer!) was last updated on Jun 13, 2012.

Text editor powered by tinymce.