Commit 848e0763 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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

Pull HID fixes from Jiri Kosina:

 - power management fix in intel-thc-hid (Even Xu)

 - nintendo gencon mapping fix (Ryan McClelland)

 - fix for UAF on device diconnect path in hid-steam (Vicki Pfau)

 - two fixes for UAF on device disconnect path in intel-ish-hid (Zhang
   Lixu)

 - fix for potential NULL dereference in hid-appleir (Daniil Dulov)

 - few other small cosmetic fixes (e.g. typos)

* tag 'hid-for-linus-2025030501' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid:
  HID: Intel-thc-hid: Intel-quickspi: Correct device state after S4
  HID: intel-thc-hid: Fix spelling mistake "intput" -> "input"
  HID: hid-steam: Fix use-after-free when detaching device
  HID: debug: Fix spelling mistake "Messanger" -> "Messenger"
  HID: appleir: Fix potential NULL dereference at raw event handle
  HID: apple: disable Fn key handling on the Omoton KB066
  HID: i2c-hid: improve i2c_hid_get_report error message
  HID: intel-ish-hid: Fix use-after-free issue in ishtp_hid_remove()
  HID: intel-ish-hid: Fix use-after-free issue in hid_ishtp_cl_remove()
  HID: google: fix unused variable warning under !CONFIG_ACPI
  HID: nintendo: fix gencon button events map
  HID: corsair-void: Update power supply values with a unified work handler
parents 0d2d0f3d db52926f
Loading
Loading
Loading
Loading
+7 −4
Original line number Diff line number Diff line
@@ -378,6 +378,12 @@ static bool apple_is_non_apple_keyboard(struct hid_device *hdev)
	return false;
}

static bool apple_is_omoton_kb066(struct hid_device *hdev)
{
	return hdev->product == USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI &&
		strcmp(hdev->name, "Bluetooth Keyboard") == 0;
}

