I have some old Playstation 1 controllers that I'd like to use on my OUYA gaming console. Using them on the PC works via an PSX-to-USB adapter.
Plugging them into the OUYA unfortunately did not work; they were not detected as controllers - or at all, as it seemed. A Microsoft Sidewinder DualStrike did also not work.
USB device detection
Linux PC
Attaching the PSX adapter with controllers to a PC shows the following lsusb output:
ID 0810:0001 Personal Communication Systems, Inc. Dual PSX Adaptor
dmesg shows:
usb 2-1.2: new low-speed USB device number 120 using ehci-pci usb 2-1.2: New USB device found, idVendor=0810, idProduct=0001 usb 2-1.2: New USB device strings: Mfr=0, Product=2, SerialNumber=0 usb 2-1.2: Product: Twin USB Joystick input: Twin USB Joystick as /devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1.2/2-1.2:1.0/input/input1460 input: Twin USB Joystick as /devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1.2/2-1.2:1.0/input/input1461 pantherlord 0003:0810:0001.05AC: input,hidraw2: USB HID v1.10 Joystick [Twin USB Joystick] on usb-0000:00:1d.7-1.2/input0 pantherlord 0003:0810:0001.05AC: Force feedback for PantherLord/GreenAsia devices by Anssi Hannula <anssi.hannula@gmail.com>
Input device files in /dev/input/ get created for both joysticks; /dev/input/js0 and /dev/input/js1.
I can then use jstest or jstest-gtk to test the controllers and see all the buttons and axes working.
OUYA
Using adb to open a shell on the OUYA gives the following dmesg output:
[ 331.002934] usb 2-1: new low speed USB device number 13 using tegra-ehci <6>[ 331.039183] usb 2-1: New USB device found, idVendor=0810, idProduct=0001 <6>[ 331.046013] usb 2-1: New USB device strings: Mfr=0, Product=2, SerialNumber=0 <6>[ 331.053437] usb 2-1: Product: Twin USB Joystick]]>
That was all. Nothing more - no more dmesg output, no input files in /dev/.
What now?
On the internet, many people used apps like usb/bt joystick center or tincore keymapper. The first has been removed from the google play store (I did not find an explanation why; the author did not respond to my e-mail), the second is still available.
But I did not want to use any of these tools. I can't look into them and do not know what they do. There just had to be a way to make it work properly.
Linux drivers
After some detours, I had the idea that Linux drivers could be missing.
The PC's dmesg output gave a hint which ones were used:
pantherlord 0003:0810:0001.05AC: input,hidraw2: USB HID v1.10 Joystick
The keywords are pantherlord, input and hidraw2.
input is a standard kernel module that is always enabled; otherwise no mouse/keyboard/joystick/touchpad would work.
pantherlord turned out to be the driver for the PSX adapter. The kernel sources tell us in drivers/hid/Kconfig:
config HID_PANTHERLORD tristate "Pantherlord/GreenAsia game controller" depends on USB_HID ---help--- Say Y here if you have a PantherLord/GreenAsia based game controller or adapter.
There is also a HIDRAW driver, which supports
HID devices (from the USB specification standpoint) that aren't strictly user interface devices
OUYA kernel configuration
One can access the current kernel configuration at /proc/config.gz by copying from the OUYA:
$ adb pull /proc/config.gz $ zless config.gz
And there I saw it:
# CONFIG_HIDRAW is not set # CONFIG_HID_PANTHERLORD is not set # CONFIG_HID_MICROSOFT is not set
The OUYA's Linux kernel had been built without support for my game controllers.
A custom OUYA linux kernel
So it turned out that the only way to get my arcade joystick and gamepad working was to compile support for them into the kernel.
While HID_PANTHERLORD could be compiled as a module (tristate in the Kconfig files), HIDRAW could not - I had to re-build the whole kernel, and not only compile & copy a single module.
The internet contained a single, but very helpful OUYA kernel compilation howto: Builing your own Ouya Kernel by Leonardo Pires, written mid of 2014. The original announcement of this HowTo seems to be Recompilando Kernel do OUYA - Por Leonardo Pires which links to a HowTo on Google Drive. The XDA forum post seems to be a low-quality and translated version of it.
I had to adjust it to the current OUYA firmware version and fix some errors in it. Here is the updated one that worked 2015-06-02:
Preparation
You have to enable ADB via the OUYA System / Debugging menu.
For the last step you have to be connected via USB to the device; uploading the kernel via network does not work.
Create a udev rules file for the OUYA so that you are able to communicate with the device over USB. Put the following into /etc/udev/rules.d/051-android.rules:
# ouya SUBSYSTEM=="usb", ATTRS{idVendor}=="2836", MODE="0666" # fastboot ouya SUBSYSTEM=="usb", ATTRS{idVendor}=="0955", MODE="0666"
Install the Android debug bridge (adb) and make it recognize the OUYA as Android device:
$ sudo apt-get install android-tools-adb $ echo "0x2836" >> ~/.android/adb_usb.ini $ adb kill-server $ adb devices List of devices attached 012d3a4efac56789 device
In your home directory, create a directory ouya-kernel:
$ cd $ mkdir ouya-kernel $ cd ouya-kernel
Ramdisk
Flashing the OUYA with a new kernel requires a ramdisk file, and we can get it from the current firmware. At the time of writing this was 1.2.1427-r1.
$ wget http://devs-ouya-tv-prod.s3.amazonaws.com/ota/RC-OUYA-1.2.1427-r1_ota.zip $ unzip RC-OUYA-1.2.1427-r1_ota.zip boot.img $ wget http://www.enck.org/tools/split_bootimg_pl.txt -O split_bootimg.pl $ perl split_bootimg.pl boot.img $ gunzip boot.img-ramdisk.gz $ mv boot.img-ramdisk ramdisk
split_bootimg.pl's homepage is http://www.enck.org/tools.html#split_bootimg.
Android NDK
We have to cross-compile the kernel for the ARM platform; and the NDK contains the correct tools for that.
android-ndk-r10e did not work for me; I got a unknown CPU architecture error during kernel compilation. android-ndk-r9d did work:
$ wget https://dl.google.com/android/ndk/android-ndk-r9d-linux-x86_64.tar.bz2 $ tar xjvf android-ndk-r9d-linux-x86_64.tar.bz2
OUYA kernel + configuration
OUYA's kernel is on github, and we fetch it from there:
$ git clone git@github.com:ouya/ouya_1_1-kernel.git
Now we have to fetch the OUYA's kernel configuration file, which can be found at /proc/config.gz:
$ adb pull /proc/config.gz $ gunzip -kc config.gz > ouya_1_1-kernel/.config
Now adjust the kernel configuration file in ouya_1_1-kernel/.config:
CONFIG_HIDRAW=y CONFIG_HID_MICROSOFT=y CONFIG_HID_PANTHERLORD=y
The kernel can be compiled now:
$ export CROSS_COMPILE=/home/cweiske/ouya-kernel/android-ndk-r9d/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86_64/bin/arm-linux-androideabi- $ export ARCH=arm $ cd ouya_1_1-kernel $ make .. wait an hour .. $ cp arch/arm/boot/zImage ../
Installing the kernel
Install the fastboot command:
$ apt-get install android-tools-fastboot $ adb reboot-bootloader $ fastboot devices -l 012d3a4efac56789 fastboot usb:2-1.2
If fastboot gives you a no permissions warning, make sure that /etc/udev/rules.d/51-android.rules contains settings for vendor 0955 - the USB IDs change when rebooting into bootloader mode!
Now it's time to install the new kernel:
$ fastboot flash:raw boot ./zImage ./ramdisk creating boot image... creating boot image - 5742592 bytes sending 'boot' (5608 KB)... OKAY [ 1.125s] writing 'boot'... OKAY [ 1.854s] finished. total time: 2.980s $ fastboot reboot
If all went well, the OUYA boots up with the fresh kernel.
Success!
dmesg on the OUYA shows us that the joysticks are recognized now:
$ adb shell $ su $ dmesg <6>[ 113.056632] usb 2-1: new low speed USB device number 2 using tegra-ehci <6>[ 113.104851] usb 2-1: New USB device found, idVendor=0810, idProduct=0001 <6>[ 113.116743] usb 2-1: New USB device strings: Mfr=0, Product=2, SerialNumber=0 <6>[ 113.124579] usb 2-1: Product: Twin USB Joystick <6>[ 113.145452] input: Twin USB Joystick as /devices/platform/tegra-ehci.2/usb2/2-1/2-1:1.0/input/input1 <6>[ 113.156314] input: Twin USB Joystick as /devices/platform/tegra-ehci.2/usb2/2-1/2-1:1.0/input/input2 <6>[ 113.167024] pantherlord 0003:0810:0001.0001: input,hidraw0: USB HID v1.10 Joystick [Twin USB Joystick] on usb-tegra-ehci.2-1/input0 <6>[ 113.179213] pantherlord 0003:0810:0001.0001: Force feedback for PantherLord/GreenAsia devices by Anssi Hannula <anssi.hannula@gmail.com>
Input mapping
The Playstation controllers did not work immediately. The axes (up/down, left/right) did work, but the keys did not. I had to provide my own key layout file for the joysticks.
Creating it was easy; I installed the KeyTest Android application (link is dead) which could be downloaded as pre-compiled .apk file (archived version).
Then I clicked all the buttons on the OUYA controller and wrote down the scan codes. Afterwards, I wrote down the scan codes of the Playstation controllers.
The resulting key layout file has to get the name Vendor_0810_Product_0001.kl.
# PSX controller mapping # Dual PSX Adaptor / Twin USB Joystick # idVendor=0810, idProduct=0001 # Linux HID_PANTHERLORD driver # X cross key 290 BUTTON_A # O circle key 289 BUTTON_B # [] square key 291 BUTTON_X # /\ triangle key 288 BUTTON_Y key 294 BUTTON_L1 key 292 BUTTON_L2 key 295 BUTTON_R1 key 293 BUTTON_R2 key 296 BUTTON_SELECT key 297 BUTTON_START key 298 BUTTON_THUMBL key 299 BUTTON_THUMBR axis 0x00 X axis 0x01 Y axis 0x02 HAT_X axis 0x03 HAT_Y axis 0x04 RZ axis 0x05 Z
Push it onto your OUYA into /system/usr/keylayout/:
$ adb push Vendor_0810_Product_0001.kl /sdcard/ $ adb shell $ su $ mount -o remount,rw /system $ mv /sdcard/Vendor_0810_Product_0001.kl /system/usr/keylayout/
Now unplug and replug the USB controller - and it works!