Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f5e7138c authored by Andre Eisenbach's avatar Andre Eisenbach
Browse files

LE: Add notification sent and congestion callbacks (2/4)

This change introduces two new callbacks for applications to better
handle LE notification flow control and transport congestion. The
notification callback is invoked when the remote platform confirms an
indication or when a local notification has been passed to the
controller. No new notifications should be sent until a callback is
received.

Congestion callbacks are triggered when a GATT operation cannot be sent
to the local Bluetooth controller. Repeatedly calling
writeCharacteristic() for example will eventually trigger a congestion
callback. Applications cannot send additional data until a further
callback is received, indicating that the congestion has cleared up.

Also fixes a memory leak issue that can trigger GKI exception for
certain GATT operations.

Change-Id: I7112bdfc1fedec2e390bd0ea52655d238683917f
parent de86d49a
Loading
Loading
Loading
Loading
+33 −5
Original line number Original line Diff line number Diff line
@@ -52,8 +52,8 @@ static void bta_gattc_cmpl_cback(UINT16 conn_id, tGATTC_OPTYPE op, tGATT_STATUS
                                  tGATT_CL_COMPLETE *p_data);
                                  tGATT_CL_COMPLETE *p_data);


static void bta_gattc_deregister_cmpl(tBTA_GATTC_RCB *p_clreg);
static void bta_gattc_deregister_cmpl(tBTA_GATTC_RCB *p_clreg);

static void bta_gattc_enc_cmpl_cback(tGATT_IF gattc_if, BD_ADDR bda);
static void bta_gattc_enc_cmpl_cback(tGATT_IF gattc_if, BD_ADDR bda);
static void bta_gattc_cong_cback (UINT16 conn_id, BOOLEAN congested);


static tGATT_CBACK bta_gattc_cl_cback =
static tGATT_CBACK bta_gattc_cl_cback =
{
{
@@ -62,7 +62,8 @@ static tGATT_CBACK bta_gattc_cl_cback =
    bta_gattc_disc_res_cback,
    bta_gattc_disc_res_cback,
    bta_gattc_disc_cmpl_cback,
    bta_gattc_disc_cmpl_cback,
    NULL,
    NULL,
    bta_gattc_enc_cmpl_cback
    bta_gattc_enc_cmpl_cback,
    bta_gattc_cong_cback
};
};


/* opcode(tGATTC_OPTYPE) order has to be comply with internal event order */
/* opcode(tGATTC_OPTYPE) order has to be comply with internal event order */
@@ -2128,6 +2129,33 @@ static void bta_gattc_cmpl_cback(UINT16 conn_id, tGATTC_OPTYPE op, tGATT_STATUS


    return;
    return;
}
}

/*******************************************************************************
**
** Function         bta_gattc_cong_cback
**
** Description      congestion callback for BTA GATT client.
**
** Returns          void
**
********************************************************************************/
static void bta_gattc_cong_cback (UINT16 conn_id, BOOLEAN congested)
{
    tBTA_GATTC_CLCB *p_clcb;
    tBTA_GATTC cb_data;

    if ((p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id)) != NULL)
    {
        if (p_clcb->p_rcb->p_cback)
        {
            cb_data.congest.conn_id = conn_id;
            cb_data.congest.congested = congested;

            (*p_clcb->p_rcb->p_cback)(BTA_GATTC_CONGEST_EVT, &cb_data);
        }
    }
}

#if BLE_INCLUDED == TRUE
#if BLE_INCLUDED == TRUE
/*******************************************************************************
/*******************************************************************************
**
**
+6 −2
Original line number Original line Diff line number Diff line
@@ -322,9 +322,13 @@ BOOLEAN bta_gattc_sm_execute(tBTA_GATTC_CLCB *p_clcb, UINT16 event, tBTA_GATTC_D
        if ((action = state_table[event][i]) != BTA_GATTC_IGNORE)
        if ((action = state_table[event][i]) != BTA_GATTC_IGNORE)
        {
        {
            (*bta_gattc_action[action])(p_clcb, p_data);
            (*bta_gattc_action[action])(p_clcb, p_data);

            if (p_clcb->buf_held)
            {
                p_clcb->buf_held = FALSE;
                p_clcb->buf_held = FALSE;
                rt = FALSE;
                rt = FALSE;
            }
            }
        }
        else
        else
        {
        {
            break;
            break;
+44 −3
Original line number Original line Diff line number Diff line
@@ -46,6 +46,8 @@ static void bta_gatts_conn_cback (tGATT_IF gatt_if, BD_ADDR bda, UINT16 conn_id,
static void bta_gatts_send_request_cback (UINT16 conn_id,
static void bta_gatts_send_request_cback (UINT16 conn_id,
                                          UINT32 trans_id,
                                          UINT32 trans_id,
                                          tGATTS_REQ_TYPE req_type, tGATTS_DATA *p_data);
                                          tGATTS_REQ_TYPE req_type, tGATTS_DATA *p_data);
static void bta_gatts_cong_cback (UINT16 conn_id, BOOLEAN congested);

static tGATT_CBACK bta_gatts_cback =
static tGATT_CBACK bta_gatts_cback =
{
{
    bta_gatts_conn_cback,
    bta_gatts_conn_cback,
@@ -53,7 +55,8 @@ static tGATT_CBACK bta_gatts_cback =
    NULL,
    NULL,
    NULL,
    NULL,
    bta_gatts_send_request_cback,
    bta_gatts_send_request_cback,
    NULL
    NULL,
    bta_gatts_cong_cback
};
};


tGATT_APPL_INFO bta_gatts_nv_cback =
tGATT_APPL_INFO bta_gatts_nv_cback =
@@ -633,10 +636,12 @@ void bta_gatts_send_rsp (tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA * p_msg)
void bta_gatts_indicate_handle (tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA * p_msg)
void bta_gatts_indicate_handle (tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA * p_msg)
{
{
    tBTA_GATTS_SRVC_CB  *p_srvc_cb;
    tBTA_GATTS_SRVC_CB  *p_srvc_cb;
    tBTA_GATTS_RCB      *p_rcb = NULL;
    tBTA_GATT_STATUS    status = BTA_GATT_ILLEGAL_PARAMETER;
    tBTA_GATT_STATUS    status = BTA_GATT_ILLEGAL_PARAMETER;
    tGATT_IF            gatt_if;
    tGATT_IF            gatt_if;
    BD_ADDR             remote_bda;
    BD_ADDR             remote_bda;
    tBTA_TRANSPORT transport;
    tBTA_TRANSPORT transport;
    tBTA_GATTS          cb_data;


    p_srvc_cb = bta_gatts_find_srvc_cb_by_attr_id (p_cb, p_msg->api_indicate.attr_id);
    p_srvc_cb = bta_gatts_find_srvc_cb_by_attr_id (p_cb, p_msg->api_indicate.attr_id);


@@ -645,6 +650,8 @@ void bta_gatts_indicate_handle (tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA * p_msg)
        if (GATT_GetConnectionInfor(p_msg->api_indicate.hdr.layer_specific,
        if (GATT_GetConnectionInfor(p_msg->api_indicate.hdr.layer_specific,
            &gatt_if, remote_bda, &transport))
            &gatt_if, remote_bda, &transport))
        {
        {
            p_rcb = bta_gatts_find_app_rcb_by_app_if(gatt_if);

            if (p_msg->api_indicate.need_confirm)
            if (p_msg->api_indicate.need_confirm)


                status = GATTS_HandleValueIndication (p_msg->api_indicate.hdr.layer_specific,
                status = GATTS_HandleValueIndication (p_msg->api_indicate.hdr.layer_specific,
@@ -669,10 +676,14 @@ void bta_gatts_indicate_handle (tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA * p_msg)
            APPL_TRACE_ERROR("Unknown connection ID: %d fail sending notification",
            APPL_TRACE_ERROR("Unknown connection ID: %d fail sending notification",
                              p_msg->api_indicate.hdr.layer_specific);
                              p_msg->api_indicate.hdr.layer_specific);
        }
        }

        if ((status != GATT_SUCCESS || !p_msg->api_indicate.need_confirm) &&
        if ((status != GATT_SUCCESS || !p_msg->api_indicate.need_confirm) &&
            p_cb->rcb[p_srvc_cb->rcb_idx].p_cback)
            p_rcb && p_cb->rcb[p_srvc_cb->rcb_idx].p_cback)
        {
        {
            (*p_cb->rcb[p_srvc_cb->rcb_idx].p_cback)(BTA_GATTS_CONF_EVT, (tBTA_GATTS *)&status);
            cb_data.req_data.status = status;
            cb_data.req_data.conn_id = p_msg->api_indicate.hdr.layer_specific;

            (*p_rcb->p_cback)(BTA_GATTS_CONF_EVT, &cb_data);
        }
        }
    }
    }
    else
    else
@@ -940,4 +951,34 @@ static void bta_gatts_conn_cback (tGATT_IF gatt_if, BD_ADDR bda, UINT16 conn_id,
        APPL_TRACE_ERROR("bta_gatts_conn_cback server_if=%d not found",gatt_if);
        APPL_TRACE_ERROR("bta_gatts_conn_cback server_if=%d not found",gatt_if);
    }
    }
}
}

/*******************************************************************************
**
** Function         bta_gatts_cong_cback
**
** Description      congestion callback.
**
** Returns          none.
**
*******************************************************************************/
static void bta_gatts_cong_cback (UINT16 conn_id, BOOLEAN congested)
{
    tBTA_GATTS_RCB *p_rcb;
    tGATT_IF gatt_if;
    tBTA_GATT_TRANSPORT transport;
    tBTA_GATTS cb_data;

    if (GATT_GetConnectionInfor(conn_id, &gatt_if, cb_data.req_data.remote_bda, &transport))
    {
        p_rcb = bta_gatts_find_app_rcb_by_app_if(gatt_if);

        if (p_rcb && p_rcb->p_cback)
        {
            cb_data.congest.conn_id = conn_id;
            cb_data.congest.congested = congested;

            (*p_rcb->p_cback)(BTA_GATTS_CONGEST_EVT, &cb_data);
        }
    }
}
#endif /* BTA_GATT_INCLUDED */
#endif /* BTA_GATT_INCLUDED */
+29 −5
Original line number Original line Diff line number Diff line
@@ -93,10 +93,11 @@ typedef struct
#define  BTA_GATT_ENCRYPED_MITM             GATT_ENCRYPED_MITM                 /* GATT_SUCCESS */
#define  BTA_GATT_ENCRYPED_MITM             GATT_ENCRYPED_MITM                 /* GATT_SUCCESS */
#define  BTA_GATT_ENCRYPED_NO_MITM          GATT_ENCRYPED_NO_MITM              /* 0x8d */
#define  BTA_GATT_ENCRYPED_NO_MITM          GATT_ENCRYPED_NO_MITM              /* 0x8d */
#define  BTA_GATT_NOT_ENCRYPTED             GATT_NOT_ENCRYPTED                 /* 0x8e */
#define  BTA_GATT_NOT_ENCRYPTED             GATT_NOT_ENCRYPTED                 /* 0x8e */
#define  BTA_GATT_CONGESTED                 GATT_CONGESTED                     /* 0x8f */


#define  BTA_GATT_DUP_REG                   0x8f                                /* 0x8f */
#define  BTA_GATT_DUP_REG                   0x90                               /* 0x90 */
#define  BTA_GATT_ALREADY_OPEN              0x90                                /* 0x90 */
#define  BTA_GATT_ALREADY_OPEN              0x91                               /* 0x91 */
#define  BTA_GATT_CANCEL                    0x91                                /* 0x91 */
#define  BTA_GATT_CANCEL                    0x92                               /* 0x92 */


                                             /* 0xE0 ~ 0xFC reserved for future use */
                                             /* 0xE0 ~ 0xFC reserved for future use */
#define  BTA_GATT_CCC_CFG_ERR                GATT_CCC_CFG_ERR     /* 0xFD Client Characteristic Configuration Descriptor Improperly Configured */
#define  BTA_GATT_CCC_CFG_ERR                GATT_CCC_CFG_ERR     /* 0xFD Client Characteristic Configuration Descriptor Improperly Configured */
@@ -133,6 +134,7 @@ typedef UINT8 tBTA_GATT_STATUS;
#define BTA_GATTC_MULT_ADV_UPD_EVT  21  /* Update parameter event */
#define BTA_GATTC_MULT_ADV_UPD_EVT  21  /* Update parameter event */
#define BTA_GATTC_MULT_ADV_DATA_EVT 22  /* Multi ADV data event */
#define BTA_GATTC_MULT_ADV_DATA_EVT 22  /* Multi ADV data event */
#define BTA_GATTC_MULT_ADV_DIS_EVT  23  /* Disable Multi ADV event */
#define BTA_GATTC_MULT_ADV_DIS_EVT  23  /* Disable Multi ADV event */
#define BTA_GATTC_CONGEST_EVT       24  /* Congestion event */


