hog-lib: Fix not waiting for UHID_START
authorLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
Fri, 25 Feb 2022 22:18:47 +0000 (14:18 -0800)
committerAyush Garg <ayush.garg@samsung.com>
Mon, 15 May 2023 09:25:53 +0000 (14:55 +0530)
With use of UHID_CREATE2 the code needs to wait for UHID_START in order
to know if the reports are numbered or not.

Fixes: https://github.com/bluez/bluez/issues/298
Signed-off-by: Manika Shrivastava <manika.sh@samsung.com>
Signed-off-by: Ayush Garg <ayush.garg@samsung.com>
profiles/input/hog-lib.c

index 5c4b7e8..1a33ad0 100755 (executable)
@@ -81,6 +81,7 @@ struct bt_hog {
        struct bt_uhid          *uhid;
        int                     uhid_fd;
        bool                    uhid_created;
+       bool                    uhid_start;
        uint64_t                uhid_flags;
        uint16_t                bcdhid;
        uint8_t                 bcountrycode;
@@ -358,8 +359,8 @@ static void report_value_cb(const guint8 *pdu, guint16 len, gpointer user_data)
                ev.u.input.size = len;
        }
 
-       /* If uhid had not been created yet queue up the input */
-       if (!hog->uhid_created) {
+       /* If uhid had not sent UHID_START yet queue up the input */
+       if (!hog->uhid_created || !hog->uhid_start) {
                if (!hog->input)
                        hog->input = queue_new();
 
@@ -809,16 +810,34 @@ static void set_numbered(void *data, void *user_data)
        }
 }
 
+static bool input_dequeue(const void *data, const void *match_data)
+{
+       const struct uhid_event *ev = data;
+       const struct bt_hog *hog = match_data;
+       int err;
+
+       err = bt_uhid_send(hog->uhid, ev);
+       if (err < 0) {
+               error("bt_uhid_send: %s (%d)", strerror(-err), -err);
+               return false;
+       }
+
+       return true;
+}
+
 static void start_flags(struct uhid_event *ev, void *user_data)
 {
        struct bt_hog *hog = user_data;
 
+       hog->uhid_start = true;
        hog->uhid_flags = ev->u.start.dev_flags;
 
        DBG("uHID device flags: 0x%16" PRIx64, hog->uhid_flags);
 
        if (hog->uhid_flags)
                g_slist_foreach(hog->reports, set_numbered, hog);
+
+       queue_remove_all(hog->input, input_dequeue, hog, free);
 }
 
 static void set_report_cb(guint8 status, const guint8 *pdu,
@@ -992,21 +1011,6 @@ fail:
        report_reply(hog, err, 0, false, 0, NULL);
 }
 
-static bool input_dequeue(const void *data, const void *match_data)
-{
-       const struct uhid_event *ev = data;
-       const struct bt_hog *hog = match_data;
-       int err;
-
-       err = bt_uhid_send(hog->uhid, ev);
-       if (err < 0) {
-               error("bt_uhid_send: %s (%d)", strerror(-err), -err);
-               return false;
-       }
-
-       return true;
-}
-
 static void uhid_create(struct bt_hog *hog, uint8_t *report_map,
                                                        size_t report_map_len)
 {
@@ -1068,10 +1072,9 @@ static void uhid_create(struct bt_hog *hog, uint8_t *report_map,
        bt_uhid_register(hog->uhid, UHID_SET_REPORT, set_report, hog);
 
        hog->uhid_created = true;
+       hog->uhid_start = false;
 
        DBG("HoG created uHID device");
-
-       queue_remove_all(hog->input, input_dequeue, hog, free);
 }
 
 static void db_report_map_write_value_cb(struct gatt_db_attribute *attr,