Skip to content

Commit 5307de6

Browse files
SuperSamusJiri Kosina
authored andcommitted
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: Martino Fontana <[email protected]> Signed-off-by: Ryan McClelland <[email protected]> Signed-off-by: Jiri Kosina <[email protected]>
1 parent 3e78a6c commit 5307de6

File tree

1 file changed

+28
-13
lines changed

1 file changed

+28
-13
lines changed

drivers/hid/hid-nintendo.c

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include <linux/device.h>
3535
#include <linux/kernel.h>
3636
#include <linux/hid.h>
37+
#include <linux/idr.h>
3738
#include <linux/input.h>
3839
#include <linux/jiffies.h>
3940
#include <linux/leds.h>
@@ -569,6 +570,7 @@ static const enum led_brightness joycon_player_led_patterns[JC_NUM_LED_PATTERNS]
569570
struct joycon_ctlr {
570571
struct hid_device *hdev;
571572
struct input_dev *input;
573+
u32 player_id;
572574
struct led_classdev leds[JC_NUM_LEDS]; /* player leds */
573575
struct led_classdev home_led;
574576
enum joycon_ctlr_state ctlr_state;
@@ -2261,7 +2263,8 @@ static int joycon_home_led_brightness_set(struct led_classdev *led,
22612263
return ret;
22622264
}
22632265

2264-
static DEFINE_SPINLOCK(joycon_input_num_spinlock);
2266+
static DEFINE_IDA(nintendo_player_id_allocator);
2267+
22652268
static int joycon_leds_create(struct joycon_ctlr *ctlr)
22662269
{
22672270
struct hid_device *hdev = ctlr->hdev;
@@ -2272,20 +2275,19 @@ static int joycon_leds_create(struct joycon_ctlr *ctlr)
22722275
char *name;
22732276
int ret;
22742277
int i;
2275-
unsigned long flags;
22762278
int player_led_pattern;
2277-
static int input_num;
2278-
2279-
/*
2280-
* Set the player leds based on controller number
2281-
* Because there is no standard concept of "player number", the pattern
2282-
* number will simply increase by 1 every time a controller is connected.
2283-
*/
2284-
spin_lock_irqsave(&joycon_input_num_spinlock, flags);
2285-
player_led_pattern = input_num++ % JC_NUM_LED_PATTERNS;
2286-
spin_unlock_irqrestore(&joycon_input_num_spinlock, flags);
22872279

22882280
/* configure the player LEDs */
2281+
ctlr->player_id = U32_MAX;
2282+
ret = ida_alloc(&nintendo_player_id_allocator, GFP_KERNEL);
2283+
if (ret < 0) {
2284+
hid_warn(hdev, "Failed to allocate player ID, skipping; ret=%d\n", ret);
2285+
goto home_led;
2286+
}
2287+
ctlr->player_id = ret;
2288+
player_led_pattern = ret % JC_NUM_LED_PATTERNS;
2289+
hid_info(ctlr->hdev, "assigned player %d led pattern", player_led_pattern + 1);
2290+
22892291
for (i = 0; i < JC_NUM_LEDS; i++) {
22902292
name = devm_kasprintf(dev, GFP_KERNEL, "%s:%s:%s",
22912293
d_name,
@@ -2767,6 +2769,7 @@ static void nintendo_hid_remove(struct hid_device *hdev)
27672769
spin_unlock_irqrestore(&ctlr->lock, flags);
27682770

27692771
destroy_workqueue(ctlr->rumble_queue);
2772+
ida_free(&nintendo_player_id_allocator, ctlr->player_id);
27702773

27712774
hid_hw_close(hdev);
27722775
hid_hw_stop(hdev);
@@ -2824,7 +2827,19 @@ static struct hid_driver nintendo_hid_driver = {
28242827
.resume = nintendo_hid_resume,
28252828
#endif
28262829
};
2827-
module_hid_driver(nintendo_hid_driver);
2830+
static int __init nintendo_init(void)
2831+
{
2832+
return hid_register_driver(&nintendo_hid_driver);
2833+
}
2834+
2835+
static void __exit nintendo_exit(void)
2836+
{
2837+
hid_unregister_driver(&nintendo_hid_driver);
2838+
ida_destroy(&nintendo_player_id_allocator);
2839+
}
2840+
2841+
module_init(nintendo_init);
2842+
module_exit(nintendo_exit);
28282843

28292844
MODULE_LICENSE("GPL");
28302845
MODULE_AUTHOR("Ryan McClelland <[email protected]>");

0 commit comments

Comments
 (0)