User Tools

Site Tools


tutorials:learn:diykinect:index.html

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
tutorials:learn:diykinect:index.html [2010/11/16 22:02]
daigo
tutorials:learn:diykinect:index.html [2016/01/28 18:05] (current)
Line 1: Line 1:
-==== Introduction! ​ ==== +[[http://learn.adafruit.com/​hacking-the-kinect|This ​tutorial ​has moved to http://learn.adafruit.com/​hacking-the-kinect]]
- +
- +
-Everyone has seen the [[http://www.adafruit.com/​blog/​2010/​11/​10/​we-have-a-winner-open-kinect-drivers-released-winner-will-use-3k-for-more-hacking-plus-an-additional-2k-goes-to-the-eff/|Xbox 360 Kinect hacked in a matter of days after our "open source driver"​ bounty]] - here's how we helped the winner and here's how you can reverse engineer USB devices as well!  +
- +
- +
- +
-USB is a very complex protocol, must more complicated than Serial or Parallel, SPI and even I2C. USB uses only two wires but they are not used as '​receive'​ and '​transmit'​ like serial. Rather, data is bidirectional and differential - that is the data sent depends on the //​difference //in voltage between the two data lines **D+** and **D-** If you want to do more USB hacking, you'll need to read [[http://​lvr.com/​usbc.htm| Jan Axelson'​s USB Complete books]], they'​re easy to follow and discuss USB in both depth and breadth. +
- +
- +
- +
-USB is also very structured. This is good for reverse engineering because it means that at least the format of packets is agreed upon and you won't have to deal with checksums. The bad news is it imeans you have to have software assistance to decode the complex packet structure. The good news is that every computer now made has a USB host core, that does a lot of the tough work for you, and there are many software libraries to assist. +
- +
- +
- +
-Today we're going to be reverse engineering the Xbox Kinect Motor, one part of the Kinect device.  +
- +
-{{  http://​www.ladyada.net/​images/​diykinect/​kinect.jpg?​nolink&​550x275  ​|}} +
- +
- +
-==== Verify the  VID & PID  ==== +
- +
- +
-The first place to start is to see what devices and "​interfaces"​ or "​configurations"​ are available for the USB device. The nicest way to do this is to use **lsusb** (linux) or **system_profiler** (Mac) which is a "list usb" program available for linux and mac. Sadly, it does not exist for windows, so find a mac or linux computer or friend, you'll only need it for a minute!  +
- +
- +
- +
-For linux, run **lsusb -vv** (ultra verbose) for Mac, run **system_profiler SPUSBDataType** +
- +
-{{  http://​www.ladyada.net/​images/​diykinect/​system_profiler.jpg?​nolink&​527x700 ​ |}} +
- +
-There'​s a bunch more stuff like USB keys and such installed but this is a good starting point. Note that the Kinect is actually 4 USB devices - a hub, a camera, a microphone (audio) and a motor. The hub is just an easy way for the device to combine three seperate chips into a single cable. We'll be investigating the **Xbox NUI Motor** since its the simplest. Note the **Vendor ID = 0x045e** and **Product ID = 0x2b0. **Every type USB device must have a unique VID and PID. The VID is the manufacturer. In this case, **0x045e** is the VID for Microsoft. All Microsoft products will have that VID. Each product has a different PID, so all Kinect Motors use PID **0x02b0** this doesn'​t differe between two Kinects, they'​ll both have the same PID. The VID/PID are used as a way to have the proper driver find the product. Its a lot better than serial COM ports because COM ports change names but VID/PID are burned into the device firmware. +
- +
-  +
- +
- +
-==== Determine the Descriptors ​ ==== +
- +
- +
-The next best thing to do after you've determined the VID/PID is to identify the **descriptor** of the device. A descriptor is a sort of '​menu'​ of what the device can do and how it likes to transfer data. In general, each device has one descriptor.//​ Sometimes// a device has more than one descriptor and you can choose which one you want but its not terribly common so we're just going to ignore it.A fantastic way to get the descriptor without having to write any software is to run **lsusb -vv **on a linux computer. We haven'​t found an equivalent for Windows or Mac, so find a friend with a linux computer. +
- +
- +
- +
-Here is the output of **lsusb** for the NUI Motor +
- +
-<code C>Device Descriptor:​ +
-  bLength ​               18 +
-  bDescriptorType ​        1 +
-  bcdUSB ​              ​2.00 +
-  bDeviceClass ​           0 (Defined at Interface level) +
-  bDeviceSubClass ​        0 +
-  bDeviceProtocol ​        0 +
-  bMaxPacketSize0 ​       64 +
-  idVendor ​          ​0x045e Microsoft Corp. +
-  idProduct ​         0x02b0 +
-  bcdDevice ​           1.05 +
-  iManufacturer ​          1 Microsoft +
-  iProduct ​               2 Xbox NUI Motor +
-  iSerial ​                0 +
-  bNumConfigurations ​     1 +
-  Configuration Descriptor:​ +
-    bLength ​                9 +
-    bDescriptorType ​        2 +
-    wTotalLength ​          18 +
-    bNumInterfaces ​         1 +
-    bConfigurationValue ​    1 +
-    iConfiguration ​         0 +
-    bmAttributes ​        ​0xc0 +
-      Self Powered +
-    MaxPower ​             100mA +
-    Interface Descriptor:​ +
-      bLength ​                9 +
-      bDescriptorType ​        4 +
-      bInterfaceNumber ​       0 +
-      bAlternateSetting ​      0 +
-      bNumEndpoints ​          0 +
-      bInterfaceClass ​      255 Vendor Specific Class +
-      bInterfaceSubClass ​     0 +
-      bInterfaceProtocol ​     0 +
-      iInterface ​             0 +
-Device Status: ​    ​0x0000 +
-  (Bus Powered)</​code>​ +
- +
-Let's see what we've got. You can see the VID and PID up there. Next we'll look at **bNumConfigurations** (how many different descriptors we have) and lucky for us the number is **1. **Next, look at the **Interface Descriptor** in particular, **bNumEndpoints** which is 0. This means there are no Endpoints.  +
- +
- +
- +
-Endpoints are a type of USB 'data pipe' - there are 4 kinds: ​    +
- +
- +
-  ***Bulk **Endpoints are for transferring a lot of data, like a disk drive. It's ok if it takes a little longer but we want big packets. This endpoint goes only in one direction (so to read and write you'd want two) +
-  ***Interrupt** Endpoints are for transferring tiny amounts of data very quickly, like for a USB mouse. In this case, the device ​has to be responsive so we want fast movement. This endpoint goes only in one direction +
-  ***Isochronous **Endpoints are for transferring a fair amount of data where the data must show up at the same time and if it can't it should just be dropped. This is for stuff like Audio and Video where timing is key. This endpoint goes only in one direction (so bidirectional audio for headphone and mic would have two EPs) +
-  ***Control Endpoints** are this weird not-quite-an-Endpoint Endpoint. They are used to transfer small amounts of data to say turn a device on or off. They'​re very '​cheap'​ to develop, and every device has one even if its not mentioned. +
- +
- +
- +
-For example, a serial port may have two Interrupt endpoints for tranferring data in and out and then a control endpoint for setting the baud rate. </​li>​For more details we really do suggest reading everything at **lvr.com** about USB as its a complex. +
- +
- +
- +
-This motor device has no Endpoints, but that doesn'​t mean you can't communicate with it. It just means it only uses a bidirectional Control Endpoint. This isn't surprising, motors are slow and don't require a lot of data to control. +
- +
- +
- +
-Contrast this to the Video/​Camera device: +
- +
-<code C>Device Descriptor:​ +
-  bLength ​               18 +
-  bDescriptorType ​        1 +
-  bcdUSB ​              ​2.00 +
-  bDeviceClass ​           0 (Defined at Interface level) +
-  bDeviceSubClass ​        0 +
-  bDeviceProtocol ​        0 +
-  bMaxPacketSize0 ​       64 +
-  idVendor ​          ​0x045e Microsoft Corp. +
-  idProduct ​         0x02ae +
-  bcdDevice ​           1.0b +
-  iManufacturer ​          2 Microsoft +
-  iProduct ​               1 Xbox NUI Camera +
-  iSerial ​                3 A00366A08793039A +
-  bNumConfigurations ​     1 +
-  Configuration Descriptor:​ +
-    bLength ​                9 +
-    bDescriptorType ​        2 +
-    wTotalLength ​          32 +
-    bNumInterfaces ​         1 +
-    bConfigurationValue ​    1 +
-    iConfiguration ​         0 +
-    bmAttributes ​        ​0xc0 +
-      Self Powered +
-    MaxPower ​              ​16mA +
-    Interface Descriptor:​ +
-      bLength ​                9 +
-      bDescriptorType ​        4 +
-      bInterfaceNumber ​       0 +
-      bAlternateSetting ​      0 +
-      bNumEndpoints ​          2 +
-      bInterfaceClass ​      255 Vendor Specific Class +
-      bInterfaceSubClass ​   255 Vendor Specific Subclass +
-      bInterfaceProtocol ​   255 Vendor Specific Protocol +
-      iInterface ​             0 +
-      Endpoint Descriptor:​ +
-        bLength ​                7 +
-        bDescriptorType ​        5 +
-        bEndpointAddress ​    ​0x81 ​ EP 1 IN +
-        bmAttributes ​           1 +
-          Transfer Type            Isochronous +
-          Synch Type               ​None +
-          Usage Type               ​Data +
-        wMaxPacketSize ​    ​0x0bc0 ​ 2x 960 bytes +
-        bInterval ​              1 +
-      Endpoint Descriptor:​ +
-        bLength ​                7 +
-        bDescriptorType ​        5 +
-        bEndpointAddress ​    ​0x82 ​ EP 2 IN +
-        bmAttributes ​           1 +
-          Transfer Type            Isochronous +
-          Synch Type               ​None +
-          Usage Type               ​Data +
-        wMaxPacketSize ​    ​0x0bc0 ​ 2x 960 bytes +
-        bInterval ​              1 +
-Device Qualifier (for other device speed): +
-  bLength ​               10 +
-  bDescriptorType ​        6 +
-  bcdUSB ​              ​2.00 +
-  bDeviceClass ​           0 (Defined at Interface level) +
-  bDeviceSubClass ​        0 +
-  bDeviceProtocol ​        0 +
-  bMaxPacketSize0 ​       64 +
-  bNumConfigurations ​     1 +
-Device Status: ​    ​0x0001 +
-  Self Powered +
-  </​code>​ +
- +
-  +
- +
- +
- +
-This device has two Isochronous endpoints **both** of which are **IN **type (data going **IN**to the computer). This makes sense: the Kinect has a IR depth camera and a normal VGA camera. Two cameras, two Endpoints. Of course, there is also a Control endpoint not mentioned here, the Control endpoint could be used to set stuff like aperture, gamma correction, any sort of built-in filter, etc. +
- +
- +
-==== Driver-maker ​ ==== +
- +
- +
-OK so back to our motor. We are ready to start sending data to it via the Control endpoint. For Mac and Linux type computers, a driver isn't necessary to send or receive data directly via USB.  +
- +
- +
- +
-For windows, however, there must be some sort of driver to '​grab'​ the device for us. Usually drivers are complex and have like, interfaces that plug into the operating system. Like the cameras would show up as a camera device, the microphones as an audio device. We're not quite ready for a detailed driver, what we'll do is make a 'shell driver'​ which has no operating system capabilities but does let us send commands to it from software.  +
- +
- +
- +
-Again, Mac/Linux people have this built into the OS kernel so skip this part if you don't use windows. +
- +
- +
- +
-For our shell, we'll use **libusb** a USB library, which is available for windows as **[[http://sourceforge.net/​projects/​libusb-win32/​|libusb-win32]]** go there and download it. +
- +
- +
- +
-We'll run the **inf-wizard** (which will make our driver shell) +
- +
-{{  http://​www.ladyada.net/​images/​diykinect/​libusbinfwiz.gif?​nolink&​619x278 ​ |}} +
- +
-The important part is entering in the matching VID and PID we found before +
- +
-{{  http://​www.ladyada.net/​images/​diykinect/​infdeets.gif?​nolink&​471x357 ​ |}} +
- +
-{{  http://​www.ladyada.net/​images/​diykinect/​infgenerated.gif?​nolink&​471x357 ​ |}} +
- +
-Now when you plug in the Kinect, it will attach itself the the LibUSB-win32 device driver +
- +
-{{  http://​www.ladyada.net/​images/​diykinect/​motordevice.gif?​nolink&​357x496 ​ |}} +
- +
- +
- +
-We didnt make matching drivers for the audio or camera so those are still driverless. +
- +
- +
-==== Installing Python & PyUSB  ==== +
- +
- +
-Now we need to start sending commands to this USB device! The fastest and easiest way we know to do this is to use LibUSB with a scripting language such as Python. There are LibUSB bindings for C and C++ and Perl but I happen to like Python so follow along! +
- +
- +
- +
-[[http://​www.python.org/​download/​|If you don't have python installed, do that now.]] +
- +
- +
- +
-Next up, [[http://​sourceforge.net/​projects/​pyusb/​|install PyUSB]] by downloading it and running **python setup.py install** in the expanded directory +
- +
-{{  http://​www.ladyada.net/​images/​diykinect/​pyusbinstall.gif?​nolink&​669x698 ​ |}} +
- +
- +
-==== Attaching to the device ​ ==== +
- +
- +
-Lets go with the first simple example program which will just attach itself to the device in question +
- +
- +
-<code C># some example code from pyusb, +
-# otherwise its all public domain. enjoy & keep hackin! - ladyada +
- +
-import usb.core +
-import usb.util +
-import sys +
- +
-# find our device +
-dev = usb.core.find(idVendor=0x045e,​ idProduct=0x02B0) +
- +
-# was it found? +
-if dev is None: +
-    raise ValueError('​Device not found'​) +
- +
-# set the active configuration. With no arguments, the first +
-# configuration will be the active one +
-dev.set_configuration() +
- +
-print "all done"​ +
-</​code>​Note that we're looking for that same VID/PID we found originally. We're not sending any data around, yetVerifythat when the device is not plugged in you get an error{{ http://​www.ladyada.net/​images/​diykinect/​notfound.gif?​nolink&​669x158 |}}and if it is plugged in, there is no error{{ http://​www.ladyada.net/​images/​diykinect/​alldone.gif?​nolink&​669x158 |}}  +
-==== What messages to send?  ==== +
- +
- +
-Now we can use Python + LibUSB to send Control Endpoint packets with the command  +
- +
- +
- +
-**ctrl_transfer****( bmRequestType,​ bmRequest, wValue, wIndex, nBytes)** +
- +
- +
- +
-This command can do both sending and receiving depending on what **bmRequestType ** says (input or output). Still, there is a lot of options here. To send the right command you need to know the **RequestType** and the right **Request** and ther right **Value** as well as the **Index** and how many bytes to read or write. +
- +
-If we were totally on our own, we would start by trying to read data from the device. This means we have to set the **RequestType** first +
- +
- +
-^Direction^Type^ ^ ^ ^Recipient^ +
-^**D7**^|**D6**|**D5**|**D4**|**D3**|**D2**|**D1**|**D0**| +
-  +
- +
- +
- +
-For **bmRequestType** the value passed is very structured so thats not as hard to guess. ([[http://​www.beyondlogic.org/​usbnutshell/​usb6.shtml|See lvr.com for more information]]) +
- +
- +
-  *Bits 2, 3 and 4 are reserves so set them to 0.  +
-  *The direction is set by bit #7, 0 is a '​write'​ out to the device, 1 is a '​read'​ from the device +
-  *The '​type'​ of message is two bits, 0 = Standard, 1 = Class, 2 = Vendor, 3 = Reserved. For many devices that are non-standard,​ you'll probably want 2 for vendor type. If its a more standard type of device, like a camera or mic, try 0 or 1. 3 Is unused +
-  *The last two bits are usd to determine the recipient for the message 0 = Device, 1 = Interface, 2 = Endpoin,t 3 = Other. Go with 0 to start, you can try 2 if there are other endpoints +
- +
-The safest thing to do is read data (no way to overwrite anything or configure) you can do that by sending packets with **0b11000000** (Read Vendor data from Device) = 0xC0.  +
- +
- +
- +
-If I were to write a fuzzer, I'd start by setting **Index **to 0 and iterating through all the byte values (255 different values) of **bmRequest** and the first few hundred **wValues**. Its pretty safe to just read random data to a USB device. Start by reading one byte to see if anything shows up, then increase the value +
- +
-<code C>import usb.core +
-import usb.util +
-import sys +
- +
-# find our device +
-dev = usb.core.find(idVendor=0x045e,​ idProduct=0x02B0) +
- +
-# was it found? +
-if dev is None: +
-    raise ValueError('​Device not found'​) +
- +
-# set the active configuration. With no arguments, the first +
-# configuration will be the active one +
-dev.set_configuration() +
- +
-# Let's fuzz around!  +
- +
-# Lets start by Reading 1 byte from the Device using different Requests +
-# bRequest is a byte so there are 255 different values +
-for bRequest in range(255):​ +
-    try: +
-        ret = dev.ctrl_transfer(0xC0,​ bRequest, 0, 0, 1) +
-        print "​bRequest ",​bRequest +
-        print ret +
-    except: +
-        # failed to get data for this request +
-        pass +
-</​code>​ +
- +
-  +
- +
-{{  http://​www.ladyada.net/​images/​diykinect/​brequestiter.gif?​nolink&​605x295 ​ |}} +
- +
-Looks like** Request **values 0, 5, 16, 50, 54, 64, 80 and 112 all return some sort of data. The rest had nothing to read +
- +
- +
- +
-Next we'll try to read more data by changing the last argument to 100 bytes +
- +
-{{  http://​www.ladyada.net/​images/​diykinect/​brequest100.gif?​nolink&​669x278 ​ |}} +
- +
-OK lots of data, but what does it mean? This is where some guessing based on the device itself would come in handy. I'm terribly lazy though and if given an option to avoid a lot of guesswork, I'll take it! +
- +
- +
-==== USB Analyzer ​ ==== +
- +
- +
-Reverse-engineering the Kinect is a little easier since we have a known-working system (Xbox 360). Instead of guessing commands, we can just see what commands the Xbox sends and '​replay them'​ +
- +
-[[http://​www.ladyada.net/​images/​diykinect/​beagle.jpg|{{ ​ http://​www.ladyada.net/​images/​diykinect/​beagle_t.jpg?​nolink&​500x301 ​ |}}]] +
- +
- +
- +
-This requires being able to listen into those commands, however. With protocols such as SPI, Serial, Parallel and i2c, you can listen in with any logic analyzer or oscilloscope. USB is fast/​complex enough to require its own kind of logic analyzer. The one we'll be using is called the[[http://​www.totalphase.com/​products/​beagle_usb480/​| Beagle480 from TotalPhase.]] This is the 'high speed' USB analyzer, which we splurged on. (For many devices, Low/Full speed is fast enough, and there'​s a lower cost analyzer available.) +
- +
- +
- +
-The USB analyzer acts as a '​tap'​ that plugs in between the Xbox and the Kinect. A computer is conneted as well. The computer receives all the data being transmitted into memory and logs it. +
- +
-[[http://​www.ladyada.net/​images/​diykinect/​beagleend.jpg|{{ ​ http://​www.ladyada.net/​images/​diykinect/​beagleend_t.jpg?​nolink&​500x204 ​ |}}]] +
- +
-From left to right there is a **DIN **connector,​** USB A** connector and **USB B** connector. The Xbox connects to the USB B and the Kinect connects to the USB A. The DIN connector is for other kinds of data sniffing (like SPI or i2c) +
- +
-[[http://​www.ladyada.net/​images/​diykinect/​beagleend2.jpg|{{ ​ http://​www.ladyada.net/​images/​diykinect/​beagleend2_t.jpg?​nolink&​500x221 ​ |}}]] +
- +
-On the other side, a single B connector which goes to the listening computer +
- +
-The best way we've found to get the right data is to make sure to get even the '​enumeration'​ (initialization) packets so plug in the listening computer and start up the software. Then plug in the other end to the devices you want to sniff. +
- +
-{{  http://​www.ladyada.net/​images/​diykinect/​saving.jpg?​nolink&​500x374 ​ |}} +
- +
- +
-==== Lookin'​ at logs  ==== +
- +
- +
-Since you probably don't have a USB analyzer, we have some logs that you can use to follow along with us. [[https://​github.com/​adafruit/​Kinect/​tree/​master/​USBlogs/​|Visit the GitHub repository and click the **Downloads** button]] +
- +
- +
- +
-[[http://​www.totalphase.com/products/​beagle_usb480/​|Make yourself a sandwich, its a big file!]] +
- +
- +
- +
-[[http://​www.totalphase.com/​products/​beagle_usb480/​|Also download the Beagle Data Center software (Mac/​Win/​Linux)]] and install it +
- +
- +
- +
-OK now that you've eaten, lets open up the **enuminit**.tdc file. This is the full enumeration and initialization.  +
- +
- +
- +
-{{ http://​www.ladyada.net/​images/​diykinect/​startscreen.gif?​nolink&​1458x813 |}} +
- +
- +
- +
-Remember that when we log the data, there'​s **a lot** of it that we can then pare down! +
- +
- +
- +
-Let start by remembering that there are **four devices** (hub, camera, mic, motor) but we only need to listen to one (motor). Click on the **Bus **tab on the lower right +
- +
-{{  http://​www.ladyada.net/​images/​diykinect/​businfo.gif?​nolink&​422x728 ​ |}} +
- +
-We have a few devices. Lets explore each one +
- +
-If you click on **Unconfigured device (0) **you'​ll see that it was not captured. This is probably because I jiggled the cable when inserting it so it started to create a device and then got disconnected. Its not important +
- +
-{{  http://​www.ladyada.net/​images/​diykinect/​dev0.gif?​nolink&​424x322 ​ |}} +
- +
-Click on **<​none>​ (1)** This device is a **Class** device type USB Hub. That's the internal hub. We can ignore this as well +
- +
-{{  http://​www.ladyada.net/​images/​diykinect/​hub.gif?​nolink&​422x496 ​ |}} +
- +
-Device #4 has a PID of 688, that's in decimal. If we convert it to hex we get **0x02b0** ​this is the Motor device! +
- +
-{{  http://​www.ladyada.net/​images/​diykinect/​pid688.gif?​nolink&​425x506 ​ |}} +
- +
-Now we can filter so that only this device'​s logs are shown \\  +
- +
-{{  http://​www.ladyada.net/​images/​diykinect/​filter.gif?​nolink&​421x257 ​ |}} +
- +
-Our log screen is much shorter now +
- +
-{{ http://​www.ladyada.net/​images/​diykinect/​control4.gif?​nolink&​1132x588 |}} +
- +
-You can see that there'​s some initialization and thn just two repeating motifs: a 1 byte message alternated with a 10 byte message. +
- +
-For the motor to move according to the xbox's wishes, there must be some command sent from the xbox to the kinect. Lets filter some more to see just commands sent **to **the device +
- +
-{{  http://​www.ladyada.net/​images/​diykinect/​filtering.gif?​nolink&​421x765 ​ |}} +
- +
-Go to the LiveFilter and select Host-to-Device +
- +
-{{  http://​www.ladyada.net/​images/​diykinect/​commands.gif?​nolink&​843x150 ​ |}} +
- +
-Now we've really pared it down. There are only **four **commands sent to the kinect ​motor, since the motor moves during initialization we can just try each one. Lets look at each command +
- +
-Command 1 has a **bRequest** of 0x06 and a **wValue** of 4, the **wLength **is 0 which means no data is written, the entire command is the **Request** and **Value** +
- +
-{{  http://​www.ladyada.net/​images/​diykinect/​command1.gif?​nolink&​424x413 ​ |}} +
- +
-Command #2 uses the same **bRequest** but with a different **wValue** of 0x01 +
- +
-{{  http://​www.ladyada.net/​images/​diykinect/​command2.gif?​nolink&​414x420 ​ |}} +
- +
-Command #3 is a different **bRequest** of 0x31 and a **wValue** of 0xffd0 +
- +
-{{  http://​www.ladyada.net/​images/​diykinect/​command3.gif?​nolink&​415x420 ​ |}} +
- +
-Command #4 is the same  **bRequest** ​ and a **wValue** of 0xfff0 +
- +
-{{  http://​www.ladyada.net/​images/​diykinect/​command4.gif?​nolink&​415x423 ​ |}} +
- +
-Now we've determined there are two request commands we can send. One is 0x06 and the other is 0x31  +
- +
-Time to experiment! +
- +
- +
-==== Command #1 & 2 - LED blinky! ​ ==== +
- +
- +
-We'll edit our python code to just send command #1 and see what happens. From our logs we know that for sending commands from host-to-device,​ we should use **bRequestType** of 0x40 (verify this by looking at the **bmRequestType** bits of the command packets), **wIndex** and **wLength** of zero +
- +
- +
- +
-For command #1, set **bRequest** to 0x06 and a **wValue** to 4. The final argument is now an empty array [to indicate no data is transmitted +
- +
- +
-<code C> +
-import usb.core +
-import usb.util +
-import sys +
- +
-# find our device +
-dev = usb.core.find(idVendor=0x045e,​ idProduct=0x02B0) +
- +
-# was it found? +
-if dev is None: +
-    raise ValueError('​Device not found'​) +
- +
-# set the active configuration. With no arguments, the first +
-# configuration will be the active one +
-dev.set_configuration() +
- +
-ret = dev.ctrl_transfer(0x40,​ 0x6, 0x1, 0, []+
-print ret +
-</​code>​We ran our python code and...nothing happened! +
- +
-OK well maybe that was some initialization command. Lets replace it with the next command #2, set **bRequest** to 0x06 and a **wValue** to 1 +
- +
-**ret = dev.ctrl_transfer(0x40,​ 0x6, 0x1, 0, [])** +
- +
-We ran this command and the motor didn't move but the LED stopped blinking.  +
- +
-For fun we ran the previous command again and the LED started blinking again. +
- +
-Now we have an idea: maybe this **bRequest** 0x6 controls the LED?  +
- +
-On your own, continue this line of thought by trying different **wValue**s from 0 on up to see what other **wValues** do, keep track of them all in a notebook or project file. +
- +
- +
-==== Command #3 & 4 - Let's move!  ==== +
- +
- +
-Having conquered one of the commands, we'll now tackle the other one. Try to replicate command #3, set **bRequest** to 0x31 and a **wValue** to 0xffd0 (also known as -48 for a 2-byte word) +
- +
-**ret = dev.ctrl_transfer(0x40,​ 0x32, 0xffd0, 0, [])** +
- +
- +
- +
-Running the python script made the motor move its '​head'​ down. +
- +
- +
- +
-Now try command #4, 0xfff0 (also known as -16 for a 2-byte word) +
- +
-**ret = dev.ctrl_transfer(0x40,​ 0x32, 0xfff0, 0, [])** +
- +
-This makes the head move up. Now we have both the motor and LED under our control! +
- +
-<object type="​application/​x-shockwave-flash"​ width="​400"​ height="​225"​ data="​http://​www.flickr.com/​apps/​video/​stewart.swf?​v=71377"​ classid="​clsid:​D27CDB6E-AE6D-11cf-96B8-444553540000"> ​   </​object>​ +
- +
- +
-==== Bonus accelerometer! ​ ==== +
/home/ladyada/public_html/wiki/data/attic/tutorials/learn/diykinect/index.html.1289944929.txt.gz · Last modified: 2016/01/28 18:05 (external edit)