All of lore.kernel.org
 help / color / mirror / Atom feed
From: Roderick Colenbrander <roderick@gaikai.com>
To: Jiri Kosina <jikos@kernel.org>,
	Benjamin Tissoires <benjamin.tissoires@redhat.com>
Cc: linux-input@vger.kernel.org, "Chris Ye" <lzye@google.com>,
	"Barnabás Pőcze" <pobrn@protonmail.com>,
	"Samuel Čavoj" <sammko@sammserver.com>,
	"Florian Märkl" <linux@florianmaerkl.de>,
	"Roderick Colenbrander" <roderick.colenbrander@sony.com>
Subject: [PATCH v5 07/13] HID: playstation: add DualSense Bluetooth support.
Date: Thu, 28 Jan 2021 09:26:51 -0800	[thread overview]
Message-ID: <20210128172657.24516-8-roderick@gaikai.com> (raw)
In-Reply-To: <20210128172657.24516-1-roderick@gaikai.com>

From: Roderick Colenbrander <roderick.colenbrander@sony.com>

This patch adds support for the DualSense when operating in Bluetooth mode.
The device has the same behavior as the DualShock 4 in that by default it
sends a limited input report (0x1), but after requesting calibration data,
it switches to an extended input report (report 49), which adds data for
touchpad, motion sensors, battery and more.

Signed-off-by: Roderick Colenbrander <roderick.colenbrander@sony.com>
---
 drivers/hid/Kconfig           |  1 +
 drivers/hid/hid-playstation.c | 41 +++++++++++++++++++++++++++++++++++
 2 files changed, 42 insertions(+)

diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 0c141f2312f7..b3ec01c7a0b7 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -856,6 +856,7 @@ config HID_PLANTRONICS
 config HID_PLAYSTATION
 	tristate "PlayStation HID Driver"
 	depends on HID
+	select CRC32
 	select POWER_SUPPLY
 	help
 	  Provides support for Sony PS5 controllers including support for
diff --git a/drivers/hid/hid-playstation.c b/drivers/hid/hid-playstation.c
index 0c3956756bf0..2da362d3dbda 100644
--- a/drivers/hid/hid-playstation.c
+++ b/drivers/hid/hid-playstation.c
@@ -6,6 +6,7 @@
  */
 
 #include <linux/bits.h>
+#include <linux/crc32.h>
 #include <linux/device.h>
 #include <linux/hid.h>
 #include <linux/input/mt.h>
@@ -45,8 +46,14 @@ struct ps_calibration_data {
 	int sens_denom;
 };
 
+/* Seed values for DualShock4 / DualSense CRC32 for different report types. */
+#define PS_INPUT_CRC32_SEED	0xA1
+#define PS_FEATURE_CRC32_SEED	0xA3
+
 #define DS_INPUT_REPORT_USB			0x01
 #define DS_INPUT_REPORT_USB_SIZE		64
+#define DS_INPUT_REPORT_BT			0x31
+#define DS_INPUT_REPORT_BT_SIZE			78
 
 #define DS_FEATURE_REPORT_CALIBRATION		0x05
 #define DS_FEATURE_REPORT_CALIBRATION_SIZE	41
@@ -292,6 +299,17 @@ static int ps_device_register_battery(struct ps_device *dev)
 	return 0;
 }
 
+/* Compute crc32 of HID data and compare against expected CRC. */
+static bool ps_check_crc32(uint8_t seed, uint8_t *data, size_t len, uint32_t report_crc)
+{
+	uint32_t crc;
+
+	crc = crc32_le(0xFFFFFFFF, &seed, 1);
+	crc = ~crc32_le(crc, data, len);
+
+	return crc == report_crc;
+}
+
 static struct input_dev *ps_gamepad_create(struct hid_device *hdev)
 {
 	struct input_dev *gamepad;
@@ -342,6 +360,17 @@ static int ps_get_report(struct hid_device *hdev, uint8_t report_id, uint8_t *bu
 		return -EINVAL;
 	}
 
+	if (hdev->bus == BUS_BLUETOOTH) {
+		/* Last 4 bytes contains crc32. */
+		uint8_t crc_offset = size - 4;
+		uint32_t report_crc = get_unaligned_le32(&buf[crc_offset]);
+
+		if (!ps_check_crc32(PS_FEATURE_CRC32_SEED, buf, crc_offset, report_crc)) {
+			hid_err(hdev, "CRC check failed for reportID=%d\n", report_id);
+			return -EILSEQ;
+		}
+	}
+
 	return 0;
 }
 
