Commit 5307de63 authored by Martino Fontana's avatar Martino Fontana Committed by Jiri Kosina

HID: nintendo: use ida for LED player id

Previously, the leds pattern would just increment with every controller
connected. This wouldn't take into consideration when controllers are
disconnected. The same controller could be connected and disconnected
with the pattern increasing player count each time.

This patch changes it by using an ID allocator in order to assign the
player id, the same way hid-playstation does.
Signed-off-by: default avatarMartino Fontana <tinozzo123@gmail.com>
Signed-off-by: default avatarRyan McClelland <rymcclel@gmail.com>
Signed-off-by: default avatarJiri Kosina <jkosina@suse.com>
parent 3e78a6c0
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#include <linux/device.h> #include <linux/device.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/hid.h> #include <linux/hid.h>
#include <linux/idr.h>
#include <linux/input.h> #include <linux/input.h>
#include <linux/jiffies.h> #include <linux/jiffies.h>
#include <linux/leds.h> #include <linux/leds.h>
...@@ -569,6 +570,7 @@ static const enum led_brightness joycon_player_led_patterns[JC_NUM_LED_PATTERNS] ...@@ -569,6 +570,7 @@ static const enum led_brightness joycon_player_led_patterns[JC_NUM_LED_PATTERNS]
struct joycon_ctlr { struct joycon_ctlr {
struct hid_device *hdev; struct hid_device *hdev;
struct input_dev *input; struct input_dev *input;
u32 player_id;
struct led_classdev leds[JC_NUM_LEDS]; /* player leds */ struct led_classdev leds[JC_NUM_LEDS]; /* player leds */
struct led_classdev home_led; struct led_classdev home_led;
enum joycon_ctlr_state ctlr_state; enum joycon_ctlr_state ctlr_state;
...@@ -2261,7 +2263,8 @@ static int joycon_home_led_brightness_set(struct led_classdev *led, ...@@ -2261,7 +2263,8 @@ static int joycon_home_led_brightness_set(struct led_classdev *led,
return ret; return ret;
} }
static DEFINE_SPINLOCK(joycon_input_num_spinlock); static DEFINE_IDA(nintendo_player_id_allocator);
static int joycon_leds_create(struct joycon_ctlr *ctlr) static int joycon_leds_create(struct joycon_ctlr *ctlr)
{ {
struct hid_device *hdev = ctlr->hdev; struct hid_device *hdev = ctlr->hdev;
...@@ -2272,20 +2275,19 @@ static int joycon_leds_create(struct joycon_ctlr *ctlr) ...@@ -2272,20 +2275,19 @@ static int joycon_leds_create(struct joycon_ctlr *ctlr)
char *name; char *name;
int ret; int ret;
int i; int i;
unsigned long flags;
int player_led_pattern; int player_led_pattern;
static int input_num;
/*
* Set the player leds based on controller number
* Because there is no standard concept of "player number", the pattern
* number will simply increase by 1 every time a controller is connected.
*/
spin_lock_irqsave(&joycon_input_num_spinlock, flags);
player_led_pattern = input_num++ % JC_NUM_LED_PATTERNS;
spin_unlock_irqrestore(&joycon_input_num_spinlock, flags);
/* configure the player LEDs */ /* configure the player LEDs */
ctlr->player_id = U32_MAX;
ret = ida_alloc(&nintendo_player_id_allocator, GFP_KERNEL);
if (ret < 0) {
hid_warn(hdev, "Failed to allocate player ID, skipping; ret=%d\n", ret);
goto home_led;
}
ctlr->player_id = ret;
player_led_pattern = ret % JC_NUM_LED_PATTERNS;
hid_info(ctlr->hdev, "assigned player %d led pattern", player_led_pattern + 1);
for (i = 0; i < JC_NUM_LEDS; i++) { for (i = 0; i < JC_NUM_LEDS; i++) {
name = devm_kasprintf(dev, GFP_KERNEL, "%s:%s:%s", name = devm_kasprintf(dev, GFP_KERNEL, "%s:%s:%s",
d_name, d_name,
...@@ -2767,6 +2769,7 @@ static void nintendo_hid_remove(struct hid_device *hdev) ...@@ -2767,6 +2769,7 @@ static void nintendo_hid_remove(struct hid_device *hdev)
spin_unlock_irqrestore(&ctlr->lock, flags); spin_unlock_irqrestore(&ctlr->lock, flags);
destroy_workqueue(ctlr->rumble_queue); destroy_workqueue(ctlr->rumble_queue);
ida_free(&nintendo_player_id_allocator, ctlr->player_id);
hid_hw_close(hdev); hid_hw_close(hdev);
hid_hw_stop(hdev); hid_hw_stop(hdev);
...@@ -2824,7 +2827,19 @@ static struct hid_driver nintendo_hid_driver = { ...@@ -2824,7 +2827,19 @@ static struct hid_driver nintendo_hid_driver = {
.resume = nintendo_hid_resume, .resume = nintendo_hid_resume,
#endif #endif
}; };
module_hid_driver(nintendo_hid_driver); static int __init nintendo_init(void)
{
return hid_register_driver(&nintendo_hid_driver);
}
static void __exit nintendo_exit(void)
{
hid_unregister_driver(&nintendo_hid_driver);
ida_destroy(&nintendo_player_id_allocator);
}
module_init(nintendo_init);
module_exit(nintendo_exit);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_AUTHOR("Ryan McClelland <rymcclel@gmail.com>"); MODULE_AUTHOR("Ryan McClelland <rymcclel@gmail.com>");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment