TL;DR: I’ve submitted a patch to the Linux Kernel that makes the SNES Mini D-Pad function as an analog stick on Linux, like most other gamepads without analog sticks. Grab the patch here if you don’t want to wait for it to make its way into the mainline kernel.
A few Christmases ago I was bought a Super Nintendo Classic (SNES Mini). The controllers that came with this microconsole use the same connector that the Wii’s classic controller used. So, when I found an old Wii Remote lying around I had to plug one in to see if I could get it working under Linux.
After pairing the Wii Remote and connecting the controller I found that it showed up as a Wii Classic Controller Pro. There was only one problem: The button mappings for that controller meant that the D-Pad was mapped to keyboard up, down, left and right. Normally a gamepad with no analog sticks will map the d-pad to analog X & Y. After looking into what it would take to fix this it became cleat that I would need to make a modification to the wiimote Linux kernel drivers.
Modifying the kernel code.
The first thing that I did was get myself a copy of the kernel code and get the modules built. There are lots of tutorials on how to do this, so I won’t over it here, although I will say it makes life easier if you can get the kernel source from your distro’s package manager because that enables you to make sure that it’s the source of the kernel running on your system. One issue that I did hit was that the Kernel magic (an identifier that is used to make sure modules matches the kernel) was different after my first attempt at building the kernel modules, which meant I could not load the modules. I found that in order to adjust this I needed to pass PATCHLEVEL=4 EXTRAVERSION=-31-generic to Make to override the values in the Makefile. So my to get the kernel magic to look like “5.4.0-31-generic SMP mod_unload” I needed to run Make like this
make PATCHLEVEL=4 EXTRAVERSION=-31-generic modules
These values will probably need to be changed for your kernel, and you may need to changes others. The other values you might need to change to get the kernel magic of your module to match your kernel are in the top of the Makefile.
Once I had the ability to rebuild the modules I located the code for the wii classic controller. In “drivers/hid/hit-wiimote-modules.c”. I disabled the code that mapped the d-pad to button presses and the code that output the analog inputs. In its place I put some code that would send different values to the analog inputs depending on the state of the analog buttons. I built the module, loaded it and it worked on the first try.
Not wanting to just leave it here I decided to try and get this code into the Linux Kernel. However, I could not submit the code I had just written because it would break the functionality of the Wii Classic Controller. I was hoping to find some way to identify the SNES Classic controller, but to the kernel it looked exactly the same as a Wii Classic Controller Pro.. The only way to be able to make this change without breaking the current functionality would be to add a kernel module option, so that the new behaviour could be turned on and off. Once this was in, and I tested it, it was time to submit the code to a Kernel mailing list.
Submitting the code the Linux Kernel
To those of you who have ever submitted code to a project on github the process of submitting code to the Linux Kernel might seem a bit strange. Code is submitted via patches sent in the bodies of emails, as it was done back when the Linux project started back in 1991. Despite common perception, pull requests are used in managing the Linux kernel codebase. What they are not used for is for taking submissions from the general public, rather they are used to manage the various forks that feed into the mainline kernel.
Some tips from my experience submitting this patch
- Read the documentation, in particular the coding style guide and the submitting patches guide. If you are submitting a full new driver that guide is probably good to check too.
- Pick the correct kernel source tree to submit the code to and find its mailing list. Different teams are responsible for different parts of the kernel and they maintain their own fork that they work on. You will need to choose the right one for your patch. They are listed here (https://git.kernel.org/). And their mailing lists are found at the bottom of the page once you click through on the appropriate source tree. In my case I submitted my code to the hid group tree. If I had submitted it to the graphics subsystem mailing list it would probably have gotten ignored.
- If you think you are going to be doing a lot of kernel patches in the future it is advisable to set yourself up with a command-line based email client so that it doesn’t mangle the text formatting. I had this problem with Gmail, so I sent the final version of my patch as an attachment but this is not the standard procedure.
- This should go without saying, but be polite and patient when it comes to getting your patch committed.
In the end I had to submit three versions of my patch before it was committed to the hid source tree. From the time it got sign off from the reviewer it took 11 days for the person that maintains the fork to commit it to the source tree.
Sometimes it can be intimidating submitting code to a large open source project. My advice to anyone embarking on this is to look into what it takes to get your code accepted into a project before you submit it. In the case of the Linux kernel, most of the advice that on getting your code accepted was in the documentation section of the source tree itself. If this doesn’t exist for the project you want to submit code to look into places like the archives of reddit, or the forums for the project (if it has one) to see what the common pitfalls for people submitting code are and avoid them. Obviously the bigger the project the easier it will be to find this information.
As for my little change, it has been committed into the fork of the Linux hid subsystem, and should make it into the release of the 5.9 kernel. If anyone out there is desperate to have it now you can grab the patch here.