typedef UINT8 tBTA_GATTC_EVT;
typedef UINT8 tBTA_GATTC_EVT;


@@ -365,6 +367,12 @@ typedef struct
    BOOLEAN             is_notify;
    BOOLEAN             is_notify;
}tBTA_GATTC_NOTIFY;
}tBTA_GATTC_NOTIFY;


typedef struct
{
    UINT16 conn_id;
    BOOLEAN congested; /* congestion indicator */
}tBTA_GATTC_CONGEST;

// btla-specific ++
// btla-specific ++
typedef struct
typedef struct
{
{
@@ -397,6 +405,7 @@ typedef union
    tBTA_GATTC_ENC_CMPL_CB  enc_cmpl;
    tBTA_GATTC_ENC_CMPL_CB  enc_cmpl;
    BD_ADDR                 remote_bda;     /* service change event */
    BD_ADDR                 remote_bda;     /* service change event */
    tBTA_GATTC_CFG_MTU      cfg_mtu;        /* configure MTU operation */
    tBTA_GATTC_CFG_MTU      cfg_mtu;        /* configure MTU operation */
    tBTA_GATTC_CONGEST      congest;
} tBTA_GATTC;
} tBTA_GATTC;


/* GATTC enable callback function */
/* GATTC enable callback function */
@@ -428,6 +437,7 @@ typedef void (tBTA_GATTC_CBACK)(tBTA_GATTC_EVT event, tBTA_GATTC *p_data);
#define BTA_GATTS_CANCEL_OPEN_EVT                       17
#define BTA_GATTS_CANCEL_OPEN_EVT                       17
#define BTA_GATTS_CLOSE_EVT                             18
#define BTA_GATTS_CLOSE_EVT                             18
#define BTA_GATTS_LISTEN_EVT                            19
#define BTA_GATTS_LISTEN_EVT                            19
#define BTA_GATTS_CONGEST_EVT                           20


typedef UINT8  tBTA_GATTS_EVT;
typedef UINT8  tBTA_GATTS_EVT;
typedef tGATT_IF tBTA_GATTS_IF;
typedef tGATT_IF tBTA_GATTS_IF;
@@ -513,6 +523,7 @@ typedef tGATTS_DATA tBTA_GATTS_REQ_DATA;


typedef struct
typedef struct
{
{
    tBTA_GATT_STATUS    status;
    BD_ADDR             remote_bda;
    BD_ADDR             remote_bda;
    UINT32              trans_id;
    UINT32              trans_id;
    UINT16              conn_id;
    UINT16              conn_id;
@@ -569,19 +580,32 @@ typedef struct
    tBTA_GATT_TRANSPORT transport;
    tBTA_GATT_TRANSPORT transport;
}tBTA_GATTS_CONN;
}tBTA_GATTS_CONN;


typedef struct
{
    UINT16 conn_id;
    BOOLEAN congested; /* report channel congestion indicator */
}tBTA_GATTS_CONGEST;

typedef struct
{
    UINT16 conn_id; /* connection ID */
    tBTA_GATT_STATUS status; /* notification/indication status */
}tBTA_GATTS_CONF;

/* GATTS callback data */
/* GATTS callback data */
typedef union
typedef union
{
{
    tBTA_GATTS_REG_OPER     reg_oper;
    tBTA_GATTS_REG_OPER     reg_oper;
    tBTA_GATTS_CREATE       create;
    tBTA_GATTS_CREATE       create;
    tBTA_GATTS_SRVC_OPER    srvc_oper;
    tBTA_GATTS_SRVC_OPER    srvc_oper;
    tBTA_GATT_STATUS        status; /*  BTA_GATTS_CONF_EVT or BTA_GATTS_LISTEN_EVT */
    tBTA_GATT_STATUS        status;      /* BTA_GATTS_LISTEN_EVT */
    tBTA_GATTS_ADD_RESULT   add_result;  /* add included service: BTA_GATTS_ADD_INCL_SRVC_EVT
    tBTA_GATTS_ADD_RESULT   add_result;  /* add included service: BTA_GATTS_ADD_INCL_SRVC_EVT
                                           add char : BTA_GATTS_ADD_CHAR_EVT
                                           add char : BTA_GATTS_ADD_CHAR_EVT
                                           add char descriptor: BTA_GATTS_ADD_CHAR_DESCR_EVT */
                                           add char descriptor: BTA_GATTS_ADD_CHAR_DESCR_EVT */
    tBTA_GATTS_REQ          req_data;
    tBTA_GATTS_REQ          req_data;
    tBTA_GATTS_CONN         conn;       /* BTA_GATTS_CONN_EVT */
    tBTA_GATTS_CONN         conn;       /* BTA_GATTS_CONN_EVT */

    tBTA_GATTS_CONGEST      congest;    /* BTA_GATTS_CONGEST_EVT callback data */
    tBTA_GATTS_CONF         confirm;    /* BTA_GATTS_CONF_EVT callback data */
}tBTA_GATTS;
}tBTA_GATTS;


/* GATTS enable callback function */
/* GATTS enable callback function */
+8 −0
Original line number Original line Diff line number Diff line
@@ -549,6 +549,7 @@ static void btif_gattc_upstreams_evt(uint16_t event, char* p_param)
                , p_data->cfg_mtu.status , p_data->cfg_mtu.mtu);
                , p_data->cfg_mtu.status , p_data->cfg_mtu.mtu);
            break;
            break;
        }
        }

        case BTIF_GATTC_SCAN_FILTER_EVT:
        case BTIF_GATTC_SCAN_FILTER_EVT:
        {
        {
            btif_gattc_cb_t *p_btif_cb = (btif_gattc_cb_t*)p_param;
            btif_gattc_cb_t *p_btif_cb = (btif_gattc_cb_t*)p_param;
@@ -608,6 +609,13 @@ static void btif_gattc_upstreams_evt(uint16_t event, char* p_param)
            break;
            break;
        }
        }


        case BTA_GATTC_CONGEST_EVT:
            HAL_CBACK(bt_gatt_callbacks, client->congestion_cb
                , p_data->congest.conn_id
                , p_data->congest.congested
            );
            break;

        default:
        default:
            ALOGE("%s: Unhandled event (%d)!", __FUNCTION__, event);
            ALOGE("%s: Unhandled event (%d)!", __FUNCTION__, event);
            break;
            break;
Loading