public inbox for linux-input@vger.kernel.org
 help / color / mirror / Atom feed
From: Vicki Pfau <vi@endrift.com>
To: Dmitry Torokhov <dmitry.torokhov@gmail.com>, linux-input@vger.kernel.org
Cc: Vicki Pfau <vi@endrift.com>
Subject: [PATCH v3 04/10] Input: xbox_gip - Add HID relaying
Date: Mon,  9 Mar 2026 22:19:58 -0700	[thread overview]
Message-ID: <20260310052017.1289494-5-vi@endrift.com> (raw)
In-Reply-To: <20260310052017.1289494-1-vi@endrift.com>

GIP allows tunneling of HID packets, with the HID descriptor embedded in
the GIP metadata exchanged during the initial handshake. This patch creates
a hid_device for this HID descriptor if found, as well as relaying the HID
packets.

Signed-off-by: Vicki Pfau <vi@endrift.com>
---
 drivers/input/joystick/gip/gip-core.c | 95 ++++++++++++++++++++++++++-
 drivers/input/joystick/gip/gip.h      |  2 +
 2 files changed, 94 insertions(+), 3 deletions(-)

diff --git a/drivers/input/joystick/gip/gip-core.c b/drivers/input/joystick/gip/gip-core.c
index 223668ca2b2a9..7355737b29d19 100644
--- a/drivers/input/joystick/gip/gip-core.c
+++ b/drivers/input/joystick/gip/gip-core.c
@@ -547,6 +547,54 @@ int gip_send_vendor_message(struct gip_attachment *attachment,
 		bytes, num_bytes);
 }
 
+static int gip_hid_ll_parse(struct hid_device *hdev)
+{
+	struct gip_attachment *attachment = hdev->driver_data;
+
+	return hid_parse_report(hdev,
+		attachment->metadata.device.hid_descriptor,
+		attachment->metadata.device.hid_descriptor_size);
+}
+
+static int gip_hid_ll_start(struct hid_device *hdev)
+{
+	return 0;
+}
+
+static void gip_hid_ll_stop(struct hid_device *hdev)
+{
+}
+
+static int gip_hid_ll_open(struct hid_device *hdev)
+{
+	return 0;
+}
+
+static void gip_hid_ll_close(struct hid_device *hdev)
+{
+}
+
+static int gip_hid_ll_raw_request(struct hid_device *hdev,
+	unsigned char reportnum, uint8_t *buf, size_t count,
+	unsigned char report_type, int reqtype)
+{
+	/*
+	 * TODO: Based on the metadata, output reports appear to be possible,
+	 * but the chatpad doesn't have the LEDs it claims to support, so
+	 * it's not clear how to test we're sending them properly.
+	 */
+	return 0;
+}
+
+static const struct hid_ll_driver gip_hid_ll_driver = {
+	.parse = gip_hid_ll_parse,
+	.start = gip_hid_ll_start,
+	.stop = gip_hid_ll_stop,
+	.open = gip_hid_ll_open,
+	.close = gip_hid_ll_close,
+	.raw_request = gip_hid_ll_raw_request,
+};
+
 static void gip_metadata_free(struct device *dev, struct gip_metadata *metadata)
 {
 	devm_kfree(dev, metadata->device.audio_formats);
@@ -1350,8 +1398,36 @@ static int gip_send_init_sequence(struct gip_attachment *attachment)
 		if (rc)
 			return rc;
 	}
+	rc = 0;
 
-	return 0;
+	if (attachment->metadata.device.hid_descriptor) {
+		struct hid_device *hdev = hid_allocate_device();
+
+		if (IS_ERR(hdev))
+			return PTR_ERR(hdev);
+
+		hdev->ll_driver = &gip_hid_ll_driver;
+		hdev->bus = BUS_USB;
+		hdev->vendor = attachment->vendor_id;
+		hdev->product = attachment->product_id;
+		hdev->dev.parent = GIP_DEV(attachment);
+		hdev->driver_data = attachment;
+		if (attachment->name)
+			strscpy(hdev->name, attachment->name);
+		else
+			strscpy(hdev->name, "Xbox Chatpad");
+		strscpy(hdev->phys, attachment->phys);
+		rc = hid_add_device(hdev);
+		if (rc) {
+			dev_err(GIP_DEV(attachment), "HID device add failed: %d\n", rc);
+			hid_destroy_device(hdev);
+		} else {
+			rcu_assign_pointer(attachment->hdev, hdev);
+			synchronize_rcu();
+		}
+	}
+
+	return rc;
 }
 
 static void gip_fragment_timeout(struct work_struct *work)
