RetroPie in an LXC/LXD container - problem with USB gamepad
-
Hi, I'm running RetroPie in an unprivileged Linux Container (LXC/LXD) on an Arch Linux host and I've got everything set up and running great except for my gamepad. The strange thing is that the gamepad works in EmulationStation, Retroarch, and jstest, but when I launch a game, it doesn't work in the game.
Basic overview of my setup is a USB Gamepad connected to an Arch Linux host running Ubuntu 18.04 in an unprivileged LXC container. USB portion of LXC container config is here and I am able to run through the input configuration in EmulationStation:
devices: js: gid: "104" mode: "0666" source: /dev/input/js0 type: unix-char uid: "0" jsevent: gid: "104" mode: "0666" source: /dev/input/event19 type: unix-char uid: "0"
I am able to load games and run with no issue launching in EmulationStation using the gamepad, but when the game actually starts, the controller doesn't respond. In Retroarch, to get the gamepad working I changed the input driver type to "linux raw" but it only works in the Retroarch interface and not in any games.
I feel like there must be a setting I can change, but I haven't been able to figure out or find a solution. Or maybe there's a better way to maps the device from the host to the container. I realize that this is not an officially supported method of running RetroPie, but I'm hoping someone might be able to help. If I install Retroarch/EmulationStation directly on the host or in a VM, everything works.
Here's my es_input.cfg after configuring the Gamepad:
<?xml version="1.0"?> <inputList> <inputAction type="onfinish"> <command>/opt/retropie/supplementary/emulationstation/scripts/inputconfiguration.sh</command> </inputAction> <inputConfig type="joystick" deviceName="USB Gamepad " deviceGUID="03000000790000001100000010010000"> <input name="pageup" type="button" id="4" value="1"/> <input name="start" type="button" id="9" value="1"/> <input name="down" type="axis" id="1" value="1"/> <input name="pagedown" type="button" id="5" value="1"/> <input name="right" type="axis" id="0" value="1"/> <input name="select" type="button" id="8" value="1"/> <input name="left" type="axis" id="0" value="-1"/> <input name="up" type="axis" id="1" value="-1"/> <input name="a" type="button" id="1" value="1"/> <input name="b" type="button" id="2" value="1"/> <input name="x" type="button" id="0" value="1"/> <input name="y" type="button" id="3" value="1"/> </inputConfig> </inputList>
Here's a Pastebin of a verbose runcommand.log file
Versions:
-Linux jax 5.0.7-arch1-1-ARCH #1 SMP PREEMPT Mon Apr 8 10:37:08 UTC 2019 x86_64 GNU/Linux
-LXC/LXD version 3.12
-RetroPie 4.4.11 -
The RetroArch log last error is about Audio, I don't think it even reaches the point of trying to initialize an input driver. Does audio work in your container ?
-
@mitu The audio does work, although in this container I have not set it up yet. I had it working in a previous version of the container, so I know it does work. I mostly followed this guide for getting the GUI and sound working. For passing the USB device to the container, I based it on Stephane Graber's example with various tweaks.
-
@mitu I changed the way I'm passing USB devices to the container to simply pass all USB devices using:
# lxc config device add retropie allusb usb mode=666
This should be simpler and passes all USB devices to the container.
Now in /dev/ I have:
retropie@retropie:/dev/bus/usb/001$ ls -la total 0 drwxr-xr-x 2 root root 140 Apr 12 12:48 . drwxr-xr-x 4 root root 80 Apr 12 12:44 .. crw-rw-rw- 1 root root 189, 0 Apr 12 12:56 001 crw-rw-rw- 1 root root 189, 1 Apr 12 12:56 002 crw-rw-rw- 1 root root 189, 2 Apr 12 12:56 003 crw-rw-rw- 1 root root 189, 3 Apr 12 12:56 004 crw-rw-rw- 1 root root 189, 18 Apr 12 12:56 019
Device 019 is the gamepad. The other devices are my USB keyboard, mouse, and root hubs.
Also:
retropie@retropie:/dev/input$ ls -la total 0 drwxr-xr-x 2 root root 60 Apr 12 12:44 . drwxr-xr-x 12 root root 560 Apr 12 12:48 .. crw-rw-rw- 1 root root 13, 0 Apr 12 12:44 js0
When I launch retroarch and set the joypad driver to hid, I now get a message that "USB Gamepad detected in Port #3", but the controller doesn't work. I'm not sure why it says Port #3. Here's some output from retroarch:
[ERROR] Interface not found (USB3.0 Hub ) (VID/PID: 2109:0812). [ERROR] Interface not found (xHCI Host Controller) (VID/PID: 1d6b:0003). [ERROR] Interface not found (Das Keyboard) (VID/PID: 24f0:0140). [INFO] Interface found: [USB Gamepad ]. [INFO] Device 0x0x56425dd23050 attached (VID/PID: 0079:0011). [INFO] [Autoconf]: 26 profiles found. [INFO] [autoconf]: selected configuration: /home/retropie/.config/retroarch/autoconfig/hid/Generic_NES_USB_Controller.cfg [ERROR] Interface not found (SteelSeries Rival 100 Gaming Mouse) (VID/PID: 1038:1702). [ERROR] Interface not found (USB2.0 Hub ) (VID/PID: 2109:2812). [ERROR] Interface not found (xHCI Host Controller) (VID/PID: 1d6b:0002). [ERROR] Interface not found (USB3.0 Hub ) (VID/PID: 2109:0812). [ERROR] Interface not found (xHCI Host Controller) (VID/PID: 1d6b:0003). [ERROR] Interface not found (Das Keyboard) (VID/PID: 24f0:0140). [INFO] Interface found: [USB Gamepad ]. [ERROR] Error claiming interface 0 . [ERROR] Interface not found (SteelSeries Rival 100 Gaming Mouse) (VID/PID: 1038:1702). [ERROR] Interface not found (USB2.0 Hub ) (VID/PID: 2109:2812). [ERROR] Interface not found (xHCI Host Controller) (VID/PID: 1d6b:0002). [INFO] Found HID driver: "libusb". [INFO] [Joypad]: Found joypad driver: "hid". [INFO] [Font]: Using font rendering backend: stb. [INFO] [X11]: Suspending screensaver (X11, xdg-screensaver). sh: 1: xdg-screensaver: not found [WARN] Could not suspend screen saver. [INFO] [Video]: Found display server: x11 [ERROR] Failed to initialize audio driver. Will continue without audio. [INFO] [Menu]: Found menu display driver: "gl". [INFO] [Font]: Using font rendering backend: stb. [INFO] [Font]: Using font rendering backend: stb.
The controller is not seen at all in EmulationStation, but does work in jstest :
retropie@retropie:/dev/input$ jstest /dev/input/js0 Driver version is 2.1.0. Joystick (USB Gamepad ) has 2 axes (X, Y) and 10 buttons (Trigger, ThumbBtn, ThumbBtn2, TopBtn, TopBtn2, PinkieBtn, BaseBtn, BaseBtn2, BaseBtn3, BaseBtn4). Testing ... (interrupt to exit) Axes: 0: 32767 1:-32767 Buttons: 0:on 1:on 2:on 3:on 4:off 5:off 6:off 7:off 8:off 9:off
-
SUCCESS!!!!
I was able to get everything working. So now I have a full Retropie system running in an unprivileged LXD container on an Arch Linux host. This configuration should allow anyone to run RetroPie on a modern kernel. Here's a summary of the steps that I took:
- On host system, install LXD. Version I used was 3.12. I created an unprivileged container, which means that the root user in the container does not have root privileges on the host. This increases security. Good references for understanding and setting up LXD/LXC can be found here and here.
- Follow this guide to configure an LXC profile that you can use to run graphics and sound inside of a container.
- On the host system, you will need to find out what devices your joystick creates and pass them through to the container. This was the part that had me stumped. On my system I had to pass through 2 devices to the container. Here's what my LXD configuration looks like
architecture: x86_64 config: image.architecture: amd64 image.description: ubuntu 18.04 LTS amd64 (release) (20190402) image.label: release image.os: ubuntu image.release: bionic image.serial: "20190402" image.version: "18.04" security.privileged: "false" volatile.base_image: 663f6663aed66a22dd708c4b07514748221522b810008c55002fcc1dd81af377 volatile.eth0.hwaddr: 00:16:3e:1c:a6:62 volatile.idmap.base: "0" volatile.idmap.current: '[{"Isuid":true,"Isgid":false,"Hostid":100000,"Nsid":0,"Maprange":1000},{"Isuid":true,"Isgid":true,"Hostid":1000,"Nsid":1000,"Maprange":1},{"Isuid":true,"Isgid":false,"Hostid":101001,"Nsid":1001,"Maprange":64535},{"Isuid":false,"Isgid":true,"Hostid":100000,"Nsid":0,"Maprange":1000},{"Isuid":true,"Isgid":true,"Hostid":1000,"Nsid":1000,"Maprange":1},{"Isuid":false,"Isgid":true,"Hostid":101001,"Nsid":1001,"Maprange":64535}]' volatile.idmap.next: '[{"Isuid":true,"Isgid":false,"Hostid":100000,"Nsid":0,"Maprange":1000},{"Isuid":true,"Isgid":true,"Hostid":1000,"Nsid":1000,"Maprange":1},{"Isuid":true,"Isgid":false,"Hostid":101001,"Nsid":1001,"Maprange":64535},{"Isuid":false,"Isgid":true,"Hostid":100000,"Nsid":0,"Maprange":1000},{"Isuid":true,"Isgid":true,"Hostid":1000,"Nsid":1000,"Maprange":1},{"Isuid":false,"Isgid":true,"Hostid":101001,"Nsid":1001,"Maprange":64535}]' volatile.last_state.idmap: '[{"Isuid":true,"Isgid":false,"Hostid":100000,"Nsid":0,"Maprange":1000},{"Isuid":true,"Isgid":true,"Hostid":1000,"Nsid":1000,"Maprange":1},{"Isuid":true,"Isgid":false,"Hostid":101001,"Nsid":1001,"Maprange":64535},{"Isuid":false,"Isgid":true,"Hostid":100000,"Nsid":0,"Maprange":1000},{"Isuid":true,"Isgid":true,"Hostid":1000,"Nsid":1000,"Maprange":1},{"Isuid":false,"Isgid":true,"Hostid":101001,"Nsid":1001,"Maprange":64535}]' volatile.last_state.power: RUNNING devices: event7: mode: "666" source: /dev/input/event7 type: unix-char js0: mode: "666" source: /dev/input/js0 type: unix-char ephemeral: false profiles: - default - gui stateful: false description: ""
- Create a container using the default profile you created in step 1, and the gui profile you created from step 2:
host $ lxc launch --profile default --profile gui ubuntu:18.04 retropie
- Start the container, login, and install retropie by following the official instructions. Also make sure that your graphics and sound are working by following step 2 above, and also confirm that your gamepad/controller was passed through successfully to the container by looking in /dev/input!
host $ lxc start retropie host $ lxc exec retropie -- sudo --user ubuntu --login ubuntu@guest ~$ sudo apt-get update && sudo apt-get upgrade ubuntu@guest ~$ sudo apt-get install -y git dialog unzip xmlstarlet ubuntu@guest ~$ git clone --depth=1 https://github.com/RetroPie/RetroPie-Setup.git ubuntu@guest ~$ cd RetroPie-Setup ubuntu@guest ~$ sudo ./retropie_setup.sh
-
Once retropie is installed, and you've confirmed graphics, sound, and your gamepad are configured, launch EmulationStation. If all goes well your gamepad will be detected. Make sure you have a game installed to test with.
-
Go to the Retroarch menu and bind your controller as normal. Also, you may need to change the joypad driver! This was the key step for me. By default retroarch uses udev, but I had to switch to sdl2. Make sure to change save configuration on exit to yes or manually save the file.
-
Launch a game. If all is working, you now have a fully functional RetroPie system running in a linux container. I recommend taking a snapshot at this so that you always have a known good configuration to quickly rollback to if necessary.
host $ lxc snapshot retropie "Working RetroPie"
That's it. I hope this helps someone. It was a fun exercise for me and now I can safely and cleanly install RetroPie on any Linux desktop without it interfering with anything on my main OS.
-
Thanks for your very detailed steps. Although very old; for future googlers with an headless server this might be important:
I spent hours troubleshooting emulation which hangs at "1 gamepad detected", and couldnt get any further even when pressing buttons. Apparantly there is an bug where emulationstation will start properly, but hangs if there arent any window managers installed... Installing xfwm4 (on the host) fixed this problem
Contributions to the project are always appreciated, so if you would like to support us with a donation you can do so here.
Hosting provided by Mythic-Beasts. See the Hosting Information page for more information.