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
next prev 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.