@@ -1784,9 +1860,16 @@ static int gip_handle_command_firmware(struct gip_attachment *attachment,
 static int gip_handle_command_hid_report(struct gip_attachment *attachment,
 	const struct gip_header *header, uint8_t *bytes, int num_bytes)
 {
-	dev_warn(GIP_DEV(attachment), "Unimplemented HID report message\n");
+	struct hid_device *hdev;
 
-	return -ENOTSUPP;
+	guard(rcu)();
+	hdev = rcu_dereference(attachment->hdev);
+	if (hdev)
+		return hid_input_report(hdev, HID_INPUT_REPORT, bytes, num_bytes, true);
+
+	dev_warn(GIP_DEV(attachment), "Got HID report with no HID descriptor\n");
+
+	return -EINVAL;
 }
 
 static int gip_handle_command_extended(struct gip_attachment *attachment,
@@ -2501,6 +2584,7 @@ static int gip_shutdown(struct gip_device *device)
 	for (i = 0; i < MAX_ATTACHMENTS; i++) {
 		struct gip_attachment *attachment = device->attachments[i];
 		struct input_dev *input;
+		struct hid_device *hdev;
 
 		if (!attachment)
 			continue;
@@ -2511,14 +2595,19 @@ static int gip_shutdown(struct gip_device *device)
 
 			rcu_read_lock();
 			input = rcu_dereference(attachment->input);
+			hdev = rcu_dereference(attachment->hdev);
 			rcu_read_unlock();
 
 			rcu_assign_pointer(attachment->input, NULL);
+			rcu_assign_pointer(attachment->hdev, NULL);
 			synchronize_rcu();
 		}
 
 		if (input)
 			input_unregister_device(input);
+
+		if (hdev)
+			hid_destroy_device(hdev);
 	}
 
 	return 0;
diff --git a/drivers/input/joystick/gip/gip.h b/drivers/input/joystick/gip/gip.h
index 63b4929b14e7f..c9d1c4f16c760 100644
--- a/drivers/input/joystick/gip/gip.h
+++ b/drivers/input/joystick/gip/gip.h
@@ -12,6 +12,7 @@
 #ifndef _GIP_H
 #define _GIP_H
 
+#include <linux/hid.h>
 #ifdef CONFIG_JOYSTICK_XBOX_GIP_LEDS
 #include <linux/led-class-multicolor.h>
 #endif
@@ -221,6 +222,7 @@ struct gip_attachment {
 	int extra_axes;
 
 	bool dpad_as_buttons;
+	struct hid_device __rcu *hdev;
 };
 
 struct gip_urb {
-- 
2.53.0


  parent reply	other threads:[~2026-03-10  5:20 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-03-10  5:19 [PATCH v3 00/10] Input: xbox_gip - Add new driver for Xbox GIP Vicki Pfau
2026-03-10  5:19 ` [PATCH v3 01/10] " Vicki Pfau
2026-03-11  0:41   ` Vicki Pfau
2026-03-10  5:19 ` [PATCH v3 02/10] Input: xpad - Remove Xbox One support Vicki Pfau
2026-03-10  5:19 ` [PATCH v3 03/10] Input: xbox_gip - Add controllable LED support Vicki Pfau
2026-03-10  5:19 ` Vicki Pfau [this message]
2026-03-10  5:19 ` [PATCH v3 05/10] Input: xbox_gip - Add battery support Vicki Pfau
2026-03-10  5:20 ` [PATCH v3 06/10] Input: xbox_gip - Add arcade stick support Vicki Pfau
2026-03-10  5:20 ` [PATCH v3 07/10] Input: Add ABS_CLUTCH, HANDBRAKE, and SHIFTER Vicki Pfau
2026-03-10  5:20 ` [PATCH v3 08/10] HID: Map more automobile simulation inputs Vicki Pfau
2026-03-10  5:20 ` [PATCH v3 09/10] Input: xbox_gip - Add wheel support Vicki Pfau
2026-03-10  5:20 ` [PATCH v3 10/10] Input: xbox_gip - Add flight stick support Vicki Pfau
2026-03-10  5:23   ` Vicki Pfau

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260310052017.1289494-5-vi@endrift.com \
    --to=vi@endrift.com \
    --cc=dmitry.torokhov@gmail.com \
    --cc=linux-input@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox