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 tGATT_CBACK bta_gattc_cl_cback =
{
bta_gattc_conn_cback,
bta_gattc_cmpl_cback,
bta_gattc_disc_res_cback,
bta_gattc_disc_cmpl_cback,
- NULL
+ NULL,
+ bta_gattc_enc_cmpl_cback
};
/* opcode(tGATTC_OPTYPE) order has to be comply with internal event order */
}
}
+
+/*******************************************************************************
+**
+** Function bta_gattc_process_enc_cmpl
+**
+** Description process encryption complete message.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_gattc_process_enc_cmpl(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_msg)
+{
+ tBTA_GATTC_RCB *p_clreg;
+ tBTA_GATTC cb_data;
+
+ p_clreg = bta_gattc_cl_get_regcb(p_msg->enc_cmpl.client_if);
+
+ if (p_clreg && p_clreg->p_cback)
+ {
+ memset(&cb_data, 0, sizeof(tBTA_GATTC));
+
+ cb_data.enc_cmpl.client_if = p_msg->enc_cmpl.client_if;
+ bdcpy(cb_data.enc_cmpl.remote_bda, p_msg->enc_cmpl.remote_bda);
+
+ (*p_clreg->p_cback)(BTA_GATTC_ENC_CMPL_CB_EVT, &cb_data);
+ }
+}
+
/*******************************************************************************
**
** Function bta_gattc_cancel_open_error
/*******************************************************************************
**
+** Function bta_gattc_enc_cmpl_cback
+**
+** Description encryption complete callback function to GATT client stack.
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_gattc_enc_cmpl_cback(tGATT_IF gattc_if, BD_ADDR bda)
+{
+ tBTA_GATTC_DATA *p_buf;
+ tBTA_GATTC_CLCB *p_clcb = NULL;
+
+ if ((p_clcb = bta_gattc_find_clcb_by_cif(gattc_if, bda)) == NULL)
+ {
+ return;
+ }
+
+#if (defined BTA_HH_LE_INCLUDED && BTA_HH_LE_INCLUDED == TRUE)
+ /* filter this event just for BTA HH LE GATT client,
+ In the future, if we want to enable encryption complete event
+ for all GATT clients, we can remove this code */
+ if (!bta_hh_le_is_hh_gatt_if(gattc_if))
+ {
+ return;
+ }
+#endif
+
+ APPL_TRACE_DEBUG1("bta_gattc_enc_cmpl_cback: cif = %d", gattc_if);
+
+ if ((p_buf = (tBTA_GATTC_DATA *) GKI_getbuf(sizeof(tBTA_GATTC_DATA))) != NULL)
+ {
+ memset(p_buf, 0, sizeof(tBTA_GATTC_DATA));
+
+ p_buf->enc_cmpl.hdr.event = BTA_GATTC_ENC_CMPL_EVT;
+ p_buf->enc_cmpl.hdr.layer_specific = p_clcb->bta_conn_id;
+ p_buf->enc_cmpl.client_if = gattc_if;
+ bdcpy(p_buf->enc_cmpl.remote_bda, bda);
+
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
** Function bta_gattc_process_api_refresh
**
** Description process refresh API to delete cache and start a new discovery
BTA_GATTC_API_REG_EVT,
BTA_GATTC_API_DEREG_EVT,
BTA_GATTC_API_LISTEN_EVT,
- BTA_GATTC_API_DISABLE_EVT
+ BTA_GATTC_API_DISABLE_EVT,
+ BTA_GATTC_ENC_CMPL_EVT
};
typedef UINT16 tBTA_GATTC_INT_EVT;
tGATT_DISCONN_REASON reason;
}tBTA_GATTC_INT_CONN;
+typedef struct
+{
+ BT_HDR hdr;
+ BD_ADDR remote_bda;
+ tBTA_GATTC_IF client_if;
+}tBTA_GATTC_ENC_CMPL;
+
typedef union
{
BT_HDR hdr;
tBTA_GATTC_CI_EVT ci_save;
tBTA_GATTC_CI_LOAD ci_load;
tBTA_GATTC_INT_CONN int_conn;
+ tBTA_GATTC_ENC_CMPL enc_cmpl;
tBTA_GATTC_INT_START_IF int_start_if;
tBTA_GATTC_INT_DEREG int_dereg;
extern void bta_gattc_process_api_open (tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA * p_msg);
extern void bta_gattc_process_api_open_cancel (tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA * p_msg);
extern void bta_gattc_deregister(tBTA_GATTC_CB *p_cb, tBTA_GATTC_RCB *p_clreg);
+extern void bta_gattc_process_enc_cmpl(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_msg);
/* function within state machine */
extern void bta_gattc_open(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
bta_gattc_listen(p_cb, (tBTA_GATTC_DATA *) p_msg);
break;
#endif
+
+ case BTA_GATTC_ENC_CMPL_EVT:
+ bta_gattc_process_enc_cmpl(p_cb, (tBTA_GATTC_DATA *) p_msg);
+ break;
+
default:
if (p_msg->event == BTA_GATTC_INT_CONN_EVT)
p_clcb = bta_gattc_find_int_conn_clcb((tBTA_GATTC_DATA *) p_msg);
NULL,
NULL,
NULL,
- bta_gatts_send_request_cback
+ bta_gatts_send_request_cback,
+ NULL
};
tGATT_APPL_INFO bta_gatts_nv_cback =
BTA_HH_GATT_READ_DESCR_CMPL_EVT,
BTA_HH_GATT_WRITE_DESCR_CMPL_EVT,
BTA_HH_API_SCPP_UPDATE_EVT,
+ BTA_HH_GATT_ENC_CMPL_EVT,
#endif
/* not handled by execute state machine */
tBTA_HH_LE_CLOSE le_close;
tBTA_GATTC_OPEN le_open;
tBTA_HH_SCPP_UPDATE le_scpp_update;
+ tBTA_GATTC_ENC_CMPL_CB le_enc_cmpl;
#endif
} tBTA_HH_DATA;
UINT8 scps_notify; /* scan refresh supported/notification enabled */
#endif
+ BOOLEAN security_pending;
} tBTA_HH_DEV_CB;
/* key board parsing control block */
extern void bta_hh_start_security(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_buf);
extern void bta_hh_security_cmpl(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_buf);
extern void bta_hh_le_update_scpp(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_buf);
-
+extern void bta_hh_le_notify_enc_cmpl(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data);
#if BTA_HH_DEBUG
extern void bta_hh_trace_dev_db(void);
#include "bta_hh_co.h"
#include "bta_gatt_api.h"
#include "srvc_api.h"
+#include "btm_int.h"
#ifndef BTA_HH_LE_RECONN
#define BTA_HH_LE_RECONN TRUE
bta_hh_le_api_disc_act(p_cb);
}
+
+/*******************************************************************************
+**
+** Function bta_hh_le_notify_enc_cmpl
+**
+** Description process GATT encryption complete event
+**
+** Returns
+**
+*******************************************************************************/
+void bta_hh_le_notify_enc_cmpl(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_buf)
+{
+ if (p_cb == NULL || p_cb->security_pending == FALSE ||
+ p_buf == NULL || p_buf->le_enc_cmpl.client_if != bta_hh_cb.gatt_if)
+ {
+ return;
+ }
+
+ p_cb->security_pending = FALSE;
+ bta_hh_start_security(p_cb, NULL);
+}
+
/*******************************************************************************
**
** Function bta_hh_start_security
void bta_hh_start_security(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_buf)
{
UINT8 sec_flag=0;
+ tBTM_SEC_DEV_REC *p_dev_rec;
+
+ p_dev_rec = btm_find_dev(p_cb->addr);
+ if (p_dev_rec)
+ {
+ if (p_dev_rec->sec_state == BTM_SEC_STATE_ENCRYPTING ||
+ p_dev_rec->sec_state == BTM_SEC_STATE_AUTHENTICATING)
+ {
+ /* if security collision happened, wait for encryption done */
+ p_cb->security_pending = TRUE;
+ return;
+ }
+ }
/* verify bond */
BTM_GetSecurityFlags(p_cb->addr, &sec_flag);
p_buf->reason = p_data->reason;
p_dev_cb->conn_id = BTA_GATT_INVALID_CONN_ID;
-
+ p_dev_cb->security_pending = FALSE;
bta_sys_sendmsg(p_buf);
}
}
case BTA_GATTC_OPEN_EVT: /* 2 */
p_dev_cb = bta_hh_le_find_dev_cb_by_bda(p_data->open.remote_bda);
- bta_hh_sm_execute(p_dev_cb, BTA_HH_GATT_OPEN_EVT, (tBTA_HH_DATA *)&p_data->open);
+ if (p_dev_cb) {
+ bta_hh_sm_execute(p_dev_cb, BTA_HH_GATT_OPEN_EVT, (tBTA_HH_DATA *)&p_data->open);
+ }
break;
case BTA_GATTC_READ_CHAR_EVT: /* 3 */
case BTA_GATTC_NOTIF_EVT: /* 10 */
bta_hh_le_input_rpt_notify(&p_data->notify);
break;
+
+ case BTA_GATTC_ENC_CMPL_CB_EVT: /* 17 */
+ p_dev_cb = bta_hh_le_find_dev_cb_by_bda(p_data->enc_cmpl.remote_bda);
+ if (p_dev_cb) {
+ bta_hh_sm_execute(p_dev_cb, BTA_HH_GATT_ENC_CMPL_EVT,
+ (tBTA_HH_DATA *)&p_data->enc_cmpl);
+ }
+ break;
+
default:
break;
}
BTA_HH_START_SEC,
BTA_HH_SEC_CMPL,
BTA_HH_LE_UPDATE_SCPP,
-
+ BTA_HH_GATT_ENC_CMPL,
#endif
BTA_HH_NUM_ACTIONS
};
,bta_hh_start_security
,bta_hh_security_cmpl
,bta_hh_le_update_scpp
+ ,bta_hh_le_notify_enc_cmpl
#endif
};
/* READ_DESCR_CMPL_EVT */ ,{BTA_HH_IGNORE, BTA_HH_IDLE_ST }
/* WRITE_DESCR_CMPL_EVT */ ,{BTA_HH_IGNORE, BTA_HH_IDLE_ST }
/* SCPP_UPDATE_EVT */ ,{BTA_HH_IGNORE, BTA_HH_IDLE_ST }
+/* BTA_HH_GATT_ENC_CMPL_EVT */ ,{BTA_HH_IGNORE, BTA_HH_IDLE_ST }
#endif
};
/* READ_DESCR_CMPL_EVT */ ,{BTA_HH_W4_LE_READ_DESCR, BTA_HH_W4_CONN_ST }
/* WRITE_DESCR_CMPL_EVT */ ,{BTA_HH_WRITE_DESCR, BTA_HH_W4_CONN_ST }
/* SCPP_UPDATE_EVT */ ,{BTA_HH_IGNORE, BTA_HH_W4_CONN_ST }
+/* BTA_HH_GATT_ENC_CMPL_EVT */ ,{BTA_HH_IGNORE, BTA_HH_W4_CONN_ST }
#endif
};
/* READ_DESCR_CMPL_EVT */ ,{BTA_HH_LE_READ_DESCR, BTA_HH_CONN_ST } /* do not currently read any descr when connection up */
/* WRITE_DESCR_CMPL_EVT */ ,{BTA_HH_WRITE_DESCR, BTA_HH_CONN_ST } /* do not currently write any descr when connection up */
/* SCPP_UPDATE_EVT */ ,{BTA_HH_LE_UPDATE_SCPP, BTA_HH_CONN_ST }
+/* BTA_HH_GATT_ENC_CMPL_EVT */ ,{BTA_HH_IGNORE, BTA_HH_CONN_ST }
#endif
};
#if (defined BTA_HH_LE_INCLUDED && BTA_HH_LE_INCLUDED == TRUE)
/* READ_DESCR_CMPL_EVT */ {BTA_HH_IGNORE, BTA_HH_W4_SEC },
/* WRITE_DESCR_CMPL_EVT */ {BTA_HH_IGNORE, BTA_HH_W4_SEC }
/* SCPP_UPDATE_EVT */ ,{BTA_HH_IGNORE, BTA_HH_W4_SEC }
+/* BTA_HH_GATT_ENC_CMPL_EVT */ ,{BTA_HH_GATT_ENC_CMPL, BTA_HH_W4_SEC }
};
#endif
#define BTA_GATTC_CANCEL_OPEN_EVT 14 /* cancel open event */
#define BTA_GATTC_SRVC_CHG_EVT 15 /* service change event */
#define BTA_GATTC_LISTEN_EVT 16 /* listen event */
+#define BTA_GATTC_ENC_CMPL_CB_EVT 17 /* encryption complete callback event */
typedef UINT8 tBTA_GATTC_EVT;
}tBTA_GATTC_OPEN_CLOSE;
// btla-specific --
+typedef struct
+{
+ tBTA_GATTC_IF client_if;
+ BD_ADDR remote_bda;
+}tBTA_GATTC_ENC_CMPL_CB;
+
typedef union
{
tBTA_GATT_STATUS status;
tBTA_GATTC_WRITE write; /* write complete data */
tBTA_GATTC_EXEC_CMPL exec_cmpl; /* execute complete */
tBTA_GATTC_NOTIFY notify; /* notification/indication event data */
+ tBTA_GATTC_ENC_CMPL_CB enc_cmpl;
BD_ADDR remote_bda; /* service change event */
} tBTA_GATTC;
btif_test_command_complete_cback,
btif_test_discovery_result_cback,
btif_test_discovery_complete_cback,
+ NULL,
NULL
};
gap_ble_c_cmpl_cback,
NULL,
NULL,
- gap_ble_s_attr_request_cback
+ gap_ble_s_attr_request_cback,
+ NULL
};
NULL,
NULL,
NULL,
- gatt_profile_request_cback
+ gatt_profile_request_cback,
+ NULL
} ;
/*******************************************************************************
tGATT_TCB *p_tcb;
tGATT_PENDING_ENC_CLCB *p_buf;
UINT16 count;
+ UINT8 i = 0;
if ((p_tcb = gatt_find_tcb_by_addr(bd_addr)) != NULL)
{
+ for (i = 0; i < GATT_MAX_APPS; i++)
+ {
+ if (gatt_cb.cl_rcb[i].in_use && gatt_cb.cl_rcb[i].app_cb.p_enc_cmpl_cb)
+ {
+ (*gatt_cb.cl_rcb[i].app_cb.p_enc_cmpl_cb)(gatt_cb.cl_rcb[i].gatt_if, bd_addr);
+ }
+ }
+
if (gatt_get_sec_act(p_tcb) == GATT_SEC_ENC_PENDING)
{
gatt_set_sec_act(p_tcb, GATT_SEC_NONE);
/* attribute request callback for ATT server */
typedef void (tGATT_REQ_CBACK )(UINT16 conn_id, UINT32 trans_id, tGATTS_REQ_TYPE type, tGATTS_DATA *p_data);
-
+/* Define a callback function when encryption is established. */
+typedef void (tGATT_ENC_CMPL_CB)(tGATT_IF gatt_if, BD_ADDR bda);
/* Define the structure that applications use to register with
tGATT_DISC_RES_CB *p_disc_res_cb;
tGATT_DISC_CMPL_CB *p_disc_cmpl_cb;
tGATT_REQ_CBACK *p_req_cb;
+ tGATT_ENC_CMPL_CB *p_enc_cmpl_cb;
} tGATT_CBACK;
/*********************** Start Handle Management Definitions **********************
srvc_eng_c_cmpl_cback,
NULL,
NULL,
- srvc_eng_s_request_cback
+ srvc_eng_s_request_cback,
+ NULL
} ;
/* type for action functions */
typedef void (*tSRVC_ENG_C_CMPL_ACTION)(tSRVC_CLCB *p_clcb, tGATTC_OPTYPE op,