Commit e3b65174 authored by Pavel Rojtberg's avatar Pavel Rojtberg Committed by Dmitry Torokhov

Input: xpad - use ida() for finding the pad_nr

The pad_nr corresponds to the lit up LED on the controller. Therefore there
should be no gaps when enumerating. Currently a LED is only re-assigned
after a controller is re-connected 4 times.

This patch uses ida to track connected pads - this way we can re-assign
freed up pad number immediately.

Consider the following case:
1. pad A is connected and gets pad_nr = 0
2. pad B is connected and gets pad_nr = 1
3. pad A is disconnected
4. pad A is connected again

using ida_simple_get() controller A now correctly gets pad_nr = 0 again.
Signed-off-by: default avatarPavel Rojtberg <rojtberg@gmail.com>
Signed-off-by: default avatarDmitry Torokhov <dmitry.torokhov@gmail.com>
parent 1f6f02b7
...@@ -243,7 +243,6 @@ static const signed short xpad_btn_triggers[] = { ...@@ -243,7 +243,6 @@ static const signed short xpad_btn_triggers[] = {
-1 -1
}; };
static const signed short xpad360_btn[] = { /* buttons for x360 controller */ static const signed short xpad360_btn[] = { /* buttons for x360 controller */
BTN_TL, BTN_TR, /* Button LB/RB */ BTN_TL, BTN_TR, /* Button LB/RB */
BTN_MODE, /* The big X button */ BTN_MODE, /* The big X button */
...@@ -345,7 +344,7 @@ struct usb_xpad { ...@@ -345,7 +344,7 @@ struct usb_xpad {
int mapping; /* map d-pad to buttons or to axes */ int mapping; /* map d-pad to buttons or to axes */
int xtype; /* type of xbox device */ int xtype; /* type of xbox device */
unsigned long pad_nr; /* the order x360 pads were attached */ int pad_nr; /* the order x360 pads were attached */
}; };
/* /*
...@@ -881,6 +880,9 @@ static int xpad_init_ff(struct usb_xpad *xpad) { return 0; } ...@@ -881,6 +880,9 @@ static int xpad_init_ff(struct usb_xpad *xpad) { return 0; }
#if defined(CONFIG_JOYSTICK_XPAD_LEDS) #if defined(CONFIG_JOYSTICK_XPAD_LEDS)
#include <linux/leds.h> #include <linux/leds.h>
#include <linux/idr.h>
static DEFINE_IDA(xpad_pad_seq);
struct xpad_led { struct xpad_led {
char name[16]; char name[16];
...@@ -962,7 +964,6 @@ static void xpad_led_set(struct led_classdev *led_cdev, ...@@ -962,7 +964,6 @@ static void xpad_led_set(struct led_classdev *led_cdev,
static int xpad_led_probe(struct usb_xpad *xpad) static int xpad_led_probe(struct usb_xpad *xpad)
{ {
static atomic_t led_seq = ATOMIC_INIT(-1);
struct xpad_led *led; struct xpad_led *led;
struct led_classdev *led_cdev; struct led_classdev *led_cdev;
int error; int error;
...@@ -974,9 +975,13 @@ static int xpad_led_probe(struct usb_xpad *xpad) ...@@ -974,9 +975,13 @@ static int xpad_led_probe(struct usb_xpad *xpad)
if (!led) if (!led)
return -ENOMEM; return -ENOMEM;
xpad->pad_nr = atomic_inc_return(&led_seq); xpad->pad_nr = ida_simple_get(&xpad_pad_seq, 0, 0, GFP_KERNEL);
if (xpad->pad_nr < 0) {
error = xpad->pad_nr;
goto err_free_mem;
}
snprintf(led->name, sizeof(led->name), "xpad%lu", xpad->pad_nr); snprintf(led->name, sizeof(led->name), "xpad%d", xpad->pad_nr);
led->xpad = xpad; led->xpad = xpad;
led_cdev = &led->led_cdev; led_cdev = &led->led_cdev;
...@@ -984,16 +989,19 @@ static int xpad_led_probe(struct usb_xpad *xpad) ...@@ -984,16 +989,19 @@ static int xpad_led_probe(struct usb_xpad *xpad)
led_cdev->brightness_set = xpad_led_set; led_cdev->brightness_set = xpad_led_set;
error = led_classdev_register(&xpad->udev->dev, led_cdev); error = led_classdev_register(&xpad->udev->dev, led_cdev);
if (error) { if (error)
kfree(led); goto err_free_id;
xpad->led = NULL;
return error;
}
/* Light up the segment corresponding to controller number */ /* Light up the segment corresponding to controller number */
xpad_identify_controller(xpad); xpad_identify_controller(xpad);
return 0; return 0;
err_free_id:
ida_simple_remove(&xpad_pad_seq, xpad->pad_nr);
err_free_mem:
kfree(led);
xpad->led = NULL;
return error;
} }
static void xpad_led_disconnect(struct usb_xpad *xpad) static void xpad_led_disconnect(struct usb_xpad *xpad)
...@@ -1002,6 +1010,7 @@ static void xpad_led_disconnect(struct usb_xpad *xpad) ...@@ -1002,6 +1010,7 @@ static void xpad_led_disconnect(struct usb_xpad *xpad)
if (xpad_led) { if (xpad_led) {
led_classdev_unregister(&xpad_led->led_cdev); led_classdev_unregister(&xpad_led->led_cdev);
ida_simple_remove(&xpad_pad_seq, xpad->pad_nr);
kfree(xpad_led); kfree(xpad_led);
} }
} }
...@@ -1011,7 +1020,6 @@ static void xpad_led_disconnect(struct usb_xpad *xpad) { } ...@@ -1011,7 +1020,6 @@ static void xpad_led_disconnect(struct usb_xpad *xpad) { }
static void xpad_identify_controller(struct usb_xpad *xpad) { } static void xpad_identify_controller(struct usb_xpad *xpad) { }
#endif #endif
static int xpad_open(struct input_dev *dev) static int xpad_open(struct input_dev *dev)
{ {
struct usb_xpad *xpad = input_get_drvdata(dev); struct usb_xpad *xpad = input_get_drvdata(dev);
......
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