Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+20 −12
Original line number Diff line number Diff line
@@ -243,7 +243,6 @@ static const signed short xpad_btn_triggers[] = {
	-1
};


static const signed short xpad360_btn[] = {  /* buttons for x360 controller */
	BTN_TL, BTN_TR,		/* Button LB/RB */
	BTN_MODE,		/* The big X button */
@@ -345,7 +344,7 @@ struct usb_xpad {

	int mapping;			/* map d-pad to buttons or to axes */
	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)
#include <linux/leds.h>
#include <linux/idr.h>

static DEFINE_IDA(xpad_pad_seq);

struct xpad_led {
	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 atomic_t led_seq = ATOMIC_INIT(-1);
	struct xpad_led *led;
	struct led_classdev *led_cdev;
	int error;
@@ -974,9 +975,13 @@ static int xpad_led_probe(struct usb_xpad *xpad)
	if (!led)
		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_cdev = &led->led_cdev;
@@ -984,16 +989,19 @@ static int xpad_led_probe(struct usb_xpad *xpad)
	led_cdev->brightness_set = xpad_led_set;

	error = led_classdev_register(&xpad->udev->dev, led_cdev);
	if (error) {
		kfree(led);
		xpad->led = NULL;
		return error;
	}
	if (error)
		goto err_free_id;

	/* Light up the segment corresponding to controller number */
	xpad_identify_controller(xpad);

	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)
@@ -1002,6 +1010,7 @@ static void xpad_led_disconnect(struct usb_xpad *xpad)

	if (xpad_led) {
		led_classdev_unregister(&xpad_led->led_cdev);
		ida_simple_remove(&xpad_pad_seq, xpad->pad_nr);
		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) { }
#endif


static int xpad_open(struct input_dev *dev)
{
	struct usb_xpad *xpad = input_get_drvdata(dev);