All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/3]  HID: playstation: add LED support
@ 2021-09-01 22:30 Roderick Colenbrander
  2021-09-01 22:30 ` [PATCH v2 1/3] HID: playstation: expose DualSense lightbar through a multi-color LED Roderick Colenbrander
                   ` (2 more replies)
  0 siblings, 3 replies; 9+ messages in thread
From: Roderick Colenbrander @ 2021-09-01 22:30 UTC (permalink / raw)
  To: Jiri Kosina, Benjamin Tissoires, Pavel Machek
  Cc: linux-input, linux-leds, Daniel J . Ogorchock, Roderick Colenbrander

Hi,

This is a resubmit of the previous patch series. The only change
is the inclusion of a description of player LEDs into the LED
documentation (Documentation/leds/well-know-leds.txt). This file
was just merged by Linus among other LED changes into git master (5.15)
and the patch series is thus relative to there as well.

Regards,

Roderick Colenbrander
Sony Interactive Entertainment, LLC

Roderick Colenbrander (3):
  HID: playstation: expose DualSense lightbar through a multi-color LED.
  leds: add new LED_FUNCTION_PLAYER for player LEDs for game
    controllers.
  HID: playstation: expose DualSense player LEDs through LED class.

 Documentation/leds/well-known-leds.txt |  14 +++
 drivers/hid/hid-playstation.c          | 157 ++++++++++++++++++++++++-
 include/dt-bindings/leds/common.h      |   3 +
 3 files changed, 173 insertions(+), 1 deletion(-)

-- 
2.31.1


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH v2 1/3] HID: playstation: expose DualSense lightbar through a multi-color LED.
  2021-09-01 22:30 [PATCH v2 0/3] HID: playstation: add LED support Roderick Colenbrander
@ 2021-09-01 22:30 ` Roderick Colenbrander
  2021-09-03 16:16   ` Pavel Machek
  2021-09-01 22:30 ` [PATCH v2 2/3] leds: add new LED_FUNCTION_PLAYER for player LEDs for game controllers Roderick Colenbrander
  2021-09-01 22:30 ` [PATCH v2 3/3] HID: playstation: expose DualSense player LEDs through LED class Roderick Colenbrander
  2 siblings, 1 reply; 9+ messages in thread
From: Roderick Colenbrander @ 2021-09-01 22:30 UTC (permalink / raw)
  To: Jiri Kosina, Benjamin Tissoires, Pavel Machek
  Cc: linux-input, linux-leds, Daniel J . Ogorchock, Roderick Colenbrander

The DualSense lightbar has so far been supported, but it was not yet
adjustable from user space. This patch exposes it through a multi-color
LED.

Signed-off-by: Roderick Colenbrander <roderick.colenbrander@sony.com>
---
 drivers/hid/hid-playstation.c | 72 +++++++++++++++++++++++++++++++++++
 1 file changed, 72 insertions(+)

diff --git a/drivers/hid/hid-playstation.c b/drivers/hid/hid-playstation.c
index ab7c82c2e886..ff2fc315a89d 100644
--- a/drivers/hid/hid-playstation.c
+++ b/drivers/hid/hid-playstation.c
@@ -11,6 +11,8 @@
 #include <linux/hid.h>
 #include <linux/idr.h>
 #include <linux/input/mt.h>
+#include <linux/leds.h>
+#include <linux/led-class-multicolor.h>
 #include <linux/module.h>
 
 #include <asm/unaligned.h>
@@ -38,6 +40,7 @@ struct ps_device {
 	uint8_t battery_capacity;
 	int battery_status;
 
+	const char *input_dev_name; /* Name of primary input device. */
 	uint8_t mac_address[6]; /* Note: stored in little endian order. */
 	uint32_t hw_version;
 	uint32_t fw_version;
@@ -147,6 +150,7 @@ struct dualsense {
 	uint8_t motor_right;
 
 	/* RGB lightbar */
+	struct led_classdev_mc lightbar;
 	bool update_lightbar;
 	uint8_t lightbar_red;
 	uint8_t lightbar_green;
@@ -288,6 +292,8 @@ static const struct {int x; int y; } ps_gamepad_hat_mapping[] = {
 	{0, 0},
 };
 
+static void dualsense_set_lightbar(struct dualsense *ds, uint8_t red, uint8_t green, uint8_t blue);
+
 /*
  * Add a new ps_device to ps_devices if it doesn't exist.
  * Return error on duplicate device, which can happen if the same
@@ -525,6 +531,45 @@ static int ps_get_report(struct hid_device *hdev, uint8_t report_id, uint8_t *bu
 	return 0;
 }
 
+/* Register a DualSense/DualShock4 RGB lightbar represented by a multicolor LED. */
+static int ps_lightbar_register(struct ps_device *ps_dev, struct led_classdev_mc *lightbar_mc_dev,
+	int (*brightness_set)(struct led_classdev *, enum led_brightness))
+{
+	struct hid_device *hdev = ps_dev->hdev;
+	struct mc_subled *mc_led_info;
+	struct led_classdev *led_cdev;
+	int ret;
+
+	mc_led_info = devm_kmalloc_array(&hdev->dev, 3, sizeof(*mc_led_info),
+					 GFP_KERNEL | __GFP_ZERO);
+	if (!mc_led_info)
+		return -ENOMEM;
+
+	mc_led_info[0].color_index = LED_COLOR_ID_RED;
+	mc_led_info[1].color_index = LED_COLOR_ID_GREEN;
+	mc_led_info[2].color_index = LED_COLOR_ID_BLUE;
+
+	lightbar_mc_dev->subled_info = mc_led_info;
+	lightbar_mc_dev->num_colors = 3;
+
+	led_cdev = &lightbar_mc_dev->led_cdev;
+	led_cdev->name = devm_kasprintf(&hdev->dev, GFP_KERNEL, "%s:rgb:indicator",
+			ps_dev->input_dev_name);
+	if (!led_cdev->name)
+		return -ENOMEM;
+	led_cdev->brightness = 255;
+	led_cdev->max_brightness = 255;
+	led_cdev->brightness_set_blocking = brightness_set;
+
+	ret = devm_led_classdev_multicolor_register(&hdev->dev, lightbar_mc_dev);
+	if (ret < 0) {
+		hid_err(hdev, "Cannot register multicolor LED device\n");
+		return ret;
+	}
+
+	return 0;
+}
+
 static struct input_dev *ps_sensors_create(struct hid_device *hdev, int accel_range, int accel_res,
 		int gyro_range, int gyro_res)
 {
@@ -761,6 +806,22 @@ static int dualsense_get_mac_address(struct dualsense *ds)
 	return ret;
 }
 
+static int dualsense_lightbar_set_brightness(struct led_classdev *cdev,
+	enum led_brightness brightness)
+{
+	struct led_classdev_mc *mc_cdev = lcdev_to_mccdev(cdev);
+	struct dualsense *ds = container_of(mc_cdev, struct dualsense, lightbar);
+	uint8_t red, green, blue;
+
+	led_mc_calc_color_components(mc_cdev, brightness);
+	red = mc_cdev->subled_info[0].brightness;
+	green = mc_cdev->subled_info[1].brightness;
+	blue = mc_cdev->subled_info[2].brightness;
+
+	dualsense_set_lightbar(ds, red, green, blue);
+	return 0;
+}
+
 static void dualsense_init_output_report(struct dualsense *ds, struct dualsense_output_report *rp,
 		void *buf)
 {
@@ -1106,10 +1167,14 @@ static int dualsense_reset_leds(struct dualsense *ds)
 
 static void dualsense_set_lightbar(struct dualsense *ds, uint8_t red, uint8_t green, uint8_t blue)
 {
+	unsigned long flags;
+
+	spin_lock_irqsave(&ds->base.lock, flags);
 	ds->update_lightbar = true;
 	ds->lightbar_red = red;
 	ds->lightbar_green = green;
 	ds->lightbar_blue = blue;
+	spin_unlock_irqrestore(&ds->base.lock, flags);
 
 	schedule_work(&ds->output_worker);
 }
@@ -1196,6 +1261,8 @@ static struct ps_device *dualsense_create(struct hid_device *hdev)
 		ret = PTR_ERR(ds->gamepad);
 		goto err;
 	}
+	/* Use gamepad input device name as primary device name for e.g. LEDs */
+	ps_dev->input_dev_name = dev_name(&ds->gamepad->dev);
 
 	ds->sensors = ps_sensors_create(hdev, DS_ACC_RANGE, DS_ACC_RES_PER_G,
 			DS_GYRO_RANGE, DS_GYRO_RES_PER_DEG_S);
@@ -1223,6 +1290,11 @@ static struct ps_device *dualsense_create(struct hid_device *hdev)
 	if (ret)
 		goto err;
 
+	ret = ps_lightbar_register(ps_dev, &ds->lightbar, dualsense_lightbar_set_brightness);
+	if (ret)
+		goto err;
+
+	/* Set default lightbar color. */
 	dualsense_set_lightbar(ds, 0, 0, 128); /* blue */
 
 	ret = ps_device_set_player_id(ps_dev);
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v2 2/3] leds: add new LED_FUNCTION_PLAYER for player LEDs for game controllers.
  2021-09-01 22:30 [PATCH v2 0/3] HID: playstation: add LED support Roderick Colenbrander
  2021-09-01 22:30 ` [PATCH v2 1/3] HID: playstation: expose DualSense lightbar through a multi-color LED Roderick Colenbrander
@ 2021-09-01 22:30 ` Roderick Colenbrander
  2021-09-03 16:17   ` Pavel Machek
  2021-09-01 22:30 ` [PATCH v2 3/3] HID: playstation: expose DualSense player LEDs through LED class Roderick Colenbrander
  2 siblings, 1 reply; 9+ messages in thread
From: Roderick Colenbrander @ 2021-09-01 22:30 UTC (permalink / raw)
  To: Jiri Kosina, Benjamin Tissoires, Pavel Machek
  Cc: linux-input, linux-leds, Daniel J . Ogorchock, Roderick Colenbrander

Player LEDs are commonly found on game controllers from Nintendo and Sony
to indicate a player ID across a number of LEDs. For example, "Player 2"
might be indicated as "-x--" on a device with 4 LEDs where "x" means on.

This patch introduces a new LED_FUNCTION_PLAYER to properly indicate
player LEDs from the kernel. Until now there was no good standard, which
resulted in inconsistent behavior across xpad, hid-sony, hid-wiimote and
other drivers. Moving forward new drivers should use LED_FUNCTION_PLAYER.

Note: management of Player IDs is left to user space, though a kernel
driver may pick a default value.

Signed-off-by: Roderick Colenbrander <roderick.colenbrander@sony.com>
---
 Documentation/leds/well-known-leds.txt | 14 ++++++++++++++
 include/dt-bindings/leds/common.h      |  3 +++
 2 files changed, 17 insertions(+)

diff --git a/Documentation/leds/well-known-leds.txt b/Documentation/leds/well-known-leds.txt
index 4a8b9dc4bf52..2160382c86be 100644
--- a/Documentation/leds/well-known-leds.txt
+++ b/Documentation/leds/well-known-leds.txt
@@ -16,6 +16,20 @@ but then try the legacy ones, too.
 
 Notice there's a list of functions in include/dt-bindings/leds/common.h .
 
+* Gamepads and joysticks
+
+Game controllers may feature LEDs to indicate a player number. This is commonly
+used on game consoles in which multiple controllers can be connected to a system.
+The "player LEDs" are then programmed with a pattern to indicate a particular
+player. For example, a game controller with 4 LEDs, may be programmed with "x---"
+to indicate player 1, "-x--" to indicate player 2 etcetera where "x" means on.
+Input drivers can utilize the LED class to expose the individual player LEDs
+of a game controller using the function "player".
+Note: tracking and management of Player IDs is the responsibility of user space,
+though drivers may pick a default value.
+
+Good: "input*:*:player-{1,2,3,4,5}
+
 * Keyboards
   
 Good: "input*:*:capslock"
diff --git a/include/dt-bindings/leds/common.h b/include/dt-bindings/leds/common.h
index 52b619d44ba2..94999c250e4d 100644
--- a/include/dt-bindings/leds/common.h
+++ b/include/dt-bindings/leds/common.h
@@ -60,6 +60,9 @@
 #define LED_FUNCTION_MICMUTE "micmute"
 #define LED_FUNCTION_MUTE "mute"
 
+/* Used for player LEDs as found on game controllers from e.g. Nintendo, Sony. */
+#define LED_FUNCTION_PLAYER "player"
+
 /* Miscelleaus functions. Use functions above if you can. */
 #define LED_FUNCTION_ACTIVITY "activity"
 #define LED_FUNCTION_ALARM "alarm"
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v2 3/3] HID: playstation: expose DualSense player LEDs through LED class.
  2021-09-01 22:30 [PATCH v2 0/3] HID: playstation: add LED support Roderick Colenbrander
  2021-09-01 22:30 ` [PATCH v2 1/3] HID: playstation: expose DualSense lightbar through a multi-color LED Roderick Colenbrander
  2021-09-01 22:30 ` [PATCH v2 2/3] leds: add new LED_FUNCTION_PLAYER for player LEDs for game controllers Roderick Colenbrander
@ 2021-09-01 22:30 ` Roderick Colenbrander
  2021-09-03 16:17   ` Pavel Machek
  2 siblings, 1 reply; 9+ messages in thread
From: Roderick Colenbrander @ 2021-09-01 22:30 UTC (permalink / raw)
  To: Jiri Kosina, Benjamin Tissoires, Pavel Machek
  Cc: linux-input, linux-leds, Daniel J . Ogorchock, Roderick Colenbrander

The DualSense player LEDs were so far not adjustable from user-space.
This patch exposes each LED individually through the LED class. Each
LED uses the new 'player' function resulting in a name like:
'inputX:white:player-1' for the first LED.

Signed-off-by: Roderick Colenbrander <roderick.colenbrander@sony.com>
---
 drivers/hid/hid-playstation.c | 85 ++++++++++++++++++++++++++++++++++-
 1 file changed, 84 insertions(+), 1 deletion(-)

diff --git a/drivers/hid/hid-playstation.c b/drivers/hid/hid-playstation.c
index ff2fc315a89d..9b96239bba5f 100644
--- a/drivers/hid/hid-playstation.c
+++ b/drivers/hid/hid-playstation.c
@@ -56,6 +56,13 @@ struct ps_calibration_data {
 	int sens_denom;
 };
 
+struct ps_led_info {
+	const char *name;
+	const char *color;
+	enum led_brightness (*brightness_get)(struct led_classdev *cdev);
+	void (*brightness_set)(struct led_classdev *cdev, enum led_brightness);
+};
+
 /* Seed values for DualShock4 / DualSense CRC32 for different report types. */
 #define PS_INPUT_CRC32_SEED	0xA1
 #define PS_OUTPUT_CRC32_SEED	0xA2
@@ -531,6 +538,32 @@ static int ps_get_report(struct hid_device *hdev, uint8_t report_id, uint8_t *bu
 	return 0;
 }
 
+static int ps_led_register(struct ps_device *ps_dev, struct led_classdev *led,
+		const struct ps_led_info *led_info)
+{
+	int ret;
+
+	led->name = devm_kasprintf(&ps_dev->hdev->dev, GFP_KERNEL,
+			"%s:%s:%s", ps_dev->input_dev_name, led_info->color, 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);
+		return ret;
+	}
+
+	return 0;
+}
+
 /* Register a DualSense/DualShock4 RGB lightbar represented by a multicolor LED. */
 static int ps_lightbar_register(struct ps_device *ps_dev, struct led_classdev_mc *lightbar_mc_dev,
 	int (*brightness_set)(struct led_classdev *, enum led_brightness))
@@ -822,6 +855,35 @@ static int dualsense_lightbar_set_brightness(struct led_classdev *cdev,
 	return 0;
 }
 
+static enum led_brightness dualsense_player_led_get_brightness(struct led_classdev *led)
+{
+	struct hid_device *hdev = to_hid_device(led->dev->parent);
+	struct dualsense *ds = hid_get_drvdata(hdev);
+
+	return !!(ds->player_leds_state & BIT(led - ds->player_leds));
+}
+
+static void dualsense_player_led_set_brightness(struct led_classdev *led, enum led_brightness value)
+{
+	struct hid_device *hdev = to_hid_device(led->dev->parent);
+	struct dualsense *ds = hid_get_drvdata(hdev);
+	unsigned long flags;
+	unsigned int led_index;
+
+	spin_lock_irqsave(&ds->base.lock, flags);
+
+	led_index = led - ds->player_leds;
+	if (value == LED_OFF)
+		ds->player_leds_state &= ~BIT(led_index);
+	else
+		ds->player_leds_state |= BIT(led_index);
+
+	ds->update_player_leds = true;
+	spin_unlock_irqrestore(&ds->base.lock, flags);
+
+	schedule_work(&ds->output_worker);
+}
+
 static void dualsense_init_output_report(struct dualsense *ds, struct dualsense_output_report *rp,
 		void *buf)
 {
@@ -1207,7 +1269,20 @@ static struct ps_device *dualsense_create(struct hid_device *hdev)
 	struct dualsense *ds;
 	struct ps_device *ps_dev;
 	uint8_t max_output_report_size;
-	int ret;
+	int i, ret;
+
+	static const struct ps_led_info player_leds_info[] = {
+		{ LED_FUNCTION_PLAYER "-1", "white", dualsense_player_led_get_brightness,
+				dualsense_player_led_set_brightness },
+		{ LED_FUNCTION_PLAYER "-2", "white", dualsense_player_led_get_brightness,
+				dualsense_player_led_set_brightness },
+		{ LED_FUNCTION_PLAYER "-3", "white", dualsense_player_led_get_brightness,
+				dualsense_player_led_set_brightness },
+		{ LED_FUNCTION_PLAYER "-4", "white", dualsense_player_led_get_brightness,
+				dualsense_player_led_set_brightness },
+		{ LED_FUNCTION_PLAYER "-5", "white", dualsense_player_led_get_brightness,
+				dualsense_player_led_set_brightness }
+	};
 
 	ds = devm_kzalloc(&hdev->dev, sizeof(*ds), GFP_KERNEL);
 	if (!ds)
@@ -1297,6 +1372,14 @@ static struct ps_device *dualsense_create(struct hid_device *hdev)
 	/* Set default lightbar color. */
 	dualsense_set_lightbar(ds, 0, 0, 128); /* blue */
 
+	for (i = 0; i < ARRAY_SIZE(player_leds_info); i++) {
+		const struct ps_led_info *led_info = &player_leds_info[i];
+
+		ret = ps_led_register(ps_dev, &ds->player_leds[i], led_info);
+		if (ret < 0)
+			goto err;
+	}
+
 	ret = ps_device_set_player_id(ps_dev);
 	if (ret) {
 		hid_err(hdev, "Failed to assign player id for DualSense: %d\n", ret);
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 1/3] HID: playstation: expose DualSense lightbar through a multi-color LED.
  2021-09-01 22:30 ` [PATCH v2 1/3] HID: playstation: expose DualSense lightbar through a multi-color LED Roderick Colenbrander
@ 2021-09-03 16:16   ` Pavel Machek
  0 siblings, 0 replies; 9+ messages in thread
From: Pavel Machek @ 2021-09-03 16:16 UTC (permalink / raw)
  To: Roderick Colenbrander
  Cc: Jiri Kosina, Benjamin Tissoires, linux-input, linux-leds,
	Daniel J . Ogorchock, Roderick Colenbrander

On Wed 2021-09-01 15:30:35, Roderick Colenbrander wrote:
> The DualSense lightbar has so far been supported, but it was not yet
> adjustable from user space. This patch exposes it through a multi-color
> LED.
> 
> Signed-off-by: Roderick Colenbrander <roderick.colenbrander@sony.com>

Ack.

									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 2/3] leds: add new LED_FUNCTION_PLAYER for player LEDs for game controllers.
  2021-09-01 22:30 ` [PATCH v2 2/3] leds: add new LED_FUNCTION_PLAYER for player LEDs for game controllers Roderick Colenbrander
@ 2021-09-03 16:17   ` Pavel Machek
  2021-09-08 10:23     ` Jiri Kosina
  0 siblings, 1 reply; 9+ messages in thread
From: Pavel Machek @ 2021-09-03 16:17 UTC (permalink / raw)
  To: Roderick Colenbrander
  Cc: Jiri Kosina, Benjamin Tissoires, linux-input, linux-leds,
	Daniel J . Ogorchock, Roderick Colenbrander

Hi!

> Player LEDs are commonly found on game controllers from Nintendo and Sony
> to indicate a player ID across a number of LEDs. For example, "Player 2"
> might be indicated as "-x--" on a device with 4 LEDs where "x" means on.
> 
> This patch introduces a new LED_FUNCTION_PLAYER to properly indicate
> player LEDs from the kernel. Until now there was no good standard, which
> resulted in inconsistent behavior across xpad, hid-sony, hid-wiimote and
> other drivers. Moving forward new drivers should use LED_FUNCTION_PLAYER.
> 
> Note: management of Player IDs is left to user space, though a kernel
> driver may pick a default value.
> 
> Signed-off-by: Roderick Colenbrander <roderick.colenbrander@sony.com>
> ---
>  Documentation/leds/well-known-leds.txt | 14 ++++++++++++++
>  include/dt-bindings/leds/common.h      |  3 +++
>  2 files changed, 17 insertions(+)
> 
> diff --git a/Documentation/leds/well-known-leds.txt b/Documentation/leds/well-known-leds.txt
> index 4a8b9dc4bf52..2160382c86be 100644
> --- a/Documentation/leds/well-known-leds.txt
> +++ b/Documentation/leds/well-known-leds.txt
> @@ -16,6 +16,20 @@ but then try the legacy ones, too.
>  
>  Notice there's a list of functions in include/dt-bindings/leds/common.h .
>  
> +* Gamepads and joysticks
> +
> +Game controllers may feature LEDs to indicate a player number. This is commonly
> +used on game consoles in which multiple controllers can be connected to a system.
> +The "player LEDs" are then programmed with a pattern to indicate a particular
> +player. For example, a game controller with 4 LEDs, may be programmed with "x---"
> +to indicate player 1, "-x--" to indicate player 2 etcetera where "x" means on.
> +Input drivers can utilize the LED class to expose the individual player LEDs
> +of a game controller using the function "player".

Thank you.

> +Note: tracking and management of Player IDs is the responsibility of user space,
> +though drivers may pick a default value.

I'm not sure we want kernel to do that.

> +Good: "input*:*:player-{1,2,3,4,5}

This goes to the top.

> +++ b/include/dt-bindings/leds/common.h
> @@ -60,6 +60,9 @@
>  #define LED_FUNCTION_MICMUTE "micmute"
>  #define LED_FUNCTION_MUTE "mute"
>  
> +/* Used for player LEDs as found on game controllers from e.g. Nintendo, Sony. */
> +#define LED_FUNCTION_PLAYER "player"
> +

Let's not add this. For consistency we'd need defines player-1, player-2, ... We don't
need the define at all.

I guess this should go through my tree?

Best regards,
									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 3/3] HID: playstation: expose DualSense player LEDs through LED class.
  2021-09-01 22:30 ` [PATCH v2 3/3] HID: playstation: expose DualSense player LEDs through LED class Roderick Colenbrander
@ 2021-09-03 16:17   ` Pavel Machek
  2021-09-07  5:28     ` Roderick Colenbrander
  0 siblings, 1 reply; 9+ messages in thread
From: Pavel Machek @ 2021-09-03 16:17 UTC (permalink / raw)
  To: Roderick Colenbrander
  Cc: Jiri Kosina, Benjamin Tissoires, linux-input, linux-leds,
	Daniel J . Ogorchock, Roderick Colenbrander

Hi!

> The DualSense player LEDs were so far not adjustable from user-space.
> This patch exposes each LED individually through the LED class. Each
> LED uses the new 'player' function resulting in a name like:
> 'inputX:white:player-1' for the first LED.
> 
>  
> +struct ps_led_info {
...
> +	enum led_brightness (*brightness_get)(struct led_classdev *cdev);
> +	void (*brightness_set)(struct led_classdev *cdev, enum led_brightness);
> +};

Do you need these fields? They are constant in the driver...

> +static enum led_brightness dualsense_player_led_get_brightness(struct led_classdev *led)
> +{
> +	struct hid_device *hdev = to_hid_device(led->dev->parent);
> +	struct dualsense *ds = hid_get_drvdata(hdev);
> +
> +	return !!(ds->player_leds_state & BIT(led - ds->player_leds));
> +}

You should not need to implement get if all it does is returning cached state.

> +static void dualsense_player_led_set_brightness(struct led_classdev *led, enum led_brightness value)
> +{
> +	struct hid_device *hdev = to_hid_device(led->dev->parent);
> +	struct dualsense *ds = hid_get_drvdata(hdev);
> +	unsigned long flags;
> +	unsigned int led_index;
> +
> +	spin_lock_irqsave(&ds->base.lock, flags);
> +
> +	led_index = led - ds->player_leds;
> +	if (value == LED_OFF)
> +		ds->player_leds_state &= ~BIT(led_index);
> +	else
> +		ds->player_leds_state |= BIT(led_index);
> +
> +	ds->update_player_leds = true;
> +	spin_unlock_irqrestore(&ds->base.lock, flags);
> +
> +	schedule_work(&ds->output_worker);
> +}

LED core can handle scheduling the work for you. You should use it, in similar
way you handle the RGB led.

Best regards,
									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 3/3] HID: playstation: expose DualSense player LEDs through LED class.
  2021-09-03 16:17   ` Pavel Machek
@ 2021-09-07  5:28     ` Roderick Colenbrander
  0 siblings, 0 replies; 9+ messages in thread
From: Roderick Colenbrander @ 2021-09-07  5:28 UTC (permalink / raw)
  To: Pavel Machek
  Cc: Roderick Colenbrander, Jiri Kosina, Benjamin Tissoires,
	linux-input, linux-leds, Daniel J . Ogorchock,
	Roderick Colenbrander

Hi Pavel,

On Fri, Sep 3, 2021 at 9:25 AM Pavel Machek <pavel@ucw.cz> wrote:
>
> Hi!
>
> > The DualSense player LEDs were so far not adjustable from user-space.
> > This patch exposes each LED individually through the LED class. Each
> > LED uses the new 'player' function resulting in a name like:
> > 'inputX:white:player-1' for the first LED.
> >
> >
> > +struct ps_led_info {
> ...
> > +     enum led_brightness (*brightness_get)(struct led_classdev *cdev);
> > +     void (*brightness_set)(struct led_classdev *cdev, enum led_brightness);
> > +};
>
> Do you need these fields? They are constant in the driver...

Currently they are constant, but over time support for some other
devices (e.g. DualShock 4) will be moved into this driver as well and
then these are needed.

>
> > +static enum led_brightness dualsense_player_led_get_brightness(struct led_classdev *led)
> > +{
> > +     struct hid_device *hdev = to_hid_device(led->dev->parent);
> > +     struct dualsense *ds = hid_get_drvdata(hdev);
> > +
> > +     return !!(ds->player_leds_state & BIT(led - ds->player_leds));
> > +}
>
> You should not need to implement get if all it does is returning cached state.

The player LEDs are configured at driver loading time with an initial
value by calling 'dualsense_set_player_leds'. This is done behind the
back of the LED framework, so it is driver internal state. The problem
is that we need to set multiple LEDs at once at driver startup and
they share a common HID output report. The LED framework has no 'group
LED support' (outside the new multicolor class), so there is no way to
really synchronize multiple LEDs right now.

> > +static void dualsense_player_led_set_brightness(struct led_classdev *led, enum led_brightness value)
> > +{
> > +     struct hid_device *hdev = to_hid_device(led->dev->parent);
> > +     struct dualsense *ds = hid_get_drvdata(hdev);
> > +     unsigned long flags;
> > +     unsigned int led_index;
> > +
> > +     spin_lock_irqsave(&ds->base.lock, flags);
> > +
> > +     led_index = led - ds->player_leds;
> > +     if (value == LED_OFF)
> > +             ds->player_leds_state &= ~BIT(led_index);
> > +     else
> > +             ds->player_leds_state |= BIT(led_index);
> > +
> > +     ds->update_player_leds = true;
> > +     spin_unlock_irqrestore(&ds->base.lock, flags);
> > +
> > +     schedule_work(&ds->output_worker);
> > +}
>
> LED core can handle scheduling the work for you. You should use it, in similar
> way you handle the RGB led.

I'm not entirely sure what you meant. I guess you mean I should use
'cdev->brightness_set_blocking' instead of 'cdev->brightness_set' when
setting up the LED, so LED core can do more things itself? That's the
main difference I saw between my RGB and regular LED code. Both rely
on updating the internal dualsense structure and calling schedule_work
to schedule a HID output report (the output report contains data for
many things outside of just the LEDs). Is that indeed what you meant
or did I miss something (it is getting late here)?

>
> Best regards,
>                                                                         Pavel
> --
> (english) http://www.livejournal.com/~pavelmachek
> (cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

Regards,
Roderick

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 2/3] leds: add new LED_FUNCTION_PLAYER for player LEDs for game controllers.
  2021-09-03 16:17   ` Pavel Machek
@ 2021-09-08 10:23     ` Jiri Kosina
  0 siblings, 0 replies; 9+ messages in thread
