Skip to content

Commit e1c24d5

Browse files
cristiccJiri Kosina
authored andcommitted
HID: playstation: Support DualSense audio jack event reporting
The DualSense controller complies with v1.0 of the USB Audio Class spec (UAC1), hence it cannot advertise any jack detection capability. However, this feature can be implemented in the generic USB audio driver via quirks, i.e. by configuring an input handler to receive hotplug events from the HID driver. When operating in USB mode, register a dedicated input device for the audio jack and use it to report all headphone and headset mic insert events. Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com> Tested-by: Benjamin Tissoires <bentiss@kernel.org> Signed-off-by: Jiri Kosina <jkosina@suse.com>
1 parent b1b4806 commit e1c24d5

1 file changed

Lines changed: 36 additions & 0 deletions

File tree

drivers/hid/hid-playstation.c

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ struct dualsense {
176176
struct input_dev *gamepad;
177177
struct input_dev *sensors;
178178
struct input_dev *touchpad;
179+
struct input_dev *jack;
179180

180181
/* Update version is used as a feature/capability version. */
181182
u16 update_version;
@@ -955,6 +956,25 @@ static struct input_dev *ps_touchpad_create(struct hid_device *hdev, int width,
955956
return touchpad;
956957
}
957958

959+
static struct input_dev *ps_headset_jack_create(struct hid_device *hdev)
960+
{
961+
struct input_dev *jack;
962+
int ret;
963+
964+
jack = ps_allocate_input_dev(hdev, "Headset Jack");
965+
if (IS_ERR(jack))
966+
return ERR_CAST(jack);
967+
968+
input_set_capability(jack, EV_SW, SW_HEADPHONE_INSERT);
969+
input_set_capability(jack, EV_SW, SW_MICROPHONE_INSERT);
970+
971+
ret = input_register_device(jack);
972+
if (ret)
973+
return ERR_PTR(ret);
974+
975+
return jack;
976+
}
977+
958978
static ssize_t firmware_version_show(struct device *dev,
959979
struct device_attribute *attr, char *buf)
960980
{
@@ -1357,8 +1377,15 @@ static void dualsense_output_worker(struct work_struct *work)
13571377
common->audio_control2 =
13581378
FIELD_PREP(DS_OUTPUT_AUDIO_FLAGS2_SP_PREAMP_GAIN, 0x2);
13591379
}
1380+
1381+
input_report_switch(ds->jack, SW_HEADPHONE_INSERT, val);
13601382
}
13611383

1384+
val = ds->plugged_state & DS_STATUS1_MIC_DETECT;
1385+
if (val != (ds->prev_plugged_state & DS_STATUS1_MIC_DETECT))
1386+
input_report_switch(ds->jack, SW_MICROPHONE_INSERT, val);
1387+
1388+
input_sync(ds->jack);
13621389
ds->prev_plugged_state = ds->plugged_state;
13631390
}
13641391

@@ -1778,6 +1805,15 @@ static struct ps_device *dualsense_create(struct hid_device *hdev)
17781805
goto err;
17791806
}
17801807

1808+
/* Bluetooth audio is currently not supported. */
1809+
if (hdev->bus == BUS_USB) {
1810+
ds->jack = ps_headset_jack_create(hdev);
1811+
if (IS_ERR(ds->jack)) {
1812+
ret = PTR_ERR(ds->jack);
1813+
goto err;
1814+
}
1815+
}
1816+
17811817
ret = ps_device_register_battery(ps_dev);
17821818
if (ret)
17831819
goto err;

0 commit comments

Comments
 (0)