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

Commit e5f468b3 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull input fixes from Dmitry Torokhov:

 - joydev now implements a blacklist to avoid creating joystick nodes
   for accelerometers found in composite devices such as PlaStation
   controllers

 - assorted driver fixes

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input:
  Input: ims-psu - check if CDC union descriptor is sane
  Input: joydev - blacklist ds3/ds4/udraw motion sensors
  Input: allow matching device IDs on property bits
  Input: factor out and export input_device_id matching code
  Input: goodix - poll the 'buffer status' bit before reading data
  Input: axp20x-pek - fix module not auto-loading for axp221 pek
  Input: tca8418 - enable interrupt after it has been requested
  Input: stmfts - fix setting ABS_MT_POSITION_* maximum size
  Input: ti_am335x_tsc - fix incorrect step config for 5 wire touchscreen
  Input: synaptics - disable kernel tracking on SMBus devices
parents ec0145e9 ea04efee
Loading
Loading
Loading
Loading
+39 −45
Original line number Diff line number Diff line
@@ -933,59 +933,53 @@ int input_set_keycode(struct input_dev *dev,
}
EXPORT_SYMBOL(input_set_keycode);

static const struct input_device_id *input_match_device(struct input_handler *handler,
							struct input_dev *dev)
bool input_match_device_id(const struct input_dev *dev,
			   const struct input_device_id *id)
{
	const struct input_device_id *id;

	for (id = handler->id_table; id->flags || id->driver_info; id++) {

	if (id->flags & INPUT_DEVICE_ID_MATCH_BUS)
		if (id->bustype != dev->id.bustype)
				continue;
			return false;

	if (id->flags & INPUT_DEVICE_ID_MATCH_VENDOR)
		if (id->vendor != dev->id.vendor)
				continue;
			return false;

	if (id->flags & INPUT_DEVICE_ID_MATCH_PRODUCT)
		if (id->product != dev->id.product)
				continue;
			return false;

	if (id->flags & INPUT_DEVICE_ID_MATCH_VERSION)
		if (id->version != dev->id.version)
				continue;

		if (!bitmap_subset(id->evbit, dev->evbit, EV_MAX))
			continue;

		if (!bitmap_subset(id->keybit, dev->keybit, KEY_MAX))
			continue;

		if (!bitmap_subset(id->relbit, dev->relbit, REL_MAX))
			continue;
			return false;

		if (!bitmap_subset(id->absbit, dev->absbit, ABS_MAX))
			continue;

		if (!bitmap_subset(id->mscbit, dev->mscbit, MSC_MAX))
			continue;

		if (!bitmap_subset(id->ledbit, dev->ledbit, LED_MAX))
			continue;

		if (!bitmap_subset(id->sndbit, dev->sndbit, SND_MAX))
			continue;
	if (!bitmap_subset(id->evbit, dev->evbit, EV_MAX) ||
	    !bitmap_subset(id->keybit, dev->keybit, KEY_MAX) ||
	    !bitmap_subset(id->relbit, dev->relbit, REL_MAX) ||
	    !bitmap_subset(id->absbit, dev->absbit, ABS_MAX) ||
	    !bitmap_subset(id->mscbit, dev->mscbit, MSC_MAX) ||
	    !bitmap_subset(id->ledbit, dev->ledbit, LED_MAX) ||
	    !bitmap_subset(id->sndbit, dev->sndbit, SND_MAX) ||
	    !bitmap_subset(id->ffbit, dev->ffbit, FF_MAX) ||
	    !bitmap_subset(id->swbit, dev->swbit, SW_MAX) ||
	    !bitmap_subset(id->propbit, dev->propbit, INPUT_PROP_MAX)) {
		return false;
	}

		if (!bitmap_subset(id->ffbit, dev->ffbit, FF_MAX))
			continue;
	return true;
}
EXPORT_SYMBOL(input_match_device_id);

		if (!bitmap_subset(id->swbit, dev->swbit, SW_MAX))
			continue;
static const struct input_device_id *input_match_device(struct input_handler *handler,
							struct input_dev *dev)
{
	const struct input_device_id *id;

		if (!handler->match || handler->match(handler, dev))
	for (id = handler->id_table; id->flags || id->driver_info; id++) {
		if (input_match_device_id(dev, id) &&
		    (!handler->match || handler->match(handler, dev))) {
			return id;
		}
	}

	return NULL;
}
+64 −6
Original line number Diff line number Diff line
@@ -747,6 +747,68 @@ static void joydev_cleanup(struct joydev *joydev)
		input_close_device(handle);
}

/*
 * These codes are copied from from hid-ids.h, unfortunately there is no common
 * usb_ids/bt_ids.h header.
 */
#define USB_VENDOR_ID_SONY			0x054c
#define USB_DEVICE_ID_SONY_PS3_CONTROLLER		0x0268
#define USB_DEVICE_ID_SONY_PS4_CONTROLLER		0x05c4
#define USB_DEVICE_ID_SONY_PS4_CONTROLLER_2		0x09cc
#define USB_DEVICE_ID_SONY_PS4_CONTROLLER_DONGLE	0x0ba0

#define USB_VENDOR_ID_THQ			0x20d6
#define USB_DEVICE_ID_THQ_PS3_UDRAW			0xcb17

#define ACCEL_DEV(vnd, prd)						\
	{								\
		.flags = INPUT_DEVICE_ID_MATCH_VENDOR |			\
				INPUT_DEVICE_ID_MATCH_PRODUCT |		\
				INPUT_DEVICE_ID_MATCH_PROPBIT,		\
		.vendor = (vnd),					\
		.product = (prd),					\
		.propbit = { BIT_MASK(INPUT_PROP_ACCELEROMETER) },	\
	}

static const struct input_device_id joydev_blacklist[] = {
	/* Avoid touchpads and touchscreens */
	{
		.flags = INPUT_DEVICE_ID_MATCH_EVBIT |
				INPUT_DEVICE_ID_MATCH_KEYBIT,
		.evbit = { BIT_MASK(EV_KEY) },
		.keybit = { [BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH) },
	},
	/* Avoid tablets, digitisers and similar devices */
	{
		.flags = INPUT_DEVICE_ID_MATCH_EVBIT |
				INPUT_DEVICE_ID_MATCH_KEYBIT,
		.evbit = { BIT_MASK(EV_KEY) },
		.keybit = { [BIT_WORD(BTN_DIGI)] = BIT_MASK(BTN_DIGI) },
	},
	/* Disable accelerometers on composite devices */
	ACCEL_DEV(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER),
	ACCEL_DEV(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER),
	ACCEL_DEV(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER_2),
	ACCEL_DEV(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER_DONGLE),
	ACCEL_DEV(USB_VENDOR_ID_THQ, USB_DEVICE_ID_THQ_PS3_UDRAW),
	{ /* sentinel */ }
};

static bool joydev_dev_is_blacklisted(struct input_dev *dev)
{
	const struct input_device_id *id;

	for (id = joydev_blacklist; id->flags; id++) {
		if (input_match_device_id(dev, id)) {
			dev_dbg(&dev->dev,
				"joydev: blacklisting '%s'\n", dev->name);
			return true;
		}
	}

	return false;
}

