Thread (42 messages) flat view 42 messages, 6 authors, 2021-01-11

Re: [PATCH v2 10/13] HID: playstation: add microphone mute support for DualSense.

From: Barnabás Pőcze <hidden>
Date: 2021-01-07 21:58:45

Hi


2021. január 2., szombat 23:31 keltezéssel, Roderick Colenbrander írta:
quoted hunk ↗ jump to hunk
From: Roderick Colenbrander <roderick.colenbrander@sony.com>

The DualSense controller has a built-in microphone exposed as an
audio device over USB (or HID using Bluetooth). A dedicated
button on the controller handles mute, but software has to configure
the device to mute the audio stream.

This patch captures the mute button and schedules an output report
to mute/unmute the audio stream as well as toggle the mute LED.

Signed-off-by: Roderick Colenbrander <roderick.colenbrander@sony.com>
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index c80c81916f4a..9b1803f8f935 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -857,6 +857,7 @@  config HID_PLAYSTATION
 	tristate "PlayStation HID Driver"
 	default !EXPERT
 	depends on HID
I think maybe "select NEW_LEDS" should be here as well?

quoted hunk ↗ jump to hunk
+	select LEDS_CLASS
 	select LEDS_CLASS_MULTICOLOR
 	select POWER_SUPPLY
 	help
diff --git a/drivers/hid/hid-playstation.c b/drivers/hid/hid-playstation.c
index 3b26445acbb9..ebf8a6550308 100644
--- a/drivers/hid/hid-playstation.c
+++ b/drivers/hid/hid-playstation.c
[...]
+static int ps_led_register(struct ps_device *ps_dev, struct led_classdev *led,
+		struct ps_led_info *led_info)
+{
+	int ret;
+
+	led->name = devm_kasprintf(&ps_dev->hdev->dev, GFP_KERNEL,
+			"playstation::%pMR::%s", ps_dev->mac_address, led_info->name);
+
+	if (!led->name)
+		return -ENOMEM;
+
+	led->brightness = 0;
+	led->max_brightness = 1;
+	led->flags = LED_CORE_SUSPENDRESUME;
+	led->brightness_get = led_info->brightness_get;
+	led->brightness_set = led_info->brightness_set;
+
+	ret = devm_led_classdev_register(&ps_dev->hdev->dev, led);
+	if (ret) {
+		hid_err(ps_dev->hdev, "Failed to register LED %s: %d\n", led_info->name, ret);
Another inconsistency with log messages is that sometimes the error code is printed,
sometimes it is not. I believe it would be preferable if there was no incosistency.

+		return ret;
+	}
+
+	return 0;
+}
[...]
+static enum led_brightness dualsense_mute_led_get_brightness(struct led_classdev *led)
+{
+	struct hid_device *hdev = to_hid_device(led->dev->parent);
+	struct dualsense *ds = hid_get_drvdata(hdev);
I think these two lines could be replaced with:
struct dualsense *ds = container_of(led, struct dualsense, mute_led);
quoted hunk ↗ jump to hunk
+
+	return ds->mic_muted;
+}
[...]
 static void dualsense_init_output_report(struct dualsense *ds, struct dualsense_output_report *rp,
 		void *buf)
 {
@@ -763,6 +820,26 @@  static void dualsense_output_worker(struct work_struct *work)
 		ds->update_lightbar = false;
 	}

+	if (ds->update_mic_mute) {
+		if (ds->mic_muted) {
+			common->valid_flag1 |= DS_OUTPUT_VALID_FLAG1_MIC_MUTE_LED_CONTROL_ENABLE;
+			common->mute_button_led = 1; /* Enable mute LED. */
+
+			/* Disable microphone */
+			common->valid_flag1 |= DS_OUTPUT_VALID_FLAG1_POWER_SAVE_CONTROL_ENABLE;
+			common->power_save_control |= DS_OUTPUT_POWER_SAVE_CONTROL_MIC_MUTE;
+		} else {
+			common->valid_flag1 |= DS_OUTPUT_VALID_FLAG1_MIC_MUTE_LED_CONTROL_ENABLE;
+			common->mute_button_led = 0; /* Disable mute LED. */
+
+			/* Enable microphone */
+			common->valid_flag1 |= DS_OUTPUT_VALID_FLAG1_POWER_SAVE_CONTROL_ENABLE;
+			common->power_save_control &= ~DS_OUTPUT_POWER_SAVE_CONTROL_MIC_MUTE;
+		}
+
I'd put the first two lines (or at least the first line) outside the conditional.

quoted hunk ↗ jump to hunk
+		ds->update_mic_mute = false;
+	}
+
 	spin_unlock_irqrestore(&ds->base.lock, flags);

 	dualsense_send_output_report(ds, &report);
@@ -777,6 +854,7 @@  static int dualsense_parse_report(struct ps_device *ps_dev, struct hid_report *r
 	uint8_t battery_data, battery_capacity, charging_status, value;
 	int battery_status;
 	uint16_t sensor_timestamp;
+	bool btn_mic_state;
 	unsigned long flags;
 	int i;
@@ -829,6 +907,22 @@  static int dualsense_parse_report(struct ps_device *ps_dev, struct hid_report *r
 	input_report_key(ds->gamepad, BTN_MODE,   ds_report->buttons[2] & DS_BUTTONS2_PS_HOME);
 	input_sync(ds->gamepad);

+	/* The DualSense has an internal microphone, which can be muted through a mute button
+	 * on the device. The driver expected to read the button state and program the device
[...]
"The driver is expected" ?


Regards,
Barnabás Pőcze
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help