* [PATCH v2 RESEND] HID: nintendo: cleanup LED code
@ 2023-09-06 10:26 Martino Fontana
2023-09-06 13:48 ` kernel test robot
0 siblings, 1 reply; 2+ messages in thread
From: Martino Fontana @ 2023-09-06 10:26 UTC (permalink / raw)
To: djogorchock, jikos, benjamin.tissoires, linux-input, linux-kernel
Cc: Martino Fontana
- Only turn on the nth LED, instead of all the LEDs up to n. This better
matches Nintendo consoles' behaviour, as they never turn on more than
one LED.
(Note that the behavior still consinsts in increasing the player number
every time a controller is connected, never decreasing it. It should be
as is described in https://bugzilla.kernel.org/show_bug.cgi?id=216225.
However, any implementation here would stop making sense as soon as a
non-Nintendo controller is connected, which is why I'm not bothering.)
- Split part of `joycon_home_led_brightness_set` (which is called by hid)
into `joycon_set_home_led` (which is what actually sets the LEDs), for
consistency with player LEDs.
- `joycon_player_led_brightness_set` won't try it to "determine which player
led this is" anymore: it's already looking at every LED brightness value.
- Instead of first registering the `led_classdev`, then attempting to set
the LED and unregistering the `led_classdev` if it fails, first attempt
to set the LED, then register the `led_classdev` only if it succeeds
(the class is still filled up in either case).
- If setting the player LEDs fails, still attempt setting the home LED.
(I don't know there's a third party controller where this may actually
happen, but who knows...)
- Use `JC_NUM_LEDS` where appropriate instead of 4.
- Print return codes in more places.
- Use spinlock instead of mutex for `input_num`. Copy its value to a local
variable, so that it can be unlocked immediately.
- `input_num` starts counting from 0
- Less holding of mutexes in general.
Changes for v2:
Applied suggestions, commit message explains more stuff, restored `return ret`
when `devm_led_classdev_register` fails (since all other hid drivers do this).
If setting LED fails, `hid_warn` now explicitly says "skipping registration".
Signed-off-by: Martino Fontana <tinozzo123@gmail.com>
---
drivers/hid/hid-nintendo.c | 117 ++++++++++++++++++-------------------
1 file changed, 57 insertions(+), 60 deletions(-)
diff --git a/drivers/hid/hid-nintendo.c b/drivers/hid/hid-nintendo.c
index a5ebe857a..dd7c7fce3 100644
--- a/drivers/hid/hid-nintendo.c
+++ b/drivers/hid/hid-nintendo.c
@@ -699,6 +699,25 @@ static int joycon_set_player_leds(struct joycon_ctlr *ctlr, u8 flash, u8 on)
return joycon_send_subcmd(ctlr, req, 1, HZ/4);
}
+static int joycon_set_home_led(struct joycon_ctlr *ctlr, enum led_brightness brightness)
+{
+ struct joycon_subcmd_request *req;
+ u8 buffer[sizeof(*req) + 5] = { 0 };
+ u8 *data;
+
+ req = (struct joycon_subcmd_request *)buffer;
+ req->subcmd_id = JC_SUBCMD_SET_HOME_LIGHT;
+ data = req->data;
+ data[0] = 0x01;
+ data[1] = brightness << 4;
+ data[2] = brightness | (brightness << 4);
+ data[3] = 0x11;
+ data[4] = 0x11;
+
+ hid_dbg(ctlr->hdev, "setting home led brightness\n");
+ return joycon_send_subcmd(ctlr, req, 5, HZ/4);
+}
+
static int joycon_request_spi_flash_read(struct joycon_ctlr *ctlr,
u32 start_addr, u8 size, u8 **reply)
{
@@ -1849,7 +1868,6 @@ static int joycon_player_led_brightness_set(struct led_classdev *led,
int val = 0;
int i;
int ret;
- int num;
ctlr = hid_get_drvdata(hdev);
if (!ctlr) {
@@ -1857,21 +1875,10 @@ static int joycon_player_led_brightness_set(struct led_classdev *led,
return -ENODEV;
}
- /* determine which player led this is */
- for (num = 0; num < JC_NUM_LEDS; num++) {
- if (&ctlr->leds[num] == led)
- break;
- }
- if (num >= JC_NUM_LEDS)
- return -EINVAL;
+ for (i = 0; i < JC_NUM_LEDS; i++)
+ val |= ctlr->leds[i].brightness << i;
mutex_lock(&ctlr->output_mutex);
- for (i = 0; i < JC_NUM_LEDS; i++) {
- if (i == num)
- val |= brightness << i;
- else
- val |= ctlr->leds[i].brightness << i;
- }
ret = joycon_set_player_leds(ctlr, 0, val);
mutex_unlock(&ctlr->output_mutex);
@@ -1884,9 +1891,6 @@ static int joycon_home_led_brightness_set(struct led_classdev *led,
struct device *dev = led->dev->parent;
struct hid_device *hdev = to_hid_device(dev);
struct joycon_ctlr *ctlr;
- struct joycon_subcmd_request *req;
- u8 buffer[sizeof(*req) + 5] = { 0 };
- u8 *data;
int ret;
ctlr = hid_get_drvdata(hdev);
@@ -1894,25 +1898,13 @@ static int joycon_home_led_brightness_set(struct led_classdev *led,
hid_err(hdev, "No controller data\n");
return -ENODEV;
}
-
- req = (struct joycon_subcmd_request *)buffer;
- req->subcmd_id = JC_SUBCMD_SET_HOME_LIGHT;
- data = req->data;
- data[0] = 0x01;
- data[1] = brightness << 4;
- data[2] = brightness | (brightness << 4);
- data[3] = 0x11;
- data[4] = 0x11;
-
- hid_dbg(hdev, "setting home led brightness\n");
mutex_lock(&ctlr->output_mutex);
- ret = joycon_send_subcmd(ctlr, req, 5, HZ/4);
+ ret = joycon_set_home_led(ctlr, brightness);
mutex_unlock(&ctlr->output_mutex);
-
return ret;
}
-static DEFINE_MUTEX(joycon_input_num_mutex);
+static DEFINE_SPINLOCK(joycon_input_num_spinlock);
static int joycon_leds_create(struct joycon_ctlr *ctlr)
{
struct hid_device *hdev = ctlr->hdev;
@@ -1920,17 +1912,16 @@ static int joycon_leds_create(struct joycon_ctlr *ctlr)
const char *d_name = dev_name(dev);
struct led_classdev *led;
char *name;
- int ret = 0;
+ int ret;
int i;
- static int input_num = 1;
+ unsigned long flags;
+ int player_led_number;
+ static int input_num;
- /* Set the default controller player leds based on controller number */
- mutex_lock(&joycon_input_num_mutex);
- mutex_lock(&ctlr->output_mutex);
- ret = joycon_set_player_leds(ctlr, 0, 0xF >> (4 - input_num));
- if (ret)
- hid_warn(ctlr->hdev, "Failed to set leds; ret=%d\n", ret);
- mutex_unlock(&ctlr->output_mutex);
+ /* Set the player leds based on controller number */
+ spin_lock_irqsave(&joycon_input_num_spinlock, flags);
+ player_led_number = input_num++ % JC_NUM_LEDS;
+ spin_unlock_irqrestore(&joycon_input_num_spinlock, flags);
/* configure the player LEDs */
for (i = 0; i < JC_NUM_LEDS; i++) {
@@ -1938,31 +1929,34 @@ static int joycon_leds_create(struct joycon_ctlr *ctlr)
d_name,
"green",
joycon_player_led_names[i]);
- if (!name) {
- mutex_unlock(&joycon_input_num_mutex);
+ if (!name)
return -ENOMEM;
- }
led = &ctlr->leds[i];
led->name = name;
- led->brightness = ((i + 1) <= input_num) ? 1 : 0;
+ led->brightness = (i == player_led_number) ? 1 : 0;
led->max_brightness = 1;
led->brightness_set_blocking =
joycon_player_led_brightness_set;
led->flags = LED_CORE_SUSPENDRESUME | LED_HW_PLUGGABLE;
+ }
+ mutex_lock(&ctlr->output_mutex);
+ ret = joycon_set_player_leds(ctlr, 0, 0x1 << player_led_number);
+ mutex_unlock(&ctlr->output_mutex);
+ if (ret) {
+ hid_warn(hdev, "Failed to set players LEDs, skipping registration; ret=%d\n", ret);
+ goto home_led;
+ }
+ for (i = 0; i < JC_NUM_LEDS; i++) {
+ led = &ctlr->leds[i];
ret = devm_led_classdev_register(&hdev->dev, led);
- if (ret) {
- hid_err(hdev, "Failed registering %s LED\n", led->name);
- mutex_unlock(&joycon_input_num_mutex);
+ if (ret)
+ hid_err(hdev, "Failed to register player %d LED; ret=%d\n", i + 1, ret);
return ret;
- }
}
- if (++input_num > 4)
- input_num = 1;
- mutex_unlock(&joycon_input_num_mutex);
-
+home_led:
/* configure the home LED */
if (jc_type_has_right(ctlr)) {
name = devm_kasprintf(dev, GFP_KERNEL, "%s:%s:%s",
@@ -1978,17 +1972,20 @@ static int joycon_leds_create(struct joycon_ctlr *ctlr)
led->max_brightness = 0xF;
led->brightness_set_blocking = joycon_home_led_brightness_set;
led->flags = LED_CORE_SUSPENDRESUME | LED_HW_PLUGGABLE;
- ret = devm_led_classdev_register(&hdev->dev, led);
- if (ret) {
- hid_err(hdev, "Failed registering home led\n");
- return ret;
- }
+
/* Set the home LED to 0 as default state */
- ret = joycon_home_led_brightness_set(led, 0);
+ mutex_lock(&ctlr->output_mutex);
+ ret = joycon_set_home_led(ctlr, 0);
+ mutex_unlock(&ctlr->output_mutex);
if (ret) {
- hid_warn(hdev, "Failed to set home LED default, unregistering home LED");
- devm_led_classdev_unregister(&hdev->dev, led);
+ hid_warn(hdev, "Failed to set home LED, skipping registration; ret=%d\n", ret);
+ return 0;
}
+
+ ret = devm_led_classdev_register(&hdev->dev, led);
+ if (ret)
+ hid_err(hdev, "Failed to register home LED; ret=%d\n", ret);
+ return ret
}
return 0;
--
2.41.0
^ permalink raw reply related [flat|nested] 2+ messages in thread* Re: [PATCH v2 RESEND] HID: nintendo: cleanup LED code
2023-09-06 10:26 [PATCH v2 RESEND] HID: nintendo: cleanup LED code Martino Fontana
@ 2023-09-06 13:48 ` kernel test robot
0 siblings, 0 replies; 2+ messages in thread
From: kernel test robot @ 2023-09-06 13:48 UTC (permalink / raw)
To: Martino Fontana, djogorchock, jikos, benjamin.tissoires,
linux-input, linux-kernel
Cc: oe-kbuild-all, Martino Fontana
Hi Martino,
kernel test robot noticed the following build errors:
[auto build test ERROR on hid/for-next]
[also build test ERROR on linus/master v6.5 next-20230906]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Martino-Fontana/HID-nintendo-cleanup-LED-code/20230906-183111
base: https://git.kernel.org/pub/scm/linux/kernel/git/hid/hid.git for-next
patch link: https://lore.kernel.org/r/20230906102831.16734-2-tinozzo123%40gmail.com
patch subject: [PATCH v2 RESEND] HID: nintendo: cleanup LED code
config: parisc-randconfig-r011-20230906 (https://download.01.org/0day-ci/archive/20230906/202309062140.CiSKWeEO-lkp@intel.com/config)
compiler: hppa-linux-gcc (GCC) 13.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20230906/202309062140.CiSKWeEO-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202309062140.CiSKWeEO-lkp@intel.com/
All error/warnings (new ones prefixed by >>):
drivers/hid/hid-nintendo.c: In function 'joycon_leds_create':
>> drivers/hid/hid-nintendo.c:1954:17: warning: this 'if' clause does not guard... [-Wmisleading-indentation]
1954 | if (ret)
| ^~
drivers/hid/hid-nintendo.c:1956:25: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'if'
1956 | return ret;
| ^~~~~~
drivers/hid/hid-nintendo.c:1986:17: warning: this 'if' clause does not guard... [-Wmisleading-indentation]
1986 | if (ret)
| ^~
drivers/hid/hid-nintendo.c:1988:25: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'if'
1988 | return ret
| ^~~~~~
>> drivers/hid/hid-nintendo.c:1988:35: error: expected ';' before '}' token
1988 | return ret
| ^
| ;
1989 | }
| ~
vim +1988 drivers/hid/hid-nintendo.c
1906
1907 static DEFINE_SPINLOCK(joycon_input_num_spinlock);
1908 static int joycon_leds_create(struct joycon_ctlr *ctlr)
1909 {
1910 struct hid_device *hdev = ctlr->hdev;
1911 struct device *dev = &hdev->dev;
1912 const char *d_name = dev_name(dev);
1913 struct led_classdev *led;
1914 char *name;
1915 int ret;
1916 int i;
1917 unsigned long flags;
1918 int player_led_number;
1919 static int input_num;
1920
1921 /* Set the player leds based on controller number */
1922 spin_lock_irqsave(&joycon_input_num_spinlock, flags);
1923 player_led_number = input_num++ % JC_NUM_LEDS;
1924 spin_unlock_irqrestore(&joycon_input_num_spinlock, flags);
1925
1926 /* configure the player LEDs */
1927 for (i = 0; i < JC_NUM_LEDS; i++) {
1928 name = devm_kasprintf(dev, GFP_KERNEL, "%s:%s:%s",
1929 d_name,
1930 "green",
1931 joycon_player_led_names[i]);
1932 if (!name)
1933 return -ENOMEM;
1934
1935 led = &ctlr->leds[i];
1936 led->name = name;
1937 led->brightness = (i == player_led_number) ? 1 : 0;
1938 led->max_brightness = 1;
1939 led->brightness_set_blocking =
1940 joycon_player_led_brightness_set;
1941 led->flags = LED_CORE_SUSPENDRESUME | LED_HW_PLUGGABLE;
1942 }
1943 mutex_lock(&ctlr->output_mutex);
1944 ret = joycon_set_player_leds(ctlr, 0, 0x1 << player_led_number);
1945 mutex_unlock(&ctlr->output_mutex);
1946 if (ret) {
1947 hid_warn(hdev, "Failed to set players LEDs, skipping registration; ret=%d\n", ret);
1948 goto home_led;
1949 }
1950
1951 for (i = 0; i < JC_NUM_LEDS; i++) {
1952 led = &ctlr->leds[i];
1953 ret = devm_led_classdev_register(&hdev->dev, led);
> 1954 if (ret)
1955 hid_err(hdev, "Failed to register player %d LED; ret=%d\n", i + 1, ret);
> 1956 return ret;
1957 }
1958
1959 home_led:
1960 /* configure the home LED */
1961 if (jc_type_has_right(ctlr)) {
1962 name = devm_kasprintf(dev, GFP_KERNEL, "%s:%s:%s",
1963 d_name,
1964 "blue",
1965 LED_FUNCTION_PLAYER5);
1966 if (!name)
1967 return -ENOMEM;
1968
1969 led = &ctlr->home_led;
1970 led->name = name;
1971 led->brightness = 0;
1972 led->max_brightness = 0xF;
1973 led->brightness_set_blocking = joycon_home_led_brightness_set;
1974 led->flags = LED_CORE_SUSPENDRESUME | LED_HW_PLUGGABLE;
1975
1976 /* Set the home LED to 0 as default state */
1977 mutex_lock(&ctlr->output_mutex);
1978 ret = joycon_set_home_led(ctlr, 0);
1979 mutex_unlock(&ctlr->output_mutex);
1980 if (ret) {
1981 hid_warn(hdev, "Failed to set home LED, skipping registration; ret=%d\n", ret);
1982 return 0;
1983 }
1984
1985 ret = devm_led_classdev_register(&hdev->dev, led);
1986 if (ret)
1987 hid_err(hdev, "Failed to register home LED; ret=%d\n", ret);
> 1988 return ret
1989 }
1990
1991 return 0;
1992 }
1993
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2023-09-06 13:49 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-09-06 10:26 [PATCH v2 RESEND] HID: nintendo: cleanup LED code Martino Fontana
2023-09-06 13:48 ` kernel test robot
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox