emilyst / hid-nx-dkms

Alternative Linux kernel HID driver for Nintendo Switch controllers
GNU General Public License v2.0
40 stars 6 forks source link

Add support for the Nintendo Switch Mega Drive 6 button controller #7

Open nfp0 opened 1 year ago

nfp0 commented 1 year ago

Excellent work in getting all the official Nintendo Switch controllers supported! I really hope I can see your work being mainlined soon. I'm rooting for it.

I believe the only controller missing is the 6 button Mega Drive controller that Nintendo sells exclusively in Japan. The user on this post seems to have the controller and posted the Linux mappings. https://github.com/gabomdq/SDL_GameControllerDB/issues/546#issuecomment-1038115146

I hope it helps.

emilyst commented 1 year ago

Excellent work in getting all the official Nintendo Switch controllers supported! I really hope I can see your work being mainlined soon. I'm rooting for it.

Yeah, maybe! I really should try contacting linux-input one of these days.

I believe the only controller missing is the 6 button Mega Drive controller that Nintendo sells exclusively in Japan. The user on this post seems to have the controller and posted the Linux mappings. gabomdq/SDL_GameControllerDB#546 (comment)

I hope it helps.

Ah, thanks, this is super neat. Unfortunately, I don't think it tells me the bits which the hardware will use to report its inputs. So I don't think I can use it.

For example, to implement the N64 controller, I had to know which bits would be set for which inputs before I could implement it. I couldn't find this online, so I ended up figuring it out for myself. I wrote it up as a little text file like this:

//         1098 7654 3210 9876 5432 1098 7654 3210

// C up    0000 0000 0000 0001 1000 0000 0000 0001
// C left  0000 0000 0000 0000 1000 0000 0000 0010
// R       0000 0000 0000 0000 1000 0000 0100 0000
// C down  0000 0000 0000 0000 1000 0000 1000 0000
// C right 0000 0000 0000 0000 1000 0001 0000 0000
// start   0000 0000 0000 0000 1000 0010 0000 0000
// ZR      0000 0000 0000 0000 1000 1000 0000 0000
// home    0000 0000 0000 0000 1001 0000 0000 0000
// cap     0000 0000 0000 0000 1010 0000 0000 0000
// down    0000 0000 0000 0001 1000 0000 0000 0000
// up      0000 0000 0000 0010 1000 0000 0000 0000
// right   0000 0000 0000 0100 1000 0000 0000 0000
// left    0000 0000 0000 1000 1000 0000 0000 0000
// L       0000 0000 0100 0000 1000 0000 0000 0000
// Z       0000 0000 1000 0000 1000 0000 0000 0000

That allowed me to figure out which of these constants the N64 controller would report when a given button was pressed. From there, I could map those bits to the actual buttons we report from the kernel layer.

So I'm missing two rather important pieces of information:

It's reasonable to think I could guess, but the NSO MD/Gen controller does some weird stuff. It maps its C to the bit which corresponds to the right shoulder button, for example. And it reports itself as a different device (either Gen or SNES controller) depending on whether you use Bluetooth or USB (though I forget which is which).

I'm giving all this info in case someone actually has one of these controllers in hand and is willing to try to reverse the information for me. I found I was unable to get one of the Japanese controllers with six buttons.

I'll leave this issue open, both so that people can see this specific controller variety isn't fully implemented, and in case someone is willing to supply the info (or even a patch).

Thanks again!

nfp0 commented 1 year ago

Thanks for the thorough explanation!

I don't have the controller myself so I won't be able to help you much further. I can tell you you can find the VID and PID here on this RetroArch mapping for the MD/Genesis 6 button controller, according to @pitibatou Not sure if that helps, but that file also tells you the current button mappings on udev for that controller.

@pitibatou Can you help us getting this controller mapped? You're the only person I've seen on GitHub that owns the 6 button controller.

emilyst commented 1 year ago

Interesting, yeah, I think I've looked at that in the past. That matches the device ID for the SNES controller (compare here, where they had to hack around the conflict). (Side note: I believe both of these assume hid-generic handles the inputs, which works okay-ish for these relatively less complicated controllers.)

Anyways, that seems to suggest that the six-button variant is mostly identical at the driver level to the three-button variant, except that it reports these additional buttons. It's probably the case that this happens regardless of whether it's reporting itself as a SNES controller or MD/Genesis controller (though the device ID would differ in that case).

All of that is to say—I could maybe take a guess based on that file (if I were to look up how hid-generic determines how to map the device inputs in the kernel layer), but it would still be a guess, and I'm pretty sure I'd flub it.

Anyways, the point is, this likely gives me the first piece of information I asked about above, but maybe not the second piece. Knowing for certain which bits it sets for which buttons would be useful then, and I could just add those mappings and hope it works for any MD/Genesis controller.

nfp0 commented 1 year ago

(compare here, where they had to hack around the conflict)

Yeah I know. I'm the one who commited that! :smile:

this likely gives me the first piece of information I asked about above, but maybe not the second piece

I understand. Yes, it's better to leave it as is if it would be guesswork with no way of testing. But could @pitibatou check those bits and help us if he reads this? Or would you need to check it yourself?

emilyst commented 1 year ago

(compare here, where they had to hack around the conflict)

Yeah I know. I'm the one who commited that! 😄

Heh, sorry, I missed that. Thanks!

this likely gives me the first piece of information I asked about above, but maybe not the second piece

I understand. Yes, it's better to leave it as is if it would be guesswork with no way of testing. But could @PitiBatou check those bits and help us if he reads this? Or would you need to check it yourself?

If someone definitively says the bitfield maps a specific way that doesn't conflict with what I already have, I'll toss it in and wait to see if someone with a six-button controller complains.

Honestly, I could probably figure it out from that file if I were motivated enough to dig into the Linux hid-generic code (and all the other HID input code), but I'm just not willing to spend hours on it, only to end up with something that could be wrong anyway.

emilyst commented 1 year ago

A curiosity: If I take the button mapping code I have and replace the constants with the actual bitfield positions, I get this:

static const struct nx_con_button_mapping gencon_button_mappings[] = {
    { BTN_EAST, BIT(2),     },  /* "A" */
    { BTN_SOUTH,    BIT(3),     },  /* "B" */
    { BTN_WEST, BIT(6),     },  /* "C" */
    { BTN_SELECT,   BIT(7),     },  /* "Mode" */
    { BTN_START,    BIT(9),     },  /* "Start" */
    { BTN_0,    BIT(12),    },  /* "Home" */
    { BTN_1,    BIT(13),    },  /* "Screenshot" */
    { /* sentinel */ },
};

Note that the last four buttons' bits (for the Mode, Start, Home, and Screenshot buttons) correspond precisely to what both the six-button and three-button variants use as their indices in the autoconfig files: 7, 9, 12, and 13.

This correspondence does not apply to the case of any of the buttons A, B, C, X, Y, or Z. The autoconfig files are consistent between themselves. This makes me suspicious that somehow I myself flubbed this up in my implementation, and now I need to do some more testing to see if I got this right.

emilyst commented 1 year ago

This correspondence does not apply to the case of any of the buttons A, B, C, X, Y, or Z. The autoconfig files are consistent between themselves. This makes me suspicious that somehow I myself flubbed this up in my implementation, and now I need to do some more testing to see if I got this right.

Heh, wow, I thought I was losing my mind. So I experimented. Note this is with USB:

% sudo xxd -a -b -g4 -l 4 /dev/hidraw0  # holding down "A" (leftmost letter button)
00000000: 00110000010010011001000100001000                   0I..
% sudo xxd -a -b -g4 -l 4 /dev/hidraw0  # holding down "B" (middle letter button)
00000000: 00110000011010111001000100000100                   0k..
% sudo xxd -a -b -g4 -l 4 /dev/hidraw0  # holding down "C" (rightmost letter button)
00000000: 00110000111101001001000101000000                   0..@

Repeating the experiment with Bluetooth yields the same result.

If we begin counting at zero, starting at the first bit on the right, then "A" is bit 3, "B" is bit 2, and C is bit 6, which is what I originally had. So that confirms for me that hid-generic isn't just mapping the bit position set in the scan code to the numerical index of the event code from the controller. It also confirms the code is correct as written.

That is a relief, at least. Anyway, you can ignore all this.

nfp0 commented 1 year ago

Glad that you managed to figure it out! :slightly_smiling_face: But note that the screenshot button is not mapped on the 6-button controller. I just mapped it on the 3-button to have a way to access the important X button. On the 6-button, X is mapped to X.

Anyway, if I ever manage to get a 6-button (I wish!), I'll make sure to give you the mappings.

emilyst commented 1 year ago

Glad that you managed to figure it out! 🙂 But note that the screenshot button is not mapped on the 6-button controller. I just mapped it on the 3-button to have a way to access the important X button. On the 6-button, X is mapped to X.

Ah, that clears up that confusion.

Anyway, if I ever manage to get a 6-button (I wish!), I'll make sure to give you the mappings.

Yeah, this would be rad. You (or anyone else) can even use the same command I used above (xxd -a -b -g4 -l 4 /dev/hidraw0) to print out the raw scan codes in binary while buttons are being held down.

offalynne commented 1 year ago

Related, I would love to have hid-nx-dkms 3b Genesis controller mappings (Bluetooth and USB) for the SDL community db ! Unfortunately I lack the hardware and so can not generate it myself.

nfp0 commented 1 year ago

@offalynne I have the Genesis/Mega Drive 3b (but not the 6b) controller. How can I help? I also recently got the N64 controller by some miracle.

emilyst commented 1 year ago

If you're looking for the values reported by the hid-nx module for the three-button Genesis controller, you can find those here: https://github.com/emilyst/hid-nx-dkms/blob/974d6c407296c47390d99f008933846c86f52bb9/hid-nx.c#L457-L466

In the first column, there are the values this driver reports. In the second column is the corresponding scan code from the controller. (c.f. this struct).

Values like BTN_SOUTH, etc., come from the Linux kernel input event codes. You can see the definitions for those over in this Linux kernel header.

Does that help?

offalynne commented 1 year ago

Looking for SDL mappings for https://github.com/gabomdq/SDL_GameControllerDB, both wired and wireless. Mapping tool: https://www.generalarcade.com/gamepadtool/

I have the SNES and N64 pads and got those covered, but not the Genesis.

jpwhiting commented 1 year ago

Here's the data for an NES style joycon I gathered the other day using steam-runtime-input-monitor and evemu-describe:

{
  "added" : {
    "interface_flags" : [
      "raw-hid"
    ],
    "type_flags" : [
    ],
    "dev_node" : "/dev/hidraw5",
    "subsystem" : "hidraw",
    "sys_path" : "/sys/devices/pci0000:00/0000:00:14.0/usb3/3-1/3-1:1.0/bluetooth/hci0/hci0:768/0005:057E:2007.013E/hidraw/hidraw5",
    "bus_type" : "0x0005",
    "vendor_id" : "0x057e",
    "product_id" : "0x2007",
    "version" : "0x0000",
    "udev_properties" : [
      "ACTION=add",
      "DEVNAME=/dev/hidraw5",
      "DEVPATH=/devices/pci0000:00/0000:00:14.0/usb3/3-1/3-1:1.0/bluetooth/hci0/hci0:768/0005:057E:2007.013E/hidraw/hidraw5",
      "MAJOR=240",
      "MINOR=5",
      "SEQNUM=93010",
      "SUBSYSTEM=hidraw",
      "USEC_INITIALIZED=601135262805"
    ],
    "hid_ancestor" : {
      "sys_path" : "/sys/devices/pci0000:00/0000:00:14.0/usb3/3-1/3-1:1.0/bluetooth/hci0/hci0:768/0005:057E:2007.013E",
      "name" : null,
      "bus_type" : "0x0005",
      "vendor_id" : "0x057e",
      "product_id" : "0x2007",
      "uniq" : null
    }
  }
}
{
  "added" : {
    "interface_flags" : [
      "event",
      "readable",
      "read-write"
    ],
    "type_flags" : [
      "joystick"
    ],
    "dev_node" : "/dev/input/event20",
    "subsystem" : "input",
    "sys_path" : "/sys/devices/pci0000:00/0000:00:14.0/usb3/3-1/3-1:1.0/bluetooth/hci0/hci0:768/0005:057E:2007.013E/input/input351/event20",
    "bus_type" : "0x0005",
    "vendor_id" : "0x057e",
    "product_id" : "0x2007",
    "version" : "0x0001",
    "evdev" : {
      "types" : [
        "SYN",
        "KEY",
        "ABS",
        "MSC",
        "REP"
      ],
      "absolute_axes" : [
        "X",
        "Y",
        "RX",
        "RY",
        "HAT0X",
        "HAT0Y"
      ],
      "relative_axes" : [
      ],
      "keys" : [
        "BTN_A",
        "BTN_B",
        "BTN_C",
        "BTN_X",
        "BTN_Y",
        "BTN_Z",
        "BTN_TL",
        "BTN_TR",
        "BTN_TL2",
        "BTN_TR2",
        "BTN_SELECT",
        "BTN_START",
        "BTN_MODE",
        "BTN_THUMBL",
        "BTN_THUMBR"
      ],
      "input_properties" : [
      ]
    },
    "udev_properties" : [
      "ACTION=add",
      "CURRENT_TAGS=:seat:uaccess:",
      "DEVNAME=/dev/input/event20",
      "DEVPATH=/devices/pci0000:00/0000:00:14.0/usb3/3-1/3-1:1.0/bluetooth/hci0/hci0:768/0005:057E:2007.013E/input/input351/event20",
      "ID_BUS=bluetooth",
      "ID_FOR_SEAT=input-pci-0000_00_14_0-usb-0_1_1_0",
      "ID_INPUT=1",
      "ID_INPUT_JOYSTICK=1",
      "ID_INPUT_JOYSTICK_INTEGRATION=external",
      "ID_PATH=pci-0000:00:14.0-usb-0:1:1.0",
      "ID_PATH_TAG=pci-0000_00_14_0-usb-0_1_1_0",
      "LIBINPUT_DEVICE_GROUP=5/57e/2007:50:2f:9b:12:a6:aa",
      "MAJOR=13",
      "MINOR=84",
      "SEQNUM=93008",
      "SUBSYSTEM=input",
      "TAGS=:seat:uaccess:",
      "USEC_INITIALIZED=601135303516"
    ],
    "hid_ancestor" : {
      "sys_path" : "/sys/devices/pci0000:00/0000:00:14.0/usb3/3-1/3-1:1.0/bluetooth/hci0/hci0:768/0005:057E:2007.013E",
      "name" : null,
      "bus_type" : "0x0005",
      "vendor_id" : "0x057e",
      "product_id" : "0x2007",
      "uniq" : null
    },
    "input_ancestor" : {
      "sys_path" : "/sys/devices/pci0000:00/0000:00:14.0/usb3/3-1/3-1:1.0/bluetooth/hci0/hci0:768/0005:057E:2007.013E/input/input351",
      "name" : "NES Controller (R)",
      "bus_type" : "0x0005",
      "vendor_id" : "0x057e",
      "product_id" : "0x2007",
      "version" : "0x0001"
    }
  }
}

