Skip to content

Instantly share code, notes, and snippets.

@camthesaxman
Created March 3, 2022 01:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save camthesaxman/af7099505103a555518741b4083eaea8 to your computer and use it in GitHub Desktop.
Save camthesaxman/af7099505103a555518741b4083eaea8 to your computer and use it in GitHub Desktop.
Kernel Module to fix wrong button mapping of PowerA wired Nintendo Switch controller
obj-m += powera_switch_fix.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
/**
* Linux kernel module to fix up the wrong button mapping for the
* PowerA Wired Nintendo Switch controller
*/
#include <linux/hid.h>
#include <linux/input.h>
#include <linux/module.h>
MODULE_VERSION("0.1");
MODULE_LICENSE("GPL");
static const struct hid_device_id hidTable[] = {
{ HID_USB_DEVICE(0x20D6, 0xA711) },
{ 0 },
};
// button mapping
static const unsigned int buttonmap[] = {
[1] = BTN_WEST, // Y button
[2] = BTN_SOUTH, // B button
[3] = BTN_EAST, // A button
[4] = BTN_NORTH, // X button
[5] = BTN_TL, // L button
[6] = BTN_TR, // R button
[7] = BTN_TL2, // ZL button
[8] = BTN_TR2, // ZR button
[9] = BTN_SELECT, // - button
[10] = BTN_START, // + button
[11] = BTN_THUMBL, // left stick press
[12] = BTN_THUMBR, // right stick press
[13] = BTN_MODE, // home button
[14] = BTN_C, // camera button, not sure what else to map this to
};
static int my_mapping(struct hid_device *hdev, struct hid_input *hi,
struct hid_field *field, struct hid_usage *usage,
unsigned long **bit, int *max)
{
if ((usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON) {
unsigned int button = usage->hid & HID_USAGE;
if (button >= ARRAY_SIZE(buttonmap))
return -1;
button = buttonmap[button];
if (button == 0)
return -1;
hid_map_usage_clear(hi, usage, bit, max, EV_KEY, button);
return 1;
}
return 0;
}
static struct hid_driver driver = {
.name = "powera_switch_fix",
.id_table = hidTable,
.input_mapping = my_mapping,
};
static int __init my_init(void)
{
printk(KERN_INFO "%s: module_init\n", driver.name);
return hid_register_driver(&driver);
}
static void __exit my_exit(void)
{
printk(KERN_INFO "%s: module_exit\n", driver.name);
hid_unregister_driver(&driver);
}
module_init(my_init);
module_exit(my_exit);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment