Re: [PATCH BlueZ 2/2] input/hog: Cache the HID report map

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Luiz,

I sent a v2 that changes the cache to use gatt_db. Please take another
look. Thanks!


On Tue, Dec 8, 2020 at 5:58 PM Luiz Augusto von Dentz
<luiz.dentz@xxxxxxxxx> wrote:
>
> Hi Sonny,
>
> On Tue, Dec 8, 2020 at 5:16 PM Sonny Sasaka <sonnysasaka@xxxxxxxxxxxx> wrote:
> >
> > To optimize BLE HID devices reconnection response, we can cache the
> > report map so that the subsequent reconnections do not need round trip
> > time to read the report map.
>
> While the idea is pretty good we need to find a way to persist it
> across reboots/restarts. In theory we could save the value on the
> gatt_db instance and then make changes to device.c:store_desc to
> attempt to read if there is a value stored in the db save it on file
> as well so the next time the cache is loaded it should restore the
> report map, or any other descriptor that have its value saved in the
> database. That said we may need to introduce some sort of property for
> values stored in the db since normally the values store in the
> database shall not be persisted on file, in fact it would cause a lot
> of fime access updating the cache if we were to trigger updates
> everytime the db is updated with a value.
>
> > Reviewed-by: Alain Michaud <alainm@xxxxxxxxxxxx>
> >
> > ---
> >  profiles/input/hog-lib.c | 142 ++++++++++++++++++++++++++-------------
> >  1 file changed, 96 insertions(+), 46 deletions(-)
> >
> > diff --git a/profiles/input/hog-lib.c b/profiles/input/hog-lib.c
> > index ee811d301..1e198ea64 100644
> > --- a/profiles/input/hog-lib.c
> > +++ b/profiles/input/hog-lib.c
> > @@ -95,6 +95,8 @@ struct bt_hog {
> >         struct queue            *bas;
> >         GSList                  *instances;
> >         struct queue            *gatt_op;
> > +       uint8_t                 report_map[HOG_REPORT_MAP_MAX_SIZE];
> > +       ssize_t                 report_map_len;
> >  };
> >
> >  struct report {
> > @@ -276,6 +278,8 @@ static void find_included(struct bt_hog *hog, GAttrib *attrib,
> >         free(req);
> >  }
> >
> > +static void uhid_create(struct bt_hog *hog);
> > +
> >  static void report_value_cb(const guint8 *pdu, guint16 len, gpointer user_data)
> >  {
> >         struct report *report = user_data;
> > @@ -924,57 +928,17 @@ static char *item2string(char *str, uint8_t *buf, uint8_t len)
> >         return str;
> >  }
> >
> > -static void report_map_read_cb(guint8 status, const guint8 *pdu, guint16 plen,
> > -                                                       gpointer user_data)
> > +static void uhid_create(struct bt_hog *hog)
> >  {
> > -       struct gatt_request *req = user_data;
> > -       struct bt_hog *hog = req->user_data;
> > -       uint8_t value[HOG_REPORT_MAP_MAX_SIZE];
> >         struct uhid_event ev;
> > -       ssize_t vlen;
> > -       char itemstr[20]; /* 5x3 (data) + 4 (continuation) + 1 (null) */
> > -       int i, err;
> >         GError *gerr = NULL;
> > +       int i, err;
> >
> > -       destroy_gatt_req(req);
> > -
> > -       DBG("HoG inspecting report map");
> > -
> > -       if (status != 0) {
> > -               error("Report Map read failed: %s", att_ecode2str(status));
> > -               return;
> > -       }
> > -
> > -       vlen = dec_read_resp(pdu, plen, value, sizeof(value));
> > -       if (vlen < 0) {
> > -               error("ATT protocol error");
> > +       if (!hog->report_map_len) {
> > +               warn("Failed to initiate UHID_CREATE without report map");
> >                 return;
> >         }
> >
> > -       DBG("Report MAP:");
> > -       for (i = 0; i < vlen;) {
> > -               ssize_t ilen = 0;
> > -               bool long_item = false;
> > -
> > -               if (get_descriptor_item_info(&value[i], vlen - i, &ilen,
> > -                                                               &long_item)) {
> > -                       /* Report ID is short item with prefix 100001xx */
> > -                       if (!long_item && (value[i] & 0xfc) == 0x84)
> > -                               hog->has_report_id = TRUE;
> > -
> > -                       DBG("\t%s", item2string(itemstr, &value[i], ilen));
> > -
> > -                       i += ilen;
> > -               } else {
> > -                       error("Report Map parsing failed at %d", i);
> > -
> > -                       /* Just print remaining items at once and break */
> > -                       DBG("\t%s", item2string(itemstr, &value[i], vlen - i));
> > -                       break;
> > -               }
> > -       }
> > -
> > -       /* create uHID device */
> >         memset(&ev, 0, sizeof(ev));
> >         ev.type = UHID_CREATE;
> >
> > @@ -1004,8 +968,8 @@ static void report_map_read_cb(guint8 status, const guint8 *pdu, guint16 plen,
> >         ev.u.create.version = hog->version;
> >         ev.u.create.country = hog->bcountrycode;
> >         ev.u.create.bus = BUS_BLUETOOTH;
> > -       ev.u.create.rd_data = value;
> > -       ev.u.create.rd_size = vlen;
> > +       ev.u.create.rd_data = hog->report_map;
> > +       ev.u.create.rd_size = hog->report_map_len;
> >
> >         err = bt_uhid_send(hog->uhid, &ev);
> >         if (err < 0) {
> > @@ -1018,6 +982,62 @@ static void report_map_read_cb(guint8 status, const guint8 *pdu, guint16 plen,
> >         bt_uhid_register(hog->uhid, UHID_SET_REPORT, set_report, hog);
> >
> >         hog->uhid_created = true;
> > +}
> > +
> > +static void report_map_read_cb(guint8 status, const guint8 *pdu, guint16 plen,
> > +                                                       gpointer user_data)
> > +{
> > +       struct gatt_request *req = user_data;
> > +       struct bt_hog *hog = req->user_data;
> > +       ssize_t vlen;
> > +       char itemstr[20]; /* 5x3 (data) + 4 (continuation) + 1 (null) */
> > +       int i;
> > +
> > +       destroy_gatt_req(req);
> > +
> > +       DBG("HoG inspecting report map");
> > +
> > +       if (status != 0) {
> > +               error("Report Map read failed: %s", att_ecode2str(status));
> > +               return;
> > +       }
> > +
> > +       vlen = dec_read_resp(pdu, plen, hog->report_map,
> > +                                               sizeof(hog->report_map));
> > +       if (vlen < 0) {
> > +               error("ATT protocol error");
> > +               return;
> > +       }
> > +
> > +       hog->report_map_len = vlen;
> > +
> > +       DBG("Report MAP:");
> > +       for (i = 0; i < vlen;) {
> > +               ssize_t ilen = 0;
> > +               bool long_item = false;
> > +
> > +               if (get_descriptor_item_info(&hog->report_map[i], vlen - i,
> > +                                               &ilen, &long_item)) {
> > +                       /* Report ID is short item with prefix 100001xx */
> > +                       if (!long_item && (hog->report_map[i] & 0xfc) == 0x84)
> > +                               hog->has_report_id = TRUE;
> > +
> > +                       DBG("\t%s", item2string(itemstr, &hog->report_map[i],
> > +                                                                       ilen));
> > +
> > +                       i += ilen;
> > +               } else {
> > +                       error("Report Map parsing failed at %d", i);
> > +
> > +                       /* Just print remaining items at once and break */
> > +                       DBG("\t%s", item2string(itemstr, &hog->report_map[i],
> > +                                               vlen - i));
> > +                       break;
> > +               }
> > +       }
> > +
> > +       /* create uHID device */
> > +       uhid_create(hog);
> >
> >         DBG("HoG created uHID device");
> >  }
> > @@ -1602,6 +1622,12 @@ bool bt_hog_attach(struct bt_hog *hog, void *gatt)
> >                 bt_hog_attach(instance, gatt);
> >         }
> >
> > +       /* Try to initiate UHID_CREATE if we already have the report map to
> > +        * avoid re-reading the report map from the peer device.
> > +        */
> > +       if (hog->report_map_len > 0)
> > +               uhid_create(hog);
> > +
> >         if (!hog->uhid_created) {
> >                 DBG("HoG discovering characteristics");
> >                 if (hog->attr)
> > @@ -1627,6 +1653,29 @@ bool bt_hog_attach(struct bt_hog *hog, void *gatt)
> >         return true;
> >  }
> >
> > +static void uhid_destroy(struct bt_hog *hog)
> > +{
> > +       int err;
> > +       struct uhid_event ev;
> > +
> > +       if (!hog->uhid_created)
> > +               return;
> > +
> > +       bt_uhid_unregister_all(hog->uhid);
> > +
> > +       memset(&ev, 0, sizeof(ev));
> > +       ev.type = UHID_DESTROY;
> > +
> > +       err = bt_uhid_send(hog->uhid, &ev);
> > +
> > +       if (err < 0) {
> > +               error("bt_uhid_send: %s", strerror(-err));
> > +               return;
> > +       }
> > +
> > +       hog->uhid_created = false;
> > +}
> > +
> >  void bt_hog_detach(struct bt_hog *hog)
> >  {
> >         GSList *l;
> > @@ -1660,6 +1709,7 @@ void bt_hog_detach(struct bt_hog *hog)
> >         queue_foreach(hog->gatt_op, (void *) cancel_gatt_req, NULL);
> >         g_attrib_unref(hog->attrib);
> >         hog->attrib = NULL;
> > +       uhid_destroy(hog);
> >  }
> >
> >  int bt_hog_set_control_point(struct bt_hog *hog, bool suspend)
> > --
> > 2.26.2
> >
>
>
> --
> Luiz Augusto von Dentz



[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux