From 774ae18f339d3f4e535ce11ab4f9087f3acb3d87 Mon Sep 17 00:00:00 2001 From: Sorgelig Date: Sat, 10 Jul 2021 16:39:05 +0800 Subject: [PATCH] dualsense: give mute button and led to system. --- drivers/hid/hid-playstation.c | 79 +++++++++++++++++++++++------------ 1 file changed, 52 insertions(+), 27 deletions(-) diff --git a/drivers/hid/hid-playstation.c b/drivers/hid/hid-playstation.c index 509661dc7..10a7cc358 100644 --- a/drivers/hid/hid-playstation.c +++ b/drivers/hid/hid-playstation.c @@ -131,6 +131,7 @@ struct dualsense { struct led_classdev led; /* player leds */ struct led_classdev rgbled[3]; /* lightbar */ + struct led_classdev muteled; /* mute led */ /* Calibration data for accelerometer and gyroscope. */ struct ps_calibration_data accel_calib_data[3]; @@ -155,7 +156,6 @@ struct dualsense { /* Microphone */ bool update_mic_mute; bool mic_muted; - bool last_btn_mic_state; /* Player leds */ bool update_player_leds; @@ -281,6 +281,7 @@ static const int ps_gamepad_buttons[] = { BTN_THUMBL, /* L3 */ BTN_THUMBR, /* R3 */ BTN_MODE, /* PS Home */ + BTN_Z }; static const struct {int x; int y; } ps_gamepad_hat_mapping[] = { @@ -873,7 +874,6 @@ 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; uint32_t sensor_timestamp; - bool btn_mic_state; unsigned long flags; int i; @@ -927,25 +927,9 @@ static int dualsense_parse_report(struct ps_device *ps_dev, struct hid_report *r input_report_key(ds->gamepad, BTN_THUMBL, ds_report->buttons[1] & DS_BUTTONS1_L3); input_report_key(ds->gamepad, BTN_THUMBR, ds_report->buttons[1] & DS_BUTTONS1_R3); input_report_key(ds->gamepad, BTN_MODE, ds_report->buttons[2] & DS_BUTTONS2_PS_HOME); + input_report_key(ds->gamepad, BTN_Z, ds_report->buttons[2] & DS_BUTTONS2_MIC_MUTE); input_sync(ds->gamepad); - /* - * The DualSense has an internal microphone, which can be muted through a mute button - * on the device. The driver is expected to read the button state and program the device - * to mute/unmute audio at the hardware level. - */ - btn_mic_state = !!(ds_report->buttons[2] & DS_BUTTONS2_MIC_MUTE); - if (btn_mic_state && !ds->last_btn_mic_state) { - spin_lock_irqsave(&ps_dev->lock, flags); - ds->update_mic_mute = true; - ds->mic_muted = !ds->mic_muted; /* toggle */ - spin_unlock_irqrestore(&ps_dev->lock, flags); - - /* Schedule updating of microphone state at hardware level. */ - schedule_work(&ds->output_worker); - } - ds->last_btn_mic_state = btn_mic_state; - /* Parse and calibrate gyroscope data. */ for (i = 0; i < ARRAY_SIZE(ds_report->gyro); i++) { int raw_data = (short)le16_to_cpu(ds_report->gyro[i]); @@ -1161,6 +1145,49 @@ static int ds_leds_create(struct dualsense *ds) return 0; } +static int dualsense_muteled_brightness_set(struct led_classdev *led, enum led_brightness brightness) +{ + struct device *dev = led->dev->parent; + struct hid_device *hdev = to_hid_device(dev); + struct dualsense *ds = hid_get_drvdata(hdev); + + if (!ds) { + hid_err(hdev, "No controller data\n"); + return -ENODEV; + } + + + ds->update_mic_mute = true; + ds->mic_muted = brightness; + schedule_work(&ds->output_worker); + return 0; +} + +static int ds_muteled_create(struct dualsense *ds) +{ + struct hid_device *hdev = ds->base.hdev; + struct device *dev = &hdev->dev; + int ret; + + /* configure the player LEDs */ + ds->muteled.name = devm_kasprintf(dev, GFP_KERNEL,"%s:mute", dev_name(dev)); + if (!ds->muteled.name) return -ENOMEM; + + ds->muteled.brightness = 0; + ds->muteled.max_brightness = 1; + ds->muteled.brightness_set_blocking = dualsense_muteled_brightness_set; + ds->muteled.flags = LED_CORE_SUSPENDRESUME | LED_HW_PLUGGABLE; + + ret = devm_led_classdev_register(&hdev->dev, &ds->muteled); + if (ret) + { + hid_err(hdev, "Failed registering %s LED\n", ds->muteled.name); + return ret; + } + + return 0; +} + static int dualsense_lightbar_brightness_set(struct led_classdev *led, enum led_brightness brightness) { struct device *dev = led->dev->parent; @@ -1293,18 +1320,16 @@ static struct ps_device *dualsense_create(struct hid_device *hdev) * from software. */ ret = dualsense_reset_leds(ds); - if (ret) - goto err; + if (ret) goto err; ret = ds_lightbar_create(ds); - if (ret) - goto err; + if (ret) goto err; + + ret = ds_muteled_create(ds); + if (ret) goto err; - /* Set player LEDs to our player id. */ - //dualsense_set_player_leds(ds); ret = ds_leds_create(ds); - if (ret) - goto err; + if (ret) goto err; /* * Reporting hardware and firmware is important as there are frequent updates, which