Re: [PATCH v2 3/3] attrib/gattrib: Add tracking all the internal request id

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

 



Hi Lukasz:

On Thu, Dec 18, 2014 at 5:46 AM, Lukasz Rymanowski
<lukasz.rymanowski@xxxxxxxxx> wrote:
> With this patch gattrib track all the pending request id's to bt_att.
> When doing g_attrib_cancel_all, only those own by gattrib will be
> canceled.
> ---
>  attrib/gattrib.c | 95 ++++++++++++++++++++++++--------------------------------
>  1 file changed, 41 insertions(+), 54 deletions(-)
>
> diff --git a/attrib/gattrib.c b/attrib/gattrib.c
> index f986a77..5709d84 100644
> --- a/attrib/gattrib.c
> +++ b/attrib/gattrib.c
> @@ -54,9 +54,13 @@ struct _GAttrib {
>         struct queue *track_ids;
>  };
>
> +struct id_pair {
> +       unsigned int org_id;
> +       unsigned int pend_id;
> +};
>
>  struct attrib_callbacks {
> -       unsigned int id;
> +       struct id_pair *id;
>         GAttribResultFunc result_func;
>         GAttribNotifyFunc notify_func;
>         GDestroyNotify destroy_func;
> @@ -65,20 +69,6 @@ struct attrib_callbacks {
>         uint16_t notify_handle;
>  };
>
> -struct id_pair {
> -       unsigned int org_id;
> -       unsigned int pend_id;
> -};
> -
> -
> -static bool find_with_pend_id(const void *data, const void *user_data)
> -{
> -       const struct id_pair *p = data;
> -       unsigned int pending = PTR_TO_UINT(user_data);
> -
> -       return (p->pend_id == pending);
> -}
> -
>  static bool find_with_org_id(const void *data, const void *user_data)
>  {
>         const struct id_pair *p = data;
> @@ -87,37 +77,22 @@ static bool find_with_org_id(const void *data, const void *user_data)
>         return (p->org_id == orig_id);
>  }
>
> -static void remove_stored_ids(GAttrib *attrib, unsigned int pending_id)
> -{
> -       struct id_pair *p;
> -
> -       p = queue_remove_if(attrib->track_ids, find_with_pend_id,
> -                                               UINT_TO_PTR(pending_id));
> -
> -       free(p);
> -}
> -
> -static void store_id(GAttrib *attrib, unsigned int org_id,
> +static struct id_pair *store_id(GAttrib *attrib, unsigned int org_id,
>                                                         unsigned int pend_id)
>  {
>         struct id_pair *t;
>
> -       t = queue_find(attrib->track_ids, find_with_org_id,
> -                                                       UINT_TO_PTR(org_id));
> -       if (t) {
> -               t->pend_id = pend_id;
> -               return;
> -       }
> -
>         t = new0(struct id_pair, 1);
>         if (!t)
> -               return;
> +               return NULL;
>
>         t->org_id = org_id;
>         t->pend_id = pend_id;
>
> -       if (!queue_push_tail(attrib->track_ids, t))
> -               free(t);
> +       if (queue_push_tail(attrib->track_ids, t))
> +               return t;
> +
> +       return NULL;
>  }
>
>  GAttrib *g_attrib_new(GIOChannel *io, guint16 mtu)
> @@ -185,6 +160,9 @@ static void attrib_callbacks_destroy(void *data)
>         if (cb->destroy_func)
>                 cb->destroy_func(cb->user_data);
>
> +       if (queue_remove(cb->parent->track_ids, cb->id))
> +               free(cb->id);
> +
>         free(data);
>  }
>
> @@ -291,8 +269,6 @@ static void attrib_callback_result(uint8_t opcode, const void *pdu,
>         if (cb->result_func)
>                 cb->result_func(status, buf, length + 1, cb->user_data);
>
> -       remove_stored_ids(cb->parent, cb->id);
> -
>         free(buf);
>  }
>
> @@ -328,6 +304,7 @@ guint g_attrib_send(GAttrib *attrib, guint id, const guint8 *pdu, guint16 len,
>         struct attrib_callbacks *cb = NULL;
>         bt_att_response_func_t response_cb = NULL;
>         bt_att_destroy_func_t destroy_cb = NULL;
> +       unsigned int pend_id;
>
>         if (!attrib)
>                 return 0;
> @@ -349,32 +326,36 @@ guint g_attrib_send(GAttrib *attrib, guint id, const guint8 *pdu, guint16 len,
>
>         }
>
> -       cb->id = bt_att_send(attrib->att, pdu[0], (void *) pdu + 1, len - 1,
> +       pend_id = bt_att_send(attrib->att, pdu[0], (void *) pdu + 1, len - 1,
>                                                 response_cb, cb, destroy_cb);
>
> -       if (id == 0)
> -               return cb->id;
> +       /*
> +        * We store here pair as it is easier to handle it in response and in
> +        * case where user request us to use specific id request - see below.
> +        */
> +       if (id == 0) {
> +               cb->id = store_id(attrib, pend_id, pend_id);
> +               return pend_id;
> +       }
>
>         /*
>          * If user what us to use given id, lets keep track on that so we give
>          * user a possibility to cancel ongoing request.
>          */
> -       store_id(attrib, id, cb->id);
> +       cb->id = store_id(attrib, id, pend_id);
>         return id;
>  }
>
>  gboolean g_attrib_cancel(GAttrib *attrib, guint id)
>  {
>         struct id_pair *p;
> -       unsigned int pend_id;
>
>         if (!attrib)
>                 return FALSE;
>
>         /*
> -        * Let's try to find actual pending request id on the tracking id queue.
> -        * If there is no such it means it is not tracked id and we can cancel
> -        * it.
> +        * If request belongs to gattrib and is not yet done it has to be on
> +        * the tracking id queue
>          *
>          * FIXME: It can happen that on the queue there is id_pair with
>          * given id which was provided by the user. In the same time it might
> @@ -386,14 +367,18 @@ gboolean g_attrib_cancel(GAttrib *attrib, guint id)
>          */
>         p = queue_remove_if(attrib->track_ids, find_with_org_id,
>                                                         UINT_TO_PTR(id));
> -       if (p) {
> -               pend_id = p->pend_id;
> -               free(p);
> -       } else {
> -               pend_id = id;
> -       }
> +       if (!p)
> +               return FALSE;
>
> -       return bt_att_cancel(attrib->att, pend_id);
> +       return bt_att_cancel(attrib->att, p->pend_id);
> +}
> +
> +static void cancel_request(void *data, void *user_data)
> +{
> +       struct id_pair *p = data;
> +       GAttrib *attrib = user_data;
> +
> +       bt_att_cancel(attrib->att, p->pend_id);
>  }
>
>  gboolean g_attrib_cancel_all(GAttrib *attrib)
> @@ -401,9 +386,11 @@ gboolean g_attrib_cancel_all(GAttrib *attrib)
>         if (!attrib)
>                 return FALSE;
>
> +       /* Cancel only request which belongs to gattrib */
> +       queue_foreach(attrib->track_ids, cancel_request, attrib);
>         queue_remove_all(attrib->track_ids, NULL, NULL, free);
>
> -       return bt_att_cancel_all(attrib->att);
> +       return TRUE;
>  }
>
>  guint g_attrib_register(GAttrib *attrib, guint8 opcode, guint16 handle,
> --
> 1.8.4

I think you can eliminate a lot of memory management, the additional
queue and more by putting the pend_id and org_id both into
attrib_callbacks and then keeping all the pending requests, regardless
of whether they have a callback function, in the attrib->callbacks
queue.

The request can be cancelled in attrib_callbacks_destroy then.

--
Michael Janssen
--
To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[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