@@ -543,6 +572,17 @@ static int dualsense_parse_report(struct ps_device *ps_dev, struct hid_report *r
 	if (hdev->bus == BUS_USB && report->id == DS_INPUT_REPORT_USB &&
 			size == DS_INPUT_REPORT_USB_SIZE) {
 		ds_report = (struct dualsense_input_report *)&data[1];
+	} else if (hdev->bus == BUS_BLUETOOTH && report->id == DS_INPUT_REPORT_BT &&
+			size == DS_INPUT_REPORT_BT_SIZE) {
+		/* Last 4 bytes of input report contain crc32 */
+		uint32_t report_crc = get_unaligned_le32(&data[size - 4]);
+
+		if (!ps_check_crc32(PS_INPUT_CRC32_SEED, data, size - 4, report_crc)) {
+			hid_err(hdev, "DualSense input CRC's check failed\n");
+			return -EILSEQ;
+		}
+
+		ds_report = (struct dualsense_input_report *)&data[2];
 	} else {
 		hid_err(hdev, "Unhandled reportID=%d\n", report->id);
 		return -1;
@@ -806,6 +846,7 @@ static void ps_remove(struct hid_device *hdev)
 }
 
 static const struct hid_device_id ps_devices[] = {
+	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS5_CONTROLLER) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS5_CONTROLLER) },
 	{ }
 };
-- 
2.26.2


  parent reply	other threads:[~2021-01-28 17:30 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-01-28 17:26 [PATCH v5 00/13] HID: new driver for PS5 'DualSense' controller Roderick Colenbrander
2021-01-28 17:26 ` [PATCH v5 01/13] HID: playstation: initial DualSense USB support Roderick Colenbrander
2021-01-28 17:26 ` [PATCH v5 02/13] HID: playstation: use DualSense MAC address as unique identifier Roderick Colenbrander
2021-01-28 17:26 ` [PATCH v5 03/13] HID: playstation: add DualSense battery support Roderick Colenbrander
2021-01-28 17:26 ` [PATCH v5 04/13] HID: playstation: add DualSense touchpad support Roderick Colenbrander
2021-01-28 17:26 ` [PATCH v5 05/13] HID: playstation: add DualSense accelerometer and gyroscope support Roderick Colenbrander
2021-01-28 17:26 ` [PATCH v5 06/13] HID: playstation: track devices in list Roderick Colenbrander
2021-01-28 17:26 ` Roderick Colenbrander [this message]
2021-01-28 17:26 ` [PATCH v5 08/13] HID: playstation: add DualSense classic rumble support Roderick Colenbrander
2021-01-28 17:26 ` [PATCH v5 09/13] HID: playstation: add DualSense lightbar support Roderick Colenbrander
2021-01-28 17:26 ` [PATCH v5 10/13] HID: playstation: add microphone mute support for DualSense Roderick Colenbrander
2021-01-28 17:26 ` [PATCH v5 11/13] HID: playstation: add DualSense player LEDs support Roderick Colenbrander
2021-01-28 17:26 ` [PATCH v5 12/13] HID: playstation: DualSense set LEDs to default player id Roderick Colenbrander
2021-01-28 17:26 ` [PATCH v5 13/13] HID: playstation: report DualSense hardware and firmware version Roderick Colenbrander
2021-02-05 17:01 ` [PATCH v5 00/13] HID: new driver for PS5 'DualSense' controller Benjamin Tissoires
2021-02-06  4:03   ` Barnabás Pőcze
2021-02-07  6:05     ` Roderick Colenbrander

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=20210128172657.24516-8-roderick@gaikai.com \
    --to=roderick@gaikai.com \
    --cc=benjamin.tissoires@redhat.com \
    --cc=jikos@kernel.org \
    --cc=linux-input@vger.kernel.org \
    --cc=linux@florianmaerkl.de \
    --cc=lzye@google.com \
    --cc=pobrn@protonmail.com \
    --cc=roderick.colenbrander@sony.com \
    --cc=sammko@sammserver.com \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.