Tuesday, August 6, 2013

Facedancer

At this point my motivation was a bit lower, since I had a mostly working solution.
But there was an option I had run across in my searches, the Facedancer.

This performs a function very similar to the 2 Teensy setup used with Salamax, but all in one package and with more flexibility in some ways (can support host mode) and less in others (limited number of USB endpoints). Basically it presents itself to your computer as a USB serial port, and then you can read and write data that will go out the other end and seem like a hardware device to whatever it is connected to.

I didn't feel like doing surface mount soldering, so I passed on it initially, but eventually they found a partner to make and distribute fully assembled boards.  So I went ahead and ordered one.

The original PC based code for it is in Python, not my 1st language, so I decided to port it to .Net (and the port is available on the repository under the /contrib/facedancer section).

What I was essentially trying to do, once I got the basics working, was set up a passthrough device, that would pass all the traffic the facedancer received to a physical device also connected to the computer. Using the LibUSBDotNet library I was able to pass on whatever packets the facedancer got to the real device, and read back their responses.

I found two great references that I used during this process to learn about the USB protocol:
USB in a NutShell
USB Made Simple

Eventually I was able to get to a point where I could emulate a keyboard, and finally the 360 controller. I could then also inject additional HID report packets to simulate button presses.

However there were two limitations to this approach:
The facedancer is not suited (although it may be possible to improve this) to low latency or high speed communication. There is an interval of about 100ms between each packet it sends out, which means you are looking at latency of up to 100ms, which is not so great for a controller.
The USB chip it is based on  (the Max3421E) has a limited number of endpoints, besides the control endpoint (0) it has 1 endpoint which can only receive data from the host (1) and 2 which can only send data from the host (2,3). The full usb spec allows up to 16 total endpoints (including 0), which can both send and receive. So if the device you are passing traffic through for has more endpoints than this, you won't be able to capture them all. In the case of the controllers this isn't too much of an issue, as there is only 1 endpoint in each direction that matters for button presses, although there are others that are used for audio, etc. if there is a headset connected. It did require that I map the facedancer endpoints to the correct device endpoints in my translation code.

One additional note, although I didn't get to this point, the facedancer is quite long (about 2 7/8").
If you want to fit it in a 5" long project box, a standard mini usb cable will probably need about 2" of clearance or more if you don't want to bend it too sharply and potentially damage it, that would need about a 7" box. If you are able to pass it straight out through a hole in the box, you will still probably need about 1 1/4", which puts it at about 5 1/2". If you want a plug on your project box rather than running the cables out, I was able to find a mini USB to a standard size type A with a right angle connector here but then you end up needing Male/Male USB cables, which are not something you are likely to have lying around. Unfortunately I wasn't able to find a panel mount jack that combined a female type B connector (which is more "correct") and a right angled mini USB jack.
You can get right angle mini usb cables, that need about 5/8" clearance on each end for a total of 4 1/8".

No comments:

Post a Comment