Skip to contentSkip to conversation

input: HID gamepad quirk system for broken SDP records

PATCH New Pakrohk 1 participant 2 messages Jul 22 Bluetooth drivers

lore
Share & tools
lore

Pakrohk

author
#0 lore raw

cover input: HID gamepad quirk system for broken SDP records

Some Bluetooth gamepads (like DualShock 4 v2) have incomplete or malformed HID SDP records, causing BlueZ to fail with -ENOENT. Windows and Android handle this gracefully; Linux does not.

This patch adds a minimal quirk system that only activates for specifically matched devices. When extract_hid_record() fails, the dispatcher tries built-in quirks before giving up. The quirk injects the correct BT HID report descriptor so the kernel's hid-playstation driver can create an input device.

The patch includes one quirk (TG170W / DualShock 4 v2) as an example. The system is modular -- new quirks can be added as separate files in quirks/.

I previously included an external quirk profile system (JSON + HMAC signatures) and a crypto extension to bt_crypto. Based on your feedback, I've stripped those out. The core quirk system works without them.

Questions:
1. Is this approach acceptable for upstream?
2. For external quirk profiles (user-installable via JSON), what crypto approach does BlueZ prefer? The existing bt_crypto uses AF_ALG which is being deprecated. Should I wait for an upstream decision, use a different library, or skip signatures entirely?

Pakrohk (1):
input: add HID gamepad quirk system for broken SDP records

 profiles/input/quirk.c         |  77 +++++++++++
 profiles/input/quirk.h         |  37 ++++++
 profiles/input/quirks/tg170w.c | 232 +++++++++++++++++++++++++++++++++
 3 files changed, 346 insertions(+)
 create mode 100644 profiles/input/quirk.c
 create mode 100644 profiles/input/quirk.h
 create mode 100644 profiles/input/quirks/tg170w.c
Signature · 1 line
2.54.0
author
#1 lore raw

PATCH 1/1 input: add HID gamepad quirk system for broken SDP records

Add a modular quirk system for third-party gamepad controllers that expose incomplete or malformed HID SDP records over Bluetooth.

When BlueZ fails to parse an SDP record (returns -ENOENT), the quirk system checks for known gamepads and injects a fallback HID report descriptor so the kernel HID driver can create an input device.

Currently supported:
- Sony DualShock 4 v2 (CUH-ZCT2x) / VID:054c PID:09cc

The quirk system uses multi-factor matching (VID/PID + device name + SDP provider) to avoid false positives. It does NOT globally weaken HID parsing - quirks only activate for specifically matched controllers.

---
 profiles/input/quirk.c         |  77 +++++++++++
 profiles/input/quirk.h         |  37 ++++++
 profiles/input/quirks/tg170w.c | 232 +++++++++++++++++++++++++++++++++
 3 files changed, 346 insertions(+)
 create mode 100644 profiles/input/quirk.c
 create mode 100644 profiles/input/quirk.h
 create mode 100644 profiles/input/quirks/tg170w.c
profiles/input/quirk.c new file +77 -0
new file mode 100644
index 0000000..053f45b
@@ -0,0 +1,77 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2026  Gamepad Quirk Support
+ *
+ *  Dispatcher for gamepad HID quirks. When BlueZ fails to parse an SDP
+ *  record for a known gamepad, this layer injects a fallback HID report
+ *  descriptor so the kernel HID driver can create an input device.
+ *
+ *  This does NOT weaken HID parsing globally — quirks only activate for
+ *  specifically matched controllers.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "bluetooth/bluetooth.h"
+#include "bluetooth/hidp.h"
+
+#include "src/log.h"
+
+#include "quirk.h"
+
+/* Individual quirk declarations */
+extern struct gamepad_quirk tg170w_quirk;
+
+static struct gamepad_quirk *quirks[] = {
+	&tg170w_quirk,
+	NULL
+};
+
+bool gamepad_quirk_match(struct input_device *idev)
+{
+	int i;
+
+	/* Check built-in quirks first */
+	for (i = 0; quirks[i]; i++) {
+		if (quirks[i]->match(idev))
+			return true;
+	}
+
+	/* Then check external (file-based) quirks */
+	if (external_quirk_match(idev))
+		return true;
+
+	return false;
+}
+
+int gamepad_quirk_apply(struct input_device *idev,
+			struct hidp_connadd_req *req)
+{
+	int i;
+
+	/* Try built-in quirks first */
+	for (i = 0; quirks[i]; i++) {
+		if (!quirks[i]->match(idev))
+			continue;
+
+		DBG("Applying HID quirk: %s", quirks[i]->name);
+
+		return quirks[i]->apply(idev, req);
+	}
+
+	/* Try external quirks */
+	if (external_quirk_match(idev)) {
+		return external_quirk_apply(idev, req);
+	}
+
+	return -1;
+}
profiles/input/quirk.h new file +37 -0
new file mode 100644
index 0000000..08e0bce
@@ -0,0 +1,37 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2026  Gamepad Quirk Support
+ *
+ *  Minimal HID fallback for third-party gamepads with broken SDP records.
+ *  Only activates for specifically matched devices.
+ */
+
+#ifndef __INPUT_QUIRK_H
+#define __INPUT_QUIRK_H
+
+#include <stdbool.h>
+
+struct input_device;
+struct hidp_connadd_req;
+
+struct gamepad_quirk {
+	const char *name;
+	bool (*match)(struct input_device *idev);
+	int (*apply)(struct input_device *idev,
+			struct hidp_connadd_req *req);
+};
+
+bool gamepad_quirk_match(struct input_device *idev);
+
+int gamepad_quirk_apply(struct input_device *idev,
+			struct hidp_connadd_req *req);
+
+/* External quirk support (quirk-profile.c) */
+bool external_quirk_match(struct input_device *idev);
+int external_quirk_apply(struct input_device *idev,
+			struct hidp_connadd_req *req);
+
+#endif
profiles/input/quirks/tg170w.c new file +232 -0

232 lines not on this page · raw message

Signature · 1 line
2.54.0