From: Jiri Kosina @ 2021-09-08 10:23 UTC (permalink / raw)
  To: Pavel Machek
  Cc: Roderick Colenbrander, Benjamin Tissoires, linux-input,
	linux-leds, Daniel J . Ogorchock, Roderick Colenbrander

On Fri, 3 Sep 2021, Pavel Machek wrote:

> > Player LEDs are commonly found on game controllers from Nintendo and Sony
> > to indicate a player ID across a number of LEDs. For example, "Player 2"
> > might be indicated as "-x--" on a device with 4 LEDs where "x" means on.
> > 
> > This patch introduces a new LED_FUNCTION_PLAYER to properly indicate
> > player LEDs from the kernel. Until now there was no good standard, which
> > resulted in inconsistent behavior across xpad, hid-sony, hid-wiimote and
> > other drivers. Moving forward new drivers should use LED_FUNCTION_PLAYER.
> > 
> > Note: management of Player IDs is left to user space, though a kernel
> > driver may pick a default value.
> > 
> > Signed-off-by: Roderick Colenbrander <roderick.colenbrander@sony.com>
> > ---
> >  Documentation/leds/well-known-leds.txt | 14 ++++++++++++++
> >  include/dt-bindings/leds/common.h      |  3 +++
> >  2 files changed, 17 insertions(+)
> > 
> > diff --git a/Documentation/leds/well-known-leds.txt b/Documentation/leds/well-known-leds.txt
> > index 4a8b9dc4bf52..2160382c86be 100644
> > --- a/Documentation/leds/well-known-leds.txt
> > +++ b/Documentation/leds/well-known-leds.txt
> > @@ -16,6 +16,20 @@ but then try the legacy ones, too.
> >  
> >  Notice there's a list of functions in include/dt-bindings/leds/common.h .
> >  
> > +* Gamepads and joysticks
> > +
> > +Game controllers may feature LEDs to indicate a player number. This is commonly
> > +used on game consoles in which multiple controllers can be connected to a system.
> > +The "player LEDs" are then programmed with a pattern to indicate a particular
> > +player. For example, a game controller with 4 LEDs, may be programmed with "x---"
> > +to indicate player 1, "-x--" to indicate player 2 etcetera where "x" means on.
> > +Input drivers can utilize the LED class to expose the individual player LEDs
> > +of a game controller using the function "player".
> 
> Thank you.
> 
> > +Note: tracking and management of Player IDs is the responsibility of user space,
> > +though drivers may pick a default value.
> 
> I'm not sure we want kernel to do that.
> 
> > +Good: "input*:*:player-{1,2,3,4,5}
> 
> This goes to the top.
> 
> > +++ b/include/dt-bindings/leds/common.h
> > @@ -60,6 +60,9 @@
> >  #define LED_FUNCTION_MICMUTE "micmute"
> >  #define LED_FUNCTION_MUTE "mute"
> >  
> > +/* Used for player LEDs as found on game controllers from e.g. Nintendo, Sony. */
> > +#define LED_FUNCTION_PLAYER "player"
> > +
> 
> Let's not add this. For consistency we'd need defines player-1, player-2, ... We don't
> need the define at all.
> 
> I guess this should go through my tree?

Once you provide your Reviewed/Acked-by, I can take it through my tree 
with the rest of the series.

Thanks,

-- 
Jiri Kosina
SUSE Labs


^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2021-09-08 10:23 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-09-01 22:30 [PATCH v2 0/3] HID: playstation: add LED support Roderick Colenbrander
2021-09-01 22:30 ` [PATCH v2 1/3] HID: playstation: expose DualSense lightbar through a multi-color LED Roderick Colenbrander
2021-09-03 16:16   ` Pavel Machek
2021-09-01 22:30 ` [PATCH v2 2/3] leds: add new LED_FUNCTION_PLAYER for player LEDs for game controllers Roderick Colenbrander
2021-09-03 16:17   ` Pavel Machek
2021-09-08 10:23     ` Jiri Kosina
2021-09-01 22:30 ` [PATCH v2 3/3] HID: playstation: expose DualSense player LEDs through LED class Roderick Colenbrander
2021-09-03 16:17   ` Pavel Machek
2021-09-07  5:28     ` Roderick Colenbrander

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.