Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Requirements for implementing the Matter BTP protocol on top of trouble-host #135

Open
ivmarkov opened this issue Oct 9, 2024 · 2 comments

Comments

@ivmarkov
Copy link

ivmarkov commented Oct 9, 2024

(This is a follow up on the Embassy Matrix room discussion here.)

Overview

I'm currently researching for a way to layer the Matter BTP protocol (section "4.18. Bluetooth Transport Protocol (BTP)" of the Matter Core Spec V1.3) on top of trouble-host.

(

).

A very short, informal summary of what are the BTP protocol requirements w.r.t. a GATT Server: it boils down to modeling a duplex read/write pipe on top of two characteristics (referred to as C1 and C2) in the BTP spec:

  • C1 has a Write-Confirmed permission, and serves as the "read" end of the pipe, from the POV of the device which is being commissioned (the GATT server), and as the "write" end of the pipe from the point of view of the Commissioner (your phone)
  • C2 is a CCCD "indicate" characteristics that serves as the "write" end of the pipe, from the POV of the device which is being commissioned

In terms of requirements around these two characteristics:

  • W.r.t. C1 we need the Matter BTP implementation code to be notified about every single incoming write request, with the following data:
    • Peer BT address (possibly coming from the GATT connection itself)
    • Data offset
    • Data length
    • Data octets
    • ATT MTU
    • Moreover, the notifications should arrive in the user code (Matter BTP implementation) sequentially one after the other, so that the BTP implementation has the chance to inspect each incoming data chunk separately
    • The GATT server should support confirmed (acknowledged) writes, as this is what the BTP protocol mandates
  • W.r.t. C2:
    • We need to be able to notify (or rather "indicate") a remote peer - at any point in time - with a slice of data octets
    • We also need to know when a remote peer is subscribing/unsubscribing to/from characteristic C2

Additionally, we must be able to advertise our own vendor-specific payload, which is described in "5.4.2.5.6. Advertising Data" of the Matter Core Spec.

In terms of how a GATT "peripheral", specific to the purposes of the BTP protocol might look like, you can look here. (Do note that whether the C1 writes are coming via a blocking callback or are somehow "pulled" using async next external style iteration is not set in stone and we can change that.)

Challenges with trouble-host

One challenge identified so far is that trouble-host uses a static storage for each characteristic which is the same across all connections and which gets overwritten each time we get a write on the characteristic.

While this is not necessarily a problem per se, Matter BTP simply does not need and cannot make use of such a "single static storage per characteristic" model.

======

One way to completely bypass the static storage is to implement a "give me the read/write data and I'll store it myself somewhere" user-style callback exercised here.

Whether such a callback is preserving the "attribute table" without its data aspect or not is orthogonal to the Matter BTP implementation, because in it, the characteristic are static.

=====

Another way would be to keep the "attribute-table" and the "single, static, fixed-size storage of each characteristic" intact, and then hack our way around it. Also a WIP POC to be implementing an rs-matter GATT Peripheral specific to the BTP stack, using this approach/hack.

Turns out, it might not be as difficult as I think, by just making use of GattEvents, which - while dispatched "post-factum" after the data was read/written - still would allow us to figure out what data the peer was sending to us, by just reading it "post-factum" from the static characteristic storage, before it gets overwritten with the next characteristic Write request coming from the peer.

My next step is to try to prototype this approach, with another PR. Extensions to trouble-host would still be necessary:

  • At the very least, we need to know the data-length and data-offset of the last characteristic write (for which the GattEvent is dispatched).
  • We need a way to "indicate" on C2. Not sure if this is in-place, as I only see a GattServer::notify (i.e. unconfirmed notification) method
  • For C1, I'm not sure if trouble-host supports confirmed writes
  • There could be other needs too, as I might find out when prototyping this second PR.
@lulf
Copy link
Member

lulf commented Oct 14, 2024

  • Regarding confirmed writes, that is not supported by trouble-host at this point, but should probably not be a lot of work since I think it's a matter of using a different form of response to the att request.
  • Indication is basically notification without ACK, and should be implementable in a similar manner as notifications today (but probably with different CCCD configuration as well as different payload).

@alexmoon
Copy link

* Indication is basically notification without ACK, and should be implementable in a similar manner as notifications today (but probably with different CCCD configuration as well as different payload).

Just a real minor nit, but for clarity, indication's have ACKs and notifications do not. It is also possible to have both notifications and indications allowed for a characteristic and the client could enable one or the other (or both).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants