Commit 2043ae90 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'hid-for-linus-2025060301' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid

Pull HID updates from Jiri Kosina:

 - support for Apple Magic Mouse 2 USB-C (Aditya Garg)

 - power management improvement for multitouch devices (Werner Sembach)

 - fix for ACPI initialization in intel-thc driver (Wentao Guan)

 - adaptation of HID drivers to use new gpio_chip's line setter
   callbacks (Bartosz Golaszewski)

 - fix potential OOB in usbhid_parse() (Terry Junge)

 - make it possible to set hid_mouse_ignore_list dynamically (the same
   way we handle other quirks) (Aditya Garg)

 - other small assorted fixes and device ID additions

* tag 'hid-for-linus-2025060301' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid:
  HID: multitouch: Disable touchpad on firmware level while not in use
  HID: core: Add functions for HID drivers to react on first open and last close call
  HID: HID_APPLETB_BL should depend on X86
  HID: HID_APPLETB_KBD should depend on X86
  HID: appletb-kbd: Use secs_to_jiffies() instead of msecs_to_jiffies()
  HID: intel-thc-hid: intel-thc: make read-only arrays static const
  HID: magicmouse: Apple Magic Mouse 2 USB-C support
  HID: mcp2221: use new line value setter callbacks
  HID: mcp2200: use new line value setter callbacks
  HID: cp2112: use new line value setter callbacks
  HID: cp2112: use lock guards
  HID: cp2112: hold the lock for the entire direction_output() call
  HID: cp2112: destroy mutex on driver detach
  HID: intel-thc-hid: intel-quicki2c: pass correct arguments to acpi_evaluate_object
  HID: corsair-void: Use to_delayed_work()
  HID: hid-logitech: use sysfs_emit_at() instead of scnprintf()
  HID: quirks: Add HID_QUIRK_IGNORE_MOUSE quirk
  HID: usbhid: Eliminate recurrent out-of-bounds bug in usbhid_parse()
  HID: Kysona: Add periodic online check
parents efe19d34 c48228c4
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -151,6 +151,7 @@ config HID_APPLEIR
config HID_APPLETB_BL
	tristate "Apple Touch Bar Backlight"
	depends on BACKLIGHT_CLASS_DEVICE
	depends on X86 || COMPILE_TEST
	help
	  Say Y here if you want support for the backlight of Touch Bars on x86
	  MacBook Pros.
@@ -163,6 +164,7 @@ config HID_APPLETB_KBD
	depends on USB_HID
	depends on BACKLIGHT_CLASS_DEVICE
	depends on INPUT
	depends on X86 || COMPILE_TEST
	select INPUT_SPARSEKMAP
	select HID_APPLETB_BL
	help
+6 −3
Original line number Diff line number Diff line
@@ -172,7 +172,8 @@ static void appletb_inactivity_timer(struct timer_list *t)
		if (!kbd->has_dimmed) {
			backlight_device_set_brightness(kbd->backlight_dev, 1);
			kbd->has_dimmed = true;
			mod_timer(&kbd->inactivity_timer, jiffies + msecs_to_jiffies(appletb_tb_idle_timeout * 1000));
			mod_timer(&kbd->inactivity_timer,
				jiffies + secs_to_jiffies(appletb_tb_idle_timeout));
		} else if (!kbd->has_turned_off) {
			backlight_device_set_brightness(kbd->backlight_dev, 0);
			kbd->has_turned_off = true;
@@ -188,7 +189,8 @@ static void reset_inactivity_timer(struct appletb_kbd *kbd)
			kbd->has_dimmed = false;
			kbd->has_turned_off = false;
		}
		mod_timer(&kbd->inactivity_timer, jiffies + msecs_to_jiffies(appletb_tb_dim_timeout * 1000));
		mod_timer(&kbd->inactivity_timer,
			jiffies + secs_to_jiffies(appletb_tb_dim_timeout));
	}
}

@@ -407,7 +409,8 @@ static int appletb_kbd_probe(struct hid_device *hdev, const struct hid_device_id
	} else {
		backlight_device_set_brightness(kbd->backlight_dev, 2);
		timer_setup(&kbd->inactivity_timer, appletb_inactivity_timer, 0);
		mod_timer(&kbd->inactivity_timer, jiffies + msecs_to_jiffies(appletb_tb_dim_timeout * 1000));
		mod_timer(&kbd->inactivity_timer,
			jiffies + secs_to_jiffies(appletb_tb_dim_timeout));
	}

	kbd->inp_handler.event = appletb_kbd_inp_event;
+8 −1
Original line number Diff line number Diff line
@@ -2396,6 +2396,9 @@ int hid_hw_open(struct hid_device *hdev)
		ret = hdev->ll_driver->open(hdev);
		if (ret)
			hdev->ll_open_count--;

		if (hdev->driver->on_hid_hw_open)
			hdev->driver->on_hid_hw_open(hdev);
	}

	mutex_unlock(&hdev->ll_open_lock);
@@ -2415,8 +2418,12 @@ EXPORT_SYMBOL_GPL(hid_hw_open);
void hid_hw_close(struct hid_device *hdev)
{
	mutex_lock(&hdev->ll_open_lock);
	if (!--hdev->ll_open_count)
	if (!--hdev->ll_open_count) {
		hdev->ll_driver->close(hdev);

		if (hdev->driver->on_hid_hw_close)
			hdev->driver->on_hid_hw_close(hdev);
	}
	mutex_unlock(&hdev->ll_open_lock);
}
EXPORT_SYMBOL_GPL(hid_hw_close);
+2 −2
Original line number Diff line number Diff line
@@ -507,7 +507,7 @@ static void corsair_void_status_work_handler(struct work_struct *work)
	struct delayed_work *delayed_work;
	int battery_ret;

	delayed_work = container_of(work, struct delayed_work, work);
	delayed_work = to_delayed_work(work);
	drvdata = container_of(delayed_work, struct corsair_void_drvdata,
			       delayed_status_work);

@@ -525,7 +525,7 @@ static void corsair_void_firmware_work_handler(struct work_struct *work)
	struct delayed_work *delayed_work;
	int firmware_ret;

	delayed_work = container_of(work, struct delayed_work, work);
	delayed_work = to_delayed_work(work);
	drvdata = container_of(delayed_work, struct corsair_void_drvdata,
			       delayed_firmware_work);

+32 −34
Original line number Diff line number Diff line
@@ -17,11 +17,13 @@
 */

#include <linux/bitops.h>
#include <linux/cleanup.h>
#include <linux/gpio/driver.h>
#include <linux/hid.h>
#include <linux/hidraw.h>
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/nls.h>
#include <linux/string_choices.h>
#include <linux/usb/ch9.h>
@@ -185,7 +187,7 @@ static int cp2112_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
	u8 *buf = dev->in_out_buffer;
	int ret;

	mutex_lock(&dev->lock);
	guard(mutex)(&dev->lock);

	ret = hid_hw_raw_request(hdev, CP2112_GPIO_CONFIG, buf,
				 CP2112_GPIO_CONFIG_LENGTH, HID_FEATURE_REPORT,
@@ -194,7 +196,7 @@ static int cp2112_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
		hid_err(hdev, "error requesting GPIO config: %d\n", ret);
		if (ret >= 0)
			ret = -EIO;
		goto exit;
		return ret;
	}

	buf[1] &= ~BIT(offset);
@@ -207,25 +209,19 @@ static int cp2112_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
		hid_err(hdev, "error setting GPIO config: %d\n", ret);
		if (ret >= 0)
			ret = -EIO;
		goto exit;
		return ret;
	}

	ret = 0;

exit:
	mutex_unlock(&dev->lock);
	return ret;
	return 0;
}

static void cp2112_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
static int cp2112_gpio_set_unlocked(struct cp2112_device *dev,
				    unsigned int offset, int value)
{
	struct cp2112_device *dev = gpiochip_get_data(chip);
	struct hid_device *hdev = dev->hdev;
	u8 *buf = dev->in_out_buffer;
	int ret;

	mutex_lock(&dev->lock);

	buf[0] = CP2112_GPIO_SET;
	buf[1] = value ? CP2112_GPIO_ALL_GPIO_MASK : 0;
	buf[2] = BIT(offset);
@@ -236,7 +232,17 @@ static void cp2112_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
	if (ret < 0)
		hid_err(hdev, "error setting GPIO values: %d\n", ret);

	mutex_unlock(&dev->lock);
	return ret;
}

static int cp2112_gpio_set(struct gpio_chip *chip, unsigned int offset,
			   int value)
{
	struct cp2112_device *dev = gpiochip_get_data(chip);

	guard(mutex)(&dev->lock);

	return cp2112_gpio_set_unlocked(dev, offset, value);
}

static int cp2112_gpio_get_all(struct gpio_chip *chip)
@@ -246,23 +252,17 @@ static int cp2112_gpio_get_all(struct gpio_chip *chip)
	u8 *buf = dev->in_out_buffer;
	int ret;

	mutex_lock(&dev->lock);
	guard(mutex)(&dev->lock);

	ret = hid_hw_raw_request(hdev, CP2112_GPIO_GET, buf,
				 CP2112_GPIO_GET_LENGTH, HID_FEATURE_REPORT,
				 HID_REQ_GET_REPORT);
	if (ret != CP2112_GPIO_GET_LENGTH) {
		hid_err(hdev, "error requesting GPIO values: %d\n", ret);
		ret = ret < 0 ? ret : -EIO;
		goto exit;
		return ret < 0 ? ret : -EIO;
	}

	ret = buf[1];

exit:
	mutex_unlock(&dev->lock);

	return ret;
	return buf[1];
}

static int cp2112_gpio_get(struct gpio_chip *chip, unsigned int offset)
@@ -284,14 +284,14 @@ static int cp2112_gpio_direction_output(struct gpio_chip *chip,
	u8 *buf = dev->in_out_buffer;
	int ret;

	mutex_lock(&dev->lock);
	guard(mutex)(&dev->lock);

	ret = hid_hw_raw_request(hdev, CP2112_GPIO_CONFIG, buf,
				 CP2112_GPIO_CONFIG_LENGTH, HID_FEATURE_REPORT,
				 HID_REQ_GET_REPORT);
	if (ret != CP2112_GPIO_CONFIG_LENGTH) {
		hid_err(hdev, "error requesting GPIO config: %d\n", ret);
		goto fail;
		return ret < 0 ? ret : -EIO;
	}

	buf[1] |= 1 << offset;
@@ -302,22 +302,16 @@ static int cp2112_gpio_direction_output(struct gpio_chip *chip,
				 HID_REQ_SET_REPORT);
	if (ret < 0) {
		hid_err(hdev, "error setting GPIO config: %d\n", ret);
		goto fail;
		return ret;
	}

	mutex_unlock(&dev->lock);

	/*
	 * Set gpio value when output direction is already set,
	 * as specified in AN495, Rev. 0.2, cpt. 4.4
	 */
	cp2112_gpio_set(chip, offset, value);
	cp2112_gpio_set_unlocked(dev, offset, value);

	return 0;

fail:
	mutex_unlock(&dev->lock);
	return ret < 0 ? ret : -EIO;
}

static int cp2112_hid_get(struct hid_device *hdev, unsigned char report_number,
@@ -1205,7 +1199,11 @@ static int cp2112_probe(struct hid_device *hdev, const struct hid_device_id *id)
	if (!dev->in_out_buffer)
		return -ENOMEM;

	mutex_init(&dev->lock);
	ret = devm_mutex_init(&hdev->dev, &dev->lock);
	if (ret) {
		hid_err(hdev, "mutex init failed\n");
		return ret;
	}

	ret = hid_parse(hdev);
	if (ret) {
@@ -1290,7 +1288,7 @@ static int cp2112_probe(struct hid_device *hdev, const struct hid_device_id *id)
	dev->gc.label			= "cp2112_gpio";
	dev->gc.direction_input		= cp2112_gpio_direction_input;
	dev->gc.direction_output	= cp2112_gpio_direction_output;
	dev->gc.set			= cp2112_gpio_set;
	dev->gc.set_rv			= cp2112_gpio_set;
	dev->gc.get			= cp2112_gpio_get;
	dev->gc.base			= -1;
	dev->gc.ngpio			= CP2112_GPIO_MAX_GPIO;
Loading