Skip to content

Commit

Permalink
xpadneo, quirks: Prevent applying heuristics for some known vendors
Browse files Browse the repository at this point in the history
Our GameSir heuristics are a bit weak: They share the same descriptor
length with genuine Microsoft controllers, and the heuristics bit mask
only has two bits set. However, it conflicts with just one genuine
known OUI until now. So we can fix this by adding a quirk flag to apply
no heuristics.

Fixes: #514
Signed-off-by: Kai Krakow <[email protected]>
  • Loading branch information
kakra committed Dec 7, 2024
1 parent 4cdccfd commit 82326de
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 9 deletions.
30 changes: 24 additions & 6 deletions docs/heuristics/gamesir-nova.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,27 @@
Gamesir Nova uses random MAC OUIs. We collect them here to implement a
working heuristic matcher.

| OUI | Bit representation | descriptor length
| ------------ | --------------------------------------- | -----------------
| 3E:42:6C | `0011 1110 : 0100 0010 : 0110 1100` | 283
| ED:BC:9A | `1110 1101 : 1011 1100 : 1001 1010` | 283
| 6A:07:14 | `0110 1010 : 0000 0111 : 0001 0100` | 283
| **AND mask** | **`0010 1000 : 0000 0000 : 0000 0000`** | **mask 0x28**
We also collect OUIs here which should not match the heuristics because we
are seeing conflicts with some official vendors.

Officially validated OUIs are marked with a "+".

| OUI | Vendor | Bit representation | descriptor length
| ------------ | --------- | --------------------------------------- | -------------------
| 3E:42:6C | GameSir | `0011 1110 : 0100 0010 : 0110 1100` | 283
| ED:BC:9A | GameSir | `1110 1101 : 1011 1100 : 1001 1010` | 283
| 6A:07:14 | GameSir | `0110 1010 : 0000 0111 : 0001 0100` | 283
| **AND mask** | | **`0010 1000 : 0000 0000 : 0000 0000`** | **mask 0x28**
| 44:16:22 + | Microsoft | `0100 0100 : 0001 0110 : 0010 0010` |
| 68:6C:E6 + | Microsoft | `0110 1000 : 0110 1100 : 1110 0110` | 283 inval match
| 98:7A:14 + | Microsoft | `1001 1000 : 0111 1010 : 0001 0100` |
| C8:3F:26 + | Microsoft | `1100 1000 : 0011 1111 : 0010 0110` |
| **AND mask** | | **`0000 0000 : 0000 0000 : 0000 0000`** | **mask 0x00**
| 98:B6:E9 + | Nintendo | `1001 1000 : 1011 0110 : 1110 1001` |
| **AND mask** | | **`0010 1000 : 1011 0110 : 1110 1001`** | **mask 0x98 B6 E9**
| 98:B6:E8 | GuliKit | `1001 1000 : 1011 0110 : 1110 1000` |
| 98:B6:EA | GuliKit | `1001 1000 : 1011 0110 : 1110 1010` |
| 98:B6:EC | GuliKit | `1001 1000 : 1011 0110 : 1110 1100` |
| **AND mask** | | **`0010 1000 : 1011 0110 : 1110 1000`** | **mask 0x98 B6 E8**
| E4:17:D8 + | 8BitDo | `1110 0100 : 0001 0111 : 1101 1000` |
| **AND mask** | | **`1110 0100 : 0001 0111 : 1101 1000`** | **mask 0xE4 17 D8**
9 changes: 6 additions & 3 deletions hid-xpadneo/src/hid-xpadneo.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,8 @@ MODULE_PARM_DESC(quirks,
", use Nintendo mappings = " __stringify(XPADNEO_QUIRK_NINTENDO)
", use Share button mappings = " __stringify(XPADNEO_QUIRK_SHARE_BUTTON)
", reversed motor masking = " __stringify(XPADNEO_QUIRK_REVERSE_MASK)
", swapped motor masking = " __stringify(XPADNEO_QUIRK_SWAPPED_MASK));
", swapped motor masking = " __stringify(XPADNEO_QUIRK_SWAPPED_MASK)
", apply no heuristics = " __stringify(XPADNEO_QUIRK_NO_HEURISTICS));

static DEFINE_IDA(xpadneo_device_id_allocator);

Expand All @@ -103,6 +104,7 @@ struct quirk {
};

static const struct quirk xpadneo_quirks[] = {
DEVICE_OUI_QUIRK("68:6C:E6", XPADNEO_QUIRK_NO_HEURISTICS),
DEVICE_OUI_QUIRK("98:B6:EA",
XPADNEO_QUIRK_NO_PULSE | XPADNEO_QUIRK_NO_TRIGGER_RUMBLE |
XPADNEO_QUIRK_REVERSE_MASK),
Expand Down Expand Up @@ -1176,10 +1178,11 @@ static int xpadneo_init_hw(struct hid_device *hdev)
* uniq ID "aa:bb:cc:dd:ee:ff" to u8, so we get the first OUI byte
*/
if ((xdata->original_rsize == 283)
&& ((xdata->quirks & XPADNEO_QUIRK_NO_HEURISTICS) == 0)
&& ((xdata->quirks & XPADNEO_QUIRK_SIMPLE_CLONE) == 0)
&& (strscpy(oui, xdata->gamepad->uniq, sizeof(oui)) == -E2BIG)
&& (kstrtou8(oui, 16, &oui_byte) == 0)
&& XPADNEO_OUI_MASK(oui_byte, XPADNEO_OUI_MASK_GAMESIR_NOVA)
&& ((xdata->quirks & XPADNEO_QUIRK_SIMPLE_CLONE) == 0)) {
&& XPADNEO_OUI_MASK(oui_byte, XPADNEO_OUI_MASK_GAMESIR_NOVA)) {
hid_info(hdev, "enabling heuristic GameSir Nova quirks\n");
xdata->quirks |= XPADNEO_QUIRK_SIMPLE_CLONE;
}
Expand Down
1 change: 1 addition & 0 deletions hid-xpadneo/src/xpadneo.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ do { \
#define XPADNEO_QUIRK_SHARE_BUTTON 64
#define XPADNEO_QUIRK_REVERSE_MASK 128
#define XPADNEO_QUIRK_SWAPPED_MASK 256
#define XPADNEO_QUIRK_NO_HEURISTICS 512

#define XPADNEO_QUIRK_NO_HAPTICS (XPADNEO_QUIRK_NO_PULSE|XPADNEO_QUIRK_NO_MOTOR_MASK)
#define XPADNEO_QUIRK_SIMPLE_CLONE (XPADNEO_QUIRK_NO_HAPTICS|XPADNEO_QUIRK_NO_TRIGGER_RUMBLE)
Expand Down

0 comments on commit 82326de

Please sign in to comment.