and

# EVEMU 1.3
# Kernel: 6.2.11-arch1-1
# DMI: dmi:bvnDellInc.:bvr1.12.0:bd02/09/2023:br1.12:svnDellInc.:pnXPS139305:pvr:rvnDellInc.:rn0PPYW4:rvrA00:cvnDellInc.:ct10:cvr:sku0A5C:
# Input device name: "NES Controller (R)"
# Input device ID: bus 0x05 vendor 0x57e product 0x2007 version 0x01
# Supported events:
#   Event type 0 (EV_SYN)
#     Event code 0 (SYN_REPORT)
#     Event code 1 (SYN_CONFIG)
#     Event code 2 (SYN_MT_REPORT)
#     Event code 3 (SYN_DROPPED)
#     Event code 4 ((null))
#     Event code 5 ((null))
#     Event code 6 ((null))
#     Event code 7 ((null))
#     Event code 8 ((null))
#     Event code 9 ((null))
#     Event code 10 ((null))
#     Event code 11 ((null))
#     Event code 12 ((null))
#     Event code 13 ((null))
#     Event code 14 ((null))
#     Event code 15 (SYN_MAX)
#   Event type 1 (EV_KEY)
#     Event code 304 (BTN_SOUTH)
#     Event code 305 (BTN_EAST)
#     Event code 306 (BTN_C)
#     Event code 307 (BTN_NORTH)
#     Event code 308 (BTN_WEST)
#     Event code 309 (BTN_Z)
#     Event code 310 (BTN_TL)
#     Event code 311 (BTN_TR)
#     Event code 312 (BTN_TL2)
#     Event code 313 (BTN_TR2)
#     Event code 314 (BTN_SELECT)
#     Event code 315 (BTN_START)
#     Event code 316 (BTN_MODE)
#     Event code 317 (BTN_THUMBL)
#     Event code 318 (BTN_THUMBR)
#     Event code 319 ((null))
#   Event type 3 (EV_ABS)
#     Event code 0 (ABS_X)
#       Value    32768
#       Min          0
#       Max      65535
#       Fuzz       255
#       Flat      4095
#       Resolution   0
#     Event code 1 (ABS_Y)
#       Value    32768
#       Min          0
#       Max      65535
#       Fuzz       255
#       Flat      4095
#       Resolution   0
#     Event code 3 (ABS_RX)
#       Value    32768
#       Min          0
#       Max      65535
#       Fuzz       255
#       Flat      4095
#       Resolution   0
#     Event code 4 (ABS_RY)
#       Value    32768
#       Min          0
#       Max      65535
#       Fuzz       255
#       Flat      4095
#       Resolution   0
#     Event code 16 (ABS_HAT0X)
#       Value        0
#       Min         -1
#       Max          1
#       Fuzz         0
#       Flat         0
#       Resolution   0
#     Event code 17 (ABS_HAT0Y)
#       Value        0
#       Min         -1
#       Max          1
#       Fuzz         0
#       Flat         0
#       Resolution   0
#   Event type 4 (EV_MSC)
#     Event code 4 (MSC_SCAN)
#   Event type 20 (EV_REP)
#     Event code 0 (REP_DELAY)
#     Event code 1 (REP_PERIOD)
# Properties:
N: NES Controller (R)
I: 0005 057e 2007 0001
P: 00 00 00 00 00 00 00 00
B: 00 0b 00 00 00 00 00 00 00
B: 01 00 00 00 00 00 00 00 00
B: 01 00 00 00 00 00 00 00 00
B: 01 00 00 00 00 00 00 00 00
B: 01 00 00 00 00 00 00 00 00
B: 01 00 00 00 00 00 00 ff ff
B: 01 00 00 00 00 00 00 00 00
B: 01 00 00 00 00 00 00 00 00
B: 01 00 00 00 00 00 00 00 00
B: 01 00 00 00 00 00 00 00 00
B: 01 00 00 00 00 00 00 00 00
B: 01 00 00 00 00 00 00 00 00
B: 01 00 00 00 00 00 00 00 00
B: 02 00 00 00 00 00 00 00 00
B: 03 1b 00 03 00 00 00 00 00
B: 04 10 00 00 00 00 00 00 00
B: 05 00 00 00 00 00 00 00 00
B: 11 00 00 00 00 00 00 00 00
B: 12 00 00 00 00 00 00 00 00
B: 14 03 00 00 00 00 00 00 00
B: 15 00 00 00 00 00 00 00 00
B: 15 00 00 00 00 00 00 00 00
A: 00 0 65535 255 4095 0
A: 01 0 65535 255 4095 0
A: 03 0 65535 255 4095 0
A: 04 0 65535 255 4095 0
A: 10 -1 1 0 0 0
A: 11 -1 1 0 0 0

If someone want's to add it to SDL_GameControllerDB (If not I'll look into adding it myself later)

emilyst commented 1 year ago

Looking for SDL mappings for https://github.com/gabomdq/SDL_GameControllerDB, both wired and wireless. Mapping tool: https://www.generalarcade.com/gamepadtool/

I have the SNES and N64 pads and got those covered, but not the Genesis.

Okay, I think I see. You want someone to run that program and supply you the output.

I think your request should go into a new issue. If you want to open a dedicated issue, please do. If you have a new topic to discuss, even if it's related to an existing one, it's encouraged to open a new issue for that topic. That way it's easier for myself and others to keep track of.

This has gotten pretty off-topic for six-button Genesis controller support, so I'd like to ask that we stop discussing the SDL mappings here.

I think I can find time today to try to run that program with a three-button controller using the hid-nx module, but I am not certain. This request is a little beyond the scope of a problem, bug, or other issue with my module, so it's a lower priority.

nfp0 commented 1 year ago

Looking for SDL mappings for https://github.com/gabomdq/SDL_GameControllerDB, both wired and wireless. Mapping tool: https://www.generalarcade.com/gamepadtool/

I have the SNES and N64 pads and got those covered, but not the Genesis.

@offalynne I believe I've already given you the mappings for the 3btn controller here: https://github.com/gabomdq/SDL_GameControllerDB/issues/546

Is this not what you needed?

offalynne commented 1 year ago

Looking for SDL mappings for https://github.com/gabomdq/SDL_GameControllerDB, both wired and wireless. Mapping tool: https://www.generalarcade.com/gamepadtool/ I have the SNES and N64 pads and got those covered, but not the Genesis.

@offalynne I believe I've already given you the mappings for the 3btn controller here: gabomdq/SDL_GameControllerDB#546

Is this not what you needed?

The mapping (and helpfully, the GUID) are different via hid-nx-dkms.

nfp0 commented 11 months ago

Yeah, maybe! I really should try contacting linux-input one of these days.

@emilyst Have you managed to try and get your work mainlined? Would love to see it! :slightly_smiling_face:

emilyst commented 11 months ago

I haven't, as I've been very busy with a demanding day job this year.

mcpat-it commented 10 months ago

I got my 6B MD/Gen controller

dmesg:

[13692.030184] nx 0005:057E:2017.000F: unknown main item tag 0x0
[13692.032370] nx 0005:057E:2017.000F: hidraw0: BLUETOOTH HID v80.01 Gamepad [MD             /Gen Control Pad] on b8:27:eb:74:4e:19
[13692.129292] nx 0005:057E:2017.000F: controller MAC = 80:D2:E5:BE:B6:8D
[13692.160191] input: MD/Gen Control Pad as /devices/platform/soc/3f201000.seria             l/serial0/serial0-0/bluetooth/hci0/hci0:11/0005:057E:2017.000F/input/input18

`evtest'

root@rpizerosm:~# evtest
No device specified, trying to scan all of /dev/input/event*
Available devices:
/dev/input/event0:      MD/Gen Control Pad
/dev/input/event1:      Rotary Encoder Volume
Select the device event number [0-1]: 0
Input driver version is 1.0.1
Input device ID: bus 0x5 vendor 0x57e product 0x2017 version 0x8001
Input device name: "MD/Gen Control Pad"
Supported events:
  Event type 0 (EV_SYN)
  Event type 1 (EV_KEY)
    Event code 304 (BTN_SOUTH)
    Event code 305 (BTN_EAST)
    Event code 308 (BTN_WEST)
    Event code 314 (BTN_SELECT)
    Event code 315 (BTN_START)
    Event code 316 (BTN_MODE)
    Event code 317 (BTN_THUMBL)
    Event code 544 (BTN_DPAD_UP)
    Event code 546 (BTN_DPAD_LEFT)
    Event code 547 (BTN_DPAD_RIGHT)
  Event type 3 (EV_ABS)
    Event code 16 (ABS_HAT0X)
      Value      0
      Min       -1
      Max        1
    Event code 17 (ABS_HAT0Y)
      Value      0
      Min       -1
      Max        1
Properties:
Testing ... (interrupt to exit)
Event: time 1696021100.196493, type 1 (EV_KEY), code 546 (BTN_DPAD_LEFT), value 1
Event: time 1696021100.196493, -------------- SYN_REPORT ------------
Event: time 1696021100.286495, type 1 (EV_KEY), code 546 (BTN_DPAD_LEFT), value 0
Event: time 1696021100.286495, -------------- SYN_REPORT ------------
Event: time 1696021100.826480, type 1 (EV_KEY), code 544 (BTN_DPAD_UP), value 1
Event: time 1696021100.826480, -------------- SYN_REPORT ------------
Event: time 1696021100.931482, type 1 (EV_KEY), code 544 (BTN_DPAD_UP), value 0
Event: time 1696021100.931482, -------------- SYN_REPORT ------------
Event: time 1696021101.516464, type 1 (EV_KEY), code 547 (BTN_DPAD_RIGHT), value 1
Event: time 1696021101.516464, -------------- SYN_REPORT ------------
Event: time 1696021101.636485, type 1 (EV_KEY), code 547 (BTN_DPAD_RIGHT), value 0
Event: time 1696021101.636485, -------------- SYN_REPORT ------------

Patch hid-nx.c

static const struct nx_con_button_mapping gencon_button_mappings[] = {
    { BTN_SOUTH,    NX_CON_BTN_A,       },
    { BTN_EAST, NX_CON_BTN_B,       },
    { BTN_WEST, NX_CON_BTN_R,       },
    { BTN_DPAD_LEFT,    NX_CON_BTN_X,       },
    { BTN_DPAD_UP,      NX_CON_BTN_Y,       },
    { BTN_DPAD_RIGHT,   NX_CON_BTN_L,       },
    { BTN_THUMBL,   NX_CON_BTN_ZR,      },
    { BTN_START,    NX_CON_BTN_PLUS,    },
    { BTN_SELECT,   NX_CON_BTN_HOME,    },
    { BTN_MODE, NX_CON_BTN_CAP,     },
    { /* sentinel */ },
};

Would be great if we can differ between 3B and 6B, would it be possible?