xref: /openbmc/linux/drivers/hid/hid-playstation.c (revision 9a87ffc99ec8eb8d35eed7c4f816d75f5cc9662e)
1bc2e15a9SRoderick Colenbrander // SPDX-License-Identifier: GPL-2.0-or-later
2bc2e15a9SRoderick Colenbrander /*
3bc2e15a9SRoderick Colenbrander  *  HID driver for Sony DualSense(TM) controller.
4bc2e15a9SRoderick Colenbrander  *
5f55b9b56SRoderick Colenbrander  *  Copyright (c) 2020-2022 Sony Interactive Entertainment
6bc2e15a9SRoderick Colenbrander  */
7bc2e15a9SRoderick Colenbrander 
8bc2e15a9SRoderick Colenbrander #include <linux/bits.h>
9799b2b53SRoderick Colenbrander #include <linux/crc32.h>
10bc2e15a9SRoderick Colenbrander #include <linux/device.h>
11bc2e15a9SRoderick Colenbrander #include <linux/hid.h>
12949aaccdSRoderick Colenbrander #include <linux/idr.h>
13bc2e15a9SRoderick Colenbrander #include <linux/input/mt.h>
14fc97b4d6SRoderick Colenbrander #include <linux/leds.h>
15fc97b4d6SRoderick Colenbrander #include <linux/led-class-multicolor.h>
16bc2e15a9SRoderick Colenbrander #include <linux/module.h>
17bc2e15a9SRoderick Colenbrander 
18bc2e15a9SRoderick Colenbrander #include <asm/unaligned.h>
19bc2e15a9SRoderick Colenbrander 
20bc2e15a9SRoderick Colenbrander #include "hid-ids.h"
21bc2e15a9SRoderick Colenbrander 
2253f04e83SRoderick Colenbrander /* List of connected playstation devices. */
2353f04e83SRoderick Colenbrander static DEFINE_MUTEX(ps_devices_lock);
2453f04e83SRoderick Colenbrander static LIST_HEAD(ps_devices_list);
2553f04e83SRoderick Colenbrander 
26949aaccdSRoderick Colenbrander static DEFINE_IDA(ps_player_id_allocator);
27949aaccdSRoderick Colenbrander 
28bc2e15a9SRoderick Colenbrander #define HID_PLAYSTATION_VERSION_PATCH 0x8000
29bc2e15a9SRoderick Colenbrander 
30bc2e15a9SRoderick Colenbrander /* Base class for playstation devices. */
31bc2e15a9SRoderick Colenbrander struct ps_device {
3253f04e83SRoderick Colenbrander 	struct list_head list;
33bc2e15a9SRoderick Colenbrander 	struct hid_device *hdev;
34d30bca44SRoderick Colenbrander 	spinlock_t lock;
35d30bca44SRoderick Colenbrander 
36949aaccdSRoderick Colenbrander 	uint32_t player_id;
37949aaccdSRoderick Colenbrander 
38d30bca44SRoderick Colenbrander 	struct power_supply_desc battery_desc;
39d30bca44SRoderick Colenbrander 	struct power_supply *battery;
40d30bca44SRoderick Colenbrander 	uint8_t battery_capacity;
41d30bca44SRoderick Colenbrander 	int battery_status;
42d30bca44SRoderick Colenbrander 
43fc97b4d6SRoderick Colenbrander 	const char *input_dev_name; /* Name of primary input device. */
44b99dcefdSRoderick Colenbrander 	uint8_t mac_address[6]; /* Note: stored in little endian order. */
450b25b55dSRoderick Colenbrander 	uint32_t hw_version;
460b25b55dSRoderick Colenbrander 	uint32_t fw_version;
47bc2e15a9SRoderick Colenbrander 
48bc2e15a9SRoderick Colenbrander 	int (*parse_report)(struct ps_device *dev, struct hid_report *report, u8 *data, int size);
49182934a1SRoderick Colenbrander 	void (*remove)(struct ps_device *dev);
50bc2e15a9SRoderick Colenbrander };
51bc2e15a9SRoderick Colenbrander 
52402987c5SRoderick Colenbrander /* Calibration data for playstation motion sensors. */
53402987c5SRoderick Colenbrander struct ps_calibration_data {
54402987c5SRoderick Colenbrander 	int abs_code;
55402987c5SRoderick Colenbrander 	short bias;
56402987c5SRoderick Colenbrander 	int sens_numer;
57402987c5SRoderick Colenbrander 	int sens_denom;
58402987c5SRoderick Colenbrander };
59402987c5SRoderick Colenbrander 
608c0ab553SRoderick Colenbrander struct ps_led_info {
618c0ab553SRoderick Colenbrander 	const char *name;
628c0ab553SRoderick Colenbrander 	const char *color;
63316f57fbSRoderick Colenbrander 	int max_brightness;
648c0ab553SRoderick Colenbrander 	enum led_brightness (*brightness_get)(struct led_classdev *cdev);
658c0ab553SRoderick Colenbrander 	int (*brightness_set)(struct led_classdev *cdev, enum led_brightness);
6682d93f64SRoderick Colenbrander 	int (*blink_set)(struct led_classdev *led, unsigned long *on, unsigned long *off);
678c0ab553SRoderick Colenbrander };
688c0ab553SRoderick Colenbrander 
69799b2b53SRoderick Colenbrander /* Seed values for DualShock4 / DualSense CRC32 for different report types. */
70799b2b53SRoderick Colenbrander #define PS_INPUT_CRC32_SEED	0xA1
7151151098SRoderick Colenbrander #define PS_OUTPUT_CRC32_SEED	0xA2
72799b2b53SRoderick Colenbrander #define PS_FEATURE_CRC32_SEED	0xA3
73799b2b53SRoderick Colenbrander 
74bc2e15a9SRoderick Colenbrander #define DS_INPUT_REPORT_USB			0x01
75bc2e15a9SRoderick Colenbrander #define DS_INPUT_REPORT_USB_SIZE		64
76799b2b53SRoderick Colenbrander #define DS_INPUT_REPORT_BT			0x31
77799b2b53SRoderick Colenbrander #define DS_INPUT_REPORT_BT_SIZE			78
7851151098SRoderick Colenbrander #define DS_OUTPUT_REPORT_USB			0x02
7951151098SRoderick Colenbrander #define DS_OUTPUT_REPORT_USB_SIZE		63
8051151098SRoderick Colenbrander #define DS_OUTPUT_REPORT_BT			0x31
8151151098SRoderick Colenbrander #define DS_OUTPUT_REPORT_BT_SIZE		78
82bc2e15a9SRoderick Colenbrander 
83402987c5SRoderick Colenbrander #define DS_FEATURE_REPORT_CALIBRATION		0x05
84402987c5SRoderick Colenbrander #define DS_FEATURE_REPORT_CALIBRATION_SIZE	41
85b99dcefdSRoderick Colenbrander #define DS_FEATURE_REPORT_PAIRING_INFO		0x09
86b99dcefdSRoderick Colenbrander #define DS_FEATURE_REPORT_PAIRING_INFO_SIZE	20
870b25b55dSRoderick Colenbrander #define DS_FEATURE_REPORT_FIRMWARE_INFO		0x20
880b25b55dSRoderick Colenbrander #define DS_FEATURE_REPORT_FIRMWARE_INFO_SIZE	64
89b99dcefdSRoderick Colenbrander 
90bc2e15a9SRoderick Colenbrander /* Button masks for DualSense input report. */
91bc2e15a9SRoderick Colenbrander #define DS_BUTTONS0_HAT_SWITCH	GENMASK(3, 0)
92bc2e15a9SRoderick Colenbrander #define DS_BUTTONS0_SQUARE	BIT(4)
93bc2e15a9SRoderick Colenbrander #define DS_BUTTONS0_CROSS	BIT(5)
94bc2e15a9SRoderick Colenbrander #define DS_BUTTONS0_CIRCLE	BIT(6)
95bc2e15a9SRoderick Colenbrander #define DS_BUTTONS0_TRIANGLE	BIT(7)
96bc2e15a9SRoderick Colenbrander #define DS_BUTTONS1_L1		BIT(0)
97bc2e15a9SRoderick Colenbrander #define DS_BUTTONS1_R1		BIT(1)
98bc2e15a9SRoderick Colenbrander #define DS_BUTTONS1_L2		BIT(2)
99bc2e15a9SRoderick Colenbrander #define DS_BUTTONS1_R2		BIT(3)
100bc2e15a9SRoderick Colenbrander #define DS_BUTTONS1_CREATE	BIT(4)
101bc2e15a9SRoderick Colenbrander #define DS_BUTTONS1_OPTIONS	BIT(5)
102bc2e15a9SRoderick Colenbrander #define DS_BUTTONS1_L3		BIT(6)
103bc2e15a9SRoderick Colenbrander #define DS_BUTTONS1_R3		BIT(7)
104bc2e15a9SRoderick Colenbrander #define DS_BUTTONS2_PS_HOME	BIT(0)
105bc2e15a9SRoderick Colenbrander #define DS_BUTTONS2_TOUCHPAD	BIT(1)
106c26e48b1SRoderick Colenbrander #define DS_BUTTONS2_MIC_MUTE	BIT(2)
107bc2e15a9SRoderick Colenbrander 
108d30bca44SRoderick Colenbrander /* Status field of DualSense input report. */
109d30bca44SRoderick Colenbrander #define DS_STATUS_BATTERY_CAPACITY	GENMASK(3, 0)
110d30bca44SRoderick Colenbrander #define DS_STATUS_CHARGING		GENMASK(7, 4)
111d30bca44SRoderick Colenbrander #define DS_STATUS_CHARGING_SHIFT	4
112d30bca44SRoderick Colenbrander 
1139fecab24SRoderick Colenbrander /* Feature version from DualSense Firmware Info report. */
1149fecab24SRoderick Colenbrander #define DS_FEATURE_VERSION(major, minor) ((major & 0xff) << 8 | (minor & 0xff))
1159fecab24SRoderick Colenbrander 
116f6bb05fcSRoderick Colenbrander /*
117f6bb05fcSRoderick Colenbrander  * Status of a DualSense touch point contact.
118f6bb05fcSRoderick Colenbrander  * Contact IDs, with highest bit set are 'inactive'
119f6bb05fcSRoderick Colenbrander  * and any associated data is then invalid.
120f6bb05fcSRoderick Colenbrander  */
121f6bb05fcSRoderick Colenbrander #define DS_TOUCH_POINT_INACTIVE BIT(7)
122f6bb05fcSRoderick Colenbrander 
12351151098SRoderick Colenbrander  /* Magic value required in tag field of Bluetooth output report. */
12451151098SRoderick Colenbrander #define DS_OUTPUT_TAG 0x10
12551151098SRoderick Colenbrander /* Flags for DualSense output report. */
12651151098SRoderick Colenbrander #define DS_OUTPUT_VALID_FLAG0_COMPATIBLE_VIBRATION BIT(0)
12751151098SRoderick Colenbrander #define DS_OUTPUT_VALID_FLAG0_HAPTICS_SELECT BIT(1)
128c26e48b1SRoderick Colenbrander #define DS_OUTPUT_VALID_FLAG1_MIC_MUTE_LED_CONTROL_ENABLE BIT(0)
129c26e48b1SRoderick Colenbrander #define DS_OUTPUT_VALID_FLAG1_POWER_SAVE_CONTROL_ENABLE BIT(1)
1308e5198a1SRoderick Colenbrander #define DS_OUTPUT_VALID_FLAG1_LIGHTBAR_CONTROL_ENABLE BIT(2)
1318e5198a1SRoderick Colenbrander #define DS_OUTPUT_VALID_FLAG1_RELEASE_LEDS BIT(3)
132949aaccdSRoderick Colenbrander #define DS_OUTPUT_VALID_FLAG1_PLAYER_INDICATOR_CONTROL_ENABLE BIT(4)
1338e5198a1SRoderick Colenbrander #define DS_OUTPUT_VALID_FLAG2_LIGHTBAR_SETUP_CONTROL_ENABLE BIT(1)
1349fecab24SRoderick Colenbrander #define DS_OUTPUT_VALID_FLAG2_COMPATIBLE_VIBRATION2 BIT(2)
135c26e48b1SRoderick Colenbrander #define DS_OUTPUT_POWER_SAVE_CONTROL_MIC_MUTE BIT(4)
1368e5198a1SRoderick Colenbrander #define DS_OUTPUT_LIGHTBAR_SETUP_LIGHT_OUT BIT(1)
13751151098SRoderick Colenbrander 
138f6bb05fcSRoderick Colenbrander /* DualSense hardware limits */
139402987c5SRoderick Colenbrander #define DS_ACC_RES_PER_G	8192
140402987c5SRoderick Colenbrander #define DS_ACC_RANGE		(4*DS_ACC_RES_PER_G)
141402987c5SRoderick Colenbrander #define DS_GYRO_RES_PER_DEG_S	1024
142402987c5SRoderick Colenbrander #define DS_GYRO_RANGE		(2048*DS_GYRO_RES_PER_DEG_S)
143f6bb05fcSRoderick Colenbrander #define DS_TOUCHPAD_WIDTH	1920
144f6bb05fcSRoderick Colenbrander #define DS_TOUCHPAD_HEIGHT	1080
145f6bb05fcSRoderick Colenbrander 
146bc2e15a9SRoderick Colenbrander struct dualsense {
147bc2e15a9SRoderick Colenbrander 	struct ps_device base;
148bc2e15a9SRoderick Colenbrander 	struct input_dev *gamepad;
149402987c5SRoderick Colenbrander 	struct input_dev *sensors;
150f6bb05fcSRoderick Colenbrander 	struct input_dev *touchpad;
151402987c5SRoderick Colenbrander 
1529fecab24SRoderick Colenbrander 	/* Update version is used as a feature/capability version. */
1539fecab24SRoderick Colenbrander 	uint16_t update_version;
1549fecab24SRoderick Colenbrander 
155402987c5SRoderick Colenbrander 	/* Calibration data for accelerometer and gyroscope. */
156402987c5SRoderick Colenbrander 	struct ps_calibration_data accel_calib_data[3];
157402987c5SRoderick Colenbrander 	struct ps_calibration_data gyro_calib_data[3];
158402987c5SRoderick Colenbrander 
159402987c5SRoderick Colenbrander 	/* Timestamp for sensor data */
160402987c5SRoderick Colenbrander 	bool sensor_timestamp_initialized;
161402987c5SRoderick Colenbrander 	uint32_t prev_sensor_timestamp;
162402987c5SRoderick Colenbrander 	uint32_t sensor_timestamp_us;
16351151098SRoderick Colenbrander 
16451151098SRoderick Colenbrander 	/* Compatible rumble state */
1659fecab24SRoderick Colenbrander 	bool use_vibration_v2;
16651151098SRoderick Colenbrander 	bool update_rumble;
16751151098SRoderick Colenbrander 	uint8_t motor_left;
16851151098SRoderick Colenbrander 	uint8_t motor_right;
16951151098SRoderick Colenbrander 
1708e5198a1SRoderick Colenbrander 	/* RGB lightbar */
171fc97b4d6SRoderick Colenbrander 	struct led_classdev_mc lightbar;
1728e5198a1SRoderick Colenbrander 	bool update_lightbar;
1738e5198a1SRoderick Colenbrander 	uint8_t lightbar_red;
1748e5198a1SRoderick Colenbrander 	uint8_t lightbar_green;
1758e5198a1SRoderick Colenbrander 	uint8_t lightbar_blue;
1768e5198a1SRoderick Colenbrander 
177c26e48b1SRoderick Colenbrander 	/* Microphone */
178c26e48b1SRoderick Colenbrander 	bool update_mic_mute;
179c26e48b1SRoderick Colenbrander 	bool mic_muted;
180c26e48b1SRoderick Colenbrander 	bool last_btn_mic_state;
181c26e48b1SRoderick Colenbrander 
182949aaccdSRoderick Colenbrander 	/* Player leds */
183949aaccdSRoderick Colenbrander 	bool update_player_leds;
184949aaccdSRoderick Colenbrander 	uint8_t player_leds_state;
185949aaccdSRoderick Colenbrander 	struct led_classdev player_leds[5];
186949aaccdSRoderick Colenbrander 
18751151098SRoderick Colenbrander 	struct work_struct output_worker;
188182934a1SRoderick Colenbrander 	bool output_worker_initialized;
18951151098SRoderick Colenbrander 	void *output_report_dmabuf;
19051151098SRoderick Colenbrander 	uint8_t output_seq; /* Sequence number for output report. */
191bc2e15a9SRoderick Colenbrander };
192bc2e15a9SRoderick Colenbrander 
193bc2e15a9SRoderick Colenbrander struct dualsense_touch_point {
194bc2e15a9SRoderick Colenbrander 	uint8_t contact;
195bc2e15a9SRoderick Colenbrander 	uint8_t x_lo;
196bc2e15a9SRoderick Colenbrander 	uint8_t x_hi:4, y_lo:4;
197bc2e15a9SRoderick Colenbrander 	uint8_t y_hi;
198bc2e15a9SRoderick Colenbrander } __packed;
199bc2e15a9SRoderick Colenbrander static_assert(sizeof(struct dualsense_touch_point) == 4);
200bc2e15a9SRoderick Colenbrander 
201bc2e15a9SRoderick Colenbrander /* Main DualSense input report excluding any BT/USB specific headers. */
202bc2e15a9SRoderick Colenbrander struct dualsense_input_report {
203bc2e15a9SRoderick Colenbrander 	uint8_t x, y;
204bc2e15a9SRoderick Colenbrander 	uint8_t rx, ry;
205bc2e15a9SRoderick Colenbrander 	uint8_t z, rz;
206bc2e15a9SRoderick Colenbrander 	uint8_t seq_number;
207bc2e15a9SRoderick Colenbrander 	uint8_t buttons[4];
208bc2e15a9SRoderick Colenbrander 	uint8_t reserved[4];
209bc2e15a9SRoderick Colenbrander 
210bc2e15a9SRoderick Colenbrander 	/* Motion sensors */
211bc2e15a9SRoderick Colenbrander 	__le16 gyro[3]; /* x, y, z */
212bc2e15a9SRoderick Colenbrander 	__le16 accel[3]; /* x, y, z */
213bc2e15a9SRoderick Colenbrander 	__le32 sensor_timestamp;
214bc2e15a9SRoderick Colenbrander 	uint8_t reserved2;
215bc2e15a9SRoderick Colenbrander 
216bc2e15a9SRoderick Colenbrander 	/* Touchpad */
217bc2e15a9SRoderick Colenbrander 	struct dualsense_touch_point points[2];
218bc2e15a9SRoderick Colenbrander 
219bc2e15a9SRoderick Colenbrander 	uint8_t reserved3[12];
220bc2e15a9SRoderick Colenbrander 	uint8_t status;
221bc2e15a9SRoderick Colenbrander 	uint8_t reserved4[10];
222bc2e15a9SRoderick Colenbrander } __packed;
223bc2e15a9SRoderick Colenbrander /* Common input report size shared equals the size of the USB report minus 1 byte for ReportID. */
224bc2e15a9SRoderick Colenbrander static_assert(sizeof(struct dualsense_input_report) == DS_INPUT_REPORT_USB_SIZE - 1);
225bc2e15a9SRoderick Colenbrander 
22651151098SRoderick Colenbrander /* Common data between DualSense BT/USB main output report. */
22751151098SRoderick Colenbrander struct dualsense_output_report_common {
22851151098SRoderick Colenbrander 	uint8_t valid_flag0;
22951151098SRoderick Colenbrander 	uint8_t valid_flag1;
23051151098SRoderick Colenbrander 
23151151098SRoderick Colenbrander 	/* For DualShock 4 compatibility mode. */
23251151098SRoderick Colenbrander 	uint8_t motor_right;
23351151098SRoderick Colenbrander 	uint8_t motor_left;
23451151098SRoderick Colenbrander 
23551151098SRoderick Colenbrander 	/* Audio controls */
23651151098SRoderick Colenbrander 	uint8_t reserved[4];
23751151098SRoderick Colenbrander 	uint8_t mute_button_led;
23851151098SRoderick Colenbrander 
23951151098SRoderick Colenbrander 	uint8_t power_save_control;
24051151098SRoderick Colenbrander 	uint8_t reserved2[28];
24151151098SRoderick Colenbrander 
24251151098SRoderick Colenbrander 	/* LEDs and lightbar */
24351151098SRoderick Colenbrander 	uint8_t valid_flag2;
24451151098SRoderick Colenbrander 	uint8_t reserved3[2];
24551151098SRoderick Colenbrander 	uint8_t lightbar_setup;
24651151098SRoderick Colenbrander 	uint8_t led_brightness;
24751151098SRoderick Colenbrander 	uint8_t player_leds;
24851151098SRoderick Colenbrander 	uint8_t lightbar_red;
24951151098SRoderick Colenbrander 	uint8_t lightbar_green;
25051151098SRoderick Colenbrander 	uint8_t lightbar_blue;
25151151098SRoderick Colenbrander } __packed;
25251151098SRoderick Colenbrander static_assert(sizeof(struct dualsense_output_report_common) == 47);
25351151098SRoderick Colenbrander 
25451151098SRoderick Colenbrander struct dualsense_output_report_bt {
25551151098SRoderick Colenbrander 	uint8_t report_id; /* 0x31 */
25651151098SRoderick Colenbrander 	uint8_t seq_tag;
25751151098SRoderick Colenbrander 	uint8_t tag;
25851151098SRoderick Colenbrander 	struct dualsense_output_report_common common;
25951151098SRoderick Colenbrander 	uint8_t reserved[24];
26051151098SRoderick Colenbrander 	__le32 crc32;
26151151098SRoderick Colenbrander } __packed;
26251151098SRoderick Colenbrander static_assert(sizeof(struct dualsense_output_report_bt) == DS_OUTPUT_REPORT_BT_SIZE);
26351151098SRoderick Colenbrander 
26451151098SRoderick Colenbrander struct dualsense_output_report_usb {
26551151098SRoderick Colenbrander 	uint8_t report_id; /* 0x02 */
26651151098SRoderick Colenbrander 	struct dualsense_output_report_common common;
26751151098SRoderick Colenbrander 	uint8_t reserved[15];
26851151098SRoderick Colenbrander } __packed;
26951151098SRoderick Colenbrander static_assert(sizeof(struct dualsense_output_report_usb) == DS_OUTPUT_REPORT_USB_SIZE);
27051151098SRoderick Colenbrander 
27151151098SRoderick Colenbrander /*
27251151098SRoderick Colenbrander  * The DualSense has a main output report used to control most features. It is
27351151098SRoderick Colenbrander  * largely the same between Bluetooth and USB except for different headers and CRC.
27451151098SRoderick Colenbrander  * This structure hide the differences between the two to simplify sending output reports.
27551151098SRoderick Colenbrander  */
27651151098SRoderick Colenbrander struct dualsense_output_report {
27751151098SRoderick Colenbrander 	uint8_t *data; /* Start of data */
27851151098SRoderick Colenbrander 	uint8_t len; /* Size of output report */
27951151098SRoderick Colenbrander 
28051151098SRoderick Colenbrander 	/* Points to Bluetooth data payload in case for a Bluetooth report else NULL. */
28151151098SRoderick Colenbrander 	struct dualsense_output_report_bt *bt;
28251151098SRoderick Colenbrander 	/* Points to USB data payload in case for a USB report else NULL. */
28351151098SRoderick Colenbrander 	struct dualsense_output_report_usb *usb;
28451151098SRoderick Colenbrander 	/* Points to common section of report, so past any headers. */
28551151098SRoderick Colenbrander 	struct dualsense_output_report_common *common;
28651151098SRoderick Colenbrander };
28751151098SRoderick Colenbrander 
288f55b9b56SRoderick Colenbrander #define DS4_INPUT_REPORT_USB			0x01
289f55b9b56SRoderick Colenbrander #define DS4_INPUT_REPORT_USB_SIZE		64
2902d77474aSRoderick Colenbrander #define DS4_INPUT_REPORT_BT			0x11
2912d77474aSRoderick Colenbrander #define DS4_INPUT_REPORT_BT_SIZE		78
2924e463ec4SRoderick Colenbrander #define DS4_OUTPUT_REPORT_USB			0x05
2934e463ec4SRoderick Colenbrander #define DS4_OUTPUT_REPORT_USB_SIZE		32
2942d77474aSRoderick Colenbrander #define DS4_OUTPUT_REPORT_BT			0x11
2952d77474aSRoderick Colenbrander #define DS4_OUTPUT_REPORT_BT_SIZE		78
296f55b9b56SRoderick Colenbrander 
29712882ed8SRoderick Colenbrander #define DS4_FEATURE_REPORT_CALIBRATION		0x02
29812882ed8SRoderick Colenbrander #define DS4_FEATURE_REPORT_CALIBRATION_SIZE	37
2992d77474aSRoderick Colenbrander #define DS4_FEATURE_REPORT_CALIBRATION_BT	0x05
3002d77474aSRoderick Colenbrander #define DS4_FEATURE_REPORT_CALIBRATION_BT_SIZE	41
3019a62280aSRoderick Colenbrander #define DS4_FEATURE_REPORT_FIRMWARE_INFO	0xa3
3029a62280aSRoderick Colenbrander #define DS4_FEATURE_REPORT_FIRMWARE_INFO_SIZE	49
303f55b9b56SRoderick Colenbrander #define DS4_FEATURE_REPORT_PAIRING_INFO		0x12
304f55b9b56SRoderick Colenbrander #define DS4_FEATURE_REPORT_PAIRING_INFO_SIZE	16
305f55b9b56SRoderick Colenbrander 
30675203824SRoderick Colenbrander /*
30775203824SRoderick Colenbrander  * Status of a DualShock4 touch point contact.
30875203824SRoderick Colenbrander  * Contact IDs, with highest bit set are 'inactive'
30975203824SRoderick Colenbrander  * and any associated data is then invalid.
31075203824SRoderick Colenbrander  */
31175203824SRoderick Colenbrander #define DS4_TOUCH_POINT_INACTIVE BIT(7)
31275203824SRoderick Colenbrander 
3138871ed30SRoderick Colenbrander /* Status field of DualShock4 input report. */
3148871ed30SRoderick Colenbrander #define DS4_STATUS0_BATTERY_CAPACITY	GENMASK(3, 0)
3158871ed30SRoderick Colenbrander #define DS4_STATUS0_CABLE_STATE		BIT(4)
3168871ed30SRoderick Colenbrander /* Battery status within batery_status field. */
3178871ed30SRoderick Colenbrander #define DS4_BATTERY_STATUS_FULL		11
318c64ed0cdSRoderick Colenbrander /* Status1 bit2 contains dongle connection state:
319c64ed0cdSRoderick Colenbrander  * 0 = connectd
320c64ed0cdSRoderick Colenbrander  * 1 = disconnected
321c64ed0cdSRoderick Colenbrander  */
322c64ed0cdSRoderick Colenbrander #define DS4_STATUS1_DONGLE_STATE	BIT(2)
3238871ed30SRoderick Colenbrander 
32458feecb4SRoderick Colenbrander /* The lower 6 bits of hw_control of the Bluetooth main output report
32558feecb4SRoderick Colenbrander  * control the interval at which Dualshock 4 reports data:
32658feecb4SRoderick Colenbrander  * 0x00 - 1ms
32758feecb4SRoderick Colenbrander  * 0x01 - 1ms
32858feecb4SRoderick Colenbrander  * 0x02 - 2ms
32958feecb4SRoderick Colenbrander  * 0x3E - 62ms
33058feecb4SRoderick Colenbrander  * 0x3F - disabled
33158feecb4SRoderick Colenbrander  */
33258feecb4SRoderick Colenbrander #define DS4_OUTPUT_HWCTL_BT_POLL_MASK	0x3F
33358feecb4SRoderick Colenbrander /* Default to 4ms poll interval, which is same as USB (not adjustable). */
33458feecb4SRoderick Colenbrander #define DS4_BT_DEFAULT_POLL_INTERVAL_MS	4
3352d77474aSRoderick Colenbrander #define DS4_OUTPUT_HWCTL_CRC32		0x40
3362d77474aSRoderick Colenbrander #define DS4_OUTPUT_HWCTL_HID		0x80
3372d77474aSRoderick Colenbrander 
3384e463ec4SRoderick Colenbrander /* Flags for DualShock4 output report. */
3394e463ec4SRoderick Colenbrander #define DS4_OUTPUT_VALID_FLAG0_MOTOR		0x01
3404521109aSRoderick Colenbrander #define DS4_OUTPUT_VALID_FLAG0_LED		0x02
3414521109aSRoderick Colenbrander #define DS4_OUTPUT_VALID_FLAG0_LED_BLINK	0x04
3424e463ec4SRoderick Colenbrander 
34375203824SRoderick Colenbrander /* DualShock4 hardware limits */
34412882ed8SRoderick Colenbrander #define DS4_ACC_RES_PER_G	8192
34512882ed8SRoderick Colenbrander #define DS4_ACC_RANGE		(4*DS_ACC_RES_PER_G)
34612882ed8SRoderick Colenbrander #define DS4_GYRO_RES_PER_DEG_S	1024
34712882ed8SRoderick Colenbrander #define DS4_GYRO_RANGE		(2048*DS_GYRO_RES_PER_DEG_S)
34882d93f64SRoderick Colenbrander #define DS4_LIGHTBAR_MAX_BLINK	255 /* 255 centiseconds */
34975203824SRoderick Colenbrander #define DS4_TOUCHPAD_WIDTH	1920
35075203824SRoderick Colenbrander #define DS4_TOUCHPAD_HEIGHT	942
35175203824SRoderick Colenbrander 
352c64ed0cdSRoderick Colenbrander enum dualshock4_dongle_state {
353c64ed0cdSRoderick Colenbrander 	DONGLE_DISCONNECTED,
354c64ed0cdSRoderick Colenbrander 	DONGLE_CALIBRATING,
355c64ed0cdSRoderick Colenbrander 	DONGLE_CONNECTED,
356c64ed0cdSRoderick Colenbrander 	DONGLE_DISABLED
357c64ed0cdSRoderick Colenbrander };
358c64ed0cdSRoderick Colenbrander 
359f55b9b56SRoderick Colenbrander struct dualshock4 {
360f55b9b56SRoderick Colenbrander 	struct ps_device base;
361f55b9b56SRoderick Colenbrander 	struct input_dev *gamepad;
36212882ed8SRoderick Colenbrander 	struct input_dev *sensors;
36375203824SRoderick Colenbrander 	struct input_dev *touchpad;
36412882ed8SRoderick Colenbrander 
36512882ed8SRoderick Colenbrander 	/* Calibration data for accelerometer and gyroscope. */
36612882ed8SRoderick Colenbrander 	struct ps_calibration_data accel_calib_data[3];
36712882ed8SRoderick Colenbrander 	struct ps_calibration_data gyro_calib_data[3];
36812882ed8SRoderick Colenbrander 
369c64ed0cdSRoderick Colenbrander 	/* Only used on dongle to track state transitions. */
370c64ed0cdSRoderick Colenbrander 	enum dualshock4_dongle_state dongle_state;
371c64ed0cdSRoderick Colenbrander 	/* Used during calibration. */
372c64ed0cdSRoderick Colenbrander 	struct work_struct dongle_hotplug_worker;
373c64ed0cdSRoderick Colenbrander 
37412882ed8SRoderick Colenbrander 	/* Timestamp for sensor data */
37512882ed8SRoderick Colenbrander 	bool sensor_timestamp_initialized;
37612882ed8SRoderick Colenbrander 	uint32_t prev_sensor_timestamp;
37712882ed8SRoderick Colenbrander 	uint32_t sensor_timestamp_us;
3784e463ec4SRoderick Colenbrander 
37958feecb4SRoderick Colenbrander 	/* Bluetooth poll interval */
38058feecb4SRoderick Colenbrander 	bool update_bt_poll_interval;
38158feecb4SRoderick Colenbrander 	uint8_t bt_poll_interval;
38258feecb4SRoderick Colenbrander 
3834e463ec4SRoderick Colenbrander 	bool update_rumble;
3844e463ec4SRoderick Colenbrander 	uint8_t motor_left;
3854e463ec4SRoderick Colenbrander 	uint8_t motor_right;
3864e463ec4SRoderick Colenbrander 
3874521109aSRoderick Colenbrander 	/* Lightbar leds */
3884521109aSRoderick Colenbrander 	bool update_lightbar;
38982d93f64SRoderick Colenbrander 	bool update_lightbar_blink;
3904521109aSRoderick Colenbrander 	bool lightbar_enabled; /* For use by global LED control. */
3914521109aSRoderick Colenbrander 	uint8_t lightbar_red;
3924521109aSRoderick Colenbrander 	uint8_t lightbar_green;
3934521109aSRoderick Colenbrander 	uint8_t lightbar_blue;
39482d93f64SRoderick Colenbrander 	uint8_t lightbar_blink_on; /* In increments of 10ms. */
39582d93f64SRoderick Colenbrander 	uint8_t lightbar_blink_off; /* In increments of 10ms. */
3964521109aSRoderick Colenbrander 	struct led_classdev lightbar_leds[4];
3974521109aSRoderick Colenbrander 
3984e463ec4SRoderick Colenbrander 	struct work_struct output_worker;
3994e463ec4SRoderick Colenbrander 	bool output_worker_initialized;
4004e463ec4SRoderick Colenbrander 	void *output_report_dmabuf;
401f55b9b56SRoderick Colenbrander };
402f55b9b56SRoderick Colenbrander 
40375203824SRoderick Colenbrander struct dualshock4_touch_point {
40475203824SRoderick Colenbrander 	uint8_t contact;
40575203824SRoderick Colenbrander 	uint8_t x_lo;
40675203824SRoderick Colenbrander 	uint8_t x_hi:4, y_lo:4;
40775203824SRoderick Colenbrander 	uint8_t y_hi;
40875203824SRoderick Colenbrander } __packed;
40975203824SRoderick Colenbrander static_assert(sizeof(struct dualshock4_touch_point) == 4);
41075203824SRoderick Colenbrander 
41175203824SRoderick Colenbrander struct dualshock4_touch_report {
41275203824SRoderick Colenbrander 	uint8_t timestamp;
41375203824SRoderick Colenbrander 	struct dualshock4_touch_point points[2];
41475203824SRoderick Colenbrander } __packed;
41575203824SRoderick Colenbrander static_assert(sizeof(struct dualshock4_touch_report) == 9);
41675203824SRoderick Colenbrander 
417f55b9b56SRoderick Colenbrander /* Main DualShock4 input report excluding any BT/USB specific headers. */
418f55b9b56SRoderick Colenbrander struct dualshock4_input_report_common {
419f55b9b56SRoderick Colenbrander 	uint8_t x, y;
420f55b9b56SRoderick Colenbrander 	uint8_t rx, ry;
421f55b9b56SRoderick Colenbrander 	uint8_t buttons[3];
422f55b9b56SRoderick Colenbrander 	uint8_t z, rz;
42312882ed8SRoderick Colenbrander 
42412882ed8SRoderick Colenbrander 	/* Motion sensors */
42512882ed8SRoderick Colenbrander 	__le16 sensor_timestamp;
42612882ed8SRoderick Colenbrander 	uint8_t sensor_temperature;
42712882ed8SRoderick Colenbrander 	__le16 gyro[3]; /* x, y, z */
42812882ed8SRoderick Colenbrander 	__le16 accel[3]; /* x, y, z */
42912882ed8SRoderick Colenbrander 	uint8_t reserved2[5];
43012882ed8SRoderick Colenbrander 
4318871ed30SRoderick Colenbrander 	uint8_t status[2];
43212882ed8SRoderick Colenbrander 	uint8_t reserved3;
433f55b9b56SRoderick Colenbrander } __packed;
4348871ed30SRoderick Colenbrander static_assert(sizeof(struct dualshock4_input_report_common) == 32);
435f55b9b56SRoderick Colenbrander 
436f55b9b56SRoderick Colenbrander struct dualshock4_input_report_usb {
437f55b9b56SRoderick Colenbrander 	uint8_t report_id; /* 0x01 */
438f55b9b56SRoderick Colenbrander 	struct dualshock4_input_report_common common;
43975203824SRoderick Colenbrander 	uint8_t num_touch_reports;
44075203824SRoderick Colenbrander 	struct dualshock4_touch_report touch_reports[3];
44175203824SRoderick Colenbrander 	uint8_t reserved[3];
442f55b9b56SRoderick Colenbrander } __packed;
443f55b9b56SRoderick Colenbrander static_assert(sizeof(struct dualshock4_input_report_usb) == DS4_INPUT_REPORT_USB_SIZE);
444f55b9b56SRoderick Colenbrander 
4452d77474aSRoderick Colenbrander struct dualshock4_input_report_bt {
4462d77474aSRoderick Colenbrander 	uint8_t report_id; /* 0x11 */
4472d77474aSRoderick Colenbrander 	uint8_t reserved[2];
4482d77474aSRoderick Colenbrander 	struct dualshock4_input_report_common common;
4492d77474aSRoderick Colenbrander 	uint8_t num_touch_reports;
4502d77474aSRoderick Colenbrander 	struct dualshock4_touch_report touch_reports[4]; /* BT has 4 compared to 3 for USB */
4512d77474aSRoderick Colenbrander 	uint8_t reserved2[2];
4522d77474aSRoderick Colenbrander 	__le32 crc32;
4532d77474aSRoderick Colenbrander } __packed;
4542d77474aSRoderick Colenbrander static_assert(sizeof(struct dualshock4_input_report_bt) == DS4_INPUT_REPORT_BT_SIZE);
4552d77474aSRoderick Colenbrander 
4564e463ec4SRoderick Colenbrander /* Common data between Bluetooth and USB DualShock4 output reports. */
4574e463ec4SRoderick Colenbrander struct dualshock4_output_report_common {
4584e463ec4SRoderick Colenbrander 	uint8_t valid_flag0;
4594e463ec4SRoderick Colenbrander 	uint8_t valid_flag1;
4604e463ec4SRoderick Colenbrander 
4614e463ec4SRoderick Colenbrander 	uint8_t reserved;
4624e463ec4SRoderick Colenbrander 
4634e463ec4SRoderick Colenbrander 	uint8_t motor_right;
4644e463ec4SRoderick Colenbrander 	uint8_t motor_left;
4654e463ec4SRoderick Colenbrander 
4664e463ec4SRoderick Colenbrander 	uint8_t lightbar_red;
4674e463ec4SRoderick Colenbrander 	uint8_t lightbar_green;
4684e463ec4SRoderick Colenbrander 	uint8_t lightbar_blue;
4694e463ec4SRoderick Colenbrander 	uint8_t lightbar_blink_on;
4704e463ec4SRoderick Colenbrander 	uint8_t lightbar_blink_off;
4714e463ec4SRoderick Colenbrander } __packed;
4724e463ec4SRoderick Colenbrander 
4734e463ec4SRoderick Colenbrander struct dualshock4_output_report_usb {
4744e463ec4SRoderick Colenbrander 	uint8_t report_id; /* 0x5 */
4754e463ec4SRoderick Colenbrander 	struct dualshock4_output_report_common common;
4764e463ec4SRoderick Colenbrander 	uint8_t reserved[21];
4774e463ec4SRoderick Colenbrander } __packed;
4784e463ec4SRoderick Colenbrander static_assert(sizeof(struct dualshock4_output_report_usb) == DS4_OUTPUT_REPORT_USB_SIZE);
4794e463ec4SRoderick Colenbrander 
4802d77474aSRoderick Colenbrander struct dualshock4_output_report_bt {
4812d77474aSRoderick Colenbrander 	uint8_t report_id; /* 0x11 */
4822d77474aSRoderick Colenbrander 	uint8_t hw_control;
4832d77474aSRoderick Colenbrander 	uint8_t audio_control;
4842d77474aSRoderick Colenbrander 	struct dualshock4_output_report_common common;
4852d77474aSRoderick Colenbrander 	uint8_t reserved[61];
4862d77474aSRoderick Colenbrander 	__le32 crc32;
4872d77474aSRoderick Colenbrander } __packed;
4882d77474aSRoderick Colenbrander static_assert(sizeof(struct dualshock4_output_report_bt) == DS4_OUTPUT_REPORT_BT_SIZE);
4892d77474aSRoderick Colenbrander 
4904e463ec4SRoderick Colenbrander /*
4914e463ec4SRoderick Colenbrander  * The DualShock4 has a main output report used to control most features. It is
4924e463ec4SRoderick Colenbrander  * largely the same between Bluetooth and USB except for different headers and CRC.
4934e463ec4SRoderick Colenbrander  * This structure hide the differences between the two to simplify sending output reports.
4944e463ec4SRoderick Colenbrander  */
4954e463ec4SRoderick Colenbrander struct dualshock4_output_report {
4964e463ec4SRoderick Colenbrander 	uint8_t *data; /* Start of data */
4974e463ec4SRoderick Colenbrander 	uint8_t len; /* Size of output report */
4984e463ec4SRoderick Colenbrander 
4992d77474aSRoderick Colenbrander 	/* Points to Bluetooth data payload in case for a Bluetooth report else NULL. */
5002d77474aSRoderick Colenbrander 	struct dualshock4_output_report_bt *bt;
5014e463ec4SRoderick Colenbrander 	/* Points to USB data payload in case for a USB report else NULL. */
5024e463ec4SRoderick Colenbrander 	struct dualshock4_output_report_usb *usb;
5034e463ec4SRoderick Colenbrander 	/* Points to common section of report, so past any headers. */
5044e463ec4SRoderick Colenbrander 	struct dualshock4_output_report_common *common;
5054e463ec4SRoderick Colenbrander };
5064e463ec4SRoderick Colenbrander 
507bc2e15a9SRoderick Colenbrander /*
508bc2e15a9SRoderick Colenbrander  * Common gamepad buttons across DualShock 3 / 4 and DualSense.
509bc2e15a9SRoderick Colenbrander  * Note: for device with a touchpad, touchpad button is not included
510bc2e15a9SRoderick Colenbrander  *        as it will be part of the touchpad device.
511bc2e15a9SRoderick Colenbrander  */
512bc2e15a9SRoderick Colenbrander static const int ps_gamepad_buttons[] = {
513bc2e15a9SRoderick Colenbrander 	BTN_WEST, /* Square */
514bc2e15a9SRoderick Colenbrander 	BTN_NORTH, /* Triangle */
515bc2e15a9SRoderick Colenbrander 	BTN_EAST, /* Circle */
516bc2e15a9SRoderick Colenbrander 	BTN_SOUTH, /* Cross */
517bc2e15a9SRoderick Colenbrander 	BTN_TL, /* L1 */
518bc2e15a9SRoderick Colenbrander 	BTN_TR, /* R1 */
519bc2e15a9SRoderick Colenbrander 	BTN_TL2, /* L2 */
520bc2e15a9SRoderick Colenbrander 	BTN_TR2, /* R2 */
521bc2e15a9SRoderick Colenbrander 	BTN_SELECT, /* Create (PS5) / Share (PS4) */
522bc2e15a9SRoderick Colenbrander 	BTN_START, /* Option */
523bc2e15a9SRoderick Colenbrander 	BTN_THUMBL, /* L3 */
524bc2e15a9SRoderick Colenbrander 	BTN_THUMBR, /* R3 */
525bc2e15a9SRoderick Colenbrander 	BTN_MODE, /* PS Home */
526bc2e15a9SRoderick Colenbrander };
527bc2e15a9SRoderick Colenbrander 
528bc2e15a9SRoderick Colenbrander static const struct {int x; int y; } ps_gamepad_hat_mapping[] = {
529bc2e15a9SRoderick Colenbrander 	{0, -1}, {1, -1}, {1, 0}, {1, 1}, {0, 1}, {-1, 1}, {-1, 0}, {-1, -1},
530bc2e15a9SRoderick Colenbrander 	{0, 0},
531bc2e15a9SRoderick Colenbrander };
532bc2e15a9SRoderick Colenbrander 
533c64ed0cdSRoderick Colenbrander static int dualshock4_get_calibration_data(struct dualshock4 *ds4);
534182934a1SRoderick Colenbrander static inline void dualsense_schedule_work(struct dualsense *ds);
5354e463ec4SRoderick Colenbrander static inline void dualshock4_schedule_work(struct dualshock4 *ds4);
536fc97b4d6SRoderick Colenbrander static void dualsense_set_lightbar(struct dualsense *ds, uint8_t red, uint8_t green, uint8_t blue);
537c64ed0cdSRoderick Colenbrander static void dualshock4_set_default_lightbar_colors(struct dualshock4 *ds4);
538fc97b4d6SRoderick Colenbrander 
53953f04e83SRoderick Colenbrander /*
54053f04e83SRoderick Colenbrander  * Add a new ps_device to ps_devices if it doesn't exist.
54153f04e83SRoderick Colenbrander  * Return error on duplicate device, which can happen if the same
54253f04e83SRoderick Colenbrander  * device is connected using both Bluetooth and USB.
54353f04e83SRoderick Colenbrander  */
ps_devices_list_add(struct ps_device * dev)54453f04e83SRoderick Colenbrander static int ps_devices_list_add(struct ps_device *dev)
54553f04e83SRoderick Colenbrander {
54653f04e83SRoderick Colenbrander 	struct ps_device *entry;
54753f04e83SRoderick Colenbrander 
54853f04e83SRoderick Colenbrander 	mutex_lock(&ps_devices_lock);
54953f04e83SRoderick Colenbrander 	list_for_each_entry(entry, &ps_devices_list, list) {
55053f04e83SRoderick Colenbrander 		if (!memcmp(entry->mac_address, dev->mac_address, sizeof(dev->mac_address))) {
55153f04e83SRoderick Colenbrander 			hid_err(dev->hdev, "Duplicate device found for MAC address %pMR.\n",
55253f04e83SRoderick Colenbrander 					dev->mac_address);
55353f04e83SRoderick Colenbrander 			mutex_unlock(&ps_devices_lock);
55453f04e83SRoderick Colenbrander 			return -EEXIST;
55553f04e83SRoderick Colenbrander 		}
55653f04e83SRoderick Colenbrander 	}
55753f04e83SRoderick Colenbrander 
55853f04e83SRoderick Colenbrander 	list_add_tail(&dev->list, &ps_devices_list);
55953f04e83SRoderick Colenbrander 	mutex_unlock(&ps_devices_lock);
56053f04e83SRoderick Colenbrander 	return 0;
56153f04e83SRoderick Colenbrander }
56253f04e83SRoderick Colenbrander 
ps_devices_list_remove(struct ps_device * dev)56353f04e83SRoderick Colenbrander static int ps_devices_list_remove(struct ps_device *dev)
56453f04e83SRoderick Colenbrander {
56553f04e83SRoderick Colenbrander 	mutex_lock(&ps_devices_lock);
56653f04e83SRoderick Colenbrander 	list_del(&dev->list);
56753f04e83SRoderick Colenbrander 	mutex_unlock(&ps_devices_lock);
56853f04e83SRoderick Colenbrander 	return 0;
56953f04e83SRoderick Colenbrander }
57053f04e83SRoderick Colenbrander 
ps_device_set_player_id(struct ps_device * dev)571949aaccdSRoderick Colenbrander static int ps_device_set_player_id(struct ps_device *dev)
572949aaccdSRoderick Colenbrander {
573949aaccdSRoderick Colenbrander 	int ret = ida_alloc(&ps_player_id_allocator, GFP_KERNEL);
574949aaccdSRoderick Colenbrander 
575949aaccdSRoderick Colenbrander 	if (ret < 0)
576949aaccdSRoderick Colenbrander 		return ret;
577949aaccdSRoderick Colenbrander 
578949aaccdSRoderick Colenbrander 	dev->player_id = ret;
579949aaccdSRoderick Colenbrander 	return 0;
580949aaccdSRoderick Colenbrander }
581949aaccdSRoderick Colenbrander 
ps_device_release_player_id(struct ps_device * dev)582949aaccdSRoderick Colenbrander static void ps_device_release_player_id(struct ps_device *dev)
583949aaccdSRoderick Colenbrander {
584949aaccdSRoderick Colenbrander 	ida_free(&ps_player_id_allocator, dev->player_id);
585949aaccdSRoderick Colenbrander 
586949aaccdSRoderick Colenbrander 	dev->player_id = U32_MAX;
587949aaccdSRoderick Colenbrander }
588949aaccdSRoderick Colenbrander 
ps_allocate_input_dev(struct hid_device * hdev,const char * name_suffix)589bc2e15a9SRoderick Colenbrander static struct input_dev *ps_allocate_input_dev(struct hid_device *hdev, const char *name_suffix)
590bc2e15a9SRoderick Colenbrander {
591bc2e15a9SRoderick Colenbrander 	struct input_dev *input_dev;
592bc2e15a9SRoderick Colenbrander 
593bc2e15a9SRoderick Colenbrander 	input_dev = devm_input_allocate_device(&hdev->dev);
594bc2e15a9SRoderick Colenbrander 	if (!input_dev)
595bc2e15a9SRoderick Colenbrander 		return ERR_PTR(-ENOMEM);
596bc2e15a9SRoderick Colenbrander 
597bc2e15a9SRoderick Colenbrander 	input_dev->id.bustype = hdev->bus;
598bc2e15a9SRoderick Colenbrander 	input_dev->id.vendor = hdev->vendor;
599bc2e15a9SRoderick Colenbrander 	input_dev->id.product = hdev->product;
600bc2e15a9SRoderick Colenbrander 	input_dev->id.version = hdev->version;
601bc2e15a9SRoderick Colenbrander 	input_dev->uniq = hdev->uniq;
602bc2e15a9SRoderick Colenbrander 
603bc2e15a9SRoderick Colenbrander 	if (name_suffix) {
604bc2e15a9SRoderick Colenbrander 		input_dev->name = devm_kasprintf(&hdev->dev, GFP_KERNEL, "%s %s", hdev->name,
605bc2e15a9SRoderick Colenbrander 				name_suffix);
606bc2e15a9SRoderick Colenbrander 		if (!input_dev->name)
607bc2e15a9SRoderick Colenbrander 			return ERR_PTR(-ENOMEM);
608bc2e15a9SRoderick Colenbrander 	} else {
609bc2e15a9SRoderick Colenbrander 		input_dev->name = hdev->name;
610bc2e15a9SRoderick Colenbrander 	}
611bc2e15a9SRoderick Colenbrander 
612bc2e15a9SRoderick Colenbrander 	input_set_drvdata(input_dev, hdev);
613bc2e15a9SRoderick Colenbrander 
614bc2e15a9SRoderick Colenbrander 	return input_dev;
615bc2e15a9SRoderick Colenbrander }
616bc2e15a9SRoderick Colenbrander 
617d30bca44SRoderick Colenbrander static enum power_supply_property ps_power_supply_props[] = {
618d30bca44SRoderick Colenbrander 	POWER_SUPPLY_PROP_STATUS,
619d30bca44SRoderick Colenbrander 	POWER_SUPPLY_PROP_PRESENT,
620d30bca44SRoderick Colenbrander 	POWER_SUPPLY_PROP_CAPACITY,
621d30bca44SRoderick Colenbrander 	POWER_SUPPLY_PROP_SCOPE,
622d30bca44SRoderick Colenbrander };
623d30bca44SRoderick Colenbrander 
ps_battery_get_property(struct power_supply * psy,enum power_supply_property psp,union power_supply_propval * val)624d30bca44SRoderick Colenbrander static int ps_battery_get_property(struct power_supply *psy,
625d30bca44SRoderick Colenbrander 		enum power_supply_property psp,
626d30bca44SRoderick Colenbrander 		union power_supply_propval *val)
627d30bca44SRoderick Colenbrander {
628d30bca44SRoderick Colenbrander 	struct ps_device *dev = power_supply_get_drvdata(psy);
629d30bca44SRoderick Colenbrander 	uint8_t battery_capacity;
630d30bca44SRoderick Colenbrander 	int battery_status;
631d30bca44SRoderick Colenbrander 	unsigned long flags;
6325fb52551SRoderick Colenbrander 	int ret = 0;
633d30bca44SRoderick Colenbrander 
634d30bca44SRoderick Colenbrander 	spin_lock_irqsave(&dev->lock, flags);
635d30bca44SRoderick Colenbrander 	battery_capacity = dev->battery_capacity;
636d30bca44SRoderick Colenbrander 	battery_status = dev->battery_status;
637d30bca44SRoderick Colenbrander 	spin_unlock_irqrestore(&dev->lock, flags);
638d30bca44SRoderick Colenbrander 
639d30bca44SRoderick Colenbrander 	switch (psp) {
640d30bca44SRoderick Colenbrander 	case POWER_SUPPLY_PROP_STATUS:
641d30bca44SRoderick Colenbrander 		val->intval = battery_status;
642d30bca44SRoderick Colenbrander 		break;
643d30bca44SRoderick Colenbrander 	case POWER_SUPPLY_PROP_PRESENT:
644d30bca44SRoderick Colenbrander 		val->intval = 1;
645d30bca44SRoderick Colenbrander 		break;
646d30bca44SRoderick Colenbrander 	case POWER_SUPPLY_PROP_CAPACITY:
647d30bca44SRoderick Colenbrander 		val->intval = battery_capacity;
648d30bca44SRoderick Colenbrander 		break;
649d30bca44SRoderick Colenbrander 	case POWER_SUPPLY_PROP_SCOPE:
650d30bca44SRoderick Colenbrander 		val->intval = POWER_SUPPLY_SCOPE_DEVICE;
651d30bca44SRoderick Colenbrander 		break;
652d30bca44SRoderick Colenbrander 	default:
653d30bca44SRoderick Colenbrander 		ret = -EINVAL;
654d30bca44SRoderick Colenbrander 		break;
655d30bca44SRoderick Colenbrander 	}
656d30bca44SRoderick Colenbrander 
6575fb52551SRoderick Colenbrander 	return ret;
658d30bca44SRoderick Colenbrander }
659d30bca44SRoderick Colenbrander 
ps_device_register_battery(struct ps_device * dev)660d30bca44SRoderick Colenbrander static int ps_device_register_battery(struct ps_device *dev)
661d30bca44SRoderick Colenbrander {
662d30bca44SRoderick Colenbrander 	struct power_supply *battery;
663d30bca44SRoderick Colenbrander 	struct power_supply_config battery_cfg = { .drv_data = dev };
664d30bca44SRoderick Colenbrander 	int ret;
665d30bca44SRoderick Colenbrander 
666d30bca44SRoderick Colenbrander 	dev->battery_desc.type = POWER_SUPPLY_TYPE_BATTERY;
667d30bca44SRoderick Colenbrander 	dev->battery_desc.properties = ps_power_supply_props;
668d30bca44SRoderick Colenbrander 	dev->battery_desc.num_properties = ARRAY_SIZE(ps_power_supply_props);
669d30bca44SRoderick Colenbrander 	dev->battery_desc.get_property = ps_battery_get_property;
670d30bca44SRoderick Colenbrander 	dev->battery_desc.name = devm_kasprintf(&dev->hdev->dev, GFP_KERNEL,
671d30bca44SRoderick Colenbrander 			"ps-controller-battery-%pMR", dev->mac_address);
672d30bca44SRoderick Colenbrander 	if (!dev->battery_desc.name)
673d30bca44SRoderick Colenbrander 		return -ENOMEM;
674d30bca44SRoderick Colenbrander 
675d30bca44SRoderick Colenbrander 	battery = devm_power_supply_register(&dev->hdev->dev, &dev->battery_desc, &battery_cfg);
676d30bca44SRoderick Colenbrander 	if (IS_ERR(battery)) {
677d30bca44SRoderick Colenbrander 		ret = PTR_ERR(battery);
678d30bca44SRoderick Colenbrander 		hid_err(dev->hdev, "Unable to register battery device: %d\n", ret);
679d30bca44SRoderick Colenbrander 		return ret;
680d30bca44SRoderick Colenbrander 	}
681d30bca44SRoderick Colenbrander 	dev->battery = battery;
682d30bca44SRoderick Colenbrander 
683d30bca44SRoderick Colenbrander 	ret = power_supply_powers(dev->battery, &dev->hdev->dev);
684d30bca44SRoderick Colenbrander 	if (ret) {
685d30bca44SRoderick Colenbrander 		hid_err(dev->hdev, "Unable to activate battery device: %d\n", ret);
686d30bca44SRoderick Colenbrander 		return ret;
687d30bca44SRoderick Colenbrander 	}
688d30bca44SRoderick Colenbrander 
689d30bca44SRoderick Colenbrander 	return 0;
690d30bca44SRoderick Colenbrander }
691d30bca44SRoderick Colenbrander 
692799b2b53SRoderick Colenbrander /* Compute crc32 of HID data and compare against expected CRC. */
ps_check_crc32(uint8_t seed,uint8_t * data,size_t len,uint32_t report_crc)693799b2b53SRoderick Colenbrander static bool ps_check_crc32(uint8_t seed, uint8_t *data, size_t len, uint32_t report_crc)
694799b2b53SRoderick Colenbrander {
695799b2b53SRoderick Colenbrander 	uint32_t crc;
696799b2b53SRoderick Colenbrander 
697799b2b53SRoderick Colenbrander 	crc = crc32_le(0xFFFFFFFF, &seed, 1);
698799b2b53SRoderick Colenbrander 	crc = ~crc32_le(crc, data, len);
699799b2b53SRoderick Colenbrander 
700799b2b53SRoderick Colenbrander 	return crc == report_crc;
701799b2b53SRoderick Colenbrander }
702799b2b53SRoderick Colenbrander 
ps_gamepad_create(struct hid_device * hdev,int (* play_effect)(struct input_dev *,void *,struct ff_effect *))70351151098SRoderick Colenbrander static struct input_dev *ps_gamepad_create(struct hid_device *hdev,
70451151098SRoderick Colenbrander 		int (*play_effect)(struct input_dev *, void *, struct ff_effect *))
705bc2e15a9SRoderick Colenbrander {
706bc2e15a9SRoderick Colenbrander 	struct input_dev *gamepad;
707bc2e15a9SRoderick Colenbrander 	unsigned int i;
708bc2e15a9SRoderick Colenbrander 	int ret;
709bc2e15a9SRoderick Colenbrander 
710bc2e15a9SRoderick Colenbrander 	gamepad = ps_allocate_input_dev(hdev, NULL);
711bc2e15a9SRoderick Colenbrander 	if (IS_ERR(gamepad))
712bc2e15a9SRoderick Colenbrander 		return ERR_CAST(gamepad);
713bc2e15a9SRoderick Colenbrander 
714bc2e15a9SRoderick Colenbrander 	input_set_abs_params(gamepad, ABS_X, 0, 255, 0, 0);
715bc2e15a9SRoderick Colenbrander 	input_set_abs_params(gamepad, ABS_Y, 0, 255, 0, 0);
716bc2e15a9SRoderick Colenbrander 	input_set_abs_params(gamepad, ABS_Z, 0, 255, 0, 0);
717bc2e15a9SRoderick Colenbrander 	input_set_abs_params(gamepad, ABS_RX, 0, 255, 0, 0);
718bc2e15a9SRoderick Colenbrander 	input_set_abs_params(gamepad, ABS_RY, 0, 255, 0, 0);
719bc2e15a9SRoderick Colenbrander 	input_set_abs_params(gamepad, ABS_RZ, 0, 255, 0, 0);
720bc2e15a9SRoderick Colenbrander 
721bc2e15a9SRoderick Colenbrander 	input_set_abs_params(gamepad, ABS_HAT0X, -1, 1, 0, 0);
722bc2e15a9SRoderick Colenbrander 	input_set_abs_params(gamepad, ABS_HAT0Y, -1, 1, 0, 0);
723bc2e15a9SRoderick Colenbrander 
724bc2e15a9SRoderick Colenbrander 	for (i = 0; i < ARRAY_SIZE(ps_gamepad_buttons); i++)
725bc2e15a9SRoderick Colenbrander 		input_set_capability(gamepad, EV_KEY, ps_gamepad_buttons[i]);
726bc2e15a9SRoderick Colenbrander 
72751151098SRoderick Colenbrander #if IS_ENABLED(CONFIG_PLAYSTATION_FF)
72851151098SRoderick Colenbrander 	if (play_effect) {
72951151098SRoderick Colenbrander 		input_set_capability(gamepad, EV_FF, FF_RUMBLE);
73051151098SRoderick Colenbrander 		input_ff_create_memless(gamepad, NULL, play_effect);
73151151098SRoderick Colenbrander 	}
73251151098SRoderick Colenbrander #endif
73351151098SRoderick Colenbrander 
734bc2e15a9SRoderick Colenbrander 	ret = input_register_device(gamepad);
735bc2e15a9SRoderick Colenbrander 	if (ret)
736bc2e15a9SRoderick Colenbrander 		return ERR_PTR(ret);
737bc2e15a9SRoderick Colenbrander 
738bc2e15a9SRoderick Colenbrander 	return gamepad;
739bc2e15a9SRoderick Colenbrander }
740bc2e15a9SRoderick Colenbrander 
ps_get_report(struct hid_device * hdev,uint8_t report_id,uint8_t * buf,size_t size,bool check_crc)741a23b063bSRoderick Colenbrander static int ps_get_report(struct hid_device *hdev, uint8_t report_id, uint8_t *buf, size_t size,
742a23b063bSRoderick Colenbrander 		bool check_crc)
743b99dcefdSRoderick Colenbrander {
744b99dcefdSRoderick Colenbrander 	int ret;
745b99dcefdSRoderick Colenbrander 
746b99dcefdSRoderick Colenbrander 	ret = hid_hw_raw_request(hdev, report_id, buf, size, HID_FEATURE_REPORT,
747b99dcefdSRoderick Colenbrander 				 HID_REQ_GET_REPORT);
748b99dcefdSRoderick Colenbrander 	if (ret < 0) {
749b99dcefdSRoderick Colenbrander 		hid_err(hdev, "Failed to retrieve feature with reportID %d: %d\n", report_id, ret);
750b99dcefdSRoderick Colenbrander 		return ret;
751b99dcefdSRoderick Colenbrander 	}
752b99dcefdSRoderick Colenbrander 
753b99dcefdSRoderick Colenbrander 	if (ret != size) {
754b99dcefdSRoderick Colenbrander 		hid_err(hdev, "Invalid byte count transferred, expected %zu got %d\n", size, ret);
755b99dcefdSRoderick Colenbrander 		return -EINVAL;
756b99dcefdSRoderick Colenbrander 	}
757b99dcefdSRoderick Colenbrander 
758b99dcefdSRoderick Colenbrander 	if (buf[0] != report_id) {
759b99dcefdSRoderick Colenbrander 		hid_err(hdev, "Invalid reportID received, expected %d got %d\n", report_id, buf[0]);
760b99dcefdSRoderick Colenbrander 		return -EINVAL;
761b99dcefdSRoderick Colenbrander 	}
762b99dcefdSRoderick Colenbrander 
763a23b063bSRoderick Colenbrander 	if (hdev->bus == BUS_BLUETOOTH && check_crc) {
764799b2b53SRoderick Colenbrander 		/* Last 4 bytes contains crc32. */
765799b2b53SRoderick Colenbrander 		uint8_t crc_offset = size - 4;
766799b2b53SRoderick Colenbrander 		uint32_t report_crc = get_unaligned_le32(&buf[crc_offset]);
767799b2b53SRoderick Colenbrander 
768799b2b53SRoderick Colenbrander 		if (!ps_check_crc32(PS_FEATURE_CRC32_SEED, buf, crc_offset, report_crc)) {
769799b2b53SRoderick Colenbrander 			hid_err(hdev, "CRC check failed for reportID=%d\n", report_id);
770799b2b53SRoderick Colenbrander 			return -EILSEQ;
771799b2b53SRoderick Colenbrander 		}
772799b2b53SRoderick Colenbrander 	}
773799b2b53SRoderick Colenbrander 
774b99dcefdSRoderick Colenbrander 	return 0;
775b99dcefdSRoderick Colenbrander }
776b99dcefdSRoderick Colenbrander 
ps_led_register(struct ps_device * ps_dev,struct led_classdev * led,const struct ps_led_info * led_info)7778c0ab553SRoderick Colenbrander static int ps_led_register(struct ps_device *ps_dev, struct led_classdev *led,
7788c0ab553SRoderick Colenbrander 		const struct ps_led_info *led_info)
7798c0ab553SRoderick Colenbrander {
7808c0ab553SRoderick Colenbrander 	int ret;
7818c0ab553SRoderick Colenbrander 
7824521109aSRoderick Colenbrander 	if (led_info->name) {
7838c0ab553SRoderick Colenbrander 		led->name = devm_kasprintf(&ps_dev->hdev->dev, GFP_KERNEL,
7848c0ab553SRoderick Colenbrander 				"%s:%s:%s", ps_dev->input_dev_name, led_info->color, led_info->name);
7854521109aSRoderick Colenbrander 	} else {
7864521109aSRoderick Colenbrander 		/* Backwards compatible mode for hid-sony, but not compliant with LED class spec. */
7874521109aSRoderick Colenbrander 		led->name = devm_kasprintf(&ps_dev->hdev->dev, GFP_KERNEL,
7884521109aSRoderick Colenbrander 				"%s:%s", ps_dev->input_dev_name, led_info->color);
7894521109aSRoderick Colenbrander 	}
7908c0ab553SRoderick Colenbrander 
7918c0ab553SRoderick Colenbrander 	if (!led->name)
7928c0ab553SRoderick Colenbrander 		return -ENOMEM;
7938c0ab553SRoderick Colenbrander 
7948c0ab553SRoderick Colenbrander 	led->brightness = 0;
795316f57fbSRoderick Colenbrander 	led->max_brightness = led_info->max_brightness;
7968c0ab553SRoderick Colenbrander 	led->flags = LED_CORE_SUSPENDRESUME;
7978c0ab553SRoderick Colenbrander 	led->brightness_get = led_info->brightness_get;
7988c0ab553SRoderick Colenbrander 	led->brightness_set_blocking = led_info->brightness_set;
79982d93f64SRoderick Colenbrander 	led->blink_set = led_info->blink_set;
8008c0ab553SRoderick Colenbrander 
8018c0ab553SRoderick Colenbrander 	ret = devm_led_classdev_register(&ps_dev->hdev->dev, led);
8028c0ab553SRoderick Colenbrander 	if (ret) {
8038c0ab553SRoderick Colenbrander 		hid_err(ps_dev->hdev, "Failed to register LED %s: %d\n", led_info->name, ret);
8048c0ab553SRoderick Colenbrander 		return ret;
8058c0ab553SRoderick Colenbrander 	}
8068c0ab553SRoderick Colenbrander 
8078c0ab553SRoderick Colenbrander 	return 0;
8088c0ab553SRoderick Colenbrander }
8098c0ab553SRoderick Colenbrander 
810fc97b4d6SRoderick Colenbrander /* Register a DualSense/DualShock4 RGB lightbar represented by a multicolor LED. */
ps_lightbar_register(struct ps_device * ps_dev,struct led_classdev_mc * lightbar_mc_dev,int (* brightness_set)(struct led_classdev *,enum led_brightness))811fc97b4d6SRoderick Colenbrander static int ps_lightbar_register(struct ps_device *ps_dev, struct led_classdev_mc *lightbar_mc_dev,
812fc97b4d6SRoderick Colenbrander 	int (*brightness_set)(struct led_classdev *, enum led_brightness))
813fc97b4d6SRoderick Colenbrander {
814fc97b4d6SRoderick Colenbrander 	struct hid_device *hdev = ps_dev->hdev;
815fc97b4d6SRoderick Colenbrander 	struct mc_subled *mc_led_info;
816fc97b4d6SRoderick Colenbrander 	struct led_classdev *led_cdev;
817fc97b4d6SRoderick Colenbrander 	int ret;
818fc97b4d6SRoderick Colenbrander 
819fc97b4d6SRoderick Colenbrander 	mc_led_info = devm_kmalloc_array(&hdev->dev, 3, sizeof(*mc_led_info),
820fc97b4d6SRoderick Colenbrander 					 GFP_KERNEL | __GFP_ZERO);
821fc97b4d6SRoderick Colenbrander 	if (!mc_led_info)
822fc97b4d6SRoderick Colenbrander 		return -ENOMEM;
823fc97b4d6SRoderick Colenbrander 
824fc97b4d6SRoderick Colenbrander 	mc_led_info[0].color_index = LED_COLOR_ID_RED;
825fc97b4d6SRoderick Colenbrander 	mc_led_info[1].color_index = LED_COLOR_ID_GREEN;
826fc97b4d6SRoderick Colenbrander 	mc_led_info[2].color_index = LED_COLOR_ID_BLUE;
827fc97b4d6SRoderick Colenbrander 
828fc97b4d6SRoderick Colenbrander 	lightbar_mc_dev->subled_info = mc_led_info;
829fc97b4d6SRoderick Colenbrander 	lightbar_mc_dev->num_colors = 3;
830fc97b4d6SRoderick Colenbrander 
831fc97b4d6SRoderick Colenbrander 	led_cdev = &lightbar_mc_dev->led_cdev;
832fc97b4d6SRoderick Colenbrander 	led_cdev->name = devm_kasprintf(&hdev->dev, GFP_KERNEL, "%s:rgb:indicator",
833fc97b4d6SRoderick Colenbrander 			ps_dev->input_dev_name);
834fc97b4d6SRoderick Colenbrander 	if (!led_cdev->name)
835fc97b4d6SRoderick Colenbrander 		return -ENOMEM;
836fc97b4d6SRoderick Colenbrander 	led_cdev->brightness = 255;
837fc97b4d6SRoderick Colenbrander 	led_cdev->max_brightness = 255;
838fc97b4d6SRoderick Colenbrander 	led_cdev->brightness_set_blocking = brightness_set;
839fc97b4d6SRoderick Colenbrander 
840fc97b4d6SRoderick Colenbrander 	ret = devm_led_classdev_multicolor_register(&hdev->dev, lightbar_mc_dev);
841fc97b4d6SRoderick Colenbrander 	if (ret < 0) {
842fc97b4d6SRoderick Colenbrander 		hid_err(hdev, "Cannot register multicolor LED device\n");
843fc97b4d6SRoderick Colenbrander 		return ret;
844fc97b4d6SRoderick Colenbrander 	}
845fc97b4d6SRoderick Colenbrander 
846fc97b4d6SRoderick Colenbrander 	return 0;
847fc97b4d6SRoderick Colenbrander }
848fc97b4d6SRoderick Colenbrander 
ps_sensors_create(struct hid_device * hdev,int accel_range,int accel_res,int gyro_range,int gyro_res)849402987c5SRoderick Colenbrander static struct input_dev *ps_sensors_create(struct hid_device *hdev, int accel_range, int accel_res,
850402987c5SRoderick Colenbrander 		int gyro_range, int gyro_res)
851402987c5SRoderick Colenbrander {
852402987c5SRoderick Colenbrander 	struct input_dev *sensors;
853402987c5SRoderick Colenbrander 	int ret;
854402987c5SRoderick Colenbrander 
855402987c5SRoderick Colenbrander 	sensors = ps_allocate_input_dev(hdev, "Motion Sensors");
856402987c5SRoderick Colenbrander 	if (IS_ERR(sensors))
857402987c5SRoderick Colenbrander 		return ERR_CAST(sensors);
858402987c5SRoderick Colenbrander 
859402987c5SRoderick Colenbrander 	__set_bit(INPUT_PROP_ACCELEROMETER, sensors->propbit);
860402987c5SRoderick Colenbrander 	__set_bit(EV_MSC, sensors->evbit);
861402987c5SRoderick Colenbrander 	__set_bit(MSC_TIMESTAMP, sensors->mscbit);
862402987c5SRoderick Colenbrander 
863402987c5SRoderick Colenbrander 	/* Accelerometer */
864402987c5SRoderick Colenbrander 	input_set_abs_params(sensors, ABS_X, -accel_range, accel_range, 16, 0);
865402987c5SRoderick Colenbrander 	input_set_abs_params(sensors, ABS_Y, -accel_range, accel_range, 16, 0);
866402987c5SRoderick Colenbrander 	input_set_abs_params(sensors, ABS_Z, -accel_range, accel_range, 16, 0);
867402987c5SRoderick Colenbrander 	input_abs_set_res(sensors, ABS_X, accel_res);
868402987c5SRoderick Colenbrander 	input_abs_set_res(sensors, ABS_Y, accel_res);
869402987c5SRoderick Colenbrander 	input_abs_set_res(sensors, ABS_Z, accel_res);
870402987c5SRoderick Colenbrander 
871402987c5SRoderick Colenbrander 	/* Gyroscope */
872402987c5SRoderick Colenbrander 	input_set_abs_params(sensors, ABS_RX, -gyro_range, gyro_range, 16, 0);
873402987c5SRoderick Colenbrander 	input_set_abs_params(sensors, ABS_RY, -gyro_range, gyro_range, 16, 0);
874402987c5SRoderick Colenbrander 	input_set_abs_params(sensors, ABS_RZ, -gyro_range, gyro_range, 16, 0);
875402987c5SRoderick Colenbrander 	input_abs_set_res(sensors, ABS_RX, gyro_res);
876402987c5SRoderick Colenbrander 	input_abs_set_res(sensors, ABS_RY, gyro_res);
877402987c5SRoderick Colenbrander 	input_abs_set_res(sensors, ABS_RZ, gyro_res);
878402987c5SRoderick Colenbrander 
879402987c5SRoderick Colenbrander 	ret = input_register_device(sensors);
880402987c5SRoderick Colenbrander 	if (ret)
881402987c5SRoderick Colenbrander 		return ERR_PTR(ret);
882402987c5SRoderick Colenbrander 
883402987c5SRoderick Colenbrander 	return sensors;
884402987c5SRoderick Colenbrander }
885402987c5SRoderick Colenbrander 
ps_touchpad_create(struct hid_device * hdev,int width,int height,unsigned int num_contacts)886f6bb05fcSRoderick Colenbrander static struct input_dev *ps_touchpad_create(struct hid_device *hdev, int width, int height,
887f6bb05fcSRoderick Colenbrander 		unsigned int num_contacts)
888f6bb05fcSRoderick Colenbrander {
889f6bb05fcSRoderick Colenbrander 	struct input_dev *touchpad;
890f6bb05fcSRoderick Colenbrander 	int ret;
891f6bb05fcSRoderick Colenbrander 
892f6bb05fcSRoderick Colenbrander 	touchpad = ps_allocate_input_dev(hdev, "Touchpad");
893f6bb05fcSRoderick Colenbrander 	if (IS_ERR(touchpad))
894f6bb05fcSRoderick Colenbrander 		return ERR_CAST(touchpad);
895f6bb05fcSRoderick Colenbrander 
896f6bb05fcSRoderick Colenbrander 	/* Map button underneath touchpad to BTN_LEFT. */
897f6bb05fcSRoderick Colenbrander 	input_set_capability(touchpad, EV_KEY, BTN_LEFT);
898f6bb05fcSRoderick Colenbrander 	__set_bit(INPUT_PROP_BUTTONPAD, touchpad->propbit);
899f6bb05fcSRoderick Colenbrander 
900f6bb05fcSRoderick Colenbrander 	input_set_abs_params(touchpad, ABS_MT_POSITION_X, 0, width - 1, 0, 0);
901f6bb05fcSRoderick Colenbrander 	input_set_abs_params(touchpad, ABS_MT_POSITION_Y, 0, height - 1, 0, 0);
902f6bb05fcSRoderick Colenbrander 
903f6bb05fcSRoderick Colenbrander 	ret = input_mt_init_slots(touchpad, num_contacts, INPUT_MT_POINTER);
904f6bb05fcSRoderick Colenbrander 	if (ret)
905f6bb05fcSRoderick Colenbrander 		return ERR_PTR(ret);
906f6bb05fcSRoderick Colenbrander 
907f6bb05fcSRoderick Colenbrander 	ret = input_register_device(touchpad);
908f6bb05fcSRoderick Colenbrander 	if (ret)
909f6bb05fcSRoderick Colenbrander 		return ERR_PTR(ret);
910f6bb05fcSRoderick Colenbrander 
911f6bb05fcSRoderick Colenbrander 	return touchpad;
912f6bb05fcSRoderick Colenbrander }
913f6bb05fcSRoderick Colenbrander 
firmware_version_show(struct device * dev,struct device_attribute * attr,char * buf)9140b25b55dSRoderick Colenbrander static ssize_t firmware_version_show(struct device *dev,
9150b25b55dSRoderick Colenbrander 				struct device_attribute
9160b25b55dSRoderick Colenbrander 				*attr, char *buf)
9170b25b55dSRoderick Colenbrander {
9180b25b55dSRoderick Colenbrander 	struct hid_device *hdev = to_hid_device(dev);
9190b25b55dSRoderick Colenbrander 	struct ps_device *ps_dev = hid_get_drvdata(hdev);
9200b25b55dSRoderick Colenbrander 
9210b25b55dSRoderick Colenbrander 	return sysfs_emit(buf, "0x%08x\n", ps_dev->fw_version);
9220b25b55dSRoderick Colenbrander }
9230b25b55dSRoderick Colenbrander 
9240b25b55dSRoderick Colenbrander static DEVICE_ATTR_RO(firmware_version);
9250b25b55dSRoderick Colenbrander 
hardware_version_show(struct device * dev,struct device_attribute * attr,char * buf)9260b25b55dSRoderick Colenbrander static ssize_t hardware_version_show(struct device *dev,
9270b25b55dSRoderick Colenbrander 				struct device_attribute
9280b25b55dSRoderick Colenbrander 				*attr, char *buf)
9290b25b55dSRoderick Colenbrander {
9300b25b55dSRoderick Colenbrander 	struct hid_device *hdev = to_hid_device(dev);
9310b25b55dSRoderick Colenbrander 	struct ps_device *ps_dev = hid_get_drvdata(hdev);
9320b25b55dSRoderick Colenbrander 
9330b25b55dSRoderick Colenbrander 	return sysfs_emit(buf, "0x%08x\n", ps_dev->hw_version);
9340b25b55dSRoderick Colenbrander }
9350b25b55dSRoderick Colenbrander 
9360b25b55dSRoderick Colenbrander static DEVICE_ATTR_RO(hardware_version);
9370b25b55dSRoderick Colenbrander 
938b4a9af9bSGreg Kroah-Hartman static struct attribute *ps_device_attrs[] = {
9390b25b55dSRoderick Colenbrander 	&dev_attr_firmware_version.attr,
9400b25b55dSRoderick Colenbrander 	&dev_attr_hardware_version.attr,
9410b25b55dSRoderick Colenbrander 	NULL
9420b25b55dSRoderick Colenbrander };
943b4a9af9bSGreg Kroah-Hartman ATTRIBUTE_GROUPS(ps_device);
9440b25b55dSRoderick Colenbrander 
dualsense_get_calibration_data(struct dualsense * ds)945402987c5SRoderick Colenbrander static int dualsense_get_calibration_data(struct dualsense *ds)
946402987c5SRoderick Colenbrander {
947ccf1e162SRoderick Colenbrander 	struct hid_device *hdev = ds->base.hdev;
948402987c5SRoderick Colenbrander 	short gyro_pitch_bias, gyro_pitch_plus, gyro_pitch_minus;
949402987c5SRoderick Colenbrander 	short gyro_yaw_bias, gyro_yaw_plus, gyro_yaw_minus;
950402987c5SRoderick Colenbrander 	short gyro_roll_bias, gyro_roll_plus, gyro_roll_minus;
951402987c5SRoderick Colenbrander 	short gyro_speed_plus, gyro_speed_minus;
952402987c5SRoderick Colenbrander 	short acc_x_plus, acc_x_minus;
953402987c5SRoderick Colenbrander 	short acc_y_plus, acc_y_minus;
954402987c5SRoderick Colenbrander 	short acc_z_plus, acc_z_minus;
955402987c5SRoderick Colenbrander 	int speed_2x;
956402987c5SRoderick Colenbrander 	int range_2g;
957402987c5SRoderick Colenbrander 	int ret = 0;
958ccf1e162SRoderick Colenbrander 	int i;
959402987c5SRoderick Colenbrander 	uint8_t *buf;
960402987c5SRoderick Colenbrander 
961402987c5SRoderick Colenbrander 	buf = kzalloc(DS_FEATURE_REPORT_CALIBRATION_SIZE, GFP_KERNEL);
962402987c5SRoderick Colenbrander 	if (!buf)
963402987c5SRoderick Colenbrander 		return -ENOMEM;
964402987c5SRoderick Colenbrander 
965402987c5SRoderick Colenbrander 	ret = ps_get_report(ds->base.hdev, DS_FEATURE_REPORT_CALIBRATION, buf,
966a23b063bSRoderick Colenbrander 			DS_FEATURE_REPORT_CALIBRATION_SIZE, true);
967402987c5SRoderick Colenbrander 	if (ret) {
968402987c5SRoderick Colenbrander 		hid_err(ds->base.hdev, "Failed to retrieve DualSense calibration info: %d\n", ret);
969402987c5SRoderick Colenbrander 		goto err_free;
970402987c5SRoderick Colenbrander 	}
971402987c5SRoderick Colenbrander 
972402987c5SRoderick Colenbrander 	gyro_pitch_bias  = get_unaligned_le16(&buf[1]);
973402987c5SRoderick Colenbrander 	gyro_yaw_bias    = get_unaligned_le16(&buf[3]);
974402987c5SRoderick Colenbrander 	gyro_roll_bias   = get_unaligned_le16(&buf[5]);
975402987c5SRoderick Colenbrander 	gyro_pitch_plus  = get_unaligned_le16(&buf[7]);
976402987c5SRoderick Colenbrander 	gyro_pitch_minus = get_unaligned_le16(&buf[9]);
977402987c5SRoderick Colenbrander 	gyro_yaw_plus    = get_unaligned_le16(&buf[11]);
978402987c5SRoderick Colenbrander 	gyro_yaw_minus   = get_unaligned_le16(&buf[13]);
979402987c5SRoderick Colenbrander 	gyro_roll_plus   = get_unaligned_le16(&buf[15]);
980402987c5SRoderick Colenbrander 	gyro_roll_minus  = get_unaligned_le16(&buf[17]);
981402987c5SRoderick Colenbrander 	gyro_speed_plus  = get_unaligned_le16(&buf[19]);
982402987c5SRoderick Colenbrander 	gyro_speed_minus = get_unaligned_le16(&buf[21]);
983402987c5SRoderick Colenbrander 	acc_x_plus       = get_unaligned_le16(&buf[23]);
984402987c5SRoderick Colenbrander 	acc_x_minus      = get_unaligned_le16(&buf[25]);
985402987c5SRoderick Colenbrander 	acc_y_plus       = get_unaligned_le16(&buf[27]);
986402987c5SRoderick Colenbrander 	acc_y_minus      = get_unaligned_le16(&buf[29]);
987402987c5SRoderick Colenbrander 	acc_z_plus       = get_unaligned_le16(&buf[31]);
988402987c5SRoderick Colenbrander 	acc_z_minus      = get_unaligned_le16(&buf[33]);
989402987c5SRoderick Colenbrander 
990402987c5SRoderick Colenbrander 	/*
991402987c5SRoderick Colenbrander 	 * Set gyroscope calibration and normalization parameters.
992402987c5SRoderick Colenbrander 	 * Data values will be normalized to 1/DS_GYRO_RES_PER_DEG_S degree/s.
993402987c5SRoderick Colenbrander 	 */
994402987c5SRoderick Colenbrander 	speed_2x = (gyro_speed_plus + gyro_speed_minus);
995402987c5SRoderick Colenbrander 	ds->gyro_calib_data[0].abs_code = ABS_RX;
996*6f7dbbd5SRoderick Colenbrander 	ds->gyro_calib_data[0].bias = 0;
997402987c5SRoderick Colenbrander 	ds->gyro_calib_data[0].sens_numer = speed_2x*DS_GYRO_RES_PER_DEG_S;
998*6f7dbbd5SRoderick Colenbrander 	ds->gyro_calib_data[0].sens_denom = abs(gyro_pitch_plus - gyro_pitch_bias) +
999*6f7dbbd5SRoderick Colenbrander 			abs(gyro_pitch_minus - gyro_pitch_bias);
1000402987c5SRoderick Colenbrander 
1001402987c5SRoderick Colenbrander 	ds->gyro_calib_data[1].abs_code = ABS_RY;
1002*6f7dbbd5SRoderick Colenbrander 	ds->gyro_calib_data[1].bias = 0;
1003402987c5SRoderick Colenbrander 	ds->gyro_calib_data[1].sens_numer = speed_2x*DS_GYRO_RES_PER_DEG_S;
1004*6f7dbbd5SRoderick Colenbrander 	ds->gyro_calib_data[1].sens_denom = abs(gyro_yaw_plus - gyro_yaw_bias) +
1005*6f7dbbd5SRoderick Colenbrander 			abs(gyro_yaw_minus - gyro_yaw_bias);
1006402987c5SRoderick Colenbrander 
1007402987c5SRoderick Colenbrander 	ds->gyro_calib_data[2].abs_code = ABS_RZ;
1008*6f7dbbd5SRoderick Colenbrander 	ds->gyro_calib_data[2].bias = 0;
1009402987c5SRoderick Colenbrander 	ds->gyro_calib_data[2].sens_numer = speed_2x*DS_GYRO_RES_PER_DEG_S;
1010*6f7dbbd5SRoderick Colenbrander 	ds->gyro_calib_data[2].sens_denom = abs(gyro_roll_plus - gyro_roll_bias) +
1011*6f7dbbd5SRoderick Colenbrander 			abs(gyro_roll_minus - gyro_roll_bias);
1012402987c5SRoderick Colenbrander 
1013402987c5SRoderick Colenbrander 	/*
1014ccf1e162SRoderick Colenbrander 	 * Sanity check gyro calibration data. This is needed to prevent crashes
1015ccf1e162SRoderick Colenbrander 	 * during report handling of virtual, clone or broken devices not implementing
1016ccf1e162SRoderick Colenbrander 	 * calibration data properly.
1017ccf1e162SRoderick Colenbrander 	 */
1018ccf1e162SRoderick Colenbrander 	for (i = 0; i < ARRAY_SIZE(ds->gyro_calib_data); i++) {
1019ccf1e162SRoderick Colenbrander 		if (ds->gyro_calib_data[i].sens_denom == 0) {
1020ccf1e162SRoderick Colenbrander 			hid_warn(hdev, "Invalid gyro calibration data for axis (%d), disabling calibration.",
1021ccf1e162SRoderick Colenbrander 					ds->gyro_calib_data[i].abs_code);
1022ccf1e162SRoderick Colenbrander 			ds->gyro_calib_data[i].bias = 0;
1023ccf1e162SRoderick Colenbrander 			ds->gyro_calib_data[i].sens_numer = DS_GYRO_RANGE;
1024ccf1e162SRoderick Colenbrander 			ds->gyro_calib_data[i].sens_denom = S16_MAX;
1025ccf1e162SRoderick Colenbrander 		}
1026ccf1e162SRoderick Colenbrander 	}
1027ccf1e162SRoderick Colenbrander 
1028ccf1e162SRoderick Colenbrander 	/*
1029402987c5SRoderick Colenbrander 	 * Set accelerometer calibration and normalization parameters.
1030402987c5SRoderick Colenbrander 	 * Data values will be normalized to 1/DS_ACC_RES_PER_G g.
1031402987c5SRoderick Colenbrander 	 */
1032402987c5SRoderick Colenbrander 	range_2g = acc_x_plus - acc_x_minus;
1033402987c5SRoderick Colenbrander 	ds->accel_calib_data[0].abs_code = ABS_X;
1034402987c5SRoderick Colenbrander 	ds->accel_calib_data[0].bias = acc_x_plus - range_2g / 2;
1035402987c5SRoderick Colenbrander 	ds->accel_calib_data[0].sens_numer = 2*DS_ACC_RES_PER_G;
1036402987c5SRoderick Colenbrander 	ds->accel_calib_data[0].sens_denom = range_2g;
1037402987c5SRoderick Colenbrander 
1038402987c5SRoderick Colenbrander 	range_2g = acc_y_plus - acc_y_minus;
1039402987c5SRoderick Colenbrander 	ds->accel_calib_data[1].abs_code = ABS_Y;
1040402987c5SRoderick Colenbrander 	ds->accel_calib_data[1].bias = acc_y_plus - range_2g / 2;
1041402987c5SRoderick Colenbrander 	ds->accel_calib_data[1].sens_numer = 2*DS_ACC_RES_PER_G;
1042402987c5SRoderick Colenbrander 	ds->accel_calib_data[1].sens_denom = range_2g;
1043402987c5SRoderick Colenbrander 
1044402987c5SRoderick Colenbrander 	range_2g = acc_z_plus - acc_z_minus;
1045402987c5SRoderick Colenbrander 	ds->accel_calib_data[2].abs_code = ABS_Z;
1046402987c5SRoderick Colenbrander 	ds->accel_calib_data[2].bias = acc_z_plus - range_2g / 2;
1047402987c5SRoderick Colenbrander 	ds->accel_calib_data[2].sens_numer = 2*DS_ACC_RES_PER_G;
1048402987c5SRoderick Colenbrander 	ds->accel_calib_data[2].sens_denom = range_2g;
1049402987c5SRoderick Colenbrander 
1050ccf1e162SRoderick Colenbrander 	/*
1051ccf1e162SRoderick Colenbrander 	 * Sanity check accelerometer calibration data. This is needed to prevent crashes
1052ccf1e162SRoderick Colenbrander 	 * during report handling of virtual, clone or broken devices not implementing calibration
1053ccf1e162SRoderick Colenbrander 	 * data properly.
1054ccf1e162SRoderick Colenbrander 	 */
1055ccf1e162SRoderick Colenbrander 	for (i = 0; i < ARRAY_SIZE(ds->accel_calib_data); i++) {
1056ccf1e162SRoderick Colenbrander 		if (ds->accel_calib_data[i].sens_denom == 0) {
1057ccf1e162SRoderick Colenbrander 			hid_warn(hdev, "Invalid accelerometer calibration data for axis (%d), disabling calibration.",
1058ccf1e162SRoderick Colenbrander 					ds->accel_calib_data[i].abs_code);
1059ccf1e162SRoderick Colenbrander 			ds->accel_calib_data[i].bias = 0;
1060ccf1e162SRoderick Colenbrander 			ds->accel_calib_data[i].sens_numer = DS_ACC_RANGE;
1061ccf1e162SRoderick Colenbrander 			ds->accel_calib_data[i].sens_denom = S16_MAX;
1062ccf1e162SRoderick Colenbrander 		}
1063ccf1e162SRoderick Colenbrander 	}
1064ccf1e162SRoderick Colenbrander 
1065402987c5SRoderick Colenbrander err_free:
1066402987c5SRoderick Colenbrander 	kfree(buf);
1067402987c5SRoderick Colenbrander 	return ret;
1068402987c5SRoderick Colenbrander }
1069402987c5SRoderick Colenbrander 
1070182934a1SRoderick Colenbrander 
dualsense_get_firmware_info(struct dualsense * ds)10710b25b55dSRoderick Colenbrander static int dualsense_get_firmware_info(struct dualsense *ds)
10720b25b55dSRoderick Colenbrander {
10730b25b55dSRoderick Colenbrander 	uint8_t *buf;
10740b25b55dSRoderick Colenbrander 	int ret;
10750b25b55dSRoderick Colenbrander 
10760b25b55dSRoderick Colenbrander 	buf = kzalloc(DS_FEATURE_REPORT_FIRMWARE_INFO_SIZE, GFP_KERNEL);
10770b25b55dSRoderick Colenbrander 	if (!buf)
10780b25b55dSRoderick Colenbrander 		return -ENOMEM;
10790b25b55dSRoderick Colenbrander 
10800b25b55dSRoderick Colenbrander 	ret = ps_get_report(ds->base.hdev, DS_FEATURE_REPORT_FIRMWARE_INFO, buf,
1081a23b063bSRoderick Colenbrander 			DS_FEATURE_REPORT_FIRMWARE_INFO_SIZE, true);
10820b25b55dSRoderick Colenbrander 	if (ret) {
10830b25b55dSRoderick Colenbrander 		hid_err(ds->base.hdev, "Failed to retrieve DualSense firmware info: %d\n", ret);
10840b25b55dSRoderick Colenbrander 		goto err_free;
10850b25b55dSRoderick Colenbrander 	}
10860b25b55dSRoderick Colenbrander 
10870b25b55dSRoderick Colenbrander 	ds->base.hw_version = get_unaligned_le32(&buf[24]);
10880b25b55dSRoderick Colenbrander 	ds->base.fw_version = get_unaligned_le32(&buf[28]);
10890b25b55dSRoderick Colenbrander 
10909fecab24SRoderick Colenbrander 	/* Update version is some kind of feature version. It is distinct from
10919fecab24SRoderick Colenbrander 	 * the firmware version as there can be many different variations of a
10929fecab24SRoderick Colenbrander 	 * controller over time with the same physical shell, but with different
10939fecab24SRoderick Colenbrander 	 * PCBs and other internal changes. The update version (internal name) is
10949fecab24SRoderick Colenbrander 	 * used as a means to detect what features are available and change behavior.
10959fecab24SRoderick Colenbrander 	 * Note: the version is different between DualSense and DualSense Edge.
10969fecab24SRoderick Colenbrander 	 */
10979fecab24SRoderick Colenbrander 	ds->update_version = get_unaligned_le16(&buf[44]);
10989fecab24SRoderick Colenbrander 
10990b25b55dSRoderick Colenbrander err_free:
11000b25b55dSRoderick Colenbrander 	kfree(buf);
11010b25b55dSRoderick Colenbrander 	return ret;
11020b25b55dSRoderick Colenbrander }
11030b25b55dSRoderick Colenbrander 
dualsense_get_mac_address(struct dualsense * ds)1104b99dcefdSRoderick Colenbrander static int dualsense_get_mac_address(struct dualsense *ds)
1105b99dcefdSRoderick Colenbrander {
1106b99dcefdSRoderick Colenbrander 	uint8_t *buf;
1107b99dcefdSRoderick Colenbrander 	int ret = 0;
1108b99dcefdSRoderick Colenbrander 
1109b99dcefdSRoderick Colenbrander 	buf = kzalloc(DS_FEATURE_REPORT_PAIRING_INFO_SIZE, GFP_KERNEL);
1110b99dcefdSRoderick Colenbrander 	if (!buf)
1111b99dcefdSRoderick Colenbrander 		return -ENOMEM;
1112b99dcefdSRoderick Colenbrander 
1113b99dcefdSRoderick Colenbrander 	ret = ps_get_report(ds->base.hdev, DS_FEATURE_REPORT_PAIRING_INFO, buf,
1114a23b063bSRoderick Colenbrander 			DS_FEATURE_REPORT_PAIRING_INFO_SIZE, true);
1115b99dcefdSRoderick Colenbrander 	if (ret) {
1116b99dcefdSRoderick Colenbrander 		hid_err(ds->base.hdev, "Failed to retrieve DualSense pairing info: %d\n", ret);
1117b99dcefdSRoderick Colenbrander 		goto err_free;
1118b99dcefdSRoderick Colenbrander 	}
1119b99dcefdSRoderick Colenbrander 
1120b99dcefdSRoderick Colenbrander 	memcpy(ds->base.mac_address, &buf[1], sizeof(ds->base.mac_address));
1121b99dcefdSRoderick Colenbrander 
1122b99dcefdSRoderick Colenbrander err_free:
1123b99dcefdSRoderick Colenbrander 	kfree(buf);
1124b99dcefdSRoderick Colenbrander 	return ret;
1125b99dcefdSRoderick Colenbrander }
1126b99dcefdSRoderick Colenbrander 
dualsense_lightbar_set_brightness(struct led_classdev * cdev,enum led_brightness brightness)1127fc97b4d6SRoderick Colenbrander static int dualsense_lightbar_set_brightness(struct led_classdev *cdev,
1128fc97b4d6SRoderick Colenbrander 	enum led_brightness brightness)
1129fc97b4d6SRoderick Colenbrander {
1130fc97b4d6SRoderick Colenbrander 	struct led_classdev_mc *mc_cdev = lcdev_to_mccdev(cdev);
1131fc97b4d6SRoderick Colenbrander 	struct dualsense *ds = container_of(mc_cdev, struct dualsense, lightbar);
1132fc97b4d6SRoderick Colenbrander 	uint8_t red, green, blue;
1133fc97b4d6SRoderick Colenbrander 
1134fc97b4d6SRoderick Colenbrander 	led_mc_calc_color_components(mc_cdev, brightness);
1135fc97b4d6SRoderick Colenbrander 	red = mc_cdev->subled_info[0].brightness;
1136fc97b4d6SRoderick Colenbrander 	green = mc_cdev->subled_info[1].brightness;
1137fc97b4d6SRoderick Colenbrander 	blue = mc_cdev->subled_info[2].brightness;
1138fc97b4d6SRoderick Colenbrander 
1139fc97b4d6SRoderick Colenbrander 	dualsense_set_lightbar(ds, red, green, blue);
1140fc97b4d6SRoderick Colenbrander 	return 0;
1141fc97b4d6SRoderick Colenbrander }
1142fc97b4d6SRoderick Colenbrander 
dualsense_player_led_get_brightness(struct led_classdev * led)11438c0ab553SRoderick Colenbrander static enum led_brightness dualsense_player_led_get_brightness(struct led_classdev *led)
11448c0ab553SRoderick Colenbrander {
11458c0ab553SRoderick Colenbrander 	struct hid_device *hdev = to_hid_device(led->dev->parent);
11468c0ab553SRoderick Colenbrander 	struct dualsense *ds = hid_get_drvdata(hdev);
11478c0ab553SRoderick Colenbrander 
11488c0ab553SRoderick Colenbrander 	return !!(ds->player_leds_state & BIT(led - ds->player_leds));
11498c0ab553SRoderick Colenbrander }
11508c0ab553SRoderick Colenbrander 
dualsense_player_led_set_brightness(struct led_classdev * led,enum led_brightness value)11518c0ab553SRoderick Colenbrander static int dualsense_player_led_set_brightness(struct led_classdev *led, enum led_brightness value)
11528c0ab553SRoderick Colenbrander {
11538c0ab553SRoderick Colenbrander 	struct hid_device *hdev = to_hid_device(led->dev->parent);
11548c0ab553SRoderick Colenbrander 	struct dualsense *ds = hid_get_drvdata(hdev);
11558c0ab553SRoderick Colenbrander 	unsigned long flags;
11568c0ab553SRoderick Colenbrander 	unsigned int led_index;
11578c0ab553SRoderick Colenbrander 
11588c0ab553SRoderick Colenbrander 	spin_lock_irqsave(&ds->base.lock, flags);
11598c0ab553SRoderick Colenbrander 
11608c0ab553SRoderick Colenbrander 	led_index = led - ds->player_leds;
11618c0ab553SRoderick Colenbrander 	if (value == LED_OFF)
11628c0ab553SRoderick Colenbrander 		ds->player_leds_state &= ~BIT(led_index);
11638c0ab553SRoderick Colenbrander 	else
11648c0ab553SRoderick Colenbrander 		ds->player_leds_state |= BIT(led_index);
11658c0ab553SRoderick Colenbrander 
11668c0ab553SRoderick Colenbrander 	ds->update_player_leds = true;
11678c0ab553SRoderick Colenbrander 	spin_unlock_irqrestore(&ds->base.lock, flags);
11688c0ab553SRoderick Colenbrander 
1169182934a1SRoderick Colenbrander 	dualsense_schedule_work(ds);
11703c92cb4cSJiri Kosina 
11713c92cb4cSJiri Kosina 	return 0;
11728c0ab553SRoderick Colenbrander }
11738c0ab553SRoderick Colenbrander 
dualsense_init_output_report(struct dualsense * ds,struct dualsense_output_report * rp,void * buf)117451151098SRoderick Colenbrander static void dualsense_init_output_report(struct dualsense *ds, struct dualsense_output_report *rp,
117551151098SRoderick Colenbrander 		void *buf)
117651151098SRoderick Colenbrander {
117751151098SRoderick Colenbrander 	struct hid_device *hdev = ds->base.hdev;
117851151098SRoderick Colenbrander 
117951151098SRoderick Colenbrander 	if (hdev->bus == BUS_BLUETOOTH) {
118051151098SRoderick Colenbrander 		struct dualsense_output_report_bt *bt = buf;
118151151098SRoderick Colenbrander 
118251151098SRoderick Colenbrander 		memset(bt, 0, sizeof(*bt));
118351151098SRoderick Colenbrander 		bt->report_id = DS_OUTPUT_REPORT_BT;
118451151098SRoderick Colenbrander 		bt->tag = DS_OUTPUT_TAG; /* Tag must be set. Exact meaning is unclear. */
118551151098SRoderick Colenbrander 
118651151098SRoderick Colenbrander 		/*
118751151098SRoderick Colenbrander 		 * Highest 4-bit is a sequence number, which needs to be increased
118851151098SRoderick Colenbrander 		 * every report. Lowest 4-bit is tag and can be zero for now.
118951151098SRoderick Colenbrander 		 */
119051151098SRoderick Colenbrander 		bt->seq_tag = (ds->output_seq << 4) | 0x0;
119151151098SRoderick Colenbrander 		if (++ds->output_seq == 16)
119251151098SRoderick Colenbrander 			ds->output_seq = 0;
119351151098SRoderick Colenbrander 
119451151098SRoderick Colenbrander 		rp->data = buf;
119551151098SRoderick Colenbrander 		rp->len = sizeof(*bt);
119651151098SRoderick Colenbrander 		rp->bt = bt;
119751151098SRoderick Colenbrander 		rp->usb = NULL;
119851151098SRoderick Colenbrander 		rp->common = &bt->common;
119951151098SRoderick Colenbrander 	} else { /* USB */
120051151098SRoderick Colenbrander 		struct dualsense_output_report_usb *usb = buf;
120151151098SRoderick Colenbrander 
120251151098SRoderick Colenbrander 		memset(usb, 0, sizeof(*usb));
120351151098SRoderick Colenbrander 		usb->report_id = DS_OUTPUT_REPORT_USB;
120451151098SRoderick Colenbrander 
120551151098SRoderick Colenbrander 		rp->data = buf;
120651151098SRoderick Colenbrander 		rp->len = sizeof(*usb);
120751151098SRoderick Colenbrander 		rp->bt = NULL;
120851151098SRoderick Colenbrander 		rp->usb = usb;
120951151098SRoderick Colenbrander 		rp->common = &usb->common;
121051151098SRoderick Colenbrander 	}
121151151098SRoderick Colenbrander }
121251151098SRoderick Colenbrander 
dualsense_schedule_work(struct dualsense * ds)1213182934a1SRoderick Colenbrander static inline void dualsense_schedule_work(struct dualsense *ds)
1214182934a1SRoderick Colenbrander {
1215182934a1SRoderick Colenbrander 	unsigned long flags;
1216182934a1SRoderick Colenbrander 
1217182934a1SRoderick Colenbrander 	spin_lock_irqsave(&ds->base.lock, flags);
1218182934a1SRoderick Colenbrander 	if (ds->output_worker_initialized)
1219182934a1SRoderick Colenbrander 		schedule_work(&ds->output_worker);
1220182934a1SRoderick Colenbrander 	spin_unlock_irqrestore(&ds->base.lock, flags);
1221182934a1SRoderick Colenbrander }
1222182934a1SRoderick Colenbrander 
122351151098SRoderick Colenbrander /*
122451151098SRoderick Colenbrander  * Helper function to send DualSense output reports. Applies a CRC at the end of a report
122551151098SRoderick Colenbrander  * for Bluetooth reports.
122651151098SRoderick Colenbrander  */
dualsense_send_output_report(struct dualsense * ds,struct dualsense_output_report * report)122751151098SRoderick Colenbrander static void dualsense_send_output_report(struct dualsense *ds,
122851151098SRoderick Colenbrander 		struct dualsense_output_report *report)
122951151098SRoderick Colenbrander {
123051151098SRoderick Colenbrander 	struct hid_device *hdev = ds->base.hdev;
123151151098SRoderick Colenbrander 
123251151098SRoderick Colenbrander 	/* Bluetooth packets need to be signed with a CRC in the last 4 bytes. */
123351151098SRoderick Colenbrander 	if (report->bt) {
123451151098SRoderick Colenbrander 		uint32_t crc;
123551151098SRoderick Colenbrander 		uint8_t seed = PS_OUTPUT_CRC32_SEED;
123651151098SRoderick Colenbrander 
123751151098SRoderick Colenbrander 		crc = crc32_le(0xFFFFFFFF, &seed, 1);
123851151098SRoderick Colenbrander 		crc = ~crc32_le(crc, report->data, report->len - 4);
123951151098SRoderick Colenbrander 
124051151098SRoderick Colenbrander 		report->bt->crc32 = cpu_to_le32(crc);
124151151098SRoderick Colenbrander 	}
124251151098SRoderick Colenbrander 
124351151098SRoderick Colenbrander 	hid_hw_output_report(hdev, report->data, report->len);
124451151098SRoderick Colenbrander }
124551151098SRoderick Colenbrander 
dualsense_output_worker(struct work_struct * work)124651151098SRoderick Colenbrander static void dualsense_output_worker(struct work_struct *work)
124751151098SRoderick Colenbrander {
124851151098SRoderick Colenbrander 	struct dualsense *ds = container_of(work, struct dualsense, output_worker);
124951151098SRoderick Colenbrander 	struct dualsense_output_report report;
125051151098SRoderick Colenbrander 	struct dualsense_output_report_common *common;
125151151098SRoderick Colenbrander 	unsigned long flags;
125251151098SRoderick Colenbrander 
125351151098SRoderick Colenbrander 	dualsense_init_output_report(ds, &report, ds->output_report_dmabuf);
125451151098SRoderick Colenbrander 	common = report.common;
125551151098SRoderick Colenbrander 
125651151098SRoderick Colenbrander 	spin_lock_irqsave(&ds->base.lock, flags);
125751151098SRoderick Colenbrander 
125851151098SRoderick Colenbrander 	if (ds->update_rumble) {
125951151098SRoderick Colenbrander 		/* Select classic rumble style haptics and enable it. */
126051151098SRoderick Colenbrander 		common->valid_flag0 |= DS_OUTPUT_VALID_FLAG0_HAPTICS_SELECT;
12619fecab24SRoderick Colenbrander 		if (ds->use_vibration_v2)
12629fecab24SRoderick Colenbrander 			common->valid_flag2 |= DS_OUTPUT_VALID_FLAG2_COMPATIBLE_VIBRATION2;
12639fecab24SRoderick Colenbrander 		else
126451151098SRoderick Colenbrander 			common->valid_flag0 |= DS_OUTPUT_VALID_FLAG0_COMPATIBLE_VIBRATION;
126551151098SRoderick Colenbrander 		common->motor_left = ds->motor_left;
126651151098SRoderick Colenbrander 		common->motor_right = ds->motor_right;
126751151098SRoderick Colenbrander 		ds->update_rumble = false;
126851151098SRoderick Colenbrander 	}
126951151098SRoderick Colenbrander 
12708e5198a1SRoderick Colenbrander 	if (ds->update_lightbar) {
12718e5198a1SRoderick Colenbrander 		common->valid_flag1 |= DS_OUTPUT_VALID_FLAG1_LIGHTBAR_CONTROL_ENABLE;
12728e5198a1SRoderick Colenbrander 		common->lightbar_red = ds->lightbar_red;
12738e5198a1SRoderick Colenbrander 		common->lightbar_green = ds->lightbar_green;
12748e5198a1SRoderick Colenbrander 		common->lightbar_blue = ds->lightbar_blue;
12758e5198a1SRoderick Colenbrander 
12768e5198a1SRoderick Colenbrander 		ds->update_lightbar = false;
12778e5198a1SRoderick Colenbrander 	}
12788e5198a1SRoderick Colenbrander 
1279949aaccdSRoderick Colenbrander 	if (ds->update_player_leds) {
1280949aaccdSRoderick Colenbrander 		common->valid_flag1 |= DS_OUTPUT_VALID_FLAG1_PLAYER_INDICATOR_CONTROL_ENABLE;
1281949aaccdSRoderick Colenbrander 		common->player_leds = ds->player_leds_state;
1282949aaccdSRoderick Colenbrander 
1283949aaccdSRoderick Colenbrander 		ds->update_player_leds = false;
1284949aaccdSRoderick Colenbrander 	}
1285949aaccdSRoderick Colenbrander 
1286c26e48b1SRoderick Colenbrander 	if (ds->update_mic_mute) {
1287c26e48b1SRoderick Colenbrander 		common->valid_flag1 |= DS_OUTPUT_VALID_FLAG1_MIC_MUTE_LED_CONTROL_ENABLE;
1288c26e48b1SRoderick Colenbrander 		common->mute_button_led = ds->mic_muted;
1289c26e48b1SRoderick Colenbrander 
1290c26e48b1SRoderick Colenbrander 		if (ds->mic_muted) {
1291c26e48b1SRoderick Colenbrander 			/* Disable microphone */
1292c26e48b1SRoderick Colenbrander 			common->valid_flag1 |= DS_OUTPUT_VALID_FLAG1_POWER_SAVE_CONTROL_ENABLE;
1293c26e48b1SRoderick Colenbrander 			common->power_save_control |= DS_OUTPUT_POWER_SAVE_CONTROL_MIC_MUTE;
1294c26e48b1SRoderick Colenbrander 		} else {
1295c26e48b1SRoderick Colenbrander 			/* Enable microphone */
1296c26e48b1SRoderick Colenbrander 			common->valid_flag1 |= DS_OUTPUT_VALID_FLAG1_POWER_SAVE_CONTROL_ENABLE;
1297c26e48b1SRoderick Colenbrander 			common->power_save_control &= ~DS_OUTPUT_POWER_SAVE_CONTROL_MIC_MUTE;
1298c26e48b1SRoderick Colenbrander 		}
1299c26e48b1SRoderick Colenbrander 
1300c26e48b1SRoderick Colenbrander 		ds->update_mic_mute = false;
1301c26e48b1SRoderick Colenbrander 	}
1302c26e48b1SRoderick Colenbrander 
130351151098SRoderick Colenbrander 	spin_unlock_irqrestore(&ds->base.lock, flags);
130451151098SRoderick Colenbrander 
130551151098SRoderick Colenbrander 	dualsense_send_output_report(ds, &report);
130651151098SRoderick Colenbrander }
130751151098SRoderick Colenbrander 
dualsense_parse_report(struct ps_device * ps_dev,struct hid_report * report,u8 * data,int size)1308bc2e15a9SRoderick Colenbrander static int dualsense_parse_report(struct ps_device *ps_dev, struct hid_report *report,
1309bc2e15a9SRoderick Colenbrander 		u8 *data, int size)
1310bc2e15a9SRoderick Colenbrander {
1311bc2e15a9SRoderick Colenbrander 	struct hid_device *hdev = ps_dev->hdev;
1312bc2e15a9SRoderick Colenbrander 	struct dualsense *ds = container_of(ps_dev, struct dualsense, base);
1313bc2e15a9SRoderick Colenbrander 	struct dualsense_input_report *ds_report;
1314d30bca44SRoderick Colenbrander 	uint8_t battery_data, battery_capacity, charging_status, value;
1315d30bca44SRoderick Colenbrander 	int battery_status;
1316402987c5SRoderick Colenbrander 	uint32_t sensor_timestamp;
1317c26e48b1SRoderick Colenbrander 	bool btn_mic_state;
1318d30bca44SRoderick Colenbrander 	unsigned long flags;
1319f6bb05fcSRoderick Colenbrander 	int i;
1320bc2e15a9SRoderick Colenbrander 
1321bc2e15a9SRoderick Colenbrander 	/*
1322bc2e15a9SRoderick Colenbrander 	 * DualSense in USB uses the full HID report for reportID 1, but
1323bc2e15a9SRoderick Colenbrander 	 * Bluetooth uses a minimal HID report for reportID 1 and reports
1324bc2e15a9SRoderick Colenbrander 	 * the full report using reportID 49.
1325bc2e15a9SRoderick Colenbrander 	 */
1326bc2e15a9SRoderick Colenbrander 	if (hdev->bus == BUS_USB && report->id == DS_INPUT_REPORT_USB &&
1327bc2e15a9SRoderick Colenbrander 			size == DS_INPUT_REPORT_USB_SIZE) {
1328bc2e15a9SRoderick Colenbrander 		ds_report = (struct dualsense_input_report *)&data[1];
1329799b2b53SRoderick Colenbrander 	} else if (hdev->bus == BUS_BLUETOOTH && report->id == DS_INPUT_REPORT_BT &&
1330799b2b53SRoderick Colenbrander 			size == DS_INPUT_REPORT_BT_SIZE) {
1331799b2b53SRoderick Colenbrander 		/* Last 4 bytes of input report contain crc32 */
1332799b2b53SRoderick Colenbrander 		uint32_t report_crc = get_unaligned_le32(&data[size - 4]);
1333799b2b53SRoderick Colenbrander 
1334799b2b53SRoderick Colenbrander 		if (!ps_check_crc32(PS_INPUT_CRC32_SEED, data, size - 4, report_crc)) {
1335799b2b53SRoderick Colenbrander 			hid_err(hdev, "DualSense input CRC's check failed\n");
1336799b2b53SRoderick Colenbrander 			return -EILSEQ;
1337799b2b53SRoderick Colenbrander 		}
1338799b2b53SRoderick Colenbrander 
1339799b2b53SRoderick Colenbrander 		ds_report = (struct dualsense_input_report *)&data[2];
1340bc2e15a9SRoderick Colenbrander 	} else {
1341bc2e15a9SRoderick Colenbrander 		hid_err(hdev, "Unhandled reportID=%d\n", report->id);
1342bc2e15a9SRoderick Colenbrander 		return -1;
1343bc2e15a9SRoderick Colenbrander 	}
1344bc2e15a9SRoderick Colenbrander 
1345bc2e15a9SRoderick Colenbrander 	input_report_abs(ds->gamepad, ABS_X,  ds_report->x);
1346bc2e15a9SRoderick Colenbrander 	input_report_abs(ds->gamepad, ABS_Y,  ds_report->y);
1347bc2e15a9SRoderick Colenbrander 	input_report_abs(ds->gamepad, ABS_RX, ds_report->rx);
1348bc2e15a9SRoderick Colenbrander 	input_report_abs(ds->gamepad, ABS_RY, ds_report->ry);
1349bc2e15a9SRoderick Colenbrander 	input_report_abs(ds->gamepad, ABS_Z,  ds_report->z);
1350bc2e15a9SRoderick Colenbrander 	input_report_abs(ds->gamepad, ABS_RZ, ds_report->rz);
1351bc2e15a9SRoderick Colenbrander 
1352bc2e15a9SRoderick Colenbrander 	value = ds_report->buttons[0] & DS_BUTTONS0_HAT_SWITCH;
135350ab1ffdSColin Ian King 	if (value >= ARRAY_SIZE(ps_gamepad_hat_mapping))
1354bc2e15a9SRoderick Colenbrander 		value = 8; /* center */
1355bc2e15a9SRoderick Colenbrander 	input_report_abs(ds->gamepad, ABS_HAT0X, ps_gamepad_hat_mapping[value].x);
1356bc2e15a9SRoderick Colenbrander 	input_report_abs(ds->gamepad, ABS_HAT0Y, ps_gamepad_hat_mapping[value].y);
1357bc2e15a9SRoderick Colenbrander 
1358bc2e15a9SRoderick Colenbrander 	input_report_key(ds->gamepad, BTN_WEST,   ds_report->buttons[0] & DS_BUTTONS0_SQUARE);
1359bc2e15a9SRoderick Colenbrander 	input_report_key(ds->gamepad, BTN_SOUTH,  ds_report->buttons[0] & DS_BUTTONS0_CROSS);
1360bc2e15a9SRoderick Colenbrander 	input_report_key(ds->gamepad, BTN_EAST,   ds_report->buttons[0] & DS_BUTTONS0_CIRCLE);
1361bc2e15a9SRoderick Colenbrander 	input_report_key(ds->gamepad, BTN_NORTH,  ds_report->buttons[0] & DS_BUTTONS0_TRIANGLE);
1362bc2e15a9SRoderick Colenbrander 	input_report_key(ds->gamepad, BTN_TL,     ds_report->buttons[1] & DS_BUTTONS1_L1);
1363bc2e15a9SRoderick Colenbrander 	input_report_key(ds->gamepad, BTN_TR,     ds_report->buttons[1] & DS_BUTTONS1_R1);
1364bc2e15a9SRoderick Colenbrander 	input_report_key(ds->gamepad, BTN_TL2,    ds_report->buttons[1] & DS_BUTTONS1_L2);
1365bc2e15a9SRoderick Colenbrander 	input_report_key(ds->gamepad, BTN_TR2,    ds_report->buttons[1] & DS_BUTTONS1_R2);
1366bc2e15a9SRoderick Colenbrander 	input_report_key(ds->gamepad, BTN_SELECT, ds_report->buttons[1] & DS_BUTTONS1_CREATE);
1367bc2e15a9SRoderick Colenbrander 	input_report_key(ds->gamepad, BTN_START,  ds_report->buttons[1] & DS_BUTTONS1_OPTIONS);
1368bc2e15a9SRoderick Colenbrander 	input_report_key(ds->gamepad, BTN_THUMBL, ds_report->buttons[1] & DS_BUTTONS1_L3);
1369bc2e15a9SRoderick Colenbrander 	input_report_key(ds->gamepad, BTN_THUMBR, ds_report->buttons[1] & DS_BUTTONS1_R3);
1370bc2e15a9SRoderick Colenbrander 	input_report_key(ds->gamepad, BTN_MODE,   ds_report->buttons[2] & DS_BUTTONS2_PS_HOME);
1371bc2e15a9SRoderick Colenbrander 	input_sync(ds->gamepad);
1372bc2e15a9SRoderick Colenbrander 
1373c26e48b1SRoderick Colenbrander 	/*
1374c26e48b1SRoderick Colenbrander 	 * The DualSense has an internal microphone, which can be muted through a mute button
1375c26e48b1SRoderick Colenbrander 	 * on the device. The driver is expected to read the button state and program the device
1376c26e48b1SRoderick Colenbrander 	 * to mute/unmute audio at the hardware level.
1377c26e48b1SRoderick Colenbrander 	 */
1378c26e48b1SRoderick Colenbrander 	btn_mic_state = !!(ds_report->buttons[2] & DS_BUTTONS2_MIC_MUTE);
1379c26e48b1SRoderick Colenbrander 	if (btn_mic_state && !ds->last_btn_mic_state) {
1380c26e48b1SRoderick Colenbrander 		spin_lock_irqsave(&ps_dev->lock, flags);
1381c26e48b1SRoderick Colenbrander 		ds->update_mic_mute = true;
1382c26e48b1SRoderick Colenbrander 		ds->mic_muted = !ds->mic_muted; /* toggle */
1383c26e48b1SRoderick Colenbrander 		spin_unlock_irqrestore(&ps_dev->lock, flags);
1384c26e48b1SRoderick Colenbrander 
1385c26e48b1SRoderick Colenbrander 		/* Schedule updating of microphone state at hardware level. */
1386182934a1SRoderick Colenbrander 		dualsense_schedule_work(ds);
1387c26e48b1SRoderick Colenbrander 	}
1388c26e48b1SRoderick Colenbrander 	ds->last_btn_mic_state = btn_mic_state;
1389c26e48b1SRoderick Colenbrander 
1390402987c5SRoderick Colenbrander 	/* Parse and calibrate gyroscope data. */
1391402987c5SRoderick Colenbrander 	for (i = 0; i < ARRAY_SIZE(ds_report->gyro); i++) {
1392402987c5SRoderick Colenbrander 		int raw_data = (short)le16_to_cpu(ds_report->gyro[i]);
1393402987c5SRoderick Colenbrander 		int calib_data = mult_frac(ds->gyro_calib_data[i].sens_numer,
1394*6f7dbbd5SRoderick Colenbrander 					   raw_data, ds->gyro_calib_data[i].sens_denom);
1395402987c5SRoderick Colenbrander 
1396402987c5SRoderick Colenbrander 		input_report_abs(ds->sensors, ds->gyro_calib_data[i].abs_code, calib_data);
1397402987c5SRoderick Colenbrander 	}
1398402987c5SRoderick Colenbrander 
1399402987c5SRoderick Colenbrander 	/* Parse and calibrate accelerometer data. */
1400402987c5SRoderick Colenbrander 	for (i = 0; i < ARRAY_SIZE(ds_report->accel); i++) {
1401402987c5SRoderick Colenbrander 		int raw_data = (short)le16_to_cpu(ds_report->accel[i]);
1402402987c5SRoderick Colenbrander 		int calib_data = mult_frac(ds->accel_calib_data[i].sens_numer,
1403402987c5SRoderick Colenbrander 					   raw_data - ds->accel_calib_data[i].bias,
1404402987c5SRoderick Colenbrander 					   ds->accel_calib_data[i].sens_denom);
1405402987c5SRoderick Colenbrander 
1406402987c5SRoderick Colenbrander 		input_report_abs(ds->sensors, ds->accel_calib_data[i].abs_code, calib_data);
1407402987c5SRoderick Colenbrander 	}
1408402987c5SRoderick Colenbrander 
1409402987c5SRoderick Colenbrander 	/* Convert timestamp (in 0.33us unit) to timestamp_us */
1410402987c5SRoderick Colenbrander 	sensor_timestamp = le32_to_cpu(ds_report->sensor_timestamp);
1411402987c5SRoderick Colenbrander 	if (!ds->sensor_timestamp_initialized) {
1412402987c5SRoderick Colenbrander 		ds->sensor_timestamp_us = DIV_ROUND_CLOSEST(sensor_timestamp, 3);
1413402987c5SRoderick Colenbrander 		ds->sensor_timestamp_initialized = true;
1414402987c5SRoderick Colenbrander 	} else {
1415402987c5SRoderick Colenbrander 		uint32_t delta;
1416402987c5SRoderick Colenbrander 
1417402987c5SRoderick Colenbrander 		if (ds->prev_sensor_timestamp > sensor_timestamp)
1418402987c5SRoderick Colenbrander 			delta = (U32_MAX - ds->prev_sensor_timestamp + sensor_timestamp + 1);
1419402987c5SRoderick Colenbrander 		else
1420402987c5SRoderick Colenbrander 			delta = sensor_timestamp - ds->prev_sensor_timestamp;
1421402987c5SRoderick Colenbrander 		ds->sensor_timestamp_us += DIV_ROUND_CLOSEST(delta, 3);
1422402987c5SRoderick Colenbrander 	}
1423402987c5SRoderick Colenbrander 	ds->prev_sensor_timestamp = sensor_timestamp;
1424402987c5SRoderick Colenbrander 	input_event(ds->sensors, EV_MSC, MSC_TIMESTAMP, ds->sensor_timestamp_us);
1425402987c5SRoderick Colenbrander 	input_sync(ds->sensors);
1426402987c5SRoderick Colenbrander 
1427f6bb05fcSRoderick Colenbrander 	for (i = 0; i < ARRAY_SIZE(ds_report->points); i++) {
1428f6bb05fcSRoderick Colenbrander 		struct dualsense_touch_point *point = &ds_report->points[i];
1429f6bb05fcSRoderick Colenbrander 		bool active = (point->contact & DS_TOUCH_POINT_INACTIVE) ? false : true;
1430f6bb05fcSRoderick Colenbrander 
1431f6bb05fcSRoderick Colenbrander 		input_mt_slot(ds->touchpad, i);
1432f6bb05fcSRoderick Colenbrander 		input_mt_report_slot_state(ds->touchpad, MT_TOOL_FINGER, active);
1433f6bb05fcSRoderick Colenbrander 
1434f6bb05fcSRoderick Colenbrander 		if (active) {
1435f6bb05fcSRoderick Colenbrander 			int x = (point->x_hi << 8) | point->x_lo;
1436f6bb05fcSRoderick Colenbrander 			int y = (point->y_hi << 4) | point->y_lo;
1437f6bb05fcSRoderick Colenbrander 
1438f6bb05fcSRoderick Colenbrander 			input_report_abs(ds->touchpad, ABS_MT_POSITION_X, x);
1439f6bb05fcSRoderick Colenbrander 			input_report_abs(ds->touchpad, ABS_MT_POSITION_Y, y);
1440f6bb05fcSRoderick Colenbrander 		}
1441f6bb05fcSRoderick Colenbrander 	}
1442f6bb05fcSRoderick Colenbrander 	input_mt_sync_frame(ds->touchpad);
1443f6bb05fcSRoderick Colenbrander 	input_report_key(ds->touchpad, BTN_LEFT, ds_report->buttons[2] & DS_BUTTONS2_TOUCHPAD);
1444f6bb05fcSRoderick Colenbrander 	input_sync(ds->touchpad);
1445f6bb05fcSRoderick Colenbrander 
1446d30bca44SRoderick Colenbrander 	battery_data = ds_report->status & DS_STATUS_BATTERY_CAPACITY;
1447d30bca44SRoderick Colenbrander 	charging_status = (ds_report->status & DS_STATUS_CHARGING) >> DS_STATUS_CHARGING_SHIFT;
1448d30bca44SRoderick Colenbrander 
1449d30bca44SRoderick Colenbrander 	switch (charging_status) {
1450d30bca44SRoderick Colenbrander 	case 0x0:
1451d30bca44SRoderick Colenbrander 		/*
1452d30bca44SRoderick Colenbrander 		 * Each unit of battery data corresponds to 10%
1453d30bca44SRoderick Colenbrander 		 * 0 = 0-9%, 1 = 10-19%, .. and 10 = 100%
1454d30bca44SRoderick Colenbrander 		 */
1455d30bca44SRoderick Colenbrander 		battery_capacity = min(battery_data * 10 + 5, 100);
1456d30bca44SRoderick Colenbrander 		battery_status = POWER_SUPPLY_STATUS_DISCHARGING;
1457d30bca44SRoderick Colenbrander 		break;
1458d30bca44SRoderick Colenbrander 	case 0x1:
1459d30bca44SRoderick Colenbrander 		battery_capacity = min(battery_data * 10 + 5, 100);
1460d30bca44SRoderick Colenbrander 		battery_status = POWER_SUPPLY_STATUS_CHARGING;
1461d30bca44SRoderick Colenbrander 		break;
1462d30bca44SRoderick Colenbrander 	case 0x2:
1463d30bca44SRoderick Colenbrander 		battery_capacity = 100;
1464d30bca44SRoderick Colenbrander 		battery_status = POWER_SUPPLY_STATUS_FULL;
1465d30bca44SRoderick Colenbrander 		break;
1466d30bca44SRoderick Colenbrander 	case 0xa: /* voltage or temperature out of range */
1467d30bca44SRoderick Colenbrander 	case 0xb: /* temperature error */
1468d30bca44SRoderick Colenbrander 		battery_capacity = 0;
1469d30bca44SRoderick Colenbrander 		battery_status = POWER_SUPPLY_STATUS_NOT_CHARGING;
1470d30bca44SRoderick Colenbrander 		break;
1471d30bca44SRoderick Colenbrander 	case 0xf: /* charging error */
1472d30bca44SRoderick Colenbrander 	default:
1473d30bca44SRoderick Colenbrander 		battery_capacity = 0;
1474d30bca44SRoderick Colenbrander 		battery_status = POWER_SUPPLY_STATUS_UNKNOWN;
1475d30bca44SRoderick Colenbrander 	}
1476d30bca44SRoderick Colenbrander 
1477d30bca44SRoderick Colenbrander 	spin_lock_irqsave(&ps_dev->lock, flags);
1478d30bca44SRoderick Colenbrander 	ps_dev->battery_capacity = battery_capacity;
1479d30bca44SRoderick Colenbrander 	ps_dev->battery_status = battery_status;
1480d30bca44SRoderick Colenbrander 	spin_unlock_irqrestore(&ps_dev->lock, flags);
1481d30bca44SRoderick Colenbrander 
1482bc2e15a9SRoderick Colenbrander 	return 0;
1483bc2e15a9SRoderick Colenbrander }
1484bc2e15a9SRoderick Colenbrander 
dualsense_play_effect(struct input_dev * dev,void * data,struct ff_effect * effect)148551151098SRoderick Colenbrander static int dualsense_play_effect(struct input_dev *dev, void *data, struct ff_effect *effect)
148651151098SRoderick Colenbrander {
148751151098SRoderick Colenbrander 	struct hid_device *hdev = input_get_drvdata(dev);
148851151098SRoderick Colenbrander 	struct dualsense *ds = hid_get_drvdata(hdev);
148951151098SRoderick Colenbrander 	unsigned long flags;
149051151098SRoderick Colenbrander 
149151151098SRoderick Colenbrander 	if (effect->type != FF_RUMBLE)
149251151098SRoderick Colenbrander 		return 0;
149351151098SRoderick Colenbrander 
149451151098SRoderick Colenbrander 	spin_lock_irqsave(&ds->base.lock, flags);
149551151098SRoderick Colenbrander 	ds->update_rumble = true;
149651151098SRoderick Colenbrander 	ds->motor_left = effect->u.rumble.strong_magnitude / 256;
149751151098SRoderick Colenbrander 	ds->motor_right = effect->u.rumble.weak_magnitude / 256;
149851151098SRoderick Colenbrander 	spin_unlock_irqrestore(&ds->base.lock, flags);
149951151098SRoderick Colenbrander 
1500182934a1SRoderick Colenbrander 	dualsense_schedule_work(ds);
150151151098SRoderick Colenbrander 	return 0;
150251151098SRoderick Colenbrander }
150351151098SRoderick Colenbrander 
dualsense_remove(struct ps_device * ps_dev)1504182934a1SRoderick Colenbrander static void dualsense_remove(struct ps_device *ps_dev)
1505182934a1SRoderick Colenbrander {
1506182934a1SRoderick Colenbrander 	struct dualsense *ds = container_of(ps_dev, struct dualsense, base);
1507182934a1SRoderick Colenbrander 	unsigned long flags;
1508182934a1SRoderick Colenbrander 
1509182934a1SRoderick Colenbrander 	spin_lock_irqsave(&ds->base.lock, flags);
1510182934a1SRoderick Colenbrander 	ds->output_worker_initialized = false;
1511182934a1SRoderick Colenbrander 	spin_unlock_irqrestore(&ds->base.lock, flags);
1512182934a1SRoderick Colenbrander 
1513182934a1SRoderick Colenbrander 	cancel_work_sync(&ds->output_worker);
1514182934a1SRoderick Colenbrander }
1515182934a1SRoderick Colenbrander 
dualsense_reset_leds(struct dualsense * ds)15168e5198a1SRoderick Colenbrander static int dualsense_reset_leds(struct dualsense *ds)
15178e5198a1SRoderick Colenbrander {
15188e5198a1SRoderick Colenbrander 	struct dualsense_output_report report;
15198e5198a1SRoderick Colenbrander 	uint8_t *buf;
15208e5198a1SRoderick Colenbrander 
15218e5198a1SRoderick Colenbrander 	buf = kzalloc(sizeof(struct dualsense_output_report_bt), GFP_KERNEL);
15228e5198a1SRoderick Colenbrander 	if (!buf)
15238e5198a1SRoderick Colenbrander 		return -ENOMEM;
15248e5198a1SRoderick Colenbrander 
15258e5198a1SRoderick Colenbrander 	dualsense_init_output_report(ds, &report, buf);
15268e5198a1SRoderick Colenbrander 	/*
15278e5198a1SRoderick Colenbrander 	 * On Bluetooth the DualSense outputs an animation on the lightbar
15288e5198a1SRoderick Colenbrander 	 * during startup and maintains a color afterwards. We need to explicitly
15298e5198a1SRoderick Colenbrander 	 * reconfigure the lightbar before we can do any programming later on.
15308e5198a1SRoderick Colenbrander 	 * In USB the lightbar is not on by default, but redoing the setup there
15318e5198a1SRoderick Colenbrander 	 * doesn't hurt.
15328e5198a1SRoderick Colenbrander 	 */
15338e5198a1SRoderick Colenbrander 	report.common->valid_flag2 = DS_OUTPUT_VALID_FLAG2_LIGHTBAR_SETUP_CONTROL_ENABLE;
15348e5198a1SRoderick Colenbrander 	report.common->lightbar_setup = DS_OUTPUT_LIGHTBAR_SETUP_LIGHT_OUT; /* Fade light out. */
15358e5198a1SRoderick Colenbrander 	dualsense_send_output_report(ds, &report);
15368e5198a1SRoderick Colenbrander 
15378e5198a1SRoderick Colenbrander 	kfree(buf);
15388e5198a1SRoderick Colenbrander 	return 0;
15398e5198a1SRoderick Colenbrander }
15408e5198a1SRoderick Colenbrander 
dualsense_set_lightbar(struct dualsense * ds,uint8_t red,uint8_t green,uint8_t blue)15418e5198a1SRoderick Colenbrander static void dualsense_set_lightbar(struct dualsense *ds, uint8_t red, uint8_t green, uint8_t blue)
15428e5198a1SRoderick Colenbrander {
1543fc97b4d6SRoderick Colenbrander 	unsigned long flags;
1544fc97b4d6SRoderick Colenbrander 
1545fc97b4d6SRoderick Colenbrander 	spin_lock_irqsave(&ds->base.lock, flags);
15468e5198a1SRoderick Colenbrander 	ds->update_lightbar = true;
15478e5198a1SRoderick Colenbrander 	ds->lightbar_red = red;
15488e5198a1SRoderick Colenbrander 	ds->lightbar_green = green;
15498e5198a1SRoderick Colenbrander 	ds->lightbar_blue = blue;
1550fc97b4d6SRoderick Colenbrander 	spin_unlock_irqrestore(&ds->base.lock, flags);
15518e5198a1SRoderick Colenbrander 
1552182934a1SRoderick Colenbrander 	dualsense_schedule_work(ds);
15538e5198a1SRoderick Colenbrander }
15548e5198a1SRoderick Colenbrander 
dualsense_set_player_leds(struct dualsense * ds)1555949aaccdSRoderick Colenbrander static void dualsense_set_player_leds(struct dualsense *ds)
1556949aaccdSRoderick Colenbrander {
1557949aaccdSRoderick Colenbrander 	/*
1558949aaccdSRoderick Colenbrander 	 * The DualSense controller has a row of 5 LEDs used for player ids.
1559949aaccdSRoderick Colenbrander 	 * Behavior on the PlayStation 5 console is to center the player id
1560949aaccdSRoderick Colenbrander 	 * across the LEDs, so e.g. player 1 would be "--x--" with x being 'on'.
1561949aaccdSRoderick Colenbrander 	 * Follow a similar mapping here.
1562949aaccdSRoderick Colenbrander 	 */
1563949aaccdSRoderick Colenbrander 	static const int player_ids[5] = {
1564949aaccdSRoderick Colenbrander 		BIT(2),
1565949aaccdSRoderick Colenbrander 		BIT(3) | BIT(1),
1566949aaccdSRoderick Colenbrander 		BIT(4) | BIT(2) | BIT(0),
1567949aaccdSRoderick Colenbrander 		BIT(4) | BIT(3) | BIT(1) | BIT(0),
1568949aaccdSRoderick Colenbrander 		BIT(4) | BIT(3) | BIT(2) | BIT(1) | BIT(0)
1569949aaccdSRoderick Colenbrander 	};
1570949aaccdSRoderick Colenbrander 
1571949aaccdSRoderick Colenbrander 	uint8_t player_id = ds->base.player_id % ARRAY_SIZE(player_ids);
1572949aaccdSRoderick Colenbrander 
1573949aaccdSRoderick Colenbrander 	ds->update_player_leds = true;
1574949aaccdSRoderick Colenbrander 	ds->player_leds_state = player_ids[player_id];
1575182934a1SRoderick Colenbrander 	dualsense_schedule_work(ds);
1576949aaccdSRoderick Colenbrander }
1577949aaccdSRoderick Colenbrander 
dualsense_create(struct hid_device * hdev)1578bc2e15a9SRoderick Colenbrander static struct ps_device *dualsense_create(struct hid_device *hdev)
1579bc2e15a9SRoderick Colenbrander {
1580bc2e15a9SRoderick Colenbrander 	struct dualsense *ds;
1581d30bca44SRoderick Colenbrander 	struct ps_device *ps_dev;
158251151098SRoderick Colenbrander 	uint8_t max_output_report_size;
15838c0ab553SRoderick Colenbrander 	int i, ret;
15848c0ab553SRoderick Colenbrander 
15858c0ab553SRoderick Colenbrander 	static const struct ps_led_info player_leds_info[] = {
1586316f57fbSRoderick Colenbrander 		{ LED_FUNCTION_PLAYER1, "white", 1, dualsense_player_led_get_brightness,
15878c0ab553SRoderick Colenbrander 				dualsense_player_led_set_brightness },
1588316f57fbSRoderick Colenbrander 		{ LED_FUNCTION_PLAYER2, "white", 1, dualsense_player_led_get_brightness,
15898c0ab553SRoderick Colenbrander 				dualsense_player_led_set_brightness },
1590316f57fbSRoderick Colenbrander 		{ LED_FUNCTION_PLAYER3, "white", 1, dualsense_player_led_get_brightness,
15918c0ab553SRoderick Colenbrander 				dualsense_player_led_set_brightness },
1592316f57fbSRoderick Colenbrander 		{ LED_FUNCTION_PLAYER4, "white", 1, dualsense_player_led_get_brightness,
15938c0ab553SRoderick Colenbrander 				dualsense_player_led_set_brightness },
1594316f57fbSRoderick Colenbrander 		{ LED_FUNCTION_PLAYER5, "white", 1, dualsense_player_led_get_brightness,
15958c0ab553SRoderick Colenbrander 				dualsense_player_led_set_brightness }
15968c0ab553SRoderick Colenbrander 	};
1597bc2e15a9SRoderick Colenbrander 
1598bc2e15a9SRoderick Colenbrander 	ds = devm_kzalloc(&hdev->dev, sizeof(*ds), GFP_KERNEL);
1599bc2e15a9SRoderick Colenbrander 	if (!ds)
1600bc2e15a9SRoderick Colenbrander 		return ERR_PTR(-ENOMEM);
1601bc2e15a9SRoderick Colenbrander 
1602bc2e15a9SRoderick Colenbrander 	/*
1603bc2e15a9SRoderick Colenbrander 	 * Patch version to allow userspace to distinguish between
1604bc2e15a9SRoderick Colenbrander 	 * hid-generic vs hid-playstation axis and button mapping.
1605bc2e15a9SRoderick Colenbrander 	 */
1606bc2e15a9SRoderick Colenbrander 	hdev->version |= HID_PLAYSTATION_VERSION_PATCH;
1607bc2e15a9SRoderick Colenbrander 
1608d30bca44SRoderick Colenbrander 	ps_dev = &ds->base;
1609d30bca44SRoderick Colenbrander 	ps_dev->hdev = hdev;
1610d30bca44SRoderick Colenbrander 	spin_lock_init(&ps_dev->lock);
1611d30bca44SRoderick Colenbrander 	ps_dev->battery_capacity = 100; /* initial value until parse_report. */
1612d30bca44SRoderick Colenbrander 	ps_dev->battery_status = POWER_SUPPLY_STATUS_UNKNOWN;
1613d30bca44SRoderick Colenbrander 	ps_dev->parse_report = dualsense_parse_report;
1614182934a1SRoderick Colenbrander 	ps_dev->remove = dualsense_remove;
161551151098SRoderick Colenbrander 	INIT_WORK(&ds->output_worker, dualsense_output_worker);
1616182934a1SRoderick Colenbrander 	ds->output_worker_initialized = true;
1617bc2e15a9SRoderick Colenbrander 	hid_set_drvdata(hdev, ds);
1618bc2e15a9SRoderick Colenbrander 
161951151098SRoderick Colenbrander 	max_output_report_size = sizeof(struct dualsense_output_report_bt);
162051151098SRoderick Colenbrander 	ds->output_report_dmabuf = devm_kzalloc(&hdev->dev, max_output_report_size, GFP_KERNEL);
162151151098SRoderick Colenbrander 	if (!ds->output_report_dmabuf)
162251151098SRoderick Colenbrander 		return ERR_PTR(-ENOMEM);
162351151098SRoderick Colenbrander 
1624b99dcefdSRoderick Colenbrander 	ret = dualsense_get_mac_address(ds);
1625b99dcefdSRoderick Colenbrander 	if (ret) {
1626b99dcefdSRoderick Colenbrander 		hid_err(hdev, "Failed to get MAC address from DualSense\n");
1627b99dcefdSRoderick Colenbrander 		return ERR_PTR(ret);
1628b99dcefdSRoderick Colenbrander 	}
1629b99dcefdSRoderick Colenbrander 	snprintf(hdev->uniq, sizeof(hdev->uniq), "%pMR", ds->base.mac_address);
1630b99dcefdSRoderick Colenbrander 
16310b25b55dSRoderick Colenbrander 	ret = dualsense_get_firmware_info(ds);
16320b25b55dSRoderick Colenbrander 	if (ret) {
16330b25b55dSRoderick Colenbrander 		hid_err(hdev, "Failed to get firmware info from DualSense\n");
16340b25b55dSRoderick Colenbrander 		return ERR_PTR(ret);
16350b25b55dSRoderick Colenbrander 	}
16360b25b55dSRoderick Colenbrander 
16379fecab24SRoderick Colenbrander 	/* Original DualSense firmware simulated classic controller rumble through
16389fecab24SRoderick Colenbrander 	 * its new haptics hardware. It felt different from classic rumble users
16399fecab24SRoderick Colenbrander 	 * were used to. Since then new firmwares were introduced to change behavior
16409fecab24SRoderick Colenbrander 	 * and make this new 'v2' behavior default on PlayStation and other platforms.
16419fecab24SRoderick Colenbrander 	 * The original DualSense requires a new enough firmware as bundled with PS5
16429fecab24SRoderick Colenbrander 	 * software released in 2021. DualSense edge supports it out of the box.
16439fecab24SRoderick Colenbrander 	 * Both devices also support the old mode, but it is not really used.
16449fecab24SRoderick Colenbrander 	 */
16459fecab24SRoderick Colenbrander 	if (hdev->product == USB_DEVICE_ID_SONY_PS5_CONTROLLER) {
16469fecab24SRoderick Colenbrander 		/* Feature version 2.21 introduced new vibration method. */
16479fecab24SRoderick Colenbrander 		ds->use_vibration_v2 = ds->update_version >= DS_FEATURE_VERSION(2, 21);
16489fecab24SRoderick Colenbrander 	} else if (hdev->product == USB_DEVICE_ID_SONY_PS5_CONTROLLER_2) {
16499fecab24SRoderick Colenbrander 		ds->use_vibration_v2 = true;
16509fecab24SRoderick Colenbrander 	}
16519fecab24SRoderick Colenbrander 
165253f04e83SRoderick Colenbrander 	ret = ps_devices_list_add(ps_dev);
165353f04e83SRoderick Colenbrander 	if (ret)
165453f04e83SRoderick Colenbrander 		return ERR_PTR(ret);
165553f04e83SRoderick Colenbrander 
1656402987c5SRoderick Colenbrander 	ret = dualsense_get_calibration_data(ds);
1657402987c5SRoderick Colenbrander 	if (ret) {
1658402987c5SRoderick Colenbrander 		hid_err(hdev, "Failed to get calibration data from DualSense\n");
1659402987c5SRoderick Colenbrander 		goto err;
1660402987c5SRoderick Colenbrander 	}
1661402987c5SRoderick Colenbrander 
166251151098SRoderick Colenbrander 	ds->gamepad = ps_gamepad_create(hdev, dualsense_play_effect);
1663bc2e15a9SRoderick Colenbrander 	if (IS_ERR(ds->gamepad)) {
1664bc2e15a9SRoderick Colenbrander 		ret = PTR_ERR(ds->gamepad);
1665bc2e15a9SRoderick Colenbrander 		goto err;
1666bc2e15a9SRoderick Colenbrander 	}
1667fc97b4d6SRoderick Colenbrander 	/* Use gamepad input device name as primary device name for e.g. LEDs */
1668fc97b4d6SRoderick Colenbrander 	ps_dev->input_dev_name = dev_name(&ds->gamepad->dev);
1669bc2e15a9SRoderick Colenbrander 
1670402987c5SRoderick Colenbrander 	ds->sensors = ps_sensors_create(hdev, DS_ACC_RANGE, DS_ACC_RES_PER_G,
1671402987c5SRoderick Colenbrander 			DS_GYRO_RANGE, DS_GYRO_RES_PER_DEG_S);
1672402987c5SRoderick Colenbrander 	if (IS_ERR(ds->sensors)) {
1673402987c5SRoderick Colenbrander 		ret = PTR_ERR(ds->sensors);
1674402987c5SRoderick Colenbrander 		goto err;
1675402987c5SRoderick Colenbrander 	}
1676402987c5SRoderick Colenbrander 
1677f6bb05fcSRoderick Colenbrander 	ds->touchpad = ps_touchpad_create(hdev, DS_TOUCHPAD_WIDTH, DS_TOUCHPAD_HEIGHT, 2);
1678f6bb05fcSRoderick Colenbrander 	if (IS_ERR(ds->touchpad)) {
1679f6bb05fcSRoderick Colenbrander 		ret = PTR_ERR(ds->touchpad);
1680f6bb05fcSRoderick Colenbrander 		goto err;
1681f6bb05fcSRoderick Colenbrander 	}
1682f6bb05fcSRoderick Colenbrander 
1683d30bca44SRoderick Colenbrander 	ret = ps_device_register_battery(ps_dev);
1684d30bca44SRoderick Colenbrander 	if (ret)
1685d30bca44SRoderick Colenbrander 		goto err;
1686d30bca44SRoderick Colenbrander 
16870b25b55dSRoderick Colenbrander 	/*
16888e5198a1SRoderick Colenbrander 	 * The hardware may have control over the LEDs (e.g. in Bluetooth on startup).
16898e5198a1SRoderick Colenbrander 	 * Reset the LEDs (lightbar, mute, player leds), so we can control them
16908e5198a1SRoderick Colenbrander 	 * from software.
16918e5198a1SRoderick Colenbrander 	 */
16928e5198a1SRoderick Colenbrander 	ret = dualsense_reset_leds(ds);
16938e5198a1SRoderick Colenbrander 	if (ret)
16948e5198a1SRoderick Colenbrander 		goto err;
16958e5198a1SRoderick Colenbrander 
1696fc97b4d6SRoderick Colenbrander 	ret = ps_lightbar_register(ps_dev, &ds->lightbar, dualsense_lightbar_set_brightness);
1697fc97b4d6SRoderick Colenbrander 	if (ret)
1698fc97b4d6SRoderick Colenbrander 		goto err;
1699fc97b4d6SRoderick Colenbrander 
1700fc97b4d6SRoderick Colenbrander 	/* Set default lightbar color. */
17018e5198a1SRoderick Colenbrander 	dualsense_set_lightbar(ds, 0, 0, 128); /* blue */
17028e5198a1SRoderick Colenbrander 
17038c0ab553SRoderick Colenbrander 	for (i = 0; i < ARRAY_SIZE(player_leds_info); i++) {
17048c0ab553SRoderick Colenbrander 		const struct ps_led_info *led_info = &player_leds_info[i];
17058c0ab553SRoderick Colenbrander 
17068c0ab553SRoderick Colenbrander 		ret = ps_led_register(ps_dev, &ds->player_leds[i], led_info);
17078c0ab553SRoderick Colenbrander 		if (ret < 0)
17088c0ab553SRoderick Colenbrander 			goto err;
17098c0ab553SRoderick Colenbrander 	}
17108c0ab553SRoderick Colenbrander 
1711949aaccdSRoderick Colenbrander 	ret = ps_device_set_player_id(ps_dev);
1712949aaccdSRoderick Colenbrander 	if (ret) {
1713949aaccdSRoderick Colenbrander 		hid_err(hdev, "Failed to assign player id for DualSense: %d\n", ret);
1714949aaccdSRoderick Colenbrander 		goto err;
1715949aaccdSRoderick Colenbrander 	}
1716949aaccdSRoderick Colenbrander 
1717949aaccdSRoderick Colenbrander 	/* Set player LEDs to our player id. */
1718949aaccdSRoderick Colenbrander 	dualsense_set_player_leds(ds);
1719949aaccdSRoderick Colenbrander 
17208e5198a1SRoderick Colenbrander 	/*
17210b25b55dSRoderick Colenbrander 	 * Reporting hardware and firmware is important as there are frequent updates, which
17220b25b55dSRoderick Colenbrander 	 * can change behavior.
17230b25b55dSRoderick Colenbrander 	 */
17240b25b55dSRoderick Colenbrander 	hid_info(hdev, "Registered DualSense controller hw_version=0x%08x fw_version=0x%08x\n",
17250b25b55dSRoderick Colenbrander 			ds->base.hw_version, ds->base.fw_version);
17260b25b55dSRoderick Colenbrander 
1727bc2e15a9SRoderick Colenbrander 	return &ds->base;
1728bc2e15a9SRoderick Colenbrander 
1729bc2e15a9SRoderick Colenbrander err:
173053f04e83SRoderick Colenbrander 	ps_devices_list_remove(ps_dev);
1731bc2e15a9SRoderick Colenbrander 	return ERR_PTR(ret);
1732bc2e15a9SRoderick Colenbrander }
1733bc2e15a9SRoderick Colenbrander 
dualshock4_dongle_calibration_work(struct work_struct * work)1734c64ed0cdSRoderick Colenbrander static void dualshock4_dongle_calibration_work(struct work_struct *work)
1735c64ed0cdSRoderick Colenbrander {
1736c64ed0cdSRoderick Colenbrander 	struct dualshock4 *ds4 = container_of(work, struct dualshock4, dongle_hotplug_worker);
1737c64ed0cdSRoderick Colenbrander 	unsigned long flags;
1738c64ed0cdSRoderick Colenbrander 	enum dualshock4_dongle_state dongle_state;
1739c64ed0cdSRoderick Colenbrander 	int ret;
1740c64ed0cdSRoderick Colenbrander 
1741c64ed0cdSRoderick Colenbrander 	ret = dualshock4_get_calibration_data(ds4);
1742c64ed0cdSRoderick Colenbrander 	if (ret < 0) {
1743c64ed0cdSRoderick Colenbrander 		/* This call is very unlikely to fail for the dongle. When it
1744c64ed0cdSRoderick Colenbrander 		 * fails we are probably in a very bad state, so mark the
1745c64ed0cdSRoderick Colenbrander 		 * dongle as disabled. We will re-enable the dongle if a new
1746c64ed0cdSRoderick Colenbrander 		 * DS4 hotplug is detect from sony_raw_event as any issues
1747c64ed0cdSRoderick Colenbrander 		 * are likely resolved then (the dongle is quite stupid).
1748c64ed0cdSRoderick Colenbrander 		 */
1749c64ed0cdSRoderick Colenbrander 		hid_err(ds4->base.hdev, "DualShock 4 USB dongle: calibration failed, disabling device\n");
1750c64ed0cdSRoderick Colenbrander 		dongle_state = DONGLE_DISABLED;
1751c64ed0cdSRoderick Colenbrander 	} else {
1752c64ed0cdSRoderick Colenbrander 		hid_info(ds4->base.hdev, "DualShock 4 USB dongle: calibration completed\n");
1753c64ed0cdSRoderick Colenbrander 		dongle_state = DONGLE_CONNECTED;
1754c64ed0cdSRoderick Colenbrander 	}
1755c64ed0cdSRoderick Colenbrander 
1756c64ed0cdSRoderick Colenbrander 	spin_lock_irqsave(&ds4->base.lock, flags);
1757c64ed0cdSRoderick Colenbrander 	ds4->dongle_state = dongle_state;
1758c64ed0cdSRoderick Colenbrander 	spin_unlock_irqrestore(&ds4->base.lock, flags);
1759c64ed0cdSRoderick Colenbrander }
1760c64ed0cdSRoderick Colenbrander 
dualshock4_get_calibration_data(struct dualshock4 * ds4)176112882ed8SRoderick Colenbrander static int dualshock4_get_calibration_data(struct dualshock4 *ds4)
176212882ed8SRoderick Colenbrander {
176312882ed8SRoderick Colenbrander 	struct hid_device *hdev = ds4->base.hdev;
176412882ed8SRoderick Colenbrander 	short gyro_pitch_bias, gyro_pitch_plus, gyro_pitch_minus;
176512882ed8SRoderick Colenbrander 	short gyro_yaw_bias, gyro_yaw_plus, gyro_yaw_minus;
176612882ed8SRoderick Colenbrander 	short gyro_roll_bias, gyro_roll_plus, gyro_roll_minus;
176712882ed8SRoderick Colenbrander 	short gyro_speed_plus, gyro_speed_minus;
176812882ed8SRoderick Colenbrander 	short acc_x_plus, acc_x_minus;
176912882ed8SRoderick Colenbrander 	short acc_y_plus, acc_y_minus;
177012882ed8SRoderick Colenbrander 	short acc_z_plus, acc_z_minus;
177112882ed8SRoderick Colenbrander 	int speed_2x;
177212882ed8SRoderick Colenbrander 	int range_2g;
177312882ed8SRoderick Colenbrander 	int ret = 0;
177474cb485fSRoderick Colenbrander 	int i;
177512882ed8SRoderick Colenbrander 	uint8_t *buf;
177612882ed8SRoderick Colenbrander 
17772d77474aSRoderick Colenbrander 	if (ds4->base.hdev->bus == BUS_USB) {
1778c64ed0cdSRoderick Colenbrander 		int retries;
1779c64ed0cdSRoderick Colenbrander 
178012882ed8SRoderick Colenbrander 		buf = kzalloc(DS4_FEATURE_REPORT_CALIBRATION_SIZE, GFP_KERNEL);
178112882ed8SRoderick Colenbrander 		if (!buf)
178212882ed8SRoderick Colenbrander 			return -ENOMEM;
178312882ed8SRoderick Colenbrander 
1784c64ed0cdSRoderick Colenbrander 		/* We should normally receive the feature report data we asked
1785c64ed0cdSRoderick Colenbrander 		 * for, but hidraw applications such as Steam can issue feature
1786c64ed0cdSRoderick Colenbrander 		 * reports as well. In particular for Dongle reconnects, Steam
1787c64ed0cdSRoderick Colenbrander 		 * and this function are competing resulting in often receiving
1788c64ed0cdSRoderick Colenbrander 		 * data for a different HID report, so retry a few times.
1789c64ed0cdSRoderick Colenbrander 		 */
1790c64ed0cdSRoderick Colenbrander 		for (retries = 0; retries < 3; retries++) {
179112882ed8SRoderick Colenbrander 			ret = ps_get_report(hdev, DS4_FEATURE_REPORT_CALIBRATION, buf,
1792a23b063bSRoderick Colenbrander 					DS4_FEATURE_REPORT_CALIBRATION_SIZE, true);
179312882ed8SRoderick Colenbrander 			if (ret) {
1794c64ed0cdSRoderick Colenbrander 				if (retries < 2) {
1795c64ed0cdSRoderick Colenbrander 					hid_warn(hdev, "Retrying DualShock 4 get calibration report (0x02) request\n");
1796c64ed0cdSRoderick Colenbrander 					continue;
1797c64ed0cdSRoderick Colenbrander 				}
17985e25a8cdSRoderick Colenbrander 
179912882ed8SRoderick Colenbrander 				hid_err(hdev, "Failed to retrieve DualShock4 calibration info: %d\n", ret);
18005e25a8cdSRoderick Colenbrander 				ret = -EILSEQ;
180112882ed8SRoderick Colenbrander 				goto err_free;
1802c64ed0cdSRoderick Colenbrander 			} else {
1803c64ed0cdSRoderick Colenbrander 				break;
1804c64ed0cdSRoderick Colenbrander 			}
180512882ed8SRoderick Colenbrander 		}
18062d77474aSRoderick Colenbrander 	} else { /* Bluetooth */
18072d77474aSRoderick Colenbrander 		buf = kzalloc(DS4_FEATURE_REPORT_CALIBRATION_BT_SIZE, GFP_KERNEL);
18082d77474aSRoderick Colenbrander 		if (!buf)
18092d77474aSRoderick Colenbrander 			return -ENOMEM;
18102d77474aSRoderick Colenbrander 
18112d77474aSRoderick Colenbrander 		ret = ps_get_report(hdev, DS4_FEATURE_REPORT_CALIBRATION_BT, buf,
18122d77474aSRoderick Colenbrander 				DS4_FEATURE_REPORT_CALIBRATION_BT_SIZE, true);
18132d77474aSRoderick Colenbrander 		if (ret) {
18142d77474aSRoderick Colenbrander 			hid_err(hdev, "Failed to retrieve DualShock4 calibration info: %d\n", ret);
18152d77474aSRoderick Colenbrander 			goto err_free;
18162d77474aSRoderick Colenbrander 		}
18172d77474aSRoderick Colenbrander 	}
181812882ed8SRoderick Colenbrander 
181912882ed8SRoderick Colenbrander 	gyro_pitch_bias  = get_unaligned_le16(&buf[1]);
182012882ed8SRoderick Colenbrander 	gyro_yaw_bias    = get_unaligned_le16(&buf[3]);
182112882ed8SRoderick Colenbrander 	gyro_roll_bias   = get_unaligned_le16(&buf[5]);
18222d77474aSRoderick Colenbrander 	if (ds4->base.hdev->bus == BUS_USB) {
182312882ed8SRoderick Colenbrander 		gyro_pitch_plus  = get_unaligned_le16(&buf[7]);
182412882ed8SRoderick Colenbrander 		gyro_pitch_minus = get_unaligned_le16(&buf[9]);
182512882ed8SRoderick Colenbrander 		gyro_yaw_plus    = get_unaligned_le16(&buf[11]);
182612882ed8SRoderick Colenbrander 		gyro_yaw_minus   = get_unaligned_le16(&buf[13]);
182712882ed8SRoderick Colenbrander 		gyro_roll_plus   = get_unaligned_le16(&buf[15]);
182812882ed8SRoderick Colenbrander 		gyro_roll_minus  = get_unaligned_le16(&buf[17]);
18292d77474aSRoderick Colenbrander 	} else {
18302d77474aSRoderick Colenbrander 		/* BT + Dongle */
18312d77474aSRoderick Colenbrander 		gyro_pitch_plus  = get_unaligned_le16(&buf[7]);
18322d77474aSRoderick Colenbrander 		gyro_yaw_plus    = get_unaligned_le16(&buf[9]);
18332d77474aSRoderick Colenbrander 		gyro_roll_plus   = get_unaligned_le16(&buf[11]);
18342d77474aSRoderick Colenbrander 		gyro_pitch_minus = get_unaligned_le16(&buf[13]);
18352d77474aSRoderick Colenbrander 		gyro_yaw_minus   = get_unaligned_le16(&buf[15]);
18362d77474aSRoderick Colenbrander 		gyro_roll_minus  = get_unaligned_le16(&buf[17]);
18372d77474aSRoderick Colenbrander 	}
183812882ed8SRoderick Colenbrander 	gyro_speed_plus  = get_unaligned_le16(&buf[19]);
183912882ed8SRoderick Colenbrander 	gyro_speed_minus = get_unaligned_le16(&buf[21]);
184012882ed8SRoderick Colenbrander 	acc_x_plus       = get_unaligned_le16(&buf[23]);
184112882ed8SRoderick Colenbrander 	acc_x_minus      = get_unaligned_le16(&buf[25]);
184212882ed8SRoderick Colenbrander 	acc_y_plus       = get_unaligned_le16(&buf[27]);
184312882ed8SRoderick Colenbrander 	acc_y_minus      = get_unaligned_le16(&buf[29]);
184412882ed8SRoderick Colenbrander 	acc_z_plus       = get_unaligned_le16(&buf[31]);
184512882ed8SRoderick Colenbrander 	acc_z_minus      = get_unaligned_le16(&buf[33]);
184612882ed8SRoderick Colenbrander 
184712882ed8SRoderick Colenbrander 	/*
184812882ed8SRoderick Colenbrander 	 * Set gyroscope calibration and normalization parameters.
184912882ed8SRoderick Colenbrander 	 * Data values will be normalized to 1/DS4_GYRO_RES_PER_DEG_S degree/s.
185012882ed8SRoderick Colenbrander 	 */
185112882ed8SRoderick Colenbrander 	speed_2x = (gyro_speed_plus + gyro_speed_minus);
185212882ed8SRoderick Colenbrander 	ds4->gyro_calib_data[0].abs_code = ABS_RX;
185312b18bc2SRoderick Colenbrander 	ds4->gyro_calib_data[0].bias = 0;
185412882ed8SRoderick Colenbrander 	ds4->gyro_calib_data[0].sens_numer = speed_2x*DS4_GYRO_RES_PER_DEG_S;
185512b18bc2SRoderick Colenbrander 	ds4->gyro_calib_data[0].sens_denom = abs(gyro_pitch_plus - gyro_pitch_bias) +
185612b18bc2SRoderick Colenbrander 			abs(gyro_pitch_minus - gyro_pitch_bias);
185712882ed8SRoderick Colenbrander 
185812882ed8SRoderick Colenbrander 	ds4->gyro_calib_data[1].abs_code = ABS_RY;
185912b18bc2SRoderick Colenbrander 	ds4->gyro_calib_data[1].bias = 0;
186012882ed8SRoderick Colenbrander 	ds4->gyro_calib_data[1].sens_numer = speed_2x*DS4_GYRO_RES_PER_DEG_S;
186112b18bc2SRoderick Colenbrander 	ds4->gyro_calib_data[1].sens_denom = abs(gyro_yaw_plus - gyro_yaw_bias) +
186212b18bc2SRoderick Colenbrander 			abs(gyro_yaw_minus - gyro_yaw_bias);
186312882ed8SRoderick Colenbrander 
186412882ed8SRoderick Colenbrander 	ds4->gyro_calib_data[2].abs_code = ABS_RZ;
186512b18bc2SRoderick Colenbrander 	ds4->gyro_calib_data[2].bias = 0;
186612882ed8SRoderick Colenbrander 	ds4->gyro_calib_data[2].sens_numer = speed_2x*DS4_GYRO_RES_PER_DEG_S;
186712b18bc2SRoderick Colenbrander 	ds4->gyro_calib_data[2].sens_denom = abs(gyro_roll_plus - gyro_roll_bias) +
186812b18bc2SRoderick Colenbrander 			abs(gyro_roll_minus - gyro_roll_bias);
186912882ed8SRoderick Colenbrander 
187012882ed8SRoderick Colenbrander 	/*
187174cb485fSRoderick Colenbrander 	 * Sanity check gyro calibration data. This is needed to prevent crashes
187274cb485fSRoderick Colenbrander 	 * during report handling of virtual, clone or broken devices not implementing
187374cb485fSRoderick Colenbrander 	 * calibration data properly.
187474cb485fSRoderick Colenbrander 	 */
187574cb485fSRoderick Colenbrander 	for (i = 0; i < ARRAY_SIZE(ds4->gyro_calib_data); i++) {
187674cb485fSRoderick Colenbrander 		if (ds4->gyro_calib_data[i].sens_denom == 0) {
187774cb485fSRoderick Colenbrander 			hid_warn(hdev, "Invalid gyro calibration data for axis (%d), disabling calibration.",
187874cb485fSRoderick Colenbrander 					ds4->gyro_calib_data[i].abs_code);
187974cb485fSRoderick Colenbrander 			ds4->gyro_calib_data[i].bias = 0;
188074cb485fSRoderick Colenbrander 			ds4->gyro_calib_data[i].sens_numer = DS4_GYRO_RANGE;
188174cb485fSRoderick Colenbrander 			ds4->gyro_calib_data[i].sens_denom = S16_MAX;
188274cb485fSRoderick Colenbrander 		}
188374cb485fSRoderick Colenbrander 	}
188474cb485fSRoderick Colenbrander 
188574cb485fSRoderick Colenbrander 	/*
188612882ed8SRoderick Colenbrander 	 * Set accelerometer calibration and normalization parameters.
188712882ed8SRoderick Colenbrander 	 * Data values will be normalized to 1/DS4_ACC_RES_PER_G g.
188812882ed8SRoderick Colenbrander 	 */
188912882ed8SRoderick Colenbrander 	range_2g = acc_x_plus - acc_x_minus;
189012882ed8SRoderick Colenbrander 	ds4->accel_calib_data[0].abs_code = ABS_X;
189112882ed8SRoderick Colenbrander 	ds4->accel_calib_data[0].bias = acc_x_plus - range_2g / 2;
189212882ed8SRoderick Colenbrander 	ds4->accel_calib_data[0].sens_numer = 2*DS4_ACC_RES_PER_G;
189312882ed8SRoderick Colenbrander 	ds4->accel_calib_data[0].sens_denom = range_2g;
189412882ed8SRoderick Colenbrander 
189512882ed8SRoderick Colenbrander 	range_2g = acc_y_plus - acc_y_minus;
189612882ed8SRoderick Colenbrander 	ds4->accel_calib_data[1].abs_code = ABS_Y;
189712882ed8SRoderick Colenbrander 	ds4->accel_calib_data[1].bias = acc_y_plus - range_2g / 2;
189812882ed8SRoderick Colenbrander 	ds4->accel_calib_data[1].sens_numer = 2*DS4_ACC_RES_PER_G;
189912882ed8SRoderick Colenbrander 	ds4->accel_calib_data[1].sens_denom = range_2g;
190012882ed8SRoderick Colenbrander 
190112882ed8SRoderick Colenbrander 	range_2g = acc_z_plus - acc_z_minus;
190212882ed8SRoderick Colenbrander 	ds4->accel_calib_data[2].abs_code = ABS_Z;
190312882ed8SRoderick Colenbrander 	ds4->accel_calib_data[2].bias = acc_z_plus - range_2g / 2;
190412882ed8SRoderick Colenbrander 	ds4->accel_calib_data[2].sens_numer = 2*DS4_ACC_RES_PER_G;
190512882ed8SRoderick Colenbrander 	ds4->accel_calib_data[2].sens_denom = range_2g;
190612882ed8SRoderick Colenbrander 
190774cb485fSRoderick Colenbrander 	/*
190874cb485fSRoderick Colenbrander 	 * Sanity check accelerometer calibration data. This is needed to prevent crashes
190974cb485fSRoderick Colenbrander 	 * during report handling of virtual, clone or broken devices not implementing calibration
191074cb485fSRoderick Colenbrander 	 * data properly.
191174cb485fSRoderick Colenbrander 	 */
191274cb485fSRoderick Colenbrander 	for (i = 0; i < ARRAY_SIZE(ds4->accel_calib_data); i++) {
191374cb485fSRoderick Colenbrander 		if (ds4->accel_calib_data[i].sens_denom == 0) {
191474cb485fSRoderick Colenbrander 			hid_warn(hdev, "Invalid accelerometer calibration data for axis (%d), disabling calibration.",
191574cb485fSRoderick Colenbrander 					ds4->accel_calib_data[i].abs_code);
191674cb485fSRoderick Colenbrander 			ds4->accel_calib_data[i].bias = 0;
191774cb485fSRoderick Colenbrander 			ds4->accel_calib_data[i].sens_numer = DS4_ACC_RANGE;
191874cb485fSRoderick Colenbrander 			ds4->accel_calib_data[i].sens_denom = S16_MAX;
191974cb485fSRoderick Colenbrander 		}
192074cb485fSRoderick Colenbrander 	}
192174cb485fSRoderick Colenbrander 
192212882ed8SRoderick Colenbrander err_free:
192312882ed8SRoderick Colenbrander 	kfree(buf);
192412882ed8SRoderick Colenbrander 	return ret;
192512882ed8SRoderick Colenbrander }
192612882ed8SRoderick Colenbrander 
dualshock4_get_firmware_info(struct dualshock4 * ds4)19279a62280aSRoderick Colenbrander static int dualshock4_get_firmware_info(struct dualshock4 *ds4)
19289a62280aSRoderick Colenbrander {
19299a62280aSRoderick Colenbrander 	uint8_t *buf;
19309a62280aSRoderick Colenbrander 	int ret;
19319a62280aSRoderick Colenbrander 
19329a62280aSRoderick Colenbrander 	buf = kzalloc(DS4_FEATURE_REPORT_FIRMWARE_INFO_SIZE, GFP_KERNEL);
19339a62280aSRoderick Colenbrander 	if (!buf)
19349a62280aSRoderick Colenbrander 		return -ENOMEM;
19359a62280aSRoderick Colenbrander 
19362d77474aSRoderick Colenbrander 	/* Note USB and BT support the same feature report, but this report
19372d77474aSRoderick Colenbrander 	 * lacks CRC support, so must be disabled in ps_get_report.
19382d77474aSRoderick Colenbrander 	 */
19399a62280aSRoderick Colenbrander 	ret = ps_get_report(ds4->base.hdev, DS4_FEATURE_REPORT_FIRMWARE_INFO, buf,
19402d77474aSRoderick Colenbrander 			DS4_FEATURE_REPORT_FIRMWARE_INFO_SIZE, false);
19419a62280aSRoderick Colenbrander 	if (ret) {
19429a62280aSRoderick Colenbrander 		hid_err(ds4->base.hdev, "Failed to retrieve DualShock4 firmware info: %d\n", ret);
19439a62280aSRoderick Colenbrander 		goto err_free;
19449a62280aSRoderick Colenbrander 	}
19459a62280aSRoderick Colenbrander 
19469a62280aSRoderick Colenbrander 	ds4->base.hw_version = get_unaligned_le16(&buf[35]);
19479a62280aSRoderick Colenbrander 	ds4->base.fw_version = get_unaligned_le16(&buf[41]);
19489a62280aSRoderick Colenbrander 
19499a62280aSRoderick Colenbrander err_free:
19509a62280aSRoderick Colenbrander 	kfree(buf);
19519a62280aSRoderick Colenbrander 	return ret;
19529a62280aSRoderick Colenbrander }
19539a62280aSRoderick Colenbrander 
dualshock4_get_mac_address(struct dualshock4 * ds4)1954f55b9b56SRoderick Colenbrander static int dualshock4_get_mac_address(struct dualshock4 *ds4)
1955f55b9b56SRoderick Colenbrander {
19562d77474aSRoderick Colenbrander 	struct hid_device *hdev = ds4->base.hdev;
1957f55b9b56SRoderick Colenbrander 	uint8_t *buf;
1958f55b9b56SRoderick Colenbrander 	int ret = 0;
1959f55b9b56SRoderick Colenbrander 
19602d77474aSRoderick Colenbrander 	if (hdev->bus == BUS_USB) {
1961f55b9b56SRoderick Colenbrander 		buf = kzalloc(DS4_FEATURE_REPORT_PAIRING_INFO_SIZE, GFP_KERNEL);
1962f55b9b56SRoderick Colenbrander 		if (!buf)
1963f55b9b56SRoderick Colenbrander 			return -ENOMEM;
1964f55b9b56SRoderick Colenbrander 
19652d77474aSRoderick Colenbrander 		ret = ps_get_report(hdev, DS4_FEATURE_REPORT_PAIRING_INFO, buf,
19662d77474aSRoderick Colenbrander 				DS4_FEATURE_REPORT_PAIRING_INFO_SIZE, false);
1967f55b9b56SRoderick Colenbrander 		if (ret) {
19682d77474aSRoderick Colenbrander 			hid_err(hdev, "Failed to retrieve DualShock4 pairing info: %d\n", ret);
1969f55b9b56SRoderick Colenbrander 			goto err_free;
1970f55b9b56SRoderick Colenbrander 		}
1971f55b9b56SRoderick Colenbrander 
1972f55b9b56SRoderick Colenbrander 		memcpy(ds4->base.mac_address, &buf[1], sizeof(ds4->base.mac_address));
19732d77474aSRoderick Colenbrander 	} else {
19742d77474aSRoderick Colenbrander 		/* Rely on HIDP for Bluetooth */
19752d77474aSRoderick Colenbrander 		if (strlen(hdev->uniq) != 17)
19762d77474aSRoderick Colenbrander 			return -EINVAL;
19772d77474aSRoderick Colenbrander 
19782d77474aSRoderick Colenbrander 		ret = sscanf(hdev->uniq, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
19792d77474aSRoderick Colenbrander 				&ds4->base.mac_address[5], &ds4->base.mac_address[4],
19802d77474aSRoderick Colenbrander 				&ds4->base.mac_address[3], &ds4->base.mac_address[2],
19812d77474aSRoderick Colenbrander 				&ds4->base.mac_address[1], &ds4->base.mac_address[0]);
19822d77474aSRoderick Colenbrander 
19832d77474aSRoderick Colenbrander 		if (ret != sizeof(ds4->base.mac_address))
19842d77474aSRoderick Colenbrander 			return -EINVAL;
19852d77474aSRoderick Colenbrander 
19860ee29814SRoderick Colenbrander 		return 0;
19872d77474aSRoderick Colenbrander 	}
1988f55b9b56SRoderick Colenbrander 
1989f55b9b56SRoderick Colenbrander err_free:
1990f55b9b56SRoderick Colenbrander 	kfree(buf);
1991f55b9b56SRoderick Colenbrander 	return ret;
1992f55b9b56SRoderick Colenbrander }
1993f55b9b56SRoderick Colenbrander 
dualshock4_led_get_brightness(struct led_classdev * led)19944521109aSRoderick Colenbrander static enum led_brightness dualshock4_led_get_brightness(struct led_classdev *led)
19954521109aSRoderick Colenbrander {
19964521109aSRoderick Colenbrander 	struct hid_device *hdev = to_hid_device(led->dev->parent);
19974521109aSRoderick Colenbrander 	struct dualshock4 *ds4 = hid_get_drvdata(hdev);
19984521109aSRoderick Colenbrander 	unsigned int led_index;
19994521109aSRoderick Colenbrander 
20004521109aSRoderick Colenbrander 	led_index = led - ds4->lightbar_leds;
20014521109aSRoderick Colenbrander 	switch (led_index) {
20024521109aSRoderick Colenbrander 	case 0:
20034521109aSRoderick Colenbrander 		return ds4->lightbar_red;
20044521109aSRoderick Colenbrander 	case 1:
20054521109aSRoderick Colenbrander 		return ds4->lightbar_green;
20064521109aSRoderick Colenbrander 	case 2:
20074521109aSRoderick Colenbrander 		return ds4->lightbar_blue;
20084521109aSRoderick Colenbrander 	case 3:
20094521109aSRoderick Colenbrander 		return ds4->lightbar_enabled;
20104521109aSRoderick Colenbrander 	}
20114521109aSRoderick Colenbrander 
20124521109aSRoderick Colenbrander 	return -1;
20134521109aSRoderick Colenbrander }
20144521109aSRoderick Colenbrander 
dualshock4_led_set_blink(struct led_classdev * led,unsigned long * delay_on,unsigned long * delay_off)201582d93f64SRoderick Colenbrander static int dualshock4_led_set_blink(struct led_classdev *led, unsigned long *delay_on,
201682d93f64SRoderick Colenbrander 		unsigned long *delay_off)
201782d93f64SRoderick Colenbrander {
201882d93f64SRoderick Colenbrander 	struct hid_device *hdev = to_hid_device(led->dev->parent);
201982d93f64SRoderick Colenbrander 	struct dualshock4 *ds4 = hid_get_drvdata(hdev);
202082d93f64SRoderick Colenbrander 	unsigned long flags;
202182d93f64SRoderick Colenbrander 
202282d93f64SRoderick Colenbrander 	spin_lock_irqsave(&ds4->base.lock, flags);
202382d93f64SRoderick Colenbrander 
202482d93f64SRoderick Colenbrander 	if (!*delay_on && !*delay_off) {
202582d93f64SRoderick Colenbrander 		/* Default to 1 Hz (50 centiseconds on, 50 centiseconds off). */
202682d93f64SRoderick Colenbrander 		ds4->lightbar_blink_on = 50;
202782d93f64SRoderick Colenbrander 		ds4->lightbar_blink_off = 50;
202882d93f64SRoderick Colenbrander 	} else {
202982d93f64SRoderick Colenbrander 		/* Blink delays in centiseconds. */
203082d93f64SRoderick Colenbrander 		ds4->lightbar_blink_on = min_t(unsigned long, *delay_on/10, DS4_LIGHTBAR_MAX_BLINK);
203182d93f64SRoderick Colenbrander 		ds4->lightbar_blink_off = min_t(unsigned long, *delay_off/10, DS4_LIGHTBAR_MAX_BLINK);
203282d93f64SRoderick Colenbrander 	}
203382d93f64SRoderick Colenbrander 
203482d93f64SRoderick Colenbrander 	ds4->update_lightbar_blink = true;
203582d93f64SRoderick Colenbrander 
203682d93f64SRoderick Colenbrander 	spin_unlock_irqrestore(&ds4->base.lock, flags);
203782d93f64SRoderick Colenbrander 
203882d93f64SRoderick Colenbrander 	dualshock4_schedule_work(ds4);
203982d93f64SRoderick Colenbrander 
204082d93f64SRoderick Colenbrander 	*delay_on = ds4->lightbar_blink_on;
204182d93f64SRoderick Colenbrander 	*delay_off = ds4->lightbar_blink_off;
204282d93f64SRoderick Colenbrander 
204382d93f64SRoderick Colenbrander 	return 0;
204482d93f64SRoderick Colenbrander }
204582d93f64SRoderick Colenbrander 
dualshock4_led_set_brightness(struct led_classdev * led,enum led_brightness value)20464521109aSRoderick Colenbrander static int dualshock4_led_set_brightness(struct led_classdev *led, enum led_brightness value)
20474521109aSRoderick Colenbrander {
20484521109aSRoderick Colenbrander 	struct hid_device *hdev = to_hid_device(led->dev->parent);
20494521109aSRoderick Colenbrander 	struct dualshock4 *ds4 = hid_get_drvdata(hdev);
20504521109aSRoderick Colenbrander 	unsigned long flags;
20514521109aSRoderick Colenbrander 	unsigned int led_index;
20524521109aSRoderick Colenbrander 
20534521109aSRoderick Colenbrander 	spin_lock_irqsave(&ds4->base.lock, flags);
20544521109aSRoderick Colenbrander 
20554521109aSRoderick Colenbrander 	led_index = led - ds4->lightbar_leds;
20564521109aSRoderick Colenbrander 	switch (led_index) {
20574521109aSRoderick Colenbrander 	case 0:
20584521109aSRoderick Colenbrander 		ds4->lightbar_red = value;
20594521109aSRoderick Colenbrander 		break;
20604521109aSRoderick Colenbrander 	case 1:
20614521109aSRoderick Colenbrander 		ds4->lightbar_green = value;
20624521109aSRoderick Colenbrander 		break;
20634521109aSRoderick Colenbrander 	case 2:
20644521109aSRoderick Colenbrander 		ds4->lightbar_blue = value;
20654521109aSRoderick Colenbrander 		break;
20664521109aSRoderick Colenbrander 	case 3:
20674521109aSRoderick Colenbrander 		ds4->lightbar_enabled = !!value;
20684521109aSRoderick Colenbrander 	}
20694521109aSRoderick Colenbrander 
20704521109aSRoderick Colenbrander 	ds4->update_lightbar = true;
20714521109aSRoderick Colenbrander 
20724521109aSRoderick Colenbrander 	spin_unlock_irqrestore(&ds4->base.lock, flags);
20734521109aSRoderick Colenbrander 
20744521109aSRoderick Colenbrander 	dualshock4_schedule_work(ds4);
20754521109aSRoderick Colenbrander 
20764521109aSRoderick Colenbrander 	return 0;
20774521109aSRoderick Colenbrander }
20784521109aSRoderick Colenbrander 
dualshock4_init_output_report(struct dualshock4 * ds4,struct dualshock4_output_report * rp,void * buf)20794e463ec4SRoderick Colenbrander static void dualshock4_init_output_report(struct dualshock4 *ds4,
20804e463ec4SRoderick Colenbrander 		struct dualshock4_output_report *rp, void *buf)
20814e463ec4SRoderick Colenbrander {
20824e463ec4SRoderick Colenbrander 	struct hid_device *hdev = ds4->base.hdev;
20834e463ec4SRoderick Colenbrander 
20842d77474aSRoderick Colenbrander 	if (hdev->bus == BUS_BLUETOOTH) {
20852d77474aSRoderick Colenbrander 		struct dualshock4_output_report_bt *bt = buf;
20862d77474aSRoderick Colenbrander 
20872d77474aSRoderick Colenbrander 		memset(bt, 0, sizeof(*bt));
20882d77474aSRoderick Colenbrander 		bt->report_id = DS4_OUTPUT_REPORT_BT;
20892d77474aSRoderick Colenbrander 
20902d77474aSRoderick Colenbrander 		rp->data = buf;
20912d77474aSRoderick Colenbrander 		rp->len = sizeof(*bt);
20922d77474aSRoderick Colenbrander 		rp->bt = bt;
20932d77474aSRoderick Colenbrander 		rp->usb = NULL;
20942d77474aSRoderick Colenbrander 		rp->common = &bt->common;
20952d77474aSRoderick Colenbrander 	} else { /* USB */
20964e463ec4SRoderick Colenbrander 		struct dualshock4_output_report_usb *usb = buf;
20974e463ec4SRoderick Colenbrander 
20984e463ec4SRoderick Colenbrander 		memset(usb, 0, sizeof(*usb));
20994e463ec4SRoderick Colenbrander 		usb->report_id = DS4_OUTPUT_REPORT_USB;
21004e463ec4SRoderick Colenbrander 
21014e463ec4SRoderick Colenbrander 		rp->data = buf;
21024e463ec4SRoderick Colenbrander 		rp->len = sizeof(*usb);
21032d77474aSRoderick Colenbrander 		rp->bt = NULL;
21044e463ec4SRoderick Colenbrander 		rp->usb = usb;
21054e463ec4SRoderick Colenbrander 		rp->common = &usb->common;
21064e463ec4SRoderick Colenbrander 	}
21074e463ec4SRoderick Colenbrander }
21084e463ec4SRoderick Colenbrander 
dualshock4_output_worker(struct work_struct * work)21094e463ec4SRoderick Colenbrander static void dualshock4_output_worker(struct work_struct *work)
21104e463ec4SRoderick Colenbrander {
21114e463ec4SRoderick Colenbrander 	struct dualshock4 *ds4 = container_of(work, struct dualshock4, output_worker);
21124e463ec4SRoderick Colenbrander 	struct dualshock4_output_report report;
21134e463ec4SRoderick Colenbrander 	struct dualshock4_output_report_common *common;
21144e463ec4SRoderick Colenbrander 	unsigned long flags;
21154e463ec4SRoderick Colenbrander 
21164e463ec4SRoderick Colenbrander 	dualshock4_init_output_report(ds4, &report, ds4->output_report_dmabuf);
21174e463ec4SRoderick Colenbrander 	common = report.common;
21184e463ec4SRoderick Colenbrander 
21194e463ec4SRoderick Colenbrander 	spin_lock_irqsave(&ds4->base.lock, flags);
21204e463ec4SRoderick Colenbrander 
21214e463ec4SRoderick Colenbrander 	if (ds4->update_rumble) {
21224e463ec4SRoderick Colenbrander 		/* Select classic rumble style haptics and enable it. */
21234e463ec4SRoderick Colenbrander 		common->valid_flag0 |= DS4_OUTPUT_VALID_FLAG0_MOTOR;
21244e463ec4SRoderick Colenbrander 		common->motor_left = ds4->motor_left;
21254e463ec4SRoderick Colenbrander 		common->motor_right = ds4->motor_right;
21264e463ec4SRoderick Colenbrander 		ds4->update_rumble = false;
21274e463ec4SRoderick Colenbrander 	}
21284e463ec4SRoderick Colenbrander 
21294521109aSRoderick Colenbrander 	if (ds4->update_lightbar) {
21304521109aSRoderick Colenbrander 		common->valid_flag0 |= DS4_OUTPUT_VALID_FLAG0_LED;
21314521109aSRoderick Colenbrander 		/* Comptabile behavior with hid-sony, which used a dummy global LED to
21324521109aSRoderick Colenbrander 		 * allow enabling/disabling the lightbar. The global LED maps to
21334521109aSRoderick Colenbrander 		 * lightbar_enabled.
21344521109aSRoderick Colenbrander 		 */
21354521109aSRoderick Colenbrander 		common->lightbar_red = ds4->lightbar_enabled ? ds4->lightbar_red : 0;
21364521109aSRoderick Colenbrander 		common->lightbar_green = ds4->lightbar_enabled ? ds4->lightbar_green : 0;
21374521109aSRoderick Colenbrander 		common->lightbar_blue = ds4->lightbar_enabled ? ds4->lightbar_blue : 0;
21384521109aSRoderick Colenbrander 		ds4->update_lightbar = false;
21394521109aSRoderick Colenbrander 	}
21404521109aSRoderick Colenbrander 
214182d93f64SRoderick Colenbrander 	if (ds4->update_lightbar_blink) {
214282d93f64SRoderick Colenbrander 		common->valid_flag0 |= DS4_OUTPUT_VALID_FLAG0_LED_BLINK;
214382d93f64SRoderick Colenbrander 		common->lightbar_blink_on = ds4->lightbar_blink_on;
214482d93f64SRoderick Colenbrander 		common->lightbar_blink_off = ds4->lightbar_blink_off;
214582d93f64SRoderick Colenbrander 		ds4->update_lightbar_blink = false;
214682d93f64SRoderick Colenbrander 	}
214782d93f64SRoderick Colenbrander 
21484e463ec4SRoderick Colenbrander 	spin_unlock_irqrestore(&ds4->base.lock, flags);
21494e463ec4SRoderick Colenbrander 
21502d77474aSRoderick Colenbrander 	/* Bluetooth packets need additional flags as well as a CRC in the last 4 bytes. */
21512d77474aSRoderick Colenbrander 	if (report.bt) {
21522d77474aSRoderick Colenbrander 		uint32_t crc;
21532d77474aSRoderick Colenbrander 		uint8_t seed = PS_OUTPUT_CRC32_SEED;
21542d77474aSRoderick Colenbrander 
21552d77474aSRoderick Colenbrander 		/* Hardware control flags need to set to let the device know
21562d77474aSRoderick Colenbrander 		 * there is HID data as well as CRC.
21572d77474aSRoderick Colenbrander 		 */
21582d77474aSRoderick Colenbrander 		report.bt->hw_control = DS4_OUTPUT_HWCTL_HID | DS4_OUTPUT_HWCTL_CRC32;
21592d77474aSRoderick Colenbrander 
216058feecb4SRoderick Colenbrander 		if (ds4->update_bt_poll_interval) {
216158feecb4SRoderick Colenbrander 			report.bt->hw_control |= ds4->bt_poll_interval;
216258feecb4SRoderick Colenbrander 			ds4->update_bt_poll_interval = false;
216358feecb4SRoderick Colenbrander 		}
216458feecb4SRoderick Colenbrander 
21652d77474aSRoderick Colenbrander 		crc = crc32_le(0xFFFFFFFF, &seed, 1);
21662d77474aSRoderick Colenbrander 		crc = ~crc32_le(crc, report.data, report.len - 4);
21672d77474aSRoderick Colenbrander 
21682d77474aSRoderick Colenbrander 		report.bt->crc32 = cpu_to_le32(crc);
21692d77474aSRoderick Colenbrander 	}
21702d77474aSRoderick Colenbrander 
21714e463ec4SRoderick Colenbrander 	hid_hw_output_report(ds4->base.hdev, report.data, report.len);
21724e463ec4SRoderick Colenbrander }
21734e463ec4SRoderick Colenbrander 
dualshock4_parse_report(struct ps_device * ps_dev,struct hid_report * report,u8 * data,int size)2174f55b9b56SRoderick Colenbrander static int dualshock4_parse_report(struct ps_device *ps_dev, struct hid_report *report,
2175f55b9b56SRoderick Colenbrander 		u8 *data, int size)
2176f55b9b56SRoderick Colenbrander {
2177f55b9b56SRoderick Colenbrander 	struct hid_device *hdev = ps_dev->hdev;
2178f55b9b56SRoderick Colenbrander 	struct dualshock4 *ds4 = container_of(ps_dev, struct dualshock4, base);
2179f55b9b56SRoderick Colenbrander 	struct dualshock4_input_report_common *ds4_report;
218075203824SRoderick Colenbrander 	struct dualshock4_touch_report *touch_reports;
218175203824SRoderick Colenbrander 	uint8_t battery_capacity, num_touch_reports, value;
218275203824SRoderick Colenbrander 	int battery_status, i, j;
218312882ed8SRoderick Colenbrander 	uint16_t sensor_timestamp;
21848871ed30SRoderick Colenbrander 	unsigned long flags;
2185f55b9b56SRoderick Colenbrander 
2186f55b9b56SRoderick Colenbrander 	/*
2187f55b9b56SRoderick Colenbrander 	 * DualShock4 in USB uses the full HID report for reportID 1, but
2188f55b9b56SRoderick Colenbrander 	 * Bluetooth uses a minimal HID report for reportID 1 and reports
2189f55b9b56SRoderick Colenbrander 	 * the full report using reportID 17.
2190f55b9b56SRoderick Colenbrander 	 */
2191f55b9b56SRoderick Colenbrander 	if (hdev->bus == BUS_USB && report->id == DS4_INPUT_REPORT_USB &&
2192f55b9b56SRoderick Colenbrander 			size == DS4_INPUT_REPORT_USB_SIZE) {
2193f55b9b56SRoderick Colenbrander 		struct dualshock4_input_report_usb *usb = (struct dualshock4_input_report_usb *)data;
2194f55b9b56SRoderick Colenbrander 
2195f55b9b56SRoderick Colenbrander 		ds4_report = &usb->common;
219675203824SRoderick Colenbrander 		num_touch_reports = usb->num_touch_reports;
219775203824SRoderick Colenbrander 		touch_reports = usb->touch_reports;
21982d77474aSRoderick Colenbrander 	} else if (hdev->bus == BUS_BLUETOOTH && report->id == DS4_INPUT_REPORT_BT &&
21992d77474aSRoderick Colenbrander 			size == DS4_INPUT_REPORT_BT_SIZE) {
22002d77474aSRoderick Colenbrander 		struct dualshock4_input_report_bt *bt = (struct dualshock4_input_report_bt *)data;
2201da03e502SRoderick Colenbrander 		uint32_t report_crc = get_unaligned_le32(&bt->crc32);
22022d77474aSRoderick Colenbrander 
22032d77474aSRoderick Colenbrander 		/* Last 4 bytes of input report contains CRC. */
2204da03e502SRoderick Colenbrander 		if (!ps_check_crc32(PS_INPUT_CRC32_SEED, data, size - 4, report_crc)) {
22052d77474aSRoderick Colenbrander 			hid_err(hdev, "DualShock4 input CRC's check failed\n");
22062d77474aSRoderick Colenbrander 			return -EILSEQ;
22072d77474aSRoderick Colenbrander 		}
22082d77474aSRoderick Colenbrander 
22092d77474aSRoderick Colenbrander 		ds4_report = &bt->common;
22102d77474aSRoderick Colenbrander 		num_touch_reports = bt->num_touch_reports;
22112d77474aSRoderick Colenbrander 		touch_reports = bt->touch_reports;
2212f55b9b56SRoderick Colenbrander 	} else {
2213f55b9b56SRoderick Colenbrander 		hid_err(hdev, "Unhandled reportID=%d\n", report->id);
2214f55b9b56SRoderick Colenbrander 		return -1;
2215f55b9b56SRoderick Colenbrander 	}
2216f55b9b56SRoderick Colenbrander 
2217f55b9b56SRoderick Colenbrander 	input_report_abs(ds4->gamepad, ABS_X,  ds4_report->x);
2218f55b9b56SRoderick Colenbrander 	input_report_abs(ds4->gamepad, ABS_Y,  ds4_report->y);
2219f55b9b56SRoderick Colenbrander 	input_report_abs(ds4->gamepad, ABS_RX, ds4_report->rx);
2220f55b9b56SRoderick Colenbrander 	input_report_abs(ds4->gamepad, ABS_RY, ds4_report->ry);
2221f55b9b56SRoderick Colenbrander 	input_report_abs(ds4->gamepad, ABS_Z,  ds4_report->z);
2222f55b9b56SRoderick Colenbrander 	input_report_abs(ds4->gamepad, ABS_RZ, ds4_report->rz);
2223f55b9b56SRoderick Colenbrander 
2224f55b9b56SRoderick Colenbrander 	value = ds4_report->buttons[0] & DS_BUTTONS0_HAT_SWITCH;
2225f55b9b56SRoderick Colenbrander 	if (value >= ARRAY_SIZE(ps_gamepad_hat_mapping))
2226f55b9b56SRoderick Colenbrander 		value = 8; /* center */
2227f55b9b56SRoderick Colenbrander 	input_report_abs(ds4->gamepad, ABS_HAT0X, ps_gamepad_hat_mapping[value].x);
2228f55b9b56SRoderick Colenbrander 	input_report_abs(ds4->gamepad, ABS_HAT0Y, ps_gamepad_hat_mapping[value].y);
2229f55b9b56SRoderick Colenbrander 
2230f55b9b56SRoderick Colenbrander 	input_report_key(ds4->gamepad, BTN_WEST,   ds4_report->buttons[0] & DS_BUTTONS0_SQUARE);
2231f55b9b56SRoderick Colenbrander 	input_report_key(ds4->gamepad, BTN_SOUTH,  ds4_report->buttons[0] & DS_BUTTONS0_CROSS);
2232f55b9b56SRoderick Colenbrander 	input_report_key(ds4->gamepad, BTN_EAST,   ds4_report->buttons[0] & DS_BUTTONS0_CIRCLE);
2233f55b9b56SRoderick Colenbrander 	input_report_key(ds4->gamepad, BTN_NORTH,  ds4_report->buttons[0] & DS_BUTTONS0_TRIANGLE);
2234f55b9b56SRoderick Colenbrander 	input_report_key(ds4->gamepad, BTN_TL,     ds4_report->buttons[1] & DS_BUTTONS1_L1);
2235f55b9b56SRoderick Colenbrander 	input_report_key(ds4->gamepad, BTN_TR,     ds4_report->buttons[1] & DS_BUTTONS1_R1);
2236f55b9b56SRoderick Colenbrander 	input_report_key(ds4->gamepad, BTN_TL2,    ds4_report->buttons[1] & DS_BUTTONS1_L2);
2237f55b9b56SRoderick Colenbrander 	input_report_key(ds4->gamepad, BTN_TR2,    ds4_report->buttons[1] & DS_BUTTONS1_R2);
2238f55b9b56SRoderick Colenbrander 	input_report_key(ds4->gamepad, BTN_SELECT, ds4_report->buttons[1] & DS_BUTTONS1_CREATE);
2239f55b9b56SRoderick Colenbrander 	input_report_key(ds4->gamepad, BTN_START,  ds4_report->buttons[1] & DS_BUTTONS1_OPTIONS);
2240f55b9b56SRoderick Colenbrander 	input_report_key(ds4->gamepad, BTN_THUMBL, ds4_report->buttons[1] & DS_BUTTONS1_L3);
2241f55b9b56SRoderick Colenbrander 	input_report_key(ds4->gamepad, BTN_THUMBR, ds4_report->buttons[1] & DS_BUTTONS1_R3);
2242f55b9b56SRoderick Colenbrander 	input_report_key(ds4->gamepad, BTN_MODE,   ds4_report->buttons[2] & DS_BUTTONS2_PS_HOME);
2243f55b9b56SRoderick Colenbrander 	input_sync(ds4->gamepad);
2244f55b9b56SRoderick Colenbrander 
224512882ed8SRoderick Colenbrander 	/* Parse and calibrate gyroscope data. */
224612882ed8SRoderick Colenbrander 	for (i = 0; i < ARRAY_SIZE(ds4_report->gyro); i++) {
224712882ed8SRoderick Colenbrander 		int raw_data = (short)le16_to_cpu(ds4_report->gyro[i]);
224812882ed8SRoderick Colenbrander 		int calib_data = mult_frac(ds4->gyro_calib_data[i].sens_numer,
224912b18bc2SRoderick Colenbrander 					   raw_data, ds4->gyro_calib_data[i].sens_denom);
225012882ed8SRoderick Colenbrander 
225112882ed8SRoderick Colenbrander 		input_report_abs(ds4->sensors, ds4->gyro_calib_data[i].abs_code, calib_data);
225212882ed8SRoderick Colenbrander 	}
225312882ed8SRoderick Colenbrander 
225412882ed8SRoderick Colenbrander 	/* Parse and calibrate accelerometer data. */
225512882ed8SRoderick Colenbrander 	for (i = 0; i < ARRAY_SIZE(ds4_report->accel); i++) {
225612882ed8SRoderick Colenbrander 		int raw_data = (short)le16_to_cpu(ds4_report->accel[i]);
225712882ed8SRoderick Colenbrander 		int calib_data = mult_frac(ds4->accel_calib_data[i].sens_numer,
225812882ed8SRoderick Colenbrander 					   raw_data - ds4->accel_calib_data[i].bias,
225912882ed8SRoderick Colenbrander 					   ds4->accel_calib_data[i].sens_denom);
226012882ed8SRoderick Colenbrander 
226112882ed8SRoderick Colenbrander 		input_report_abs(ds4->sensors, ds4->accel_calib_data[i].abs_code, calib_data);
226212882ed8SRoderick Colenbrander 	}
226312882ed8SRoderick Colenbrander 
226412882ed8SRoderick Colenbrander 	/* Convert timestamp (in 5.33us unit) to timestamp_us */
226512882ed8SRoderick Colenbrander 	sensor_timestamp = le16_to_cpu(ds4_report->sensor_timestamp);
226612882ed8SRoderick Colenbrander 	if (!ds4->sensor_timestamp_initialized) {
226712882ed8SRoderick Colenbrander 		ds4->sensor_timestamp_us = DIV_ROUND_CLOSEST(sensor_timestamp*16, 3);
226812882ed8SRoderick Colenbrander 		ds4->sensor_timestamp_initialized = true;
226912882ed8SRoderick Colenbrander 	} else {
227012882ed8SRoderick Colenbrander 		uint16_t delta;
227112882ed8SRoderick Colenbrander 
227212882ed8SRoderick Colenbrander 		if (ds4->prev_sensor_timestamp > sensor_timestamp)
227312882ed8SRoderick Colenbrander 			delta = (U16_MAX - ds4->prev_sensor_timestamp + sensor_timestamp + 1);
227412882ed8SRoderick Colenbrander 		else
227512882ed8SRoderick Colenbrander 			delta = sensor_timestamp - ds4->prev_sensor_timestamp;
227612882ed8SRoderick Colenbrander 		ds4->sensor_timestamp_us += DIV_ROUND_CLOSEST(delta*16, 3);
227712882ed8SRoderick Colenbrander 	}
227812882ed8SRoderick Colenbrander 	ds4->prev_sensor_timestamp = sensor_timestamp;
227912882ed8SRoderick Colenbrander 	input_event(ds4->sensors, EV_MSC, MSC_TIMESTAMP, ds4->sensor_timestamp_us);
228012882ed8SRoderick Colenbrander 	input_sync(ds4->sensors);
228112882ed8SRoderick Colenbrander 
228275203824SRoderick Colenbrander 	for (i = 0; i < num_touch_reports; i++) {
228375203824SRoderick Colenbrander 		struct dualshock4_touch_report *touch_report = &touch_reports[i];
228475203824SRoderick Colenbrander 
228575203824SRoderick Colenbrander 		for (j = 0; j < ARRAY_SIZE(touch_report->points); j++) {
228675203824SRoderick Colenbrander 			struct dualshock4_touch_point *point = &touch_report->points[j];
228775203824SRoderick Colenbrander 			bool active = (point->contact & DS4_TOUCH_POINT_INACTIVE) ? false : true;
228875203824SRoderick Colenbrander 
228975203824SRoderick Colenbrander 			input_mt_slot(ds4->touchpad, j);
229075203824SRoderick Colenbrander 			input_mt_report_slot_state(ds4->touchpad, MT_TOOL_FINGER, active);
229175203824SRoderick Colenbrander 
229275203824SRoderick Colenbrander 			if (active) {
229375203824SRoderick Colenbrander 				int x = (point->x_hi << 8) | point->x_lo;
229475203824SRoderick Colenbrander 				int y = (point->y_hi << 4) | point->y_lo;
229575203824SRoderick Colenbrander 
229675203824SRoderick Colenbrander 				input_report_abs(ds4->touchpad, ABS_MT_POSITION_X, x);
229775203824SRoderick Colenbrander 				input_report_abs(ds4->touchpad, ABS_MT_POSITION_Y, y);
229875203824SRoderick Colenbrander 			}
229975203824SRoderick Colenbrander 		}
230075203824SRoderick Colenbrander 		input_mt_sync_frame(ds4->touchpad);
230175203824SRoderick Colenbrander 		input_sync(ds4->touchpad);
230275203824SRoderick Colenbrander 	}
230375203824SRoderick Colenbrander 	input_report_key(ds4->touchpad, BTN_LEFT, ds4_report->buttons[2] & DS_BUTTONS2_TOUCHPAD);
230475203824SRoderick Colenbrander 
23058871ed30SRoderick Colenbrander 	/*
23068871ed30SRoderick Colenbrander 	 * Interpretation of the battery_capacity data depends on the cable state.
23078871ed30SRoderick Colenbrander 	 * When no cable is connected (bit4 is 0):
23088871ed30SRoderick Colenbrander 	 * - 0:10: percentage in units of 10%.
23098871ed30SRoderick Colenbrander 	 * When a cable is plugged in:
23108871ed30SRoderick Colenbrander 	 * - 0-10: percentage in units of 10%.
23118871ed30SRoderick Colenbrander 	 * - 11: battery is full
23128871ed30SRoderick Colenbrander 	 * - 14: not charging due to Voltage or temperature error
23138871ed30SRoderick Colenbrander 	 * - 15: charge error
23148871ed30SRoderick Colenbrander 	 */
23158871ed30SRoderick Colenbrander 	if (ds4_report->status[0] & DS4_STATUS0_CABLE_STATE) {
23168871ed30SRoderick Colenbrander 		uint8_t battery_data = ds4_report->status[0] & DS4_STATUS0_BATTERY_CAPACITY;
23178871ed30SRoderick Colenbrander 
23188871ed30SRoderick Colenbrander 		if (battery_data < 10) {
23198871ed30SRoderick Colenbrander 			/* Take the mid-point for each battery capacity value,
23208871ed30SRoderick Colenbrander 			 * because on the hardware side 0 = 0-9%, 1=10-19%, etc.
23218871ed30SRoderick Colenbrander 			 * This matches official platform behavior, which does
23228871ed30SRoderick Colenbrander 			 * the same.
23238871ed30SRoderick Colenbrander 			 */
23248871ed30SRoderick Colenbrander 			battery_capacity = battery_data * 10 + 5;
23258871ed30SRoderick Colenbrander 			battery_status = POWER_SUPPLY_STATUS_CHARGING;
23268871ed30SRoderick Colenbrander 		} else if (battery_data == 10) {
23278871ed30SRoderick Colenbrander 			battery_capacity = 100;
23288871ed30SRoderick Colenbrander 			battery_status = POWER_SUPPLY_STATUS_CHARGING;
23298871ed30SRoderick Colenbrander 		} else if (battery_data == DS4_BATTERY_STATUS_FULL) {
23308871ed30SRoderick Colenbrander 			battery_capacity = 100;
23318871ed30SRoderick Colenbrander 			battery_status = POWER_SUPPLY_STATUS_FULL;
23328871ed30SRoderick Colenbrander 		} else { /* 14, 15 and undefined values */
23338871ed30SRoderick Colenbrander 			battery_capacity = 0;
23348871ed30SRoderick Colenbrander 			battery_status = POWER_SUPPLY_STATUS_UNKNOWN;
23358871ed30SRoderick Colenbrander 		}
23368871ed30SRoderick Colenbrander 	} else {
23378871ed30SRoderick Colenbrander 		uint8_t battery_data = ds4_report->status[0] & DS4_STATUS0_BATTERY_CAPACITY;
23388871ed30SRoderick Colenbrander 
23398871ed30SRoderick Colenbrander 		if (battery_data < 10)
23408871ed30SRoderick Colenbrander 			battery_capacity = battery_data * 10 + 5;
23418871ed30SRoderick Colenbrander 		else /* 10 */
23428871ed30SRoderick Colenbrander 			battery_capacity = 100;
23438871ed30SRoderick Colenbrander 
23448871ed30SRoderick Colenbrander 		battery_status = POWER_SUPPLY_STATUS_DISCHARGING;
23458871ed30SRoderick Colenbrander 	}
23468871ed30SRoderick Colenbrander 
23478871ed30SRoderick Colenbrander 	spin_lock_irqsave(&ps_dev->lock, flags);
23488871ed30SRoderick Colenbrander 	ps_dev->battery_capacity = battery_capacity;
23498871ed30SRoderick Colenbrander 	ps_dev->battery_status = battery_status;
23508871ed30SRoderick Colenbrander 	spin_unlock_irqrestore(&ps_dev->lock, flags);
23518871ed30SRoderick Colenbrander 
2352f55b9b56SRoderick Colenbrander 	return 0;
2353f55b9b56SRoderick Colenbrander }
2354f55b9b56SRoderick Colenbrander 
dualshock4_dongle_parse_report(struct ps_device * ps_dev,struct hid_report * report,u8 * data,int size)2355c64ed0cdSRoderick Colenbrander static int dualshock4_dongle_parse_report(struct ps_device *ps_dev, struct hid_report *report,
2356c64ed0cdSRoderick Colenbrander 		u8 *data, int size)
2357c64ed0cdSRoderick Colenbrander {
2358c64ed0cdSRoderick Colenbrander 	struct dualshock4 *ds4 = container_of(ps_dev, struct dualshock4, base);
2359c64ed0cdSRoderick Colenbrander 	bool connected = false;
2360c64ed0cdSRoderick Colenbrander 
2361c64ed0cdSRoderick Colenbrander 	/* The dongle reports data using the main USB report (0x1) no matter whether a controller
2362c64ed0cdSRoderick Colenbrander 	 * is connected with mostly zeros. The report does contain dongle status, which we use to
2363c64ed0cdSRoderick Colenbrander 	 * determine if a controller is connected and if so we forward to the regular DualShock4
2364c64ed0cdSRoderick Colenbrander 	 * parsing code.
2365c64ed0cdSRoderick Colenbrander 	 */
2366c64ed0cdSRoderick Colenbrander 	if (data[0] == DS4_INPUT_REPORT_USB && size == DS4_INPUT_REPORT_USB_SIZE) {
2367c64ed0cdSRoderick Colenbrander 		struct dualshock4_input_report_common *ds4_report = (struct dualshock4_input_report_common *)&data[1];
2368c64ed0cdSRoderick Colenbrander 		unsigned long flags;
2369c64ed0cdSRoderick Colenbrander 
2370c64ed0cdSRoderick Colenbrander 		connected = ds4_report->status[1] & DS4_STATUS1_DONGLE_STATE ? false : true;
2371c64ed0cdSRoderick Colenbrander 
2372c64ed0cdSRoderick Colenbrander 		if (ds4->dongle_state == DONGLE_DISCONNECTED && connected) {
2373c64ed0cdSRoderick Colenbrander 			hid_info(ps_dev->hdev, "DualShock 4 USB dongle: controller connected\n");
2374c64ed0cdSRoderick Colenbrander 
2375c64ed0cdSRoderick Colenbrander 			dualshock4_set_default_lightbar_colors(ds4);
2376c64ed0cdSRoderick Colenbrander 
2377c64ed0cdSRoderick Colenbrander 			spin_lock_irqsave(&ps_dev->lock, flags);
2378c64ed0cdSRoderick Colenbrander 			ds4->dongle_state = DONGLE_CALIBRATING;
2379c64ed0cdSRoderick Colenbrander 			spin_unlock_irqrestore(&ps_dev->lock, flags);
2380c64ed0cdSRoderick Colenbrander 
2381c64ed0cdSRoderick Colenbrander 			schedule_work(&ds4->dongle_hotplug_worker);
2382c64ed0cdSRoderick Colenbrander 
2383c64ed0cdSRoderick Colenbrander 			/* Don't process the report since we don't have
2384c64ed0cdSRoderick Colenbrander 			 * calibration data, but let hidraw have it anyway.
2385c64ed0cdSRoderick Colenbrander 			 */
2386c64ed0cdSRoderick Colenbrander 			return 0;
2387c64ed0cdSRoderick Colenbrander 		} else if ((ds4->dongle_state == DONGLE_CONNECTED ||
2388c64ed0cdSRoderick Colenbrander 			    ds4->dongle_state == DONGLE_DISABLED) && !connected) {
2389c64ed0cdSRoderick Colenbrander 			hid_info(ps_dev->hdev, "DualShock 4 USB dongle: controller disconnected\n");
2390c64ed0cdSRoderick Colenbrander 
2391c64ed0cdSRoderick Colenbrander 			spin_lock_irqsave(&ps_dev->lock, flags);
2392c64ed0cdSRoderick Colenbrander 			ds4->dongle_state = DONGLE_DISCONNECTED;
2393c64ed0cdSRoderick Colenbrander 			spin_unlock_irqrestore(&ps_dev->lock, flags);
2394c64ed0cdSRoderick Colenbrander 
2395c64ed0cdSRoderick Colenbrander 			/* Return 0, so hidraw can get the report. */
2396c64ed0cdSRoderick Colenbrander 			return 0;
2397c64ed0cdSRoderick Colenbrander 		} else if (ds4->dongle_state == DONGLE_CALIBRATING ||
2398c64ed0cdSRoderick Colenbrander 			   ds4->dongle_state == DONGLE_DISABLED ||
2399c64ed0cdSRoderick Colenbrander 			   ds4->dongle_state == DONGLE_DISCONNECTED) {
2400c64ed0cdSRoderick Colenbrander 			/* Return 0, so hidraw can get the report. */
2401c64ed0cdSRoderick Colenbrander 			return 0;
2402c64ed0cdSRoderick Colenbrander 		}
2403c64ed0cdSRoderick Colenbrander 	}
2404c64ed0cdSRoderick Colenbrander 
2405c64ed0cdSRoderick Colenbrander 	if (connected)
2406c64ed0cdSRoderick Colenbrander 		return dualshock4_parse_report(ps_dev, report, data, size);
2407c64ed0cdSRoderick Colenbrander 
2408c64ed0cdSRoderick Colenbrander 	return 0;
2409c64ed0cdSRoderick Colenbrander }
2410c64ed0cdSRoderick Colenbrander 
dualshock4_play_effect(struct input_dev * dev,void * data,struct ff_effect * effect)24114e463ec4SRoderick Colenbrander static int dualshock4_play_effect(struct input_dev *dev, void *data, struct ff_effect *effect)
24124e463ec4SRoderick Colenbrander {
24134e463ec4SRoderick Colenbrander 	struct hid_device *hdev = input_get_drvdata(dev);
24144e463ec4SRoderick Colenbrander 	struct dualshock4 *ds4 = hid_get_drvdata(hdev);
24154e463ec4SRoderick Colenbrander 	unsigned long flags;
24164e463ec4SRoderick Colenbrander 
24174e463ec4SRoderick Colenbrander 	if (effect->type != FF_RUMBLE)
24184e463ec4SRoderick Colenbrander 		return 0;
24194e463ec4SRoderick Colenbrander 
24204e463ec4SRoderick Colenbrander 	spin_lock_irqsave(&ds4->base.lock, flags);
24214e463ec4SRoderick Colenbrander 	ds4->update_rumble = true;
24224e463ec4SRoderick Colenbrander 	ds4->motor_left = effect->u.rumble.strong_magnitude / 256;
24234e463ec4SRoderick Colenbrander 	ds4->motor_right = effect->u.rumble.weak_magnitude / 256;
24244e463ec4SRoderick Colenbrander 	spin_unlock_irqrestore(&ds4->base.lock, flags);
24254e463ec4SRoderick Colenbrander 
24264e463ec4SRoderick Colenbrander 	dualshock4_schedule_work(ds4);
24274e463ec4SRoderick Colenbrander 	return 0;
24284e463ec4SRoderick Colenbrander }
24294e463ec4SRoderick Colenbrander 
dualshock4_remove(struct ps_device * ps_dev)24304e463ec4SRoderick Colenbrander static void dualshock4_remove(struct ps_device *ps_dev)
24314e463ec4SRoderick Colenbrander {
24324e463ec4SRoderick Colenbrander 	struct dualshock4 *ds4 = container_of(ps_dev, struct dualshock4, base);
24334e463ec4SRoderick Colenbrander 	unsigned long flags;
24344e463ec4SRoderick Colenbrander 
24354e463ec4SRoderick Colenbrander 	spin_lock_irqsave(&ds4->base.lock, flags);
24364e463ec4SRoderick Colenbrander 	ds4->output_worker_initialized = false;
24374e463ec4SRoderick Colenbrander 	spin_unlock_irqrestore(&ds4->base.lock, flags);
24384e463ec4SRoderick Colenbrander 
24394e463ec4SRoderick Colenbrander 	cancel_work_sync(&ds4->output_worker);
2440c64ed0cdSRoderick Colenbrander 
2441c64ed0cdSRoderick Colenbrander 	if (ps_dev->hdev->product == USB_DEVICE_ID_SONY_PS4_CONTROLLER_DONGLE)
2442c64ed0cdSRoderick Colenbrander 		cancel_work_sync(&ds4->dongle_hotplug_worker);
24434e463ec4SRoderick Colenbrander }
24444e463ec4SRoderick Colenbrander 
dualshock4_schedule_work(struct dualshock4 * ds4)24454e463ec4SRoderick Colenbrander static inline void dualshock4_schedule_work(struct dualshock4 *ds4)
24464e463ec4SRoderick Colenbrander {
24474e463ec4SRoderick Colenbrander 	unsigned long flags;
24484e463ec4SRoderick Colenbrander 
24494e463ec4SRoderick Colenbrander 	spin_lock_irqsave(&ds4->base.lock, flags);
24504e463ec4SRoderick Colenbrander 	if (ds4->output_worker_initialized)
24514e463ec4SRoderick Colenbrander 		schedule_work(&ds4->output_worker);
24524e463ec4SRoderick Colenbrander 	spin_unlock_irqrestore(&ds4->base.lock, flags);
24534e463ec4SRoderick Colenbrander }
24544e463ec4SRoderick Colenbrander 
dualshock4_set_bt_poll_interval(struct dualshock4 * ds4,uint8_t interval)245558feecb4SRoderick Colenbrander static void dualshock4_set_bt_poll_interval(struct dualshock4 *ds4, uint8_t interval)
245658feecb4SRoderick Colenbrander {
245758feecb4SRoderick Colenbrander 	ds4->bt_poll_interval = interval;
245858feecb4SRoderick Colenbrander 	ds4->update_bt_poll_interval = true;
245958feecb4SRoderick Colenbrander 	dualshock4_schedule_work(ds4);
246058feecb4SRoderick Colenbrander }
246158feecb4SRoderick Colenbrander 
24624521109aSRoderick Colenbrander /* Set default lightbar color based on player. */
dualshock4_set_default_lightbar_colors(struct dualshock4 * ds4)24634521109aSRoderick Colenbrander static void dualshock4_set_default_lightbar_colors(struct dualshock4 *ds4)
24644521109aSRoderick Colenbrander {
24654521109aSRoderick Colenbrander 	/* Use same player colors as PlayStation 4.
24664521109aSRoderick Colenbrander 	 * Array of colors is in RGB.
24674521109aSRoderick Colenbrander 	 */
24684521109aSRoderick Colenbrander 	static const int player_colors[4][3] = {
24694521109aSRoderick Colenbrander 		{ 0x00, 0x00, 0x40 }, /* Blue */
24704521109aSRoderick Colenbrander 		{ 0x40, 0x00, 0x00 }, /* Red */
24714521109aSRoderick Colenbrander 		{ 0x00, 0x40, 0x00 }, /* Green */
24724521109aSRoderick Colenbrander 		{ 0x20, 0x00, 0x20 }  /* Pink */
24734521109aSRoderick Colenbrander 	};
24744521109aSRoderick Colenbrander 
24754521109aSRoderick Colenbrander 	uint8_t player_id = ds4->base.player_id % ARRAY_SIZE(player_colors);
24764521109aSRoderick Colenbrander 
24774521109aSRoderick Colenbrander 	ds4->lightbar_enabled = true;
24784521109aSRoderick Colenbrander 	ds4->lightbar_red = player_colors[player_id][0];
24794521109aSRoderick Colenbrander 	ds4->lightbar_green = player_colors[player_id][1];
24804521109aSRoderick Colenbrander 	ds4->lightbar_blue = player_colors[player_id][2];
24814521109aSRoderick Colenbrander 
24824521109aSRoderick Colenbrander 	ds4->update_lightbar = true;
24834521109aSRoderick Colenbrander 	dualshock4_schedule_work(ds4);
24844521109aSRoderick Colenbrander }
24854521109aSRoderick Colenbrander 
dualshock4_create(struct hid_device * hdev)2486f55b9b56SRoderick Colenbrander static struct ps_device *dualshock4_create(struct hid_device *hdev)
2487f55b9b56SRoderick Colenbrander {
2488f55b9b56SRoderick Colenbrander 	struct dualshock4 *ds4;
2489f55b9b56SRoderick Colenbrander 	struct ps_device *ps_dev;
24904e463ec4SRoderick Colenbrander 	uint8_t max_output_report_size;
24914521109aSRoderick Colenbrander 	int i, ret;
24924521109aSRoderick Colenbrander 
24934521109aSRoderick Colenbrander 	/* The DualShock4 has an RGB lightbar, which the original hid-sony driver
24944521109aSRoderick Colenbrander 	 * exposed as a set of 4 LEDs for the 3 color channels and a global control.
24954521109aSRoderick Colenbrander 	 * Ideally this should have used the multi-color LED class, which didn't exist
24964521109aSRoderick Colenbrander 	 * yet. In addition the driver used a naming scheme not compliant with the LED
24974521109aSRoderick Colenbrander 	 * naming spec by using "<mac_address>:<color>", which contained many colons.
24984521109aSRoderick Colenbrander 	 * We use a more compliant by using "<device_name>:<color>" name now. Ideally
24994521109aSRoderick Colenbrander 	 * would have been "<device_name>:<color>:indicator", but that would break
25004521109aSRoderick Colenbrander 	 * existing applications (e.g. Android). Nothing matches against MAC address.
25014521109aSRoderick Colenbrander 	 */
25024521109aSRoderick Colenbrander 	static const struct ps_led_info lightbar_leds_info[] = {
25034521109aSRoderick Colenbrander 		{ NULL, "red", 255, dualshock4_led_get_brightness, dualshock4_led_set_brightness },
25044521109aSRoderick Colenbrander 		{ NULL, "green", 255, dualshock4_led_get_brightness, dualshock4_led_set_brightness },
25054521109aSRoderick Colenbrander 		{ NULL, "blue", 255, dualshock4_led_get_brightness, dualshock4_led_set_brightness },
250682d93f64SRoderick Colenbrander 		{ NULL, "global", 1, dualshock4_led_get_brightness, dualshock4_led_set_brightness,
250782d93f64SRoderick Colenbrander 				dualshock4_led_set_blink },
25084521109aSRoderick Colenbrander 	};
2509f55b9b56SRoderick Colenbrander 
2510f55b9b56SRoderick Colenbrander 	ds4 = devm_kzalloc(&hdev->dev, sizeof(*ds4), GFP_KERNEL);
2511f55b9b56SRoderick Colenbrander 	if (!ds4)
2512f55b9b56SRoderick Colenbrander 		return ERR_PTR(-ENOMEM);
2513f55b9b56SRoderick Colenbrander 
2514f55b9b56SRoderick Colenbrander 	/*
2515f55b9b56SRoderick Colenbrander 	 * Patch version to allow userspace to distinguish between
2516f55b9b56SRoderick Colenbrander 	 * hid-generic vs hid-playstation axis and button mapping.
2517f55b9b56SRoderick Colenbrander 	 */
2518f55b9b56SRoderick Colenbrander 	hdev->version |= HID_PLAYSTATION_VERSION_PATCH;
2519f55b9b56SRoderick Colenbrander 
2520f55b9b56SRoderick Colenbrander 	ps_dev = &ds4->base;
2521f55b9b56SRoderick Colenbrander 	ps_dev->hdev = hdev;
2522f55b9b56SRoderick Colenbrander 	spin_lock_init(&ps_dev->lock);
25238871ed30SRoderick Colenbrander 	ps_dev->battery_capacity = 100; /* initial value until parse_report. */
25248871ed30SRoderick Colenbrander 	ps_dev->battery_status = POWER_SUPPLY_STATUS_UNKNOWN;
2525f55b9b56SRoderick Colenbrander 	ps_dev->parse_report = dualshock4_parse_report;
25264e463ec4SRoderick Colenbrander 	ps_dev->remove = dualshock4_remove;
25274e463ec4SRoderick Colenbrander 	INIT_WORK(&ds4->output_worker, dualshock4_output_worker);
25284e463ec4SRoderick Colenbrander 	ds4->output_worker_initialized = true;
2529f55b9b56SRoderick Colenbrander 	hid_set_drvdata(hdev, ds4);
2530f55b9b56SRoderick Colenbrander 
253154980d30SRoderick Colenbrander 	max_output_report_size = sizeof(struct dualshock4_output_report_bt);
25324e463ec4SRoderick Colenbrander 	ds4->output_report_dmabuf = devm_kzalloc(&hdev->dev, max_output_report_size, GFP_KERNEL);
25334e463ec4SRoderick Colenbrander 	if (!ds4->output_report_dmabuf)
25344e463ec4SRoderick Colenbrander 		return ERR_PTR(-ENOMEM);
25354e463ec4SRoderick Colenbrander 
2536c64ed0cdSRoderick Colenbrander 	if (hdev->product == USB_DEVICE_ID_SONY_PS4_CONTROLLER_DONGLE) {
2537c64ed0cdSRoderick Colenbrander 		ds4->dongle_state = DONGLE_DISCONNECTED;
2538c64ed0cdSRoderick Colenbrander 		INIT_WORK(&ds4->dongle_hotplug_worker, dualshock4_dongle_calibration_work);
2539c64ed0cdSRoderick Colenbrander 
2540c64ed0cdSRoderick Colenbrander 		/* Override parse report for dongle specific hotplug handling. */
2541c64ed0cdSRoderick Colenbrander 		ps_dev->parse_report = dualshock4_dongle_parse_report;
2542c64ed0cdSRoderick Colenbrander 	}
2543c64ed0cdSRoderick Colenbrander 
2544f55b9b56SRoderick Colenbrander 	ret = dualshock4_get_mac_address(ds4);
2545f55b9b56SRoderick Colenbrander 	if (ret) {
2546f55b9b56SRoderick Colenbrander 		hid_err(hdev, "Failed to get MAC address from DualShock4\n");
2547f55b9b56SRoderick Colenbrander 		return ERR_PTR(ret);
2548f55b9b56SRoderick Colenbrander 	}
2549f55b9b56SRoderick Colenbrander 	snprintf(hdev->uniq, sizeof(hdev->uniq), "%pMR", ds4->base.mac_address);
2550f55b9b56SRoderick Colenbrander 
25519a62280aSRoderick Colenbrander 	ret = dualshock4_get_firmware_info(ds4);
25529a62280aSRoderick Colenbrander 	if (ret) {
25539a62280aSRoderick Colenbrander 		hid_err(hdev, "Failed to get firmware info from DualShock4\n");
25549a62280aSRoderick Colenbrander 		return ERR_PTR(ret);
25559a62280aSRoderick Colenbrander 	}
25569a62280aSRoderick Colenbrander 
2557f55b9b56SRoderick Colenbrander 	ret = ps_devices_list_add(ps_dev);
2558f55b9b56SRoderick Colenbrander 	if (ret)
2559f55b9b56SRoderick Colenbrander 		return ERR_PTR(ret);
2560f55b9b56SRoderick Colenbrander 
256112882ed8SRoderick Colenbrander 	ret = dualshock4_get_calibration_data(ds4);
256212882ed8SRoderick Colenbrander 	if (ret) {
256312882ed8SRoderick Colenbrander 		hid_err(hdev, "Failed to get calibration data from DualShock4\n");
256412882ed8SRoderick Colenbrander 		goto err;
256512882ed8SRoderick Colenbrander 	}
256612882ed8SRoderick Colenbrander 
25674e463ec4SRoderick Colenbrander 	ds4->gamepad = ps_gamepad_create(hdev, dualshock4_play_effect);
2568f55b9b56SRoderick Colenbrander 	if (IS_ERR(ds4->gamepad)) {
2569f55b9b56SRoderick Colenbrander 		ret = PTR_ERR(ds4->gamepad);
2570f55b9b56SRoderick Colenbrander 		goto err;
2571f55b9b56SRoderick Colenbrander 	}
2572f55b9b56SRoderick Colenbrander 
25734521109aSRoderick Colenbrander 	/* Use gamepad input device name as primary device name for e.g. LEDs */
25744521109aSRoderick Colenbrander 	ps_dev->input_dev_name = dev_name(&ds4->gamepad->dev);
25754521109aSRoderick Colenbrander 
257612882ed8SRoderick Colenbrander 	ds4->sensors = ps_sensors_create(hdev, DS4_ACC_RANGE, DS4_ACC_RES_PER_G,
257712882ed8SRoderick Colenbrander 			DS4_GYRO_RANGE, DS4_GYRO_RES_PER_DEG_S);
257812882ed8SRoderick Colenbrander 	if (IS_ERR(ds4->sensors)) {
257912882ed8SRoderick Colenbrander 		ret = PTR_ERR(ds4->sensors);
258012882ed8SRoderick Colenbrander 		goto err;
258112882ed8SRoderick Colenbrander 	}
258212882ed8SRoderick Colenbrander 
258375203824SRoderick Colenbrander 	ds4->touchpad = ps_touchpad_create(hdev, DS4_TOUCHPAD_WIDTH, DS4_TOUCHPAD_HEIGHT, 2);
258475203824SRoderick Colenbrander 	if (IS_ERR(ds4->touchpad)) {
258575203824SRoderick Colenbrander 		ret = PTR_ERR(ds4->touchpad);
258675203824SRoderick Colenbrander 		goto err;
258775203824SRoderick Colenbrander 	}
258875203824SRoderick Colenbrander 
25898871ed30SRoderick Colenbrander 	ret = ps_device_register_battery(ps_dev);
25908871ed30SRoderick Colenbrander 	if (ret)
25918871ed30SRoderick Colenbrander 		goto err;
25928871ed30SRoderick Colenbrander 
25934521109aSRoderick Colenbrander 	for (i = 0; i < ARRAY_SIZE(lightbar_leds_info); i++) {
25944521109aSRoderick Colenbrander 		const struct ps_led_info *led_info = &lightbar_leds_info[i];
25954521109aSRoderick Colenbrander 
25964521109aSRoderick Colenbrander 		ret = ps_led_register(ps_dev, &ds4->lightbar_leds[i], led_info);
25974521109aSRoderick Colenbrander 		if (ret < 0)
25984521109aSRoderick Colenbrander 			goto err;
25994521109aSRoderick Colenbrander 	}
26004521109aSRoderick Colenbrander 
260158feecb4SRoderick Colenbrander 	dualshock4_set_bt_poll_interval(ds4, DS4_BT_DEFAULT_POLL_INTERVAL_MS);
260258feecb4SRoderick Colenbrander 
2603f55b9b56SRoderick Colenbrander 	ret = ps_device_set_player_id(ps_dev);
2604f55b9b56SRoderick Colenbrander 	if (ret) {
2605f55b9b56SRoderick Colenbrander 		hid_err(hdev, "Failed to assign player id for DualShock4: %d\n", ret);
2606f55b9b56SRoderick Colenbrander 		goto err;
2607f55b9b56SRoderick Colenbrander 	}
2608f55b9b56SRoderick Colenbrander 
26094521109aSRoderick Colenbrander 	dualshock4_set_default_lightbar_colors(ds4);
26104521109aSRoderick Colenbrander 
26119a62280aSRoderick Colenbrander 	/*
26129a62280aSRoderick Colenbrander 	 * Reporting hardware and firmware is important as there are frequent updates, which
26139a62280aSRoderick Colenbrander 	 * can change behavior.
26149a62280aSRoderick Colenbrander 	 */
26159a62280aSRoderick Colenbrander 	hid_info(hdev, "Registered DualShock4 controller hw_version=0x%08x fw_version=0x%08x\n",
26169a62280aSRoderick Colenbrander 			ds4->base.hw_version, ds4->base.fw_version);
2617f55b9b56SRoderick Colenbrander 	return &ds4->base;
2618f55b9b56SRoderick Colenbrander 
2619f55b9b56SRoderick Colenbrander err:
2620f55b9b56SRoderick Colenbrander 	ps_devices_list_remove(ps_dev);
2621f55b9b56SRoderick Colenbrander 	return ERR_PTR(ret);
2622f55b9b56SRoderick Colenbrander }
2623f55b9b56SRoderick Colenbrander 
ps_raw_event(struct hid_device * hdev,struct hid_report * report,u8 * data,int size)2624bc2e15a9SRoderick Colenbrander static int ps_raw_event(struct hid_device *hdev, struct hid_report *report,
2625bc2e15a9SRoderick Colenbrander 		u8 *data, int size)
2626bc2e15a9SRoderick Colenbrander {
2627bc2e15a9SRoderick Colenbrander 	struct ps_device *dev = hid_get_drvdata(hdev);
2628bc2e15a9SRoderick Colenbrander 
2629bc2e15a9SRoderick Colenbrander 	if (dev && dev->parse_report)
2630bc2e15a9SRoderick Colenbrander 		return dev->parse_report(dev, report, data, size);
2631bc2e15a9SRoderick Colenbrander 
2632bc2e15a9SRoderick Colenbrander 	return 0;
2633bc2e15a9SRoderick Colenbrander }
2634bc2e15a9SRoderick Colenbrander 
ps_probe(struct hid_device * hdev,const struct hid_device_id * id)2635bc2e15a9SRoderick Colenbrander static int ps_probe(struct hid_device *hdev, const struct hid_device_id *id)
2636bc2e15a9SRoderick Colenbrander {
2637bc2e15a9SRoderick Colenbrander 	struct ps_device *dev;
2638bc2e15a9SRoderick Colenbrander 	int ret;
2639bc2e15a9SRoderick Colenbrander 
2640bc2e15a9SRoderick Colenbrander 	ret = hid_parse(hdev);
2641bc2e15a9SRoderick Colenbrander 	if (ret) {
2642bc2e15a9SRoderick Colenbrander 		hid_err(hdev, "Parse failed\n");
2643bc2e15a9SRoderick Colenbrander 		return ret;
2644bc2e15a9SRoderick Colenbrander 	}
2645bc2e15a9SRoderick Colenbrander 
2646bc2e15a9SRoderick Colenbrander 	ret = hid_hw_start(hdev, HID_CONNECT_HIDRAW);
2647bc2e15a9SRoderick Colenbrander 	if (ret) {
2648bc2e15a9SRoderick Colenbrander 		hid_err(hdev, "Failed to start HID device\n");
2649bc2e15a9SRoderick Colenbrander 		return ret;
2650bc2e15a9SRoderick Colenbrander 	}
2651bc2e15a9SRoderick Colenbrander 
2652bc2e15a9SRoderick Colenbrander 	ret = hid_hw_open(hdev);
2653bc2e15a9SRoderick Colenbrander 	if (ret) {
2654bc2e15a9SRoderick Colenbrander 		hid_err(hdev, "Failed to open HID device\n");
2655bc2e15a9SRoderick Colenbrander 		goto err_stop;
2656bc2e15a9SRoderick Colenbrander 	}
2657bc2e15a9SRoderick Colenbrander 
2658f55b9b56SRoderick Colenbrander 	if (hdev->product == USB_DEVICE_ID_SONY_PS4_CONTROLLER ||
2659c64ed0cdSRoderick Colenbrander 		hdev->product == USB_DEVICE_ID_SONY_PS4_CONTROLLER_2 ||
2660c64ed0cdSRoderick Colenbrander 		hdev->product == USB_DEVICE_ID_SONY_PS4_CONTROLLER_DONGLE) {
2661f55b9b56SRoderick Colenbrander 		dev = dualshock4_create(hdev);
2662f55b9b56SRoderick Colenbrander 		if (IS_ERR(dev)) {
2663f55b9b56SRoderick Colenbrander 			hid_err(hdev, "Failed to create dualshock4.\n");
2664f55b9b56SRoderick Colenbrander 			ret = PTR_ERR(dev);
2665f55b9b56SRoderick Colenbrander 			goto err_close;
2666f55b9b56SRoderick Colenbrander 		}
2667f55b9b56SRoderick Colenbrander 	} else if (hdev->product == USB_DEVICE_ID_SONY_PS5_CONTROLLER ||
2668b8a968efSRoderick Colenbrander 		hdev->product == USB_DEVICE_ID_SONY_PS5_CONTROLLER_2) {
2669bc2e15a9SRoderick Colenbrander 		dev = dualsense_create(hdev);
2670bc2e15a9SRoderick Colenbrander 		if (IS_ERR(dev)) {
2671bc2e15a9SRoderick Colenbrander 			hid_err(hdev, "Failed to create dualsense.\n");
2672bc2e15a9SRoderick Colenbrander 			ret = PTR_ERR(dev);
2673bc2e15a9SRoderick Colenbrander 			goto err_close;
2674bc2e15a9SRoderick Colenbrander 		}
2675bc2e15a9SRoderick Colenbrander 	}
2676bc2e15a9SRoderick Colenbrander 
2677bc2e15a9SRoderick Colenbrander 	return ret;
2678bc2e15a9SRoderick Colenbrander 
2679bc2e15a9SRoderick Colenbrander err_close:
2680bc2e15a9SRoderick Colenbrander 	hid_hw_close(hdev);
2681bc2e15a9SRoderick Colenbrander err_stop:
2682bc2e15a9SRoderick Colenbrander 	hid_hw_stop(hdev);
2683bc2e15a9SRoderick Colenbrander 	return ret;
2684bc2e15a9SRoderick Colenbrander }
2685bc2e15a9SRoderick Colenbrander 
ps_remove(struct hid_device * hdev)2686bc2e15a9SRoderick Colenbrander static void ps_remove(struct hid_device *hdev)
2687bc2e15a9SRoderick Colenbrander {
268853f04e83SRoderick Colenbrander 	struct ps_device *dev = hid_get_drvdata(hdev);
268953f04e83SRoderick Colenbrander 
269053f04e83SRoderick Colenbrander 	ps_devices_list_remove(dev);
2691949aaccdSRoderick Colenbrander 	ps_device_release_player_id(dev);
269253f04e83SRoderick Colenbrander 
2693182934a1SRoderick Colenbrander 	if (dev->remove)
2694182934a1SRoderick Colenbrander 		dev->remove(dev);
2695182934a1SRoderick Colenbrander 
2696bc2e15a9SRoderick Colenbrander 	hid_hw_close(hdev);
2697bc2e15a9SRoderick Colenbrander 	hid_hw_stop(hdev);
2698bc2e15a9SRoderick Colenbrander }
2699bc2e15a9SRoderick Colenbrander 
2700bc2e15a9SRoderick Colenbrander static const struct hid_device_id ps_devices[] = {
2701f55b9b56SRoderick Colenbrander 	/* Sony DualShock 4 controllers for PS4 */
27022d77474aSRoderick Colenbrander 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER) },
2703f55b9b56SRoderick Colenbrander 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER) },
27042d77474aSRoderick Colenbrander 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER_2) },
2705f55b9b56SRoderick Colenbrander 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER_2) },
2706c64ed0cdSRoderick Colenbrander 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER_DONGLE) },
2707f55b9b56SRoderick Colenbrander 	/* Sony DualSense controllers for PS5 */
2708799b2b53SRoderick Colenbrander 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS5_CONTROLLER) },
2709bc2e15a9SRoderick Colenbrander 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS5_CONTROLLER) },
2710b8a968efSRoderick Colenbrander 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS5_CONTROLLER_2) },
2711b8a968efSRoderick Colenbrander 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS5_CONTROLLER_2) },
2712bc2e15a9SRoderick Colenbrander 	{ }
2713bc2e15a9SRoderick Colenbrander };
2714bc2e15a9SRoderick Colenbrander MODULE_DEVICE_TABLE(hid, ps_devices);
2715bc2e15a9SRoderick Colenbrander 
2716bc2e15a9SRoderick Colenbrander static struct hid_driver ps_driver = {
2717bc2e15a9SRoderick Colenbrander 	.name		= "playstation",
2718bc2e15a9SRoderick Colenbrander 	.id_table	= ps_devices,
2719bc2e15a9SRoderick Colenbrander 	.probe		= ps_probe,
2720bc2e15a9SRoderick Colenbrander 	.remove		= ps_remove,
2721bc2e15a9SRoderick Colenbrander 	.raw_event	= ps_raw_event,
2722b4a9af9bSGreg Kroah-Hartman 	.driver = {
2723b4a9af9bSGreg Kroah-Hartman 		.dev_groups = ps_device_groups,
2724b4a9af9bSGreg Kroah-Hartman 	},
2725bc2e15a9SRoderick Colenbrander };
2726bc2e15a9SRoderick Colenbrander 
ps_init(void)2727949aaccdSRoderick Colenbrander static int __init ps_init(void)
2728949aaccdSRoderick Colenbrander {
2729949aaccdSRoderick Colenbrander 	return hid_register_driver(&ps_driver);
2730949aaccdSRoderick Colenbrander }
2731949aaccdSRoderick Colenbrander 
ps_exit(void)2732949aaccdSRoderick Colenbrander static void __exit ps_exit(void)
2733949aaccdSRoderick Colenbrander {
2734949aaccdSRoderick Colenbrander 	hid_unregister_driver(&ps_driver);
2735949aaccdSRoderick Colenbrander 	ida_destroy(&ps_player_id_allocator);
2736949aaccdSRoderick Colenbrander }
2737949aaccdSRoderick Colenbrander 
2738949aaccdSRoderick Colenbrander module_init(ps_init);
2739949aaccdSRoderick Colenbrander module_exit(ps_exit);
2740bc2e15a9SRoderick Colenbrander 
2741bc2e15a9SRoderick Colenbrander MODULE_AUTHOR("Sony Interactive Entertainment");
2742bc2e15a9SRoderick Colenbrander MODULE_DESCRIPTION("HID Driver for PlayStation peripherals.");
2743bc2e15a9SRoderick Colenbrander MODULE_LICENSE("GPL");
2744