Hello all,

I have just committed some NimBLE host API changes to the develop
branch.  These changes have been made as a result of issues raised in
this email thread.

Summary of changes:

1. Two new GAP event types:
    * notify_tx: we sent out a notification or indication, or an
                 indication transaction has completed (successfully or
                 not).

    * subscribe: peer has changed its subscription state for
                 notifications or indications.

2. Old GAP event "notify" renamed to notify_rx.

3. Connection descriptor no longer included in GAP event struct.
   Instead, just the connection handle is indicated.  The application
   can perform a connection lookup if necessary (ble_gap_conn_find()).
   The exception is the "disconnect" event; this event still contains
   the connection descriptor, since a lookup cannot be performed on a
   connection that is no longer established..

First, a note about the third change- it is not related to this email
thread, but I snuck it in there anyway.  Prior to this change, most GAP
events contained a connection descriptor (struct ble_gap_conn_desc)
which contains a bunch information about the relevant connection.
Having the stack do a connection lookup for every GAP event could
potentially be a performance issue if there are lots of connections and
lots of GAP events.  It is easy enough for the application to perform
the lookup in the GAP callback, and the application may not need this
information each time an event occurs, so I think the new interface just
makes more sense.  The example BLE apps (bleprph, blecent, bletiny) have
been updated to use the new interface, so you might want to take a look
at their GAP event callbacks as a reference.

The first two changes came about as a result of this email thread.
Earlier, I mentioned that received indication-acks and changes in
subscription status might be signalled via calls to the appropriate GATT
access callback.  However, after some thought, I determined that it
is better to use the GAP callback for these occurrences.  My reasoning
is that I foresee there being many "GATT server" libraries which
implement one or more services (there is already one of these:
net/nimble/host/services/mandatory).  If indication and subscription
events were handled by the GATT callback, each of these libraries would
need to provide some sort of hook for the application to learn about
these events.  With the events being handled by the GAP callback
instead, these libraries can be self-contained and only focus on
implementing attribute reads and writes.

The details of these changes are below.  I have not updated the online
documentation yet, but I plan on doing that shortly.  Finally, I just
want to remind everyone that this is a community-driven project, so if
you see anything that could be improved, please don't hesitate to voice
your thoughts or submit a pull request.

Thanks,
Chris

#define BLE_GAP_EVENT_NOTIFY_RX             12
#define BLE_GAP_EVENT_NOTIFY_TX             13
#define BLE_GAP_EVENT_SUBSCRIBE             14

struct ble_gap_event {
    /* [...] */
        /**
         * Represents a received ATT notification or indication.
         *
         * Valid for the following event types:
         *     o BLE_GAP_EVENT_NOTIFY_RX
         */
        struct {
            /** The contents of the notification or indication. */
            void *attr_data;

            /** The handle of the relevant ATT attribute. */
            uint16_t attr_handle;

            /** The number of data bytes contained in the message. */
            uint16_t attr_len;

            /** The handle of the relevant connection. */
            uint16_t conn_handle;

            /**
             * Whether the received command is a notification or an
             * indication;
             *     o 0: Notification;
             *     o 1: Indication.
             */
            uint8_t indication:1;
        } notify_rx;

        /**
         * Represents a transmitted ATT notification or indication, or a
         * completed indication transaction.
         *
         * Valid for the following event types:
         *     o BLE_GAP_EVENT_NOTIFY_TX
         */
        struct {
            /**
             * The status of the notification or indication transaction;
             *     o 0:                 Command successfully sent;
             *     o BLE_HS_EDONE:      Confirmation (indication ack) received;
             *     o BLE_HS_ETIMEOUT:   Confirmation (indication ack) never
             *                              received;
             *     o Other return code: Error.
             */
            int status;

            /** The handle of the relevant connection. */
            uint16_t conn_handle;

            /** The handle of the relevant characterstic value. */
            uint16_t attr_handle;

            /**
             * Whether the transmitted command is a notification or an
             * indication;
             *     o 0: Notification;
             *     o 1: Indication.
             */
            uint8_t indication:1;
        } notify_tx;

        /**
         * Represents a state change in a peer's subscription status.  In this
         * comment, the term "update" is used to refer to either a notification
         * or an indication.  This event is triggered by any of the following
         * occurrences:
         *     o Peer enables or disables updates via a CCCD write.
         *     o Connection is about to be terminated and the peer is
         *       subscribed to updates.
         *     o Peer is now subscribed to updates after its state was restored
         *       from persistence.  This happens when bonding is restored.
         *
         * Valid for the following event types:
         *     o BLE_GAP_EVENT_SUBSCRIBE
         */
        struct {
            /** The handle of the relevant connection. */
            uint16_t conn_handle;

            /** The value handle of the relevant characteristic. */
            uint16_t attr_handle;

            /** One of the BLE_GAP_SUBSCRIBE_REASON codes. */
            uint8_t reason;

            /** Whether the peer was previously subscribed to notifications. */
            uint8_t prev_notify:1;

            /** Whether the peer is currently subscribed to notifications. */
            uint8_t cur_notify:1;

            /** Whether the peer was previously subscribed to indications. */
            uint8_t prev_indicate:1;

            /** Whether the peer is currently subscribed to indications. */
            uint8_t cur_indicate:1;
        } subscribe;
    };
};

Reply via email to