static bool joydev_dev_is_absolute_mouse(struct input_dev *dev)
{
	DECLARE_BITMAP(jd_scratch, KEY_CNT);
@@ -807,12 +869,8 @@ static bool joydev_dev_is_absolute_mouse(struct input_dev *dev)

static bool joydev_match(struct input_handler *handler, struct input_dev *dev)
{
	/* Avoid touchpads and touchscreens */
	if (test_bit(EV_KEY, dev->evbit) && test_bit(BTN_TOUCH, dev->keybit))
		return false;

	/* Avoid tablets, digitisers and similar devices */
	if (test_bit(EV_KEY, dev->evbit) && test_bit(BTN_DIGI, dev->keybit))
	/* Disable blacklisted devices */
	if (joydev_dev_is_blacklisted(dev))
		return false;

	/* Avoid absolute mice */
+17 −12
Original line number Diff line number Diff line
@@ -234,14 +234,7 @@ static irqreturn_t tca8418_irq_handler(int irq, void *dev_id)
static int tca8418_configure(struct tca8418_keypad *keypad_data,
			     u32 rows, u32 cols)
{
	int reg, error;

	/* Write config register, if this fails assume device not present */
	error = tca8418_write_byte(keypad_data, REG_CFG,
				CFG_INT_CFG | CFG_OVR_FLOW_IEN | CFG_KE_IEN);
	if (error < 0)
		return -ENODEV;

	int reg, error = 0;

	/* Assemble a mask for row and column registers */
	reg  =  ~(~0 << rows);
@@ -257,6 +250,12 @@ static int tca8418_configure(struct tca8418_keypad *keypad_data,
	error |= tca8418_write_byte(keypad_data, REG_DEBOUNCE_DIS2, reg >> 8);
	error |= tca8418_write_byte(keypad_data, REG_DEBOUNCE_DIS3, reg >> 16);

	if (error)
		return error;

	error = tca8418_write_byte(keypad_data, REG_CFG,
				CFG_INT_CFG | CFG_OVR_FLOW_IEN | CFG_KE_IEN);

	return error;
}

@@ -268,6 +267,7 @@ static int tca8418_keypad_probe(struct i2c_client *client,
	struct input_dev *input;
	u32 rows = 0, cols = 0;
	int error, row_shift, max_keys;
	u8 reg;

	/* Check i2c driver capabilities */
	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE)) {
@@ -301,10 +301,10 @@ static int tca8418_keypad_probe(struct i2c_client *client,
	keypad_data->client = client;
	keypad_data->row_shift = row_shift;

	/* Initialize the chip or fail if chip isn't present */
	error = tca8418_configure(keypad_data, rows, cols);
	if (error < 0)
		return error;
	/* Read key lock register, if this fails assume device not present */
	error = tca8418_read_byte(keypad_data, REG_KEY_LCK_EC, &reg);
	if (error)
		return -ENODEV;

	/* Configure input device */
	input = devm_input_allocate_device(dev);
@@ -340,6 +340,11 @@ static int tca8418_keypad_probe(struct i2c_client *client,
		return error;
	}

	/* Initialize the chip */
	error = tca8418_configure(keypad_data, rows, cols);
	if (error < 0)
		return error;

	error = input_register_device(input);
	if (error) {
		dev_err(dev, "Unable to register input device, error: %d\n",
+1 −1
Original line number Diff line number Diff line
@@ -403,6 +403,7 @@ static const struct platform_device_id axp_pek_id_match[] = {
	},
	{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(platform, axp_pek_id_match);

static struct platform_driver axp20x_pek_driver = {
	.probe		= axp20x_pek_probe,
@@ -417,4 +418,3 @@ module_platform_driver(axp20x_pek_driver);
MODULE_DESCRIPTION("axp20x Power Button");
MODULE_AUTHOR("Carlo Caione <carlo@caione.org>");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:axp20x-pek");
+14 −2
Original line number Diff line number Diff line
@@ -1635,13 +1635,25 @@ ims_pcu_get_cdc_union_desc(struct usb_interface *intf)
		return NULL;
	}

	while (buflen > 0) {
	while (buflen >= sizeof(*union_desc)) {
		union_desc = (struct usb_cdc_union_desc *)buf;

		if (union_desc->bLength > buflen) {
			dev_err(&intf->dev, "Too large descriptor\n");
			return NULL;
		}

		if (union_desc->bDescriptorType == USB_DT_CS_INTERFACE &&
		    union_desc->bDescriptorSubType == USB_CDC_UNION_TYPE) {
			dev_dbg(&intf->dev, "Found union header\n");

			if (union_desc->bLength >= sizeof(*union_desc))
				return union_desc;

			dev_err(&intf->dev,
				"Union descriptor to short (%d vs %zd\n)",
				union_desc->bLength, sizeof(*union_desc));
			return NULL;
		}

		buflen -= union_desc->bLength;
Loading