Hi,

On Mon, Sep 10, 2018 at 9:56 AM Łukasz Rymanowski <
lukasz.rymanow...@codecoup.pl> wrote:

> Hi
> On Fri, 7 Sep 2018 at 21:12, Andrzej Kaczmarek <
> andrzej.kaczma...@codecoup.pl> wrote:
>
> > Hi Chris,
> >
> > On Fri, Sep 7, 2018 at 8:00 PM Christopher Collins <ch...@runtime.io>
> > wrote:
> >
> > > Hello all,
> > >
> > > TL;DR: Proposal for registration of GAP event listeners in the NimBLE
> > > host.  Currently, GAP event callbacks are specified by the code which
> > > creates a connection.  This proposal allows code to listen for GAP
> > > events without creating a connection.
> > >
> > > The NimBLE host allows the application to associate callbacks with GAP
> > > events.  Callbacks are configured *per connection*.  When the
> > > application initiates a connection, it specifies a single callback to
> > > be executed for all GAP events involving the connection.  Similarly,
> > > when the application starts advertising, it specifies the callback to
> > > use with the connection that may result.
> > >
> > > This design provides some degree of modularity.  If a package
> > > independently creates a connection, it can handle all the relevant GAP
> > > events without involving other packages in the system.  However, there
> > > is a type of modularity that this does not provide: *per event*
> > > callbacks.  If a package doesn't want to initiate any GAP events, but
> > > it wants to be notified every time a connection is established (for
> > > example), there is no way to achieve this.  The problem here is that
> > > there is only a single callback associated with each connection.  What
> > > we really need is a list of callbacks that all get called whenever a
> > > GAP event occurs.
> > >
> > > My proposal is to add the following to the NimBLE host API:
> > >
> > >     struct ble_gap_listener {
> > >         /*** Public. */
> > >         ble_gap_event_fn *fn;
> > >         void *arg;
> > >
> > >         /*** Internal. */
> > >         STAILQ_ENTRY(ble_gap_listener) next;
> > >     };
> > >
> > >     /**
> > >      * @brief Registers a BLE GAP listener.
> > >      *
> > >      * When a GAP event occurs, callbacks are executed in the following
> > >      * order:
> > >      * 1. Connection-specific GAP event callback.
> > >      * 2. Each registered listener, in the order they were registered.
> > >      *
> > >      * @param listener                 The listener to register.
> > >      */
> > >     void ble_gap_register(struct ble_gap_listener *listener);
> > >
> > >     /**
> > >      * @brief Unregisters a BLE GAP listener.
> > >      *
> > >      * @param listener                 The listener to unregister.
> > >      *
> > >      * @return                      0 on success;
> > >      *                              BLE_HS_ENOENT if the listener is
> > >      *                                  not registered.
> > >      */
> > >     int ble_gap_unregister(struct ble_gap_listener *listener);
> > >
> > > Initially, I thought this functionality could be achieved with a new
> > > package implemented on top of the host (call it `blemux`).
> > > Unfortunately, I think there are some issues that make such an approach
> > > unwieldy for the user.  I imagined such a package would be used as
> > > follows:
> > >
> > >     1. The `blemux` package exposes a GAP callback (call it
> > >        `blemux_gap_event`).
> > >     2. Elsewhere in the sytem, for each GAP function call, the caller
> > >        specifies `blemux_gap_event` as the callback.
> > >     3. Each package that is interested in GAP events registers one or
> > >        more listeners via `blemux_register()`.
> > >     4. When a GAP event occurs, `blemux_gap_event` is executed.  This
> > >        callback executes every registered listener.
> > >
> > > The problem is that packages have no guarantee that the app is using
> > > blemux.  A package can depend on `blemux` and can register listeners,
> > > but it really only works if every other BLE-aware package in the system
> > > also uses `blemux`.  If any package doesn't use `blemux`, then the GAP
> > > procedures that it initiates won't be reported to the `blemux`
> > > listeners.  A secondary problem is that this just feels like a clumsy
> > > API.  It is confusing and error prone to need to specify
> > > `blemux_gap_event` as the GAP event callback.
> > >
> > > So, I think this functionality should be implemented directly in the
> > > host.
> > >
> >
> >
> Like the idea. We could use it for mesh as well - for now we have dedicated
> API for Mesh to register for GAP events.
> With this change we could get rid of it.
>

Indeed. Also we can simplify existing services.


> > Sounds exactly like something I wrote some time ago, so I can only agree
> > with above :-)
> > Typical scenario here (and what I was doing) is that external package,
> like
> > service, wants to be notified about connection or characteristic
> > subscription state. Currently we do this by exposing extra API from
> package
> > which app needs to call from GAP callbacks in order to everything work
> > properly. It works, but it's really clunky. Hooks provided by host are
> imo
> > good way to handle this.
> >
> > I did not finish my service so forgot to send a PR with NimBLE changes,
> but
> > here they are for reference - I can create PR if they look ok.
> >
> >
> https://github.com/andrzej-kaczmarek/apache-mynewt-nimble/commit/6cc902821e6d65fbd5f72fa89e7219915afca38d
>
>
> Looks it does what it should, however ble_gap_register() sounds like a
> better name for API to me imho.
>

"Hooks" were just temporary name. I renamed everything to "event listeners"
and pushed this as a PR: https://github.com/apache/mynewt-nimble/pull/185


> >
> > The API is pretty much the same as proposed. The difference is that
> > listener struct is opaque and fields are initialized when listener is
> > registered.
> > Notified events are the ones which are notifications, i.e. do not require
> > interaction from app (so e.g. pairing event does not call listeners since
> > it does not make sense to do so).
> >
> > > Thoughts?
>
> >
> > > Thanks,
> > > Chris
> > >
> >
> >
> Best
> Łukasz
>

Best,
Andrzej



>
>
> > Best,
> > Andrzej
> >
>

Reply via email to