diff options
| author | Lucas Zampieri <lcasmz54@gmail.com> | 2026-03-14 01:05:30 +0000 |
|---|---|---|
| committer | Benjamin Tissoires <bentiss@kernel.org> | 2026-03-19 15:52:45 +0100 |
| commit | 4a58ae85c3f9b142ffba023d0f976978ade57d1b (patch) | |
| tree | bb1290dad98d07903b4ff6b846f2efa5223b37e0 /drivers/hid | |
| parent | 7a3ac62473f2bd213557e41aaab7a8f144037dfd (diff) | |
HID: input: Add support for multiple batteries per device
Add support for HID devices that report multiple batteries, each
identified by its report ID.
The hid_device->battery pointer is replaced with a batteries list.
Batteries are named using the pattern hid-{uniq}-battery-{report_id}.
The hid_get_battery() helper returns the first battery in the list for
backwards compatibility with single-battery drivers.
Signed-off-by: Lucas Zampieri <lcasmz54@gmail.com>
Signed-off-by: Benjamin Tissoires <bentiss@kernel.org>
Diffstat (limited to 'drivers/hid')
| -rw-r--r-- | drivers/hid/hid-core.c | 4 | ||||
| -rw-r--r-- | drivers/hid/hid-input.c | 44 |
2 files changed, 34 insertions, 14 deletions
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 833df14ef68f..deb6239e375c 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -2991,6 +2991,10 @@ struct hid_device *hid_allocate_device(void) mutex_init(&hdev->ll_open_lock); kref_init(&hdev->ref); +#ifdef CONFIG_HID_BATTERY_STRENGTH + INIT_LIST_HEAD(&hdev->batteries); +#endif + ret = hid_bpf_device_init(hdev); if (ret) goto out_err; diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index b5d34658b68d..8fff185fe0e6 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c @@ -507,6 +507,18 @@ static int hidinput_get_battery_property(struct power_supply *psy, return ret; } +static struct hid_battery *hidinput_find_battery(struct hid_device *dev, + int report_id) +{ + struct hid_battery *bat; + + list_for_each_entry(bat, &dev->batteries, list) { + if (bat->report_id == report_id) + return bat; + } + return NULL; +} + static int hidinput_setup_battery(struct hid_device *dev, unsigned report_type, struct hid_field *field, bool is_percentage) { @@ -517,13 +529,15 @@ static int hidinput_setup_battery(struct hid_device *dev, unsigned report_type, s32 min, max; int error; - if (dev->battery) - return 0; /* already initialized? */ + /* Check if battery for this report ID already exists */ + if (hidinput_find_battery(dev, field->report->id)) + return 0; quirks = find_battery_quirk(dev); - hid_dbg(dev, "device %x:%x:%x %d quirks %d\n", - dev->bus, dev->vendor, dev->product, dev->version, quirks); + hid_dbg(dev, "device %x:%x:%x %d quirks %d report_id %d\n", + dev->bus, dev->vendor, dev->product, dev->version, quirks, + field->report->id); if (quirks & HID_BATTERY_QUIRK_IGNORE) return 0; @@ -538,9 +552,11 @@ static int hidinput_setup_battery(struct hid_device *dev, unsigned report_type, goto err_free_bat; } - psy_desc->name = devm_kasprintf(&dev->dev, GFP_KERNEL, "hid-%s-battery", + psy_desc->name = devm_kasprintf(&dev->dev, GFP_KERNEL, + "hid-%s-battery-%d", strlen(dev->uniq) ? - dev->uniq : dev_name(&dev->dev)); + dev->uniq : dev_name(&dev->dev), + field->report->id); if (!psy_desc->name) { error = -ENOMEM; goto err_free_desc; @@ -593,7 +609,7 @@ static int hidinput_setup_battery(struct hid_device *dev, unsigned report_type, } power_supply_powers(bat->ps, &dev->dev); - dev->battery = bat; + list_add_tail(&bat->list, &dev->batteries); return 0; err_free_name: @@ -602,7 +618,6 @@ err_free_desc: devm_kfree(&dev->dev, psy_desc); err_free_bat: devm_kfree(&dev->dev, bat); - dev->battery = NULL; return error; } @@ -620,12 +635,13 @@ static bool hidinput_update_battery_charge_status(struct hid_battery *bat, return false; } -static void hidinput_update_battery(struct hid_device *dev, unsigned int usage, - int value) +static void hidinput_update_battery(struct hid_device *dev, int report_id, + unsigned int usage, int value) { - struct hid_battery *bat = dev->battery; + struct hid_battery *bat; int capacity; + bat = hidinput_find_battery(dev, report_id); if (!bat) return; @@ -661,8 +677,8 @@ static int hidinput_setup_battery(struct hid_device *dev, unsigned report_type, return 0; } -static void hidinput_update_battery(struct hid_device *dev, unsigned int usage, - int value) +static void hidinput_update_battery(struct hid_device *dev, int report_id, + unsigned int usage, int value) { } #endif /* CONFIG_HID_BATTERY_STRENGTH */ @@ -1546,7 +1562,7 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct return; if (usage->type == EV_PWR) { - hidinput_update_battery(hid, usage->hid, value); + hidinput_update_battery(hid, report->id, usage->hid, value); return; } |
