input/device: Unregister all UHID event listeners at UHID_DESTROY
authorSonny Sasaka <sonnysasaka@chromium.org>
Fri, 21 Aug 2020 04:35:36 +0000 (21:35 -0700)
committerAyush Garg <ayush.garg@samsung.com>
Mon, 12 Apr 2021 09:00:50 +0000 (14:30 +0530)
When destroying UHID, we should also unregister all event listeners so
that they don't get double registered at reconnection. It fixes a bug
where battery report is not available to kernel after reconnection and
also prevents memory leak.

Tested with Logitech M535 mouse:
* Connect mouse to the device running BlueZ
* cat /sys/class/power_supply/hid-{addr}-battery/capacity # works
* Disconnect mouse
* Reconnect mouse
* cat /sys/class/power_supply/hid-{addr}-battery/capacity # still works

Signed-off-by: Anuj Jain <anuj01.jain@samsung.com>
Signed-off-by: Ayush Garg <ayush.garg@samsung.com>
profiles/input/device.c
src/shared/uhid.c
src/shared/uhid.h

index 4740fd9..14f092f 100644 (file)
@@ -989,6 +989,8 @@ static int uhid_disconnect(struct input_device *idev)
        if (!idev->uhid_created)
                return 0;
 
+       bt_uhid_unregister_all(idev->uhid);
+
        memset(&ev, 0, sizeof(ev));
        ev.type = UHID_DESTROY;
 
index 1c684cd..576432c 100755 (executable)
@@ -218,6 +218,15 @@ bool bt_uhid_unregister(struct bt_uhid *uhid, unsigned int id)
        return true;
 }
 
+bool bt_uhid_unregister_all(struct bt_uhid *uhid)
+{
+       if (!uhid)
+               return false;
+
+       queue_remove_all(uhid->notify_list, NULL, NULL, free);
+       return true;
+}
+
 int bt_uhid_send(struct bt_uhid *uhid, const struct uhid_event *ev)
 {
        ssize_t len;
index 459a249..dbdca85 100755 (executable)
@@ -40,5 +40,6 @@ typedef void (*bt_uhid_callback_t)(struct uhid_event *ev, void *user_data);
 unsigned int bt_uhid_register(struct bt_uhid *uhid, uint32_t event,
                                bt_uhid_callback_t func, void *user_data);
 bool bt_uhid_unregister(struct bt_uhid *uhid, unsigned int id);
+bool bt_uhid_unregister_all(struct bt_uhid *uhid);
 
 int bt_uhid_send(struct bt_uhid *uhid, const struct uhid_event *ev);