Skip to content

Commit 8e5198a

Browse files
Roderick Colenbranderbentiss
authored andcommitted
HID: playstation: add initial DualSense lightbar support.
Provide initial support for the DualSense lightbar and configure it with a default PlayStation blue color. Signed-off-by: Roderick Colenbrander <roderick.colenbrander@sony.com> Reviewed-by: Barnabás Pőcze <pobrn@protonmail.com> Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
1 parent 50ab1ff commit 8e5198a

1 file changed

Lines changed: 65 additions & 0 deletions

File tree

drivers/hid/hid-playstation.c

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,10 @@ struct ps_calibration_data {
103103
/* Flags for DualSense output report. */
104104
#define DS_OUTPUT_VALID_FLAG0_COMPATIBLE_VIBRATION BIT(0)
105105
#define DS_OUTPUT_VALID_FLAG0_HAPTICS_SELECT BIT(1)
106+
#define DS_OUTPUT_VALID_FLAG1_LIGHTBAR_CONTROL_ENABLE BIT(2)
107+
#define DS_OUTPUT_VALID_FLAG1_RELEASE_LEDS BIT(3)
108+
#define DS_OUTPUT_VALID_FLAG2_LIGHTBAR_SETUP_CONTROL_ENABLE BIT(1)
109+
#define DS_OUTPUT_LIGHTBAR_SETUP_LIGHT_OUT BIT(1)
106110

107111
/* DualSense hardware limits */
108112
#define DS_ACC_RES_PER_G 8192
@@ -132,6 +136,12 @@ struct dualsense {
132136
uint8_t motor_left;
133137
uint8_t motor_right;
134138

139+
/* RGB lightbar */
140+
bool update_lightbar;
141+
uint8_t lightbar_red;
142+
uint8_t lightbar_green;
143+
uint8_t lightbar_blue;
144+
135145
struct work_struct output_worker;
136146
void *output_report_dmabuf;
137147
uint8_t output_seq; /* Sequence number for output report. */
@@ -796,6 +806,15 @@ static void dualsense_output_worker(struct work_struct *work)
796806
ds->update_rumble = false;
797807
}
798808

809+
if (ds->update_lightbar) {
810+
common->valid_flag1 |= DS_OUTPUT_VALID_FLAG1_LIGHTBAR_CONTROL_ENABLE;
811+
common->lightbar_red = ds->lightbar_red;
812+
common->lightbar_green = ds->lightbar_green;
813+
common->lightbar_blue = ds->lightbar_blue;
814+
815+
ds->update_lightbar = false;
816+
}
817+
799818
spin_unlock_irqrestore(&ds->base.lock, flags);
800819

801820
dualsense_send_output_report(ds, &report);
@@ -980,6 +999,41 @@ static int dualsense_play_effect(struct input_dev *dev, void *data, struct ff_ef
980999
return 0;
9811000
}
9821001

1002+
static int dualsense_reset_leds(struct dualsense *ds)
1003+
{
1004+
struct dualsense_output_report report;
1005+
uint8_t *buf;
1006+
1007+
buf = kzalloc(sizeof(struct dualsense_output_report_bt), GFP_KERNEL);
1008+
if (!buf)
1009+
return -ENOMEM;
1010+
1011+
dualsense_init_output_report(ds, &report, buf);
1012+
/*
1013+
* On Bluetooth the DualSense outputs an animation on the lightbar
1014+
* during startup and maintains a color afterwards. We need to explicitly
1015+
* reconfigure the lightbar before we can do any programming later on.
1016+
* In USB the lightbar is not on by default, but redoing the setup there
1017+
* doesn't hurt.
1018+
*/
1019+
report.common->valid_flag2 = DS_OUTPUT_VALID_FLAG2_LIGHTBAR_SETUP_CONTROL_ENABLE;
1020+
report.common->lightbar_setup = DS_OUTPUT_LIGHTBAR_SETUP_LIGHT_OUT; /* Fade light out. */
1021+
dualsense_send_output_report(ds, &report);
1022+
1023+
kfree(buf);
1024+
return 0;
1025+
}
1026+
1027+
static void dualsense_set_lightbar(struct dualsense *ds, uint8_t red, uint8_t green, uint8_t blue)
1028+
{
1029+
ds->update_lightbar = true;
1030+
ds->lightbar_red = red;
1031+
ds->lightbar_green = green;
1032+
ds->lightbar_blue = blue;
1033+
1034+
schedule_work(&ds->output_worker);
1035+
}
1036+
9831037
static struct ps_device *dualsense_create(struct hid_device *hdev)
9841038
{
9851039
struct dualsense *ds;
@@ -1057,6 +1111,17 @@ static struct ps_device *dualsense_create(struct hid_device *hdev)
10571111
if (ret)
10581112
goto err;
10591113

1114+
/*
1115+
* The hardware may have control over the LEDs (e.g. in Bluetooth on startup).
1116+
* Reset the LEDs (lightbar, mute, player leds), so we can control them
1117+
* from software.
1118+
*/
1119+
ret = dualsense_reset_leds(ds);
1120+
if (ret)
1121+
goto err;
1122+
1123+
dualsense_set_lightbar(ds, 0, 0, 128); /* blue */
1124+
10601125
/*
10611126
* Reporting hardware and firmware is important as there are frequent updates, which
10621127
* can change behavior.

0 commit comments

Comments
 (0)