OSDN Git Service

BLE HID device connection failure due to security error.
authorZhihai Xu <zhihaixu@google.com>
Wed, 13 Nov 2013 04:18:37 +0000 (20:18 -0800)
committerZhihai Xu <zhihaixu@google.com>
Wed, 11 Dec 2013 18:52:51 +0000 (10:52 -0800)
When HID BLE device start encryption, if some other GATT application
already start encryption(but not finished yet) by calling
gatt_security_check_start. The HID BLE device will be failed to start
encryption, which will cause it to disconnect the BLE HID connection.
The solution is to check whether we already started the encryption
, If the encryption is already started, wait until the encryption
finished, then continue to start security check for BLE HID device.
add encrytion complete event to notify all GATT client encryption done.
filter the event just for BTA HH LE GATT client.

bug:11636246
Change-Id: If58e57c623cc8cfa05208587b010bec68c71306c

14 files changed:
bta/gatt/bta_gattc_act.c
bta/gatt/bta_gattc_int.h
bta/gatt/bta_gattc_main.c
bta/gatt/bta_gatts_act.c
bta/hh/bta_hh_int.h
bta/hh/bta_hh_le.c
bta/hh/bta_hh_main.c
bta/include/bta_gatt_api.h
btif/src/btif_gatt_test.c
stack/gap/gap_ble.c
stack/gatt/gatt_attr.c
stack/gatt/gatt_auth.c
stack/include/gatt_api.h
stack/srvc/srvc_eng.c

index f5b60fa..444c357 100644 (file)
@@ -52,13 +52,16 @@ static void  bta_gattc_cmpl_cback(UINT16 conn_id, tGATTC_OPTYPE op, tGATT_STATUS
 
 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 */
@@ -399,6 +402,34 @@ void bta_gattc_process_api_open_cancel (tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA * p
 
     }
 }
+
+/*******************************************************************************
+**
+** 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
@@ -1635,6 +1666,50 @@ static void bta_gattc_conn_cback(tGATT_IF gattc_if, BD_ADDR bda, UINT16 conn_id,
 
 /*******************************************************************************
 **
+** 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
index c2056d4..1ff8f79 100644 (file)
@@ -69,7 +69,8 @@ enum
     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;
 
@@ -195,6 +196,13 @@ typedef struct
     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;
@@ -213,6 +221,7 @@ typedef union
     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;
@@ -433,6 +442,7 @@ extern void bta_gattc_start_if(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_data);
 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);
index 9427f89..650cf5e 100644 (file)
@@ -386,6 +386,11 @@ BOOLEAN bta_gattc_hdl_event(BT_HDR *p_msg)
             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);
index f59b593..f1bd88e 100644 (file)
@@ -49,7 +49,8 @@ static tGATT_CBACK bta_gatts_cback =
     NULL,
     NULL,
     NULL,
-    bta_gatts_send_request_cback
+    bta_gatts_send_request_cback,
+    NULL
 };
 
 tGATT_APPL_INFO bta_gatts_nv_cback =
index 99a8b82..ed93dd5 100644 (file)
@@ -67,6 +67,7 @@ enum
     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 */
@@ -182,6 +183,7 @@ typedef union
     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;
 
@@ -283,6 +285,7 @@ typedef struct
     UINT8               scps_notify;   /* scan refresh supported/notification enabled */
 #endif
 
+    BOOLEAN             security_pending;
 } tBTA_HH_DEV_CB;
 
 /* key board parsing control block */
@@ -404,7 +407,7 @@ extern void bta_hh_le_write_char_descr_cmpl(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *
 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);
index 5ec35b0..0201be7 100644 (file)
@@ -28,6 +28,7 @@
 #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
@@ -1257,6 +1258,28 @@ void bta_hh_security_cmpl(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_buf)
         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
@@ -1269,6 +1292,19 @@ void bta_hh_security_cmpl(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_buf)
 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);
@@ -1372,7 +1408,7 @@ void bta_hh_le_close(tBTA_GATTC_CLOSE * p_data)
         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);
     }
 }
@@ -2711,7 +2747,9 @@ static void bta_hh_gattc_callback(tBTA_GATTC_EVT event, tBTA_GATTC *p_data)
 
         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 */
@@ -2753,6 +2791,15 @@ static void bta_hh_gattc_callback(tBTA_GATTC_EVT event, tBTA_GATTC *p_data)
         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;
     }
index bf54e57..c2554c1 100644 (file)
@@ -66,7 +66,7 @@ enum
     BTA_HH_START_SEC,
     BTA_HH_SEC_CMPL,
     BTA_HH_LE_UPDATE_SCPP,
-
+    BTA_HH_GATT_ENC_CMPL,
 #endif
     BTA_HH_NUM_ACTIONS
 };
@@ -106,6 +106,7 @@ const tBTA_HH_ACTION bta_hh_action[] =
     ,bta_hh_start_security
     ,bta_hh_security_cmpl
     ,bta_hh_le_update_scpp
+    ,bta_hh_le_notify_enc_cmpl
 #endif
 };
 
@@ -140,6 +141,7 @@ const UINT8 bta_hh_st_idle[][BTA_HH_NUM_COLS] =
 /* 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
 
 };
@@ -170,6 +172,7 @@ const UINT8 bta_hh_st_w4_conn[][BTA_HH_NUM_COLS] =
 /* 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
 };
 
@@ -199,6 +202,7 @@ const UINT8 bta_hh_st_connected[][BTA_HH_NUM_COLS] =
 /* 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)
@@ -226,6 +230,7 @@ const UINT8 bta_hh_st_w4_sec[][BTA_HH_NUM_COLS] =
 /* 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
 
index 93eadd5..bf0d98c 100644 (file)
@@ -115,6 +115,7 @@ typedef UINT8 tBTA_GATT_STATUS;
 #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;
 
@@ -349,6 +350,12 @@ typedef struct
 }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;
@@ -362,6 +369,7 @@ typedef union
     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;
 
index 8c23d56..2a316fe 100644 (file)
@@ -197,6 +197,7 @@ static tGATT_CBACK btif_test_callbacks =
     btif_test_command_complete_cback,
     btif_test_discovery_result_cback,
     btif_test_discovery_complete_cback,
+    NULL,
     NULL
 };
 
index 6e3afeb..48f4723 100644 (file)
@@ -65,7 +65,8 @@ static tGATT_CBACK gap_cback =
     gap_ble_c_cmpl_cback,
     NULL,
     NULL,
-    gap_ble_s_attr_request_cback
+    gap_ble_s_attr_request_cback,
+    NULL
 };
 
 
index 459580e..9af6a60 100644 (file)
@@ -48,7 +48,8 @@ static tGATT_CBACK gatt_profile_cback =
     NULL,
     NULL,
     NULL,
-    gatt_profile_request_cback
+    gatt_profile_request_cback,
+    NULL
 } ;
 
 /*******************************************************************************
index 504b7d8..e945c90 100644 (file)
@@ -228,9 +228,18 @@ void gatt_notify_enc_cmpl(BD_ADDR bd_addr)
     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);
index 01afb71..d9704b7 100644 (file)
@@ -573,7 +573,8 @@ typedef void (tGATT_CONN_CBACK) (tGATT_IF gatt_if, BD_ADDR bda, UINT16 conn_id,
 /* 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
@@ -587,6 +588,7 @@ typedef struct
     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   **********************
index a9b466e..d8db1b0 100644 (file)
@@ -39,7 +39,8 @@ static tGATT_CBACK srvc_gatt_cback =
     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,