mirror of
https://github.com/edk2-porting/linux-next.git
synced 2025-01-13 16:14:26 +08:00
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: Pavel Rojtberg <rojtberg@gmail.com> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
This commit is contained in:
parent
1f6f02b728
commit
e3b651745a
@ -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 {
|
|||||||
|
|
||||||
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; }
|
|||||||
|
|
||||||
#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,
|
|||||||
|
|
||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
|
|
||||||
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) { }
|
|||||||
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);
|
||||||
|
Loading…
Reference in New Issue
Block a user