blob: aca49637ef2f6f73bd1349293481b505394caeb1 [file] [log] [blame]
Roderick Colenbranderbc2e15a2021-02-07 13:48:56 -08001// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * HID driver for Sony DualSense(TM) controller.
4 *
5 * Copyright (c) 2020 Sony Interactive Entertainment
6 */
7
8#include <linux/bits.h>
9#include <linux/device.h>
10#include <linux/hid.h>
11#include <linux/input/mt.h>
12#include <linux/module.h>
13
14#include <asm/unaligned.h>
15
16#include "hid-ids.h"
17
18#define HID_PLAYSTATION_VERSION_PATCH 0x8000
19
20/* Base class for playstation devices. */
21struct ps_device {
22 struct hid_device *hdev;
Roderick Colenbranderb99dcef2021-02-07 13:48:57 -080023 uint8_t mac_address[6]; /* Note: stored in little endian order. */
Roderick Colenbranderbc2e15a2021-02-07 13:48:56 -080024
25 int (*parse_report)(struct ps_device *dev, struct hid_report *report, u8 *data, int size);
26};
27
28#define DS_INPUT_REPORT_USB 0x01
29#define DS_INPUT_REPORT_USB_SIZE 64
30
Roderick Colenbranderb99dcef2021-02-07 13:48:57 -080031#define DS_FEATURE_REPORT_PAIRING_INFO 0x09
32#define DS_FEATURE_REPORT_PAIRING_INFO_SIZE 20
33
Roderick Colenbranderbc2e15a2021-02-07 13:48:56 -080034/* Button masks for DualSense input report. */
35#define DS_BUTTONS0_HAT_SWITCH GENMASK(3, 0)
36#define DS_BUTTONS0_SQUARE BIT(4)
37#define DS_BUTTONS0_CROSS BIT(5)
38#define DS_BUTTONS0_CIRCLE BIT(6)
39#define DS_BUTTONS0_TRIANGLE BIT(7)
40#define DS_BUTTONS1_L1 BIT(0)
41#define DS_BUTTONS1_R1 BIT(1)
42#define DS_BUTTONS1_L2 BIT(2)
43#define DS_BUTTONS1_R2 BIT(3)
44#define DS_BUTTONS1_CREATE BIT(4)
45#define DS_BUTTONS1_OPTIONS BIT(5)
46#define DS_BUTTONS1_L3 BIT(6)
47#define DS_BUTTONS1_R3 BIT(7)
48#define DS_BUTTONS2_PS_HOME BIT(0)
49#define DS_BUTTONS2_TOUCHPAD BIT(1)
50
51struct dualsense {
52 struct ps_device base;
53 struct input_dev *gamepad;
54};
55
56struct dualsense_touch_point {
57 uint8_t contact;
58 uint8_t x_lo;
59 uint8_t x_hi:4, y_lo:4;
60 uint8_t y_hi;
61} __packed;
62static_assert(sizeof(struct dualsense_touch_point) == 4);
63
64/* Main DualSense input report excluding any BT/USB specific headers. */
65struct dualsense_input_report {
66 uint8_t x, y;
67 uint8_t rx, ry;
68 uint8_t z, rz;
69 uint8_t seq_number;
70 uint8_t buttons[4];
71 uint8_t reserved[4];
72
73 /* Motion sensors */
74 __le16 gyro[3]; /* x, y, z */
75 __le16 accel[3]; /* x, y, z */
76 __le32 sensor_timestamp;
77 uint8_t reserved2;
78
79 /* Touchpad */
80 struct dualsense_touch_point points[2];
81
82 uint8_t reserved3[12];
83 uint8_t status;
84 uint8_t reserved4[10];
85} __packed;
86/* Common input report size shared equals the size of the USB report minus 1 byte for ReportID. */
87static_assert(sizeof(struct dualsense_input_report) == DS_INPUT_REPORT_USB_SIZE - 1);
88
89/*
90 * Common gamepad buttons across DualShock 3 / 4 and DualSense.
91 * Note: for device with a touchpad, touchpad button is not included
92 * as it will be part of the touchpad device.
93 */
94static const int ps_gamepad_buttons[] = {
95 BTN_WEST, /* Square */
96 BTN_NORTH, /* Triangle */
97 BTN_EAST, /* Circle */
98 BTN_SOUTH, /* Cross */
99 BTN_TL, /* L1 */
100 BTN_TR, /* R1 */
101 BTN_TL2, /* L2 */
102 BTN_TR2, /* R2 */
103 BTN_SELECT, /* Create (PS5) / Share (PS4) */
104 BTN_START, /* Option */
105 BTN_THUMBL, /* L3 */
106 BTN_THUMBR, /* R3 */
107 BTN_MODE, /* PS Home */
108};
109
110static const struct {int x; int y; } ps_gamepad_hat_mapping[] = {
111 {0, -1}, {1, -1}, {1, 0}, {1, 1}, {0, 1}, {-1, 1}, {-1, 0}, {-1, -1},
112 {0, 0},
113};
114
115static struct input_dev *ps_allocate_input_dev(struct hid_device *hdev, const char *name_suffix)
116{
117 struct input_dev *input_dev;
118
119 input_dev = devm_input_allocate_device(&hdev->dev);
120 if (!input_dev)
121 return ERR_PTR(-ENOMEM);
122
123 input_dev->id.bustype = hdev->bus;
124 input_dev->id.vendor = hdev->vendor;
125 input_dev->id.product = hdev->product;
126 input_dev->id.version = hdev->version;
127 input_dev->uniq = hdev->uniq;
128
129 if (name_suffix) {
130 input_dev->name = devm_kasprintf(&hdev->dev, GFP_KERNEL, "%s %s", hdev->name,
131 name_suffix);
132 if (!input_dev->name)
133 return ERR_PTR(-ENOMEM);
134 } else {
135 input_dev->name = hdev->name;
136 }
137
138 input_set_drvdata(input_dev, hdev);
139
140 return input_dev;
141}
142
143static struct input_dev *ps_gamepad_create(struct hid_device *hdev)
144{
145 struct input_dev *gamepad;
146 unsigned int i;
147 int ret;
148
149 gamepad = ps_allocate_input_dev(hdev, NULL);
150 if (IS_ERR(gamepad))
151 return ERR_CAST(gamepad);
152
153 input_set_abs_params(gamepad, ABS_X, 0, 255, 0, 0);
154 input_set_abs_params(gamepad, ABS_Y, 0, 255, 0, 0);
155 input_set_abs_params(gamepad, ABS_Z, 0, 255, 0, 0);
156 input_set_abs_params(gamepad, ABS_RX, 0, 255, 0, 0);
157 input_set_abs_params(gamepad, ABS_RY, 0, 255, 0, 0);
158 input_set_abs_params(gamepad, ABS_RZ, 0, 255, 0, 0);
159
160 input_set_abs_params(gamepad, ABS_HAT0X, -1, 1, 0, 0);
161 input_set_abs_params(gamepad, ABS_HAT0Y, -1, 1, 0, 0);
162
163 for (i = 0; i < ARRAY_SIZE(ps_gamepad_buttons); i++)
164 input_set_capability(gamepad, EV_KEY, ps_gamepad_buttons[i]);
165
166 ret = input_register_device(gamepad);
167 if (ret)
168 return ERR_PTR(ret);
169
170 return gamepad;
171}
172
Roderick Colenbranderb99dcef2021-02-07 13:48:57 -0800173static int ps_get_report(struct hid_device *hdev, uint8_t report_id, uint8_t *buf, size_t size)
174{
175 int ret;
176
177 ret = hid_hw_raw_request(hdev, report_id, buf, size, HID_FEATURE_REPORT,
178 HID_REQ_GET_REPORT);
179 if (ret < 0) {
180 hid_err(hdev, "Failed to retrieve feature with reportID %d: %d\n", report_id, ret);
181 return ret;
182 }
183
184 if (ret != size) {
185 hid_err(hdev, "Invalid byte count transferred, expected %zu got %d\n", size, ret);
186 return -EINVAL;
187 }
188
189 if (buf[0] != report_id) {
190 hid_err(hdev, "Invalid reportID received, expected %d got %d\n", report_id, buf[0]);
191 return -EINVAL;
192 }
193
194 return 0;
195}
196
197static int dualsense_get_mac_address(struct dualsense *ds)
198{
199 uint8_t *buf;
200 int ret = 0;
201
202 buf = kzalloc(DS_FEATURE_REPORT_PAIRING_INFO_SIZE, GFP_KERNEL);
203 if (!buf)
204 return -ENOMEM;
205
206 ret = ps_get_report(ds->base.hdev, DS_FEATURE_REPORT_PAIRING_INFO, buf,
207 DS_FEATURE_REPORT_PAIRING_INFO_SIZE);
208 if (ret) {
209 hid_err(ds->base.hdev, "Failed to retrieve DualSense pairing info: %d\n", ret);
210 goto err_free;
211 }
212
213 memcpy(ds->base.mac_address, &buf[1], sizeof(ds->base.mac_address));
214
215err_free:
216 kfree(buf);
217 return ret;
218}
219
Roderick Colenbranderbc2e15a2021-02-07 13:48:56 -0800220static int dualsense_parse_report(struct ps_device *ps_dev, struct hid_report *report,
221 u8 *data, int size)
222{
223 struct hid_device *hdev = ps_dev->hdev;
224 struct dualsense *ds = container_of(ps_dev, struct dualsense, base);
225 struct dualsense_input_report *ds_report;
226 uint8_t value;
227
228 /*
229 * DualSense in USB uses the full HID report for reportID 1, but
230 * Bluetooth uses a minimal HID report for reportID 1 and reports
231 * the full report using reportID 49.
232 */
233 if (hdev->bus == BUS_USB && report->id == DS_INPUT_REPORT_USB &&
234 size == DS_INPUT_REPORT_USB_SIZE) {
235 ds_report = (struct dualsense_input_report *)&data[1];
236 } else {
237 hid_err(hdev, "Unhandled reportID=%d\n", report->id);
238 return -1;
239 }
240
241 input_report_abs(ds->gamepad, ABS_X, ds_report->x);
242 input_report_abs(ds->gamepad, ABS_Y, ds_report->y);
243 input_report_abs(ds->gamepad, ABS_RX, ds_report->rx);
244 input_report_abs(ds->gamepad, ABS_RY, ds_report->ry);
245 input_report_abs(ds->gamepad, ABS_Z, ds_report->z);
246 input_report_abs(ds->gamepad, ABS_RZ, ds_report->rz);
247
248 value = ds_report->buttons[0] & DS_BUTTONS0_HAT_SWITCH;
249 if (value > ARRAY_SIZE(ps_gamepad_hat_mapping))
250 value = 8; /* center */
251 input_report_abs(ds->gamepad, ABS_HAT0X, ps_gamepad_hat_mapping[value].x);
252 input_report_abs(ds->gamepad, ABS_HAT0Y, ps_gamepad_hat_mapping[value].y);
253
254 input_report_key(ds->gamepad, BTN_WEST, ds_report->buttons[0] & DS_BUTTONS0_SQUARE);
255 input_report_key(ds->gamepad, BTN_SOUTH, ds_report->buttons[0] & DS_BUTTONS0_CROSS);
256 input_report_key(ds->gamepad, BTN_EAST, ds_report->buttons[0] & DS_BUTTONS0_CIRCLE);
257 input_report_key(ds->gamepad, BTN_NORTH, ds_report->buttons[0] & DS_BUTTONS0_TRIANGLE);
258 input_report_key(ds->gamepad, BTN_TL, ds_report->buttons[1] & DS_BUTTONS1_L1);
259 input_report_key(ds->gamepad, BTN_TR, ds_report->buttons[1] & DS_BUTTONS1_R1);
260 input_report_key(ds->gamepad, BTN_TL2, ds_report->buttons[1] & DS_BUTTONS1_L2);
261 input_report_key(ds->gamepad, BTN_TR2, ds_report->buttons[1] & DS_BUTTONS1_R2);
262 input_report_key(ds->gamepad, BTN_SELECT, ds_report->buttons[1] & DS_BUTTONS1_CREATE);
263 input_report_key(ds->gamepad, BTN_START, ds_report->buttons[1] & DS_BUTTONS1_OPTIONS);
264 input_report_key(ds->gamepad, BTN_THUMBL, ds_report->buttons[1] & DS_BUTTONS1_L3);
265 input_report_key(ds->gamepad, BTN_THUMBR, ds_report->buttons[1] & DS_BUTTONS1_R3);
266 input_report_key(ds->gamepad, BTN_MODE, ds_report->buttons[2] & DS_BUTTONS2_PS_HOME);
267 input_sync(ds->gamepad);
268
269 return 0;
270}
271
272static struct ps_device *dualsense_create(struct hid_device *hdev)
273{
274 struct dualsense *ds;
275 int ret;
276
277 ds = devm_kzalloc(&hdev->dev, sizeof(*ds), GFP_KERNEL);
278 if (!ds)
279 return ERR_PTR(-ENOMEM);
280
281 /*
282 * Patch version to allow userspace to distinguish between
283 * hid-generic vs hid-playstation axis and button mapping.
284 */
285 hdev->version |= HID_PLAYSTATION_VERSION_PATCH;
286
287 ds->base.hdev = hdev;
288 ds->base.parse_report = dualsense_parse_report;
289 hid_set_drvdata(hdev, ds);
290
Roderick Colenbranderb99dcef2021-02-07 13:48:57 -0800291 ret = dualsense_get_mac_address(ds);
292 if (ret) {
293 hid_err(hdev, "Failed to get MAC address from DualSense\n");
294 return ERR_PTR(ret);
295 }
296 snprintf(hdev->uniq, sizeof(hdev->uniq), "%pMR", ds->base.mac_address);
297
Roderick Colenbranderbc2e15a2021-02-07 13:48:56 -0800298 ds->gamepad = ps_gamepad_create(hdev);
299 if (IS_ERR(ds->gamepad)) {
300 ret = PTR_ERR(ds->gamepad);
301 goto err;
302 }
303
304 return &ds->base;
305
306err:
307 return ERR_PTR(ret);
308}
309
310static int ps_raw_event(struct hid_device *hdev, struct hid_report *report,
311 u8 *data, int size)
312{
313 struct ps_device *dev = hid_get_drvdata(hdev);
314
315 if (dev && dev->parse_report)
316 return dev->parse_report(dev, report, data, size);
317
318 return 0;
319}
320
321static int ps_probe(struct hid_device *hdev, const struct hid_device_id *id)
322{
323 struct ps_device *dev;
324 int ret;
325
326 ret = hid_parse(hdev);
327 if (ret) {
328 hid_err(hdev, "Parse failed\n");
329 return ret;
330 }
331
332 ret = hid_hw_start(hdev, HID_CONNECT_HIDRAW);
333 if (ret) {
334 hid_err(hdev, "Failed to start HID device\n");
335 return ret;
336 }
337
338 ret = hid_hw_open(hdev);
339 if (ret) {
340 hid_err(hdev, "Failed to open HID device\n");
341 goto err_stop;
342 }
343
344 if (hdev->product == USB_DEVICE_ID_SONY_PS5_CONTROLLER) {
345 dev = dualsense_create(hdev);
346 if (IS_ERR(dev)) {
347 hid_err(hdev, "Failed to create dualsense.\n");
348 ret = PTR_ERR(dev);
349 goto err_close;
350 }
351 }
352
353 return ret;
354
355err_close:
356 hid_hw_close(hdev);
357err_stop:
358 hid_hw_stop(hdev);
359 return ret;
360}
361
362static void ps_remove(struct hid_device *hdev)
363{
364 hid_hw_close(hdev);
365 hid_hw_stop(hdev);
366}
367
368static const struct hid_device_id ps_devices[] = {
369 { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS5_CONTROLLER) },
370 { }
371};
372MODULE_DEVICE_TABLE(hid, ps_devices);
373
374static struct hid_driver ps_driver = {
375 .name = "playstation",
376 .id_table = ps_devices,
377 .probe = ps_probe,
378 .remove = ps_remove,
379 .raw_event = ps_raw_event,
380};
381
382module_hid_driver(ps_driver);
383
384MODULE_AUTHOR("Sony Interactive Entertainment");
385MODULE_DESCRIPTION("HID Driver for PlayStation peripherals.");
386MODULE_LICENSE("GPL");