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,

It's already here:
https://patchwork.kernel.org/project/bluetooth/patch/20201211233047.108658-2-sonnysasaka@xxxxxxxxxxxx/.

On Fri, Dec 11, 2020 at 5:12 PM Luiz Augusto von Dentz
<luiz.dentz@xxxxxxxxx> wrote:
>
> Hi Sonny,
>
> On Fri, Dec 11, 2020 at 3:32 PM Sonny Sasaka <sonnysasaka@xxxxxxxxxxxx> wrote:
> >
> > Hi Luiz,
> >
> > I sent a v2 that changes the cache to use gatt_db. Please take another
> > look. Thanks!
>
> It doesn't seem to have reached the list yet, or perhaps my mail
> server is playing tricks on me.
>
> >
> > 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
>
>
>
> --
> 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