static inline void apple_setup_key_translation(struct input_dev *input,
		const struct apple_key_translation *table)
{
@@ -546,9 +552,6 @@ static int hidinput_apple_event(struct hid_device *hid, struct input_dev *input,
		}
	}

	if (usage->hid == 0xc0301) /* Omoton KB066 quirk */
		code = KEY_F6;

	if (usage->code != code) {
		input_event_with_scancode(input, usage->type, code, usage->hid, value);

@@ -728,7 +731,7 @@ static int apple_input_configured(struct hid_device *hdev,
{
	struct apple_sc *asc = hid_get_drvdata(hdev);

	if ((asc->quirks & APPLE_HAS_FN) && !asc->fn_found) {
	if (((asc->quirks & APPLE_HAS_FN) && !asc->fn_found) || apple_is_omoton_kb066(hdev)) {
		hid_info(hdev, "Fn key not found (Apple Wireless Keyboard clone?), disabling Fn key handling\n");
		asc->quirks &= ~APPLE_HAS_FN;
	}
+1 −1
Original line number Diff line number Diff line
@@ -188,7 +188,7 @@ static int appleir_raw_event(struct hid_device *hid, struct hid_report *report,
	static const u8 flatbattery[] = { 0x25, 0x87, 0xe0 };
	unsigned long flags;

	if (len != 5)
	if (len != 5 || !(hid->claimed & HID_CLAIMED_INPUT))
		goto out;

	if (!memcmp(data, keydown, sizeof(keydown))) {
+43 −40
Original line number Diff line number Diff line
@@ -71,11 +71,9 @@

#include <linux/bitfield.h>
#include <linux/bitops.h>
#include <linux/cleanup.h>
#include <linux/device.h>
#include <linux/hid.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/power_supply.h>
#include <linux/usb.h>
#include <linux/workqueue.h>
@@ -120,6 +118,12 @@ enum {
	CORSAIR_VOID_BATTERY_CHARGING	= 5,
};

enum {
	CORSAIR_VOID_ADD_BATTERY	= 0,
	CORSAIR_VOID_REMOVE_BATTERY	= 1,
	CORSAIR_VOID_UPDATE_BATTERY	= 2,
};

static enum power_supply_property corsair_void_battery_props[] = {
	POWER_SUPPLY_PROP_STATUS,
	POWER_SUPPLY_PROP_PRESENT,
@@ -155,12 +159,12 @@ struct corsair_void_drvdata {

	struct power_supply *battery;
	struct power_supply_desc battery_desc;
	struct mutex battery_mutex;

	struct delayed_work delayed_status_work;
	struct delayed_work delayed_firmware_work;
	struct work_struct battery_remove_work;
	struct work_struct battery_add_work;

	unsigned long battery_work_flags;
	struct work_struct battery_work;
};

/*
@@ -260,11 +264,9 @@ static void corsair_void_process_receiver(struct corsair_void_drvdata *drvdata,

	/* Inform power supply if battery values changed */
	if (memcmp(&orig_battery_data, battery_data, sizeof(*battery_data))) {
		scoped_guard(mutex, &drvdata->battery_mutex) {
			if (drvdata->battery) {
				power_supply_changed(drvdata->battery);
			}
		}
		set_bit(CORSAIR_VOID_UPDATE_BATTERY,
			&drvdata->battery_work_flags);
		schedule_work(&drvdata->battery_work);
	}
}

@@ -536,29 +538,11 @@ static void corsair_void_firmware_work_handler(struct work_struct *work)

}

static void corsair_void_battery_remove_work_handler(struct work_struct *work)
{
	struct corsair_void_drvdata *drvdata;

	drvdata = container_of(work, struct corsair_void_drvdata,
			       battery_remove_work);
	scoped_guard(mutex, &drvdata->battery_mutex) {
		if (drvdata->battery) {
			power_supply_unregister(drvdata->battery);
			drvdata->battery = NULL;
		}
	}
}

static void corsair_void_battery_add_work_handler(struct work_struct *work)
static void corsair_void_add_battery(struct corsair_void_drvdata *drvdata)
{
	struct corsair_void_drvdata *drvdata;
	struct power_supply_config psy_cfg = {};
	struct power_supply *new_supply;

	drvdata = container_of(work, struct corsair_void_drvdata,
			       battery_add_work);
	guard(mutex)(&drvdata->battery_mutex);
	if (drvdata->battery)
		return;

@@ -583,16 +567,42 @@ static void corsair_void_battery_add_work_handler(struct work_struct *work)
	drvdata->battery = new_supply;
}

static void corsair_void_battery_work_handler(struct work_struct *work)
{
	struct corsair_void_drvdata *drvdata = container_of(work,
		struct corsair_void_drvdata, battery_work);

	bool add_battery = test_and_clear_bit(CORSAIR_VOID_ADD_BATTERY,
					      &drvdata->battery_work_flags);
	bool remove_battery = test_and_clear_bit(CORSAIR_VOID_REMOVE_BATTERY,
						 &drvdata->battery_work_flags);
	bool update_battery = test_and_clear_bit(CORSAIR_VOID_UPDATE_BATTERY,
						 &drvdata->battery_work_flags);

	if (add_battery && !remove_battery) {
		corsair_void_add_battery(drvdata);
	} else if (remove_battery && !add_battery && drvdata->battery) {
		power_supply_unregister(drvdata->battery);
		drvdata->battery = NULL;
	}

	if (update_battery && drvdata->battery)
		power_supply_changed(drvdata->battery);

}

static void corsair_void_headset_connected(struct corsair_void_drvdata *drvdata)
{
	schedule_work(&drvdata->battery_add_work);
	set_bit(CORSAIR_VOID_ADD_BATTERY, &drvdata->battery_work_flags);
	schedule_work(&drvdata->battery_work);
	schedule_delayed_work(&drvdata->delayed_firmware_work,
			      msecs_to_jiffies(100));
}

static void corsair_void_headset_disconnected(struct corsair_void_drvdata *drvdata)
{
	schedule_work(&drvdata->battery_remove_work);
	set_bit(CORSAIR_VOID_REMOVE_BATTERY, &drvdata->battery_work_flags);
	schedule_work(&drvdata->battery_work);

	corsair_void_set_unknown_wireless_data(drvdata);
	corsair_void_set_unknown_batt(drvdata);
@@ -678,13 +688,7 @@ static int corsair_void_probe(struct hid_device *hid_dev,
	drvdata->battery_desc.get_property = corsair_void_battery_get_property;

	drvdata->battery = NULL;
	INIT_WORK(&drvdata->battery_remove_work,
		  corsair_void_battery_remove_work_handler);
	INIT_WORK(&drvdata->battery_add_work,
		  corsair_void_battery_add_work_handler);
	ret = devm_mutex_init(drvdata->dev, &drvdata->battery_mutex);
	if (ret)
		return ret;
	INIT_WORK(&drvdata->battery_work, corsair_void_battery_work_handler);

	ret = sysfs_create_group(&hid_dev->dev.kobj, &corsair_void_attr_group);
	if (ret)
@@ -721,8 +725,7 @@ static void corsair_void_remove(struct hid_device *hid_dev)
	struct corsair_void_drvdata *drvdata = hid_get_drvdata(hid_dev);

	hid_hw_stop(hid_dev);
	cancel_work_sync(&drvdata->battery_remove_work);
	cancel_work_sync(&drvdata->battery_add_work);
	cancel_work_sync(&drvdata->battery_work);
	if (drvdata->battery)
		power_supply_unregister(drvdata->battery);

+1 −1
Original line number Diff line number Diff line
@@ -3450,7 +3450,7 @@ static const char *keys[KEY_MAX + 1] = {
	[KEY_MACRO_RECORD_START] = "MacroRecordStart",
	[KEY_MACRO_RECORD_STOP] = "MacroRecordStop",
	[KEY_MARK_WAYPOINT] = "MarkWayPoint",	[KEY_MEDIA_REPEAT] = "MediaRepeat",
	[KEY_MEDIA_TOP_MENU] = "MediaTopMenu",	[KEY_MESSENGER] = "Messanger",
	[KEY_MEDIA_TOP_MENU] = "MediaTopMenu",	[KEY_MESSENGER] = "Messenger",
	[KEY_NAV_CHART] = "NavChar",		[KEY_NAV_INFO] = "NavInfo",
	[KEY_NEWS] = "News",			[KEY_NEXT_ELEMENT] = "NextElement",
	[KEY_NEXT_FAVORITE] = "NextFavorite",	[KEY_NOTIFICATION_CENTER] = "NotificationCenter",
+2 −0
Original line number Diff line number Diff line
@@ -268,11 +268,13 @@ static void cbas_ec_remove(struct platform_device *pdev)
	mutex_unlock(&cbas_ec_reglock);
}

#ifdef CONFIG_ACPI
static const struct acpi_device_id cbas_ec_acpi_ids[] = {
	{ "GOOG000B", 0 },
	{ }
};
MODULE_DEVICE_TABLE(acpi, cbas_ec_acpi_ids);
#endif

#ifdef CONFIG_OF
static const struct of_device_id cbas_ec_of_match[] = {
Loading