On Fri, Jan 20, 2017 at 02:27:41PM -0800, Simon Ratner wrote:
> I am talking about GATT reads, where the mbuf is pre-allocated for the app
> to fill in:
> 
> - static int
> - gatt_svr_chr_access_gap(
> -   uint16_t conn_handle,
> -   uint16_t attr_handle,
> -   struct ble_gatt_access_ctxt *ctxt, void *arg)
> - {
> -   ...
> -   os_mbuf_append(ctxt->om, data, len);
> -   ...
> - }
> -
> - Similarly, GATT read ops triggered by ble_gatt_chr_updated for sending
> out notifications.

These mbufs never actually get sent to the controller, so they don't
need the extra leading space.  After the application fills one of these
mbufs with a characteristic's value, the host copies the relevant data
into a properly allocated mbuf and sends the copy.

This may seem wasteful (in fact, that's what I'm thinking as I write
this!), but there is at least some logic here.  In the case of a GATT
read, the peer may read from different offsets of the characteristic.
In an effort to simplify the API, I decided the requested offset should
be hidden from the application.  Instead, the application always
provides the full characteristic value, and the host copies the
requested portion out of the user-filled mbuf and into the ACL data
packet.

There are some optimizations that could be done here.  In most cases,
the host is interested in the full attribute value.  The host should
probably allocate GATT read mbufs using ble_hs_mbuf_att_pkt() in these
cases so that it can just send the mbuf after the application has filled
it.

Alternatively, the host could specify the offset and length being read,
and require the application to provide only the requested range of
bytes.  This would be a little messier, but would be the most mbuf
efficient.

I'm thinking we should do the first optimization immediately.  I don't
believe it would be much work, and I don't see any downsides.  I'll take
a closer look at it today.

Chris

Reply via email to