{"id":207,"date":"2019-11-19T00:17:38","date_gmt":"2019-11-18T23:17:38","guid":{"rendered":"https:\/\/synt4x.org\/blog\/?p=207"},"modified":"2019-12-31T16:23:10","modified_gmt":"2019-12-31T15:23:10","slug":"getting-rumble-on-the-8bitdo-sn30-pro-to-work-properly-with-linux","status":"publish","type":"post","link":"https:\/\/synt4x.org\/blog\/index.php\/2019\/11\/19\/getting-rumble-on-the-8bitdo-sn30-pro-to-work-properly-with-linux\/","title":{"rendered":"Getting rumble on the 8BitDo SN30 Pro+ to work properly with Linux"},"content":{"rendered":"\n<p><strong>TLDR: <\/strong>After having owned the controller for a while I noticed that every time you install a new kernel update the fixes are undone again, and have to be re-applied. I also discovered that the controller UID is the same for all SN30 Pro+ controllers. So I&#8217;ve made the following script that fixes everything automatically instead. Save it somewhere, check that the config file paths are correct, install xpadneo using the <a rel=\"noreferrer noopener\" aria-label=\"github instructions (opens in a new tab)\" href=\"https:\/\/github.com\/atar-axis\/xpadneo\" target=\"_blank\">github instructions<\/a>, then run the script as root.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: ; notranslate\" title=\"\">\n#!\/bin\/bash\n\nif &#x5B;&#x5B; $EUID -ne 0 ]]; then\n    echo &quot;This script must be run as root&quot;\n    exit 1\nfi\n\n# Config file paths\nMP_PATH=&quot;\/etc\/modprobe.d\/99-xpadneo-bluetooth.conf&quot;\nUDEV_PATH=&quot;\/etc\/udev\/rules.d\/99-xpadneo.rules&quot;\nENV_PATH=&quot;\/etc\/environment&quot;\n\n# Look for already applied fixes\nMPFIXED=$(grep -c &quot;disable_ff=2&quot; $MP_PATH)\nUDEVFIXED=$(grep -c &quot;RUN+=\\&quot;\/bin\/sh -c &#039;echo xpadneo udev: \\$kernel &gt; \/dev\/kmsg &amp;&amp; { echo \\$kernel &gt; \/sys\/bus\/hid\/drivers\/hid-generic\/unbind; echo \\$kernel &gt; \/sys\/bus\/hid\/drivers\/microsoft\/unbind; echo \\$kernel &gt; \/sys\/bus\/hid\/drivers\/xpadneo\/bind; }; &#039;\\&quot;&quot; $UDEV_PATH)\nENVFIXED=$(grep -c &quot;8BitDo SN30 Pro+&quot; $ENV_PATH)\n\nif &#x5B;&#x5B; $MPFIXED -eq 0 ]]; then\n  # Turn off trigger rumble\n  echo &quot;options hid_xpadneo debug_level=0 disable_ff=2 trigger_rumble_damping=4 fake_dev_version=4400 combined_z_axis=n&quot; &gt;&gt; $MP_PATH\n  echo &quot;Applied fix to $MP_PATH.&quot;\nelse\n  echo &quot;Fix already applied to $MP_PATH. Skipping.&quot;\nfi\n\nif &#x5B;&#x5B; $UDEVFIXED -eq 0 ]]; then\n  # Apply dirty fix to udev rules\n  sed -i &#039;s\/RUN\/#RUN\/g&#039; $UDEV_PATH\n  echo &quot;RUN+=\\&quot;\/bin\/sh -c &#039;echo xpadneo udev: \\$kernel &gt; \/dev\/kmsg &amp;&amp; { echo \\$kernel &gt; \/sys\/bus\/hid\/drivers\/hid-generic\/unbind; echo \\$kernel &gt; \/sys\/bus\/hid\/drivers\/microsoft\/unbind; echo \\$kernel &gt; \/sys\/bus\/hid\/drivers\/xpadneo\/bind; }; &#039;\\&quot;&quot; &gt;&gt; $UDEV_PATH\n  echo &quot;Applied fix to $UDEV_PATH&quot;\nelse\n  echo &quot;Fix already applied to $UDEV_PATH. Skipping.&quot;\nfi\n\nif &#x5B;&#x5B; $ENVFIXED -eq 0 ]]; then\n  # Add SDL_CONTROLLERCONFIG environment variable\n  echo &quot;SDL_GAMECONTROLLERCONFIG=\\&quot;050000005e040000e002000030110000,8BitDo SN30 Pro+,platform:Linux,a:b0,b:b1,x:b2,y:b3,back:b6,guide:b8,start:b7,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,\\&quot;&quot; &gt;&gt; $ENV_PATH\n  echo &quot;Added &#039;SDL_CONTROLLERCONFIG&#039; variable to $ENV_PATH.&quot;\nelse\n  echo &quot;&#039;SDL_CONTROLLERCONFIG&#039; variable already present in $ENV_PATH. Skipping.&quot;\nfi\n<\/pre><\/div>\n\n\n<p>Original post follows:<\/p>\n\n\n\n<p>I recently bought an <a rel=\"noreferrer noopener\" aria-label=\"8BitDo SN30 Pro+ (opens in a new tab)\" href=\"https:\/\/www.8bitdo.com\/sn30-pro-plus\/\" target=\"_blank\">8BitDo SN30 Pro+<\/a> since my old gamepad was an ancient Logitech Dual Action. I wanted a gamepad that was wireless as well as having support for XInput. When I heard about the SN30 Pro+ I couldn&#8217;t contain myself, so I went and bought it the same day after reading a bit about it and how it works on Linux. It&#8217;s not officially supported, and there wasn&#8217;t really much definitive information regarding Linux compatibility, other than that the older SN30 Pro worked fine and it works on the raspberry pi. So I just took a gamble and bought it.<\/p>\n\n\n\n<!--more-->\n\n\n\n<p>And it does work pretty well with a standard Linux kernel (currently I&#8217;m running 5.3.11 on Arch Linux) out of the box. Holding <code>X + Start<\/code> on the controller will boot it up in XInput mode. <code>B + Start<\/code> is the old DInput mode. And <code>Y + Start<\/code> will make it behave like a Switch Pro controller. All of these different modes paired just fine with my Bluetooth adapter. (I have not tested the Apple mode <code>A + Start<\/code>). It&#8217;s just overall a really nice controller.<\/p>\n\n\n\n<p>But there was one thing that was missing when using it on Linux. Rumble! Rumble was only working when plugging the controller in through USB. When doing that, the kernel recognizes it as an Xbox 360 controller and uses the xpad kernel module. But connecting it with Bluetooth the xpad module is not used for some reason.<\/p>\n\n\n\n<p>After some experimenting it seemed like it was a limitation with evdev or the kernel modules or something like that, and I was ready to just give up on getting rumble to work for now. But then I read about <a rel=\"noreferrer noopener\" aria-label=\"xpadneo (opens in a new tab)\" href=\"https:\/\/github.com\/atar-axis\/xpadneo\" target=\"_blank\">xpadneo<\/a>, which is a kernel module specifically for the Xbox One Wireless Controller.<\/p>\n\n\n\n<p>The SN30 Pro+ is obviously not an Xbox One gamepad, but it identifies as one when you connect it wirelessly using the XInput mode. And as it turns out, xpadneo will make the SN30 Pro+ work with rumble over Bluetooth! There&#8217;s some setup required to make it work properly however.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Installation and configuration<\/h3>\n\n\n\n<p>Here&#8217;s what we need to do:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Install xpadneo<\/li><li>Disable the Trigger Force Feedback feature of xpadneo<\/li><li>Might need to get Steam to recognize the controller when using xpadneo depending on distro.<\/li><\/ul>\n\n\n\n<p>Being comfortable with the terminal, editing config files, and knowing how to compile a C source file is helpful for this guide.<\/p>\n\n\n\n<p>Installing xpadneo was very simple on Arch Linux; just install <a rel=\"noreferrer noopener\" aria-label=\"xpadneo-dkms-git (opens in a new tab)\" href=\"https:\/\/aur.archlinux.org\/packages\/xpadneo-dkms-git\/\" target=\"_blank\">xpadneo-dkms-git<\/a> from AUR. After that the kernel will automatically use the <code>hid_xpadneo<\/code> module when you connect your SN30 Pro+ over Bluetooth after you have rebooted. I&#8217;m not sure there are packages for other platforms, but <a rel=\"noreferrer noopener\" aria-label=\"the GitHub page (opens in a new tab)\" href=\"https:\/\/github.com\/atar-axis\/xpadneo\" target=\"_blank\">the GitHub page<\/a> has a very simple manual installation guide for the most common distros, including Arch.<\/p>\n\n\n\n<p>After installing it and rebooting, when you connect the controller wirelessly it will begin to rumble constantly. While it&#8217;s nice that the rumble is now working, this is obviously not what we want. This is caused by the trigger rumble feature that xpadneo has, which needs to be turned off for this controller. This can be done by adding some options to <code>\/etc\/modprobe.d\/99-xpadneo-bluetooth.conf<\/code> manually, or with the <code>configure.sh<\/code> script which will do it for you.<\/p>\n\n\n\n<p>So even if you do install the AUR package on Arch Linux you probably still want to clone the xpadneo GitHub repo to get the <code>configure.sh<\/code> script, since this makes changing the settings a lot easier. So go ahead and clone it if you haven&#8217;t already:<\/p>\n\n\n\n<p><code>git clone https:\/\/github.com\/atar-axis\/xpadneo.git<\/code><\/p>\n\n\n\n<p>Once that is done, enter the xpadneo directory and run the <code>configure.sh<\/code> script. It will show you which flags you can use to configure the module with. For the SN30 Pro+ I just had to turn off the Trigger Force Feedback feature like this:<\/p>\n\n\n\n<p><code>sudo .\/configure.sh -f 2<\/code><\/p>\n\n\n\n<p>This will update the <code>99-xpadneo-bluetooth.conf<\/code> file so it looks like this:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: ; notranslate\" title=\"\">\noptions bluetooth disable_ertm=y\noptions hid_xpadneo debug_level=0 disable_ff=2 trigger_rumble_damping=4 fake_dev_version=4400 combined_z_axis=n\n<\/pre><\/div>\n\n\n<p>If you don&#8217;t want to use the configure script you can just paste the above into your <code>99-xpadneo-bluetooth.conf<\/code> file.<\/p>\n\n\n\n<p>Disconnect the controller if it&#8217;s connected, then unload the module with <code>sudo modprobe -r hid_xpadneo<\/code>. The next time you connect the controller it won&#8217;t be vibrating constantly, and everything will work as expected! Except for Steam&#8230; in some cases. While things like native games and RetroArch are now working with rumble, using this module sometimes makes Steam not detect any controllers for some reason. Luckily there are work-arounds for that.<\/p>\n\n\n\n<p>First lets try the easier option as per <a href=\"https:\/\/github.com\/atar-axis\/xpadneo\/issues\/107#issuecomment-498858788\" target=\"_blank\" rel=\"noreferrer noopener\" aria-label=\"this post (opens in a new tab)\">this post<\/a>. Open your <code>\/etc\/udev\/rules.d\/99-xpadneo.rules<\/code> file and comment out the <code>RUN<\/code> line, and replace it with the line from that post. It will look like this:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; highlight: [24,25]; title: ; notranslate\" title=\"\">\n# XPADNEO UDEV BINDING\n# by atar-axis (dollinger.florian@gmx.de)\n\n# in general those files with a higher leading number are processed\n# and executed _later_, that means assignment in those files can overwrite\n# assignments in other rules which are parsed earlier\n\n# every block is a rule. rules are collected from the .rules files\n# according to their name. on every kernel uevent, all rules are\n# compared to that event - one by one.\n\n# kernel versions        manual binding (bind\/unbind)   bind uevent             hid_generic greedy      hid_microsoft support   gamepad     method\n# ---------------        ----------------------------   --------------          ------------------      ---------------------   -------     ------\n# &#x5B;    ... - 2.6.13 &#x5B;    no                             no                      yes                     no                      *           rmmod (not supported in xpadneo)\n# &#x5B; 2.6.13 - 4.14   &#x5B;    yes                            no                      yes                     no                      *           1: add, hid_generic\n# &#x5B;   4.14 - 4.16   &#x5B;    yes                            yes                     yes                     no                      *           2: bind, hid_generc\n# &#x5B;   4.16 - 4.20   &#x5B;    yes                            yes                     no                      no                      *           automatic\n# &#x5B;   4.20 - ...    ]    yes                            yes                     no                      yes                     02FD        3: bind, microsoft\n#                                                                                                                               02E0        automatic\n\nACTION==&quot;add&quot;, \\\nKERNEL==&quot;0005:045E:02FD.*|0005:045E:02E0.*&quot;, \\\nSUBSYSTEM==&quot;hid&quot;, \\\n#RUN:=&quot;\/bin\/sh -c &#039;echo xpadneo udev: $kernel &gt; \/dev\/kmsg; modprobe hid_xpadneo; echo $kernel &gt; \/sys\/bus\/hid\/drivers\/hid-generic\/unbind; echo $kernel &gt; \/sys\/bus\/hid\/drivers\/microsoft\/unbind; echo $kernel &gt; \/sys\/bus\/hid\/drivers\/xpadneo\/bind; echo xpadneo udev: ok &gt; \/dev\/km&gt;\nRUN+=&quot;\/bin\/sh -c &#039;echo xpadneo udev: $kernel &gt; \/dev\/kmsg &amp;amp;&amp;amp; { echo $kernel &gt; \/sys\/bus\/hid\/drivers\/hid-generic\/unbind; echo $kernel &gt; \/sys\/bus\/hid\/drivers\/microsoft\/unbind; echo $kernel &gt; \/sys\/bus\/hid\/drivers\/xpadneo\/bind; }; &#039;&quot;\n<\/pre><\/div>\n\n\n<p>Note that at least when using the AUR xpadneo package this file is overwritten on kernel upgrades.<\/p>\n\n\n\n<p>Now save it and reboot, then try launching Steam and see if the controller is detected. If not we can try to create an FNA\/SDL environment variable for the controller instead.<\/p>\n\n\n\n<p>Undo the changes in <code>99-xpadneo.rules<\/code> again before continuing (or just keep them, it works with both applied), then follow the instructions <a rel=\"noreferrer noopener\" aria-label=\"here on the Arch wiki (opens in a new tab)\" href=\"https:\/\/wiki.archlinux.org\/index.php\/Gamepad#Joystick_not_working_in_FNA\/SDL_based_games\" target=\"_blank\">here on the Arch wiki<\/a> and compile the controllermap.c file from the SDL sources (you&#8217;re going to need GCC or another compiler for this. Look up how to install it in your distro if you don&#8217;t have it), and you will get a guid for your controller when you run it that you can add to an environment variable named <code>SDL_GAMECONTROLLERCONFIG<\/code>.<\/p>\n\n\n\n<p>Where to add the environment variables varies a bit depending on your distro. You should add them in a place where they are applied even for graphical environments, so <code>~\/.bash_profile<\/code> and such is probably not enough. For distros with systemd (Or at least on Arch Linux. Look up where to add your environment variables in your distro) you can generally add simple ones like this to <code>\/etc\/environment<\/code>, which is where I ended up putting it. This is applied globally for all users however, so keep that in mind. It should look something like this:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; highlight: [6]; title: ; notranslate\" title=\"\">\n#\n# This file is parsed by pam_env module\n#\n# Syntax: simple &quot;KEY=VAL&quot; pairs on separate lines\n#\nSDL_GAMECONTROLLERCONFIG=&quot;050000005e040000e002000030110000,8BitDo SN30 Pro+,platform:Linux,a:b0,b:b1,x:b2,y:b3,back:b6,guide:b8,start:b7,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,&quot;\n<\/pre><\/div>\n\n\n<p>And that&#8217;s it! Now once you reboot one more time, Steam should recognize your controller as an Xbox One Wireless Controller and have working rumble as well.<\/p>\n\n\n\n<p>So there you have it. A bit messy to set up but once done you don&#8217;t have to worry about it. You might have to re-install the xpadneo module after kernel upgrades depending on your distro though, but that&#8217;s as simple as running the install.sh script again. And maybe the xpadneo devs will make the SN30 Pro+ work more seamlessly in the future as well so it can automatically disable trigger force feedback etc.<\/p>\n\n\n\n<p><strong>Update: <\/strong>After some more testing I noticed that games through Wine didn&#8217;t detect the controller at all. This is because Wine&#8217;s Xinput implementation is using SDL2, which means you&#8217;re going to have to do the above SDL environment variable fix to get it to work in Wine. After doing that it works perfectly. I&#8217;m now using both the fixes at the same time and they don&#8217;t appear to conflict in any way.<\/p>\n\n\n\n<p>Before doing that I also disabled the event and js type joysticks in Wine&#8217;s controller settings (run <code>wine control<\/code> in a terminal to access them), as well as added library overrides for <code>xinput1_{1-4}.dll<\/code> and <code>xinput9_1_0.dll<\/code> in <code>winecfg<\/code> and set them to builtin, although I&#8217;m not sure that was necessary. Those changes didn&#8217;t do anything to fix it by themselves; only after adding the SDL environment variable did it start to work.<\/p>\n\n\n\n<hr class=\"wp-block-separator\"\/>\n\n\n\n<h4 class=\"wp-block-heading\">Links<\/h4>\n\n\n\n<ul class=\"wp-block-list\"><li><a rel=\"noreferrer noopener\" aria-label=\"Issue regarding Steam not recognizing the SN30 Pro+ with xpadneo, where I got most of the info this post is based on. (Big thanks to pedrofleck!) (opens in a new tab)\" href=\"https:\/\/github.com\/atar-axis\/xpadneo\/issues\/140\" target=\"_blank\">GitHub Issue regarding Steam not recognizing the SN30 Pro+ with xpadneo<\/a>, where I got most of the info this post is based on. (Big thanks to pedrofleck and sinkillerj.)<\/li><li><a rel=\"noreferrer noopener\" aria-label=\"xpadneo website (opens in a new tab)\" href=\"https:\/\/atar-axis.github.io\/xpadneo\/\" target=\"_blank\">xpadneo website<\/a><\/li><li><a rel=\"noreferrer noopener\" aria-label=\"8BitDo SN30 Pro+ (opens in a new tab)\" href=\"https:\/\/www.8bitdo.com\/sn30-pro-plus\/\" target=\"_blank\">8BitDo SN30 Pro+<\/a><\/li><\/ul>\n","protected":false},"excerpt":{"rendered":"<p>TLDR: After having owned the controller for a while I noticed that every time you install a new kernel update the fixes are undone again, and have to be re-applied. I also discovered that the controller UID is the same for all SN30 Pro+ controllers. So I&#8217;ve made the following script that fixes everything automatically &hellip; <a href=\"https:\/\/synt4x.org\/blog\/index.php\/2019\/11\/19\/getting-rumble-on-the-8bitdo-sn30-pro-to-work-properly-with-linux\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Getting rumble on the 8BitDo SN30 Pro+ to work properly with Linux&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[19,46,14],"tags":[47,50,49,48,51],"class_list":["post-207","post","type-post","status-publish","format-standard","hentry","category-games","category-linux","category-technology","tag-8bitdo","tag-guide","tag-rumble","tag-sn30-pro","tag-xpadneo"],"_links":{"self":[{"href":"https:\/\/synt4x.org\/blog\/index.php\/wp-json\/wp\/v2\/posts\/207","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/synt4x.org\/blog\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/synt4x.org\/blog\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/synt4x.org\/blog\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/synt4x.org\/blog\/index.php\/wp-json\/wp\/v2\/comments?post=207"}],"version-history":[{"count":25,"href":"https:\/\/synt4x.org\/blog\/index.php\/wp-json\/wp\/v2\/posts\/207\/revisions"}],"predecessor-version":[{"id":237,"href":"https:\/\/synt4x.org\/blog\/index.php\/wp-json\/wp\/v2\/posts\/207\/revisions\/237"}],"wp:attachment":[{"href":"https:\/\/synt4x.org\/blog\/index.php\/wp-json\/wp\/v2\/media?parent=207"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/synt4x.org\/blog\/index.php\/wp-json\/wp\/v2\/categories?post=207"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/synt4x.org\/blog\/index.php\/wp-json\/wp\/v2\/tags?post=207"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}