Friday, November 27, 2015

USBProxy & CronusMax

A very long time with no update, but wanted to mention.

USBProxy (formerly usb-mitm) is working quite reliably for my needs. no soldering required. A little time to get everything set up on the BBB, and it can be a little finicky about power draw from the controler.

For someone who wants something even easier, take a look at the cronusmax (http://www.controllermax.com). It will let you use PS controllers on xboxes, XB360 controllers on XB1, as well as create macros. There is also a direct control api that you can use to send buttons from your computer directly.

Thursday, November 14, 2013

Update

My teensy based code succesfully connects maybe 1/4 to 1/3 of the time. Once it passes through the initial connection phase it is reliable. I believe it's some sort of timing issue with the USB host shield causing it to not respond to some requests. There are a few things that can be attempted to fix it.
  • do a little more setup before connecting the two sides (device & host). I can go ahead and set the configuration on the device (since controllers generally have just a single config). Also, the endpoint for HID reports, usually sends a few messages (with initial byte 0x01,0x02,0x03) before starting to send reports (which have initial byte 0x00). I can queue up those non report transmissions before starting to relay, and send those to the host without bothering the device.
  • reduce the polling time
But that is on the back burner for the moment. I'm currently working with Dominic Spill on usb-mitm. We're making an extensible framework for using the beaglebone black (although it would likely work on any system capable of using the linux gadgetfs framework) for USB sniffing relaying and injection. While the hardware is a bit more (about $45) than a Teensy 3, once you consider the 2 teensies, and the host shield, it's actually a bit cheaper. It includes the host and device ports, an ethernet port (as well as quite a bit more memory, storage, and muscle). And since it has everything you need, no soldering is needed.

We're hoping to have the basic functionality of our project done in a couple weeks. As a high level overview it connects a USB Device proxy to a USB Host proxy, and offers Injectors and Filters that modify the packets going from one side to the other.

some examples of a Device proxy:
  • connect to a physical device using libusb
  • a device emulated in software on the BBB
  • a device (emulated or real) tunneled over TCP/IP
some examples of a Host proxy:
  • connect to a physical host using gadgetfs (sort of like libusb but for talking to hosts rather than devices)
  • connect to a host emulated in software on the BBB
  • connect to a host (or multiple hosts) over TCP/IP
some examples of an Injector:
  • listen for packets over TCP/IP and send them to the device and/or host
  • replay packets from a log file
some examples of a Filter:
  • send all packets over TCP/IP (act as a USB sniffer)
  • modify the content of specific packets
  • drop specific packets
  • send packets over TCP/IP to a remote host which then decides whether to modify or drop them
The initial release will probably handle just include the physical device/host proxies, and the TCP/IP listener Injector, and the TCP/IP sniffer Filter.

Wednesday, September 25, 2013

Succcess

I have working code!
 It does seem to inexplicably fail the initialization stage about 50% of the time, but unplugging and replugging the controller a few times seems to resolve it, and once it gets past that it seems pretty reliable. Once I have all of the pieces together (waiting on a few orders), I'll take some pictures as I put together the final build (rather than the jumper wire monstrosity i have right now).

Hurray, I'm a moron!

An hour later I realize I'm a moron, and it's totally my fault it's not working.

As I said in my last post I had to add in code to the teensy usb library to handle OUT control transfers.
On a IN transfer, I can forward it on to the physical device as soon as I get it.
On an OUT transfer there is data to be sent as well as the request itself. So I have to wait for that data to arrive (in separate USB packets) before I send it on to the device.

Now for whatever reason, a control request with no data payload can be either IN or OUT. I'm not sure what the practical difference is, since there's no data besides the request, what does it matter whether it's IN or OUT? But anyway the 84 request that needs to immediately precede the 87 request is an OUT request with no data payload. As such, it was never receiving any additional data packets, so it was never getting forwarded to the physical device.

I'm now able to complete the security handshake, so I'm almost there!

Now it's just a matter of starting to poll the device for it's reports and pass them along to the Xbox.

The Return of Teensy - Software

The USB stack on the teensy is great if you are emulating one of the devices that are already set up: USB Serial, keyboard, mouse, joystick, etc. If you want to be able to emulate a totally random device a few changes are needed.

I may miss some details here, but these are the broad strokes.

The bulk of the low level USB stuff happens in two files: usb_dev.c (the actual interrupt loop and functions to handle and send requests) and usb_desc.c (the data structures and device descriptors).

A lot of the information the USB code uses is done through compiler defines. This obviously won't work if you don't even know what device will be plugged in at compile time.

I added a "USB_RAW" type, to define some of these basic values (very few of these will actually be used).

#if defined(USB_RAW)
  #define NUM_ENDPOINTS 6
  #define NUM_USB_BUFFERS 30
  #define VENDOR_ID 0x0000
  #define PRODUCT_ID 0x0000
  #define CONFIG_DESC_SIZE 9
  #define MANUFACTURER_NAME    {}
  #define MANUFACTURER_NAME_LEN    0
  #define PRODUCT_NAME        {}
  #define PRODUCT_NAME_LEN    0
  #define NUM_INTERFACE 0
  #define DEVICE_CLASS 0
  #define DEVICE_SUBCLASS 0
  #define DEVICE_PROTOCOL 0
#endif

EP0_SIZE (the maximum packet size on the control endpoint) was also set via a define, and needed to be changed to a variable, and then endpoint_config_table and list of descriptors (from usb_desc.h) needed to be changed from constants to something I could actually change, since they are populated at run time.

The host shield code basically pulls all of the descriptors from the device and uses them to populate the usb_descriptor_list structure (usb_dev.c searches this for a matching descriptor when a request comes in).  After that is complete, it sets an address, waits about 200ms for things to settle down, and then activates the USB connection on the Teensy. Whatever it's connected to starts sending requests and they are either handled directly by usb_dev.c or passed along through the host shield to the physical device.

A couple of stumbling blocks.

There seems to be some subtle difference between how the Xbox and a PC send a SET ADDRESS request to the device. The teensy uses two pair of buffers per endpoint, one to receive and one to transmit. These get toggled every time a non-setup packet is sent or received. Normally a 0 byte reply will be sent back after a setup request. For whatever reason, the Xbox causes the buffer the processor is expecting you to use, not to match up with what the program thinks it should be using. So sending this reply to the opposite buffer works for the Xbox, or putting the same reply in both buffers will work on both.

The existing USB device options on the Teensy don't have any need for control packets with a data payload being sent to the Teensy (OUT transfers, where in/out directions are relative to the USB host). It took a little while to figure out the correct initial state and proper toggling of the two flags (one for which buffer to use, and one for the USB DATA0/1 flag, which is basically just a 1 bit sequence number to help avoid dropped packets).

But now I'm up against another roadblock.
Normally the security handshake process looks like this (the numbers are the USB request types):

81: this sends 29 bytes of data (always the same on a given controller) to the Xbox

82: this sends a 34 byte security challenge to the controller
(wait 200ms)
86: this is a status check and 2 bytes (01-00) are sent to the xbox indicating it is not ready with the response
(wait 100ms)
86: this is a status check and 2 bytes (02-00) are sent to the xbox indicating it IS ready with the response (you might think the xbox would keep trying if a 1 is sent back again, but it will only try 2 times, then will reset the device and start over from the beginning)
83: a 46 byte security response is sent back to the Xbox

84: this seems to be an indicator that the 1st check was passed

87: this is another security challenge 22 bytes long
86: we have the same thing here as before, 2 of these requests
83: another security response, but only 22 bytes

87: this is another security challenge 22 bytes long, but this time the controller will send back a stall response

84: this seems to be an indicator that the 1st check was passed
87: this is another security challenge 22 bytes long
86: we have the same thing here as before, 2 of these requests
83: another security response, but only 22 bytes

And we're done.

The problem here lies in the fact that the controller will respond to that 1st 87 command properly if attached to the PC (using the facedancer to communicate to the Xbox) but will not on the Teensy. I'm not sure what exactly causes it. But what seems to be happening is the 87 request will stall if it isn't preceded by the 84 request. And the Xbox will only allow the stall if it did not send the 84 request. I'll need to verify that the 84 request is actually making it through the host shield to the controller.

Saturday, September 7, 2013

The Return of Teensy - Hardware

After asking some question on the Teensy forums (the creator is very responsive and helpful in getting hardware and software details), I decided to give the Teensy3s another go. They support all 16 endpoints, and also can use a USB Host Shield which would allow me to remove the middleman as it were, and have the physical controller hooked right to the teensy.

So right now I have 2 Teensy 3s. One is really just a glorified USB Serial adapter, so you could use a teensy2 or try to find an adapter which supports the 3.3v signaling levels on the Teensy UART. They are wired together on their 1st serial ports. The 2nd one is the brains of the operation, it is hooked up to the host shield and to the xbox, and is responsible for relaying all communication between the xbox and the controller as well as anything added over the serial port.

A word on power:
The controller requests the maximum possible (~500ma). The teensy internally runs on 3.3v, but normally converts this from the 5v it gets on the USB connector. You can power the host shield from that same 5v source as the teensy, or even off of the 3.3v the teensy provides. Byt many devices, especially HID ones won't work on that amount of power. So to play it safe I'm powering it via an external power source. As an added bonus this means the teensy can be up and running and lay all the needed groundwork before connecting to the xbox. Out of the box, the teensies are intended to get power over USB. To avoid damaging them there is a jumper which can be cut with an xacto knife, so it will no longer draw power from the USB connector, only your external source. Simlarly the host shield normally shares its own power source (3.3v) with the attached devices. There is another jumper which can be cut on here to separate the two, allowing 5v to be provided to the USB.

Preparation:
Teensy(Pinout): I cut the jumper in the second picture. You want to cut in between the two small solder pads to the left of the USB jack as you look from the bottom. Test with a multimeter. Once disconnected I was getting something like 20Mohm.
Host Shield(Pinout): I soldered on some pin headers to make my life easier but this is by no means required. I cut the VBUS jumper (closer to the middle) and ran a wire from the VBUS pad to the RAW pin. This pin is not in use, and is more convenient to access than using the pad directly.

Connections:
Power: check your power jack and verify which pin is + and which is ground. On mine the center was + and edge was ground. I wired mine to a 3 pin fan extension cable (1 is not used), so i could disconnect it from the box easily and to make sure i didn't swap my polarity. The ground connect to the ground on each teensy and both grounds on the Host Shield. The + connects to Vin on each teensy, and to the RAW pin I wired earlier on the shield.
Teensy<->Teensy: We only need two wires here, TX1 connects to RX1, and RX1 to TX1. If you were connecting a usb serial adapter directly to the teensy (after making sure it was 3.3v) you would just connect it directly to RX1,TX1, and ground).
Teensy<->Shield: there are 6 pins that need to be connected here (other than the ground and 5v power already done).
  1. 3.3v Power: you can connect this to either 3.3v pin on the teensy, you won't be hitting 100ma with the separate power for the USB, and that one has a pin already there (assuming you got the Teensy3 with header pins already installed, which I did, because I'm lazy and it was $3 more).
  2. Reset: this is the reset signal, it needs to receive voltage to NOT reset. You can just connect this to the same 3.3v pin on the Teensy as you did for the power. I connected it to pin 2 on the Teensy, so that I could reset the host shield from the Teensy if needed.
  3. SS: this is the slave select signal for the SPI bus that the host shield uses for communication with the Teensy. Wire this to CS0(10) on the Teensy.
  4. MOSI: This is Master Out Slave In, this connects to DOUT(11) on the teensy.
  5. MISO: This is Master In Slave Out, this connects to DIN(12) on the teensy.
  6. SCK: This is the clock signal for SPI, and connects to SCK(13) on the teensy.

Other: the teensy has plenty of pins left, so you could wire up one or more LEDs, for status, identification, or whatever you want.

Components:
(2) Teensy3 $22
Project Box (5x2.5x2) $5.49
USB Host Shield $20.00
1ft 90 degree right hand USB Micro cable (to xbox) $4.99
6ft 90 degree left hand USB Micro cable (to computer)$6.98
1ft 90 degree USB cable (to controller) $6.49
5cmx7cm prototyping board $9.99 for 5
DC Power Jack $8.95
5v DC power supply $5.74
3 pin fan extension cable $3.64
Total $108-$116 depending on whether you need the other 4 prototype boards.


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".