Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add pairing complete ev #1025

Merged
merged 2 commits into from Aug 25, 2022

Conversation

KKopyscinski
Copy link
Contributor

No description provided.

@KKopyscinski
Copy link
Contributor Author

This also affects SM/PER/KDU/BI-02-C, SM/PER/KDU/BI-03-C and SM/CEN/KDU/BI-03-C

@michal-narajowski
Copy link

Please update Pairing Failed opcode as there is a collision with an existing event: auto-pts/auto-pts#612

@KKopyscinski
Copy link
Contributor Author

@michal-narajowski changed to 0x8c

@@ -135,6 +135,7 @@ struct hci_conn_update;
#define BLE_GAP_EVENT_PERIODIC_SYNC_LOST 22
#define BLE_GAP_EVENT_SCAN_REQ_RCVD 23
#define BLE_GAP_EVENT_PERIODIC_TRANSFER 24
#define BLE_GAP_EVENT_PARING_FAILED 25
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you consider BLE_GAP_EVENT_PAIRING_COMPLETE with a status and reason?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

makes sense - I changed that and event is now sent also on success (ble_sm_key_exch_success)

* o BLE host error code: the encryption state change attempt
* failed for the specified reason.
*/
int reason;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

status

nimble/host/include/host/ble_sm.h Show resolved Hide resolved
@@ -2049,6 +2049,7 @@ ble_sm_key_exch_success(struct ble_sm_proc *proc, struct ble_sm_result *res)

res->app_status = 0;
res->enc_cb = 1;
ble_gap_pairing_complete_event(proc->conn_handle, res->app_status);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seems to be inconsistent. Once app_status is provided second time cmd->reason.

I would always use res->sm_err;

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also,
shouldn't we call
ble_gap_pairing_complete_event in ble_sm_process_result under if (res->enc_cb) ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it's the solution I was searching for - now ble_sm_process_result only needs to be called here

@KKopyscinski KKopyscinski changed the title Add pairing failed ev Add pairing complete ev Nov 5, 2021
@KKopyscinski
Copy link
Contributor Author

Fixed unit test

if (res->enc_cb &&
res->app_status != BLE_HS_ENOTCONN) {
/* Do not send this event on broken connection */
ble_gap_pairing_complete_event(conn_handle, res->sm_err);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't we send here:

res->app_status = BLE_HS_SM_PEER_ERR(cmd->reason); ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should send in event res->sm_err which is either BLE_SM_ERR_SUCCESS (if set by ble_sm_key_exch_success) or error code (if set by ble_sm_key_exch_success), but maybe I don't see something?

@sjanc
Copy link
Contributor

sjanc commented Apr 13, 2022

looks ok to me but please rebase

@KKopyscinski KKopyscinski force-pushed the add_pairing_failed_ev branch 2 times, most recently from 93f13eb to bc351ba Compare April 19, 2022 05:19
@KKopyscinski
Copy link
Contributor Author

looks ok to me but please rebase

rebased

Copy link
Contributor

@sjanc sjanc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rymanluk could you have a look again?

@KKopyscinski
Copy link
Contributor Author

@rymanluk @sjanc Rebased onto master, it's still required to pass these 4 tests. Retested and these are passing (SM/CEN/KDU/BI-02-C, SM/CEN/KDU/BI-03-C, SM/PER/KDU/BI-02-C, SM/PER/KDU/BI-03-C)

@utzig
Copy link
Member

utzig commented May 16, 2022

Style check summary

Our coding style is here!

apps/bttester/src/bttester.h

@@ -399,20 +356,63 @@
     uint16_t supervision_timeout;
 } __packed;
 
-#define GAP_EV_SEC_LEVEL_CHANGED	0x89
+#define GAP_EV_DEVICE_DISCONNECTED  0x83
+struct gap_device_disconnected_ev {
+    uint8_t address_type;
+    uint8_t address[6];
+} __packed;
+
+#define GAP_EV_PASSKEY_DISPLAY      0x84
+struct gap_passkey_display_ev {
+    uint8_t address_type;
+    uint8_t address[6];
+    uint32_t passkey;
+} __packed;
+
+#define GAP_EV_PASSKEY_ENTRY_REQ    0x85
+struct gap_passkey_entry_req_ev {
+    uint8_t address_type;
+    uint8_t address[6];
+} __packed;
+
+#define GAP_EV_PASSKEY_CONFIRM_REQ  0x86
+struct gap_passkey_confirm_req_ev {
+    uint8_t address_type;
+    uint8_t address[6];
+    uint32_t passkey;
+} __packed;
+
+#define GAP_EV_IDENTITY_RESOLVED    0x87
+struct gap_identity_resolved_ev {
+    uint8_t address_type;
+    uint8_t address[6];
+    uint8_t identity_address_type;
+    uint8_t identity_address[6];
+} __packed;
+
+#define GAP_EV_CONN_PARAM_UPDATE    0x88
+struct gap_conn_param_update_ev {
+    uint8_t address_type;
+    uint8_t address[6];
+    uint16_t conn_itvl;
+    uint16_t conn_latency;
+    uint16_t supervision_timeout;
+} __packed;
+
+#define GAP_EV_SEC_LEVEL_CHANGED    0x89
 struct gap_sec_level_changed_ev {
     uint8_t address_type;
     uint8_t address[6];
     uint8_t level;
 } __packed;
 
-#define GAP_EV_PAIRING_CONSENT_REQ	0x8a
+#define GAP_EV_PAIRING_CONSENT_REQ  0x8a
 struct gap_pairing_consent_req_ev {
     uint8_t address_type;
     uint8_t address[6];
 } __packed;
 
-#define GAP_EV_SEC_PAIRING_FAILED	0x8c
+#define GAP_EV_SEC_PAIRING_FAILED   0x8c
 struct gap_sec_pairing_failed_ev {
     uint8_t address_type;
     uint8_t address[6];
@@ -421,109 +421,109 @@
 
 /* GATT Service */
 /* commands */
-#define GATT_READ_SUPPORTED_COMMANDS	0x01
+#define GATT_READ_SUPPORTED_COMMANDS    0x01
 struct gatt_read_supported_commands_rp {
-	uint8_t data[0];
-} __packed;
-
-#define GATT_SERVICE_PRIMARY		0x00
-#define GATT_SERVICE_SECONDARY		0x01
-
-#define GATT_ADD_SERVICE		0x02
+    uint8_t data[0];
+} __packed;
+
+#define GATT_SERVICE_PRIMARY        0x00
+#define GATT_SERVICE_SECONDARY      0x01
+
+#define GATT_ADD_SERVICE        0x02
 struct gatt_add_service_cmd {
-	uint8_t type;
-	uint8_t uuid_length;
-	uint8_t uuid[0];
+    uint8_t type;
+    uint8_t uuid_length;
+    uint8_t uuid[0];
 } __packed;
 struct gatt_add_service_rp {
-	uint16_t svc_id;
-} __packed;
-
-#define GATT_ADD_CHARACTERISTIC		0x03
+    uint16_t svc_id;
+} __packed;
+
+#define GATT_ADD_CHARACTERISTIC     0x03
 struct gatt_add_characteristic_cmd {
-	uint16_t svc_id;
-	uint8_t properties;
-	uint8_t permissions;
-	uint8_t uuid_length;
-	uint8_t uuid[0];
+    uint16_t svc_id;
+    uint8_t properties;
+    uint8_t permissions;
+    uint8_t uuid_length;
+    uint8_t uuid[0];
 } __packed;
 struct gatt_add_characteristic_rp {
-	uint16_t char_id;
-} __packed;
-
-#define GATT_ADD_DESCRIPTOR		0x04
+    uint16_t char_id;
+} __packed;
+
+#define GATT_ADD_DESCRIPTOR     0x04
 struct gatt_add_descriptor_cmd {
-	uint16_t char_id;
-	uint8_t permissions;
-	uint8_t uuid_length;
-	uint8_t uuid[0];
+    uint16_t char_id;
+    uint8_t permissions;
+    uint8_t uuid_length;
+    uint8_t uuid[0];
 } __packed;
 struct gatt_add_descriptor_rp {
-	uint16_t desc_id;
-} __packed;
-
-#define GATT_ADD_INCLUDED_SERVICE	0x05
+    uint16_t desc_id;
+} __packed;
+
+#define GATT_ADD_INCLUDED_SERVICE   0x05
 struct gatt_add_included_service_cmd {
-	uint16_t svc_id;
+    uint16_t svc_id;
 } __packed;
 struct gatt_add_included_service_rp {
-	uint16_t included_service_id;
-} __packed;
-
-#define GATT_SET_VALUE			0x06
-	struct gatt_set_value_cmd {
-	uint16_t attr_id;
-	uint16_t len;
-	uint8_t value[0];
-} __packed;
-
-#define GATT_START_SERVER		0x07
+    uint16_t included_service_id;
+} __packed;
+
+#define GATT_SET_VALUE          0x06
+struct gatt_set_value_cmd {
+    uint16_t attr_id;
+    uint16_t len;
+    uint8_t value[0];
+} __packed;
+
+#define GATT_START_SERVER       0x07
 struct gatt_start_server_rp {
-	uint16_t db_attr_off;
-	uint8_t db_attr_cnt;
-} __packed;
-
-#define GATT_SET_ENC_KEY_SIZE		0x09
+    uint16_t db_attr_off;
+    uint8_t db_attr_cnt;
+} __packed;
+
+#define GATT_SET_ENC_KEY_SIZE       0x09
 struct gatt_set_enc_key_size_cmd {
-	uint16_t attr_id;
-	uint8_t key_size;
+    uint16_t attr_id;
+    uint8_t key_size;
 } __packed;
 
 /* Gatt Client */
 struct gatt_service {
-	uint16_t start_handle;
-	uint16_t end_handle;
-	uint8_t uuid_length;
-	uint8_t uuid[0];
+    uint16_t start_handle;
+    uint16_t end_handle;
+    uint8_t uuid_length;
+    uint8_t uuid[0];
 } __packed;
 
 struct gatt_included {
-	uint16_t included_handle;
-	struct gatt_service service;
+    uint16_t included_handle;
+    struct gatt_service service;
 } __packed;
 
 struct gatt_read_uuid_chr {
-	uint16_t handle;
-	uint8_t data[0];
+    uint16_t handle;
+    uint8_t data[0];
 } __packed;
 
 struct gatt_characteristic {
-	uint16_t characteristic_handle;
-	uint16_t value_handle;
-	uint8_t properties;
-	uint8_t uuid_length;
-	uint8_t uuid[0];
+    uint16_t characteristic_handle;
+    uint16_t value_handle;
+    uint8_t properties;
+    uint8_t uuid_length;
+    uint8_t uuid[0];
 } __packed;
 
 struct gatt_descriptor {
-	uint16_t descriptor_handle;
-	uint8_t uuid_length;
-	uint8_t uuid[0];
-} __packed;
-
-#define GATT_EXCHANGE_MTU		0x0a
-
-#define GATT_DISC_ALL_PRIM_SVCS		0x0b
+    uint16_t descriptor_handle;
+    uint8_t uuid_length;
+    uint8_t uuid[0];
+} __packed;
+
+#define GATT_EXCHANGE_MTU       0x0a
+
+#define GATT_DISC_ALL_PRIM_SVCS     0x0b
 struct gatt_disc_all_prim_svcs_cmd {
     uint8_t address_type;
     uint8_t address[6];

apps/bttester/src/gap.c

@@ -685,302 +702,314 @@
  * If the resolution procedure fails, then the Host shall disconnect
  * with the error code "Authentication failure" [...]
  */
-static void periph_privacy(struct ble_gap_conn_desc desc)
+static void
+periph_privacy(struct ble_gap_conn_desc desc)
 {
 #if !MYNEWT_VAL(BTTESTER_PRIVACY_MODE)
-	return;
+    return;
 #endif
-	int count;
-
-	SYS_LOG_DBG("");
-
-	ble_store_util_count(BLE_STORE_OBJ_TYPE_PEER_SEC, &count);
-	if (count > 0 && BLE_ADDR_IS_RPA(&desc.peer_id_addr)) {
-		SYS_LOG_DBG("Authentication failure, disconnecting");
-		ble_gap_terminate(desc.conn_handle, BLE_ERR_AUTH_FAIL);
-	}
-}
-
-static void device_connected_ev_send(struct os_event *ev)
-{
-	struct ble_gap_conn_desc desc;
-	int rc;
-
-	SYS_LOG_DBG("");
-
-	rc = gap_conn_find_by_addr((ble_addr_t *)&connected_ev, &desc);
-	if (rc) {
-		tester_rsp(BTP_SERVICE_ID_GAP, GAP_EV_DEVICE_CONNECTED,
-			   CONTROLLER_INDEX, BTP_STATUS_FAILED);
-		return;
-	}
-
-	tester_send(BTP_SERVICE_ID_GAP, GAP_EV_DEVICE_CONNECTED,
-		    CONTROLLER_INDEX, (uint8_t *) &connected_ev,
-		    sizeof(connected_ev));
-
-	periph_privacy(desc);
-}
-
-static void le_connected(uint16_t conn_handle, int status)
-{
-	struct ble_gap_conn_desc desc;
-	ble_addr_t *addr;
-	int rc;
-
-	SYS_LOG_DBG("");
-
-	if (status != 0) {
-		return;
-	}
-
-	rc = ble_gap_conn_find(conn_handle, &desc);
-	if (rc) {
-		return;
-	}
-
-	peer_id_addr = desc.peer_id_addr;
-	peer_ota_addr = desc.peer_ota_addr;
-
-	addr = &desc.peer_id_addr;
-
-	memcpy(connected_ev.address, addr->val, sizeof(connected_ev.address));
-	connected_ev.address_type = addr->type;
-	connected_ev.conn_itvl = desc.conn_itvl;
-	connected_ev.conn_latency = desc.conn_latency;
-	connected_ev.supervision_timeout = desc.supervision_timeout;
+    int count;
+
+    SYS_LOG_DBG("");
+
+    ble_store_util_count(BLE_STORE_OBJ_TYPE_PEER_SEC, &count);
+    if (count > 0 && BLE_ADDR_IS_RPA(&desc.peer_id_addr)) {
+        SYS_LOG_DBG("Authentication failure, disconnecting");
+        ble_gap_terminate(desc.conn_handle, BLE_ERR_AUTH_FAIL);
+    }
+}
+
+static void
+device_connected_ev_send(struct os_event *ev)
+{
+    struct ble_gap_conn_desc desc;
+    int rc;
+
+    SYS_LOG_DBG("");
+
+    rc = gap_conn_find_by_addr((ble_addr_t *)&connected_ev, &desc);
+    if (rc) {
+        tester_rsp(BTP_SERVICE_ID_GAP, GAP_EV_DEVICE_CONNECTED,
+               CONTROLLER_INDEX, BTP_STATUS_FAILED);
+        return;
+    }
+
+    tester_send(BTP_SERVICE_ID_GAP, GAP_EV_DEVICE_CONNECTED,
+            CONTROLLER_INDEX, (uint8_t *) &connected_ev,
+            sizeof(connected_ev));
+
+    periph_privacy(desc);
+}
+
+static void
+le_connected(uint16_t conn_handle, int status)
+{
+    struct ble_gap_conn_desc desc;
+    ble_addr_t *addr;
+    int rc;
+
+    SYS_LOG_DBG("");
+
+    if (status != 0) {
+        return;
+    }
+
+    rc = ble_gap_conn_find(conn_handle, &desc);
+    if (rc) {
+        return;
+    }
+
+    peer_id_addr = desc.peer_id_addr;
+    peer_ota_addr = desc.peer_ota_addr;
+
+    addr = &desc.peer_id_addr;
+
+    memcpy(connected_ev.address, addr->val, sizeof(connected_ev.address));
+    connected_ev.address_type = addr->type;
+    connected_ev.conn_itvl = desc.conn_itvl;
+    connected_ev.conn_latency = desc.conn_latency;
+    connected_ev.supervision_timeout = desc.supervision_timeout;
 
 #if MYNEWT_VAL(BTTESTER_CONN_RETRY)
-	os_callout_reset(&connected_ev_co,
-			 os_time_ms_to_ticks32(
-				 CONNECTED_EV_DELAY_MS(desc.conn_itvl)));
+    os_callout_reset(&connected_ev_co,
+             os_time_ms_to_ticks32(
+                 CONNECTED_EV_DELAY_MS(desc.conn_itvl)));
 #else
-	tester_send(BTP_SERVICE_ID_GAP, GAP_EV_DEVICE_CONNECTED,
-		    CONTROLLER_INDEX, (uint8_t *) &connected_ev,
-		    sizeof(connected_ev));
+    tester_send(BTP_SERVICE_ID_GAP, GAP_EV_DEVICE_CONNECTED,
+            CONTROLLER_INDEX, (uint8_t *) &connected_ev,
+            sizeof(connected_ev));
 #endif
 }
 
-static void le_disconnected(struct ble_gap_conn_desc *conn, int reason)
-{
-	struct gap_device_disconnected_ev ev;
-	ble_addr_t *addr = &conn->peer_ota_addr;
-
-	SYS_LOG_DBG("");
+static void
+le_disconnected(struct ble_gap_conn_desc *conn, int reason)
+{
+    struct gap_device_disconnected_ev ev;
+    ble_addr_t *addr = &conn->peer_ota_addr;
+
+    SYS_LOG_DBG("");
 
 #if MYNEWT_VAL(BTTESTER_CONN_RETRY)
-	int rc;
-
-	if ((reason == BLE_HS_HCI_ERR(BLE_ERR_CONN_ESTABLISHMENT)) &&
-	    os_callout_queued(&connected_ev_co)) {
-		if (connection_attempts < MYNEWT_VAL(BTTESTER_CONN_RETRY)) {
-			os_callout_stop(&connected_ev_co);
-
-			/* try connecting again */
-			rc = ble_gap_connect(own_addr_type, addr, 0,
-					     &dflt_conn_params, gap_event_cb,
-					     NULL);
-
-			if (rc == 0) {
-				connection_attempts++;
-				return;
-			}
-		}
-	} else if (os_callout_queued(&connected_ev_co)) {
-		os_callout_stop(&connected_ev_co);
-		return;
-	}
+    int rc;
+
+    if ((reason == BLE_HS_HCI_ERR(BLE_ERR_CONN_ESTABLISHMENT)) &&
+        os_callout_queued(&connected_ev_co)) {
+        if (connection_attempts < MYNEWT_VAL(BTTESTER_CONN_RETRY)) {
+            os_callout_stop(&connected_ev_co);
+
+            /* try connecting again */
+            rc = ble_gap_connect(own_addr_type, addr, 0,
+                         &dflt_conn_params, gap_event_cb,
+                         NULL);
+
+            if (rc == 0) {
+                connection_attempts++;
+                return;
+            }
+        }
+    } else if (os_callout_queued(&connected_ev_co)) {
+        os_callout_stop(&connected_ev_co);
+        return;
+    }
 #endif
 
-	connection_attempts = 0;
-	memset(&connected_ev, 0, sizeof(connected_ev));
-
-	memcpy(ev.address, addr->val, sizeof(ev.address));
-	ev.address_type = addr->type;
-
-	tester_send(BTP_SERVICE_ID_GAP, GAP_EV_DEVICE_DISCONNECTED,
-		    CONTROLLER_INDEX, (uint8_t *) &ev, sizeof(ev));
-}
-
-static void auth_passkey_oob(uint16_t conn_handle)
-{
-	struct ble_gap_conn_desc desc;
-	struct ble_sm_io pk;
-	int rc;
-
-	SYS_LOG_DBG("");
-
-	rc = ble_gap_conn_find(conn_handle, &desc);
-	if (rc) {
-		return;
-	}
-
-	memcpy(pk.oob, oob, sizeof(oob));
-	pk.action = BLE_SM_IOACT_OOB;
-
-	rc = ble_sm_inject_io(conn_handle, &pk);
-	assert(rc == 0);
-}
-
-static void auth_passkey_display(uint16_t conn_handle, unsigned int passkey)
-{
-	struct ble_gap_conn_desc desc;
-	struct gap_passkey_display_ev ev;
-	ble_addr_t *addr;
-	struct ble_sm_io pk;
-	int rc;
-
-	SYS_LOG_DBG("");
-
-	rc = ble_gap_conn_find(conn_handle, &desc);
-	if (rc) {
-		return;
-	}
-
-	rc = ble_hs_hci_util_rand(&pk.passkey, sizeof(pk.passkey));
-	assert(rc == 0);
-	/* Max value is 999999 */
-	pk.passkey %= 1000000;
-	pk.action = BLE_SM_IOACT_DISP;
-
-	rc = ble_sm_inject_io(conn_handle, &pk);
-	assert(rc == 0);
-
-	addr = &desc.peer_ota_addr;
-
-	memcpy(ev.address, addr->val, sizeof(ev.address));
-	ev.address_type = addr->type;
-	ev.passkey = sys_cpu_to_le32(pk.passkey);
-
-	tester_send(BTP_SERVICE_ID_GAP, GAP_EV_PASSKEY_DISPLAY,
-		    CONTROLLER_INDEX, (uint8_t *) &ev, sizeof(ev));
-}
-
-static void auth_passkey_entry(uint16_t conn_handle)
-{
-	struct ble_gap_conn_desc desc;
-	struct gap_passkey_entry_req_ev ev;
-	ble_addr_t *addr;
-	int rc;
-
-	SYS_LOG_DBG("");
-
-	rc = ble_gap_conn_find(conn_handle, &desc);
-	if (rc) {
-		return;
-	}
-
-	addr = &desc.peer_ota_addr;
-
-	memcpy(ev.address, addr->val, sizeof(ev.address));
-	ev.address_type = addr->type;
-
-	tester_send(BTP_SERVICE_ID_GAP, GAP_EV_PASSKEY_ENTRY_REQ,
-		    CONTROLLER_INDEX, (uint8_t *) &ev, sizeof(ev));
-}
-
-static void auth_passkey_numcmp(uint16_t conn_handle, unsigned int passkey)
-{
-	struct ble_gap_conn_desc desc;
-	struct gap_passkey_confirm_req_ev ev;
-	ble_addr_t *addr;
-	int rc;
-
-	SYS_LOG_DBG("");
-
-	rc = ble_gap_conn_find(conn_handle, &desc);
-	if (rc) {
-		return;
-	}
-
-	addr = &desc.peer_ota_addr;
-
-	memcpy(ev.address, addr->val, sizeof(ev.address));
-	ev.address_type = addr->type;
-	ev.passkey = sys_cpu_to_le32(passkey);
-
-	tester_send(BTP_SERVICE_ID_GAP, GAP_EV_PASSKEY_CONFIRM_REQ,
-		    CONTROLLER_INDEX, (uint8_t *) &ev, sizeof(ev));
-}
-
-static void auth_passkey_oob_sc(uint16_t conn_handle)
-{
-	int rc;
-	struct ble_sm_io pk;
-
-	SYS_LOG_DBG("");
-
-	memset(&pk, 0, sizeof(pk));
-
-	pk.oob_sc_data.local = &oob_data_local;
-
-	if (ble_hs_cfg.sm_oob_data_flag) {
-		pk.oob_sc_data.remote = &oob_data_remote;
-	}
-
-	pk.action = BLE_SM_IOACT_OOB_SC;
-	rc = ble_sm_inject_io(conn_handle, &pk);
-	if (rc != 0) {
-		console_printf("error providing oob; rc=%d\n", rc);
-	}
-}
-
-static void le_passkey_action(uint16_t conn_handle,
-			      struct ble_gap_passkey_params *params)
-{
-	SYS_LOG_DBG("");
-
-	switch (params->action) {
-	case BLE_SM_IOACT_NONE:
-		break;
-	case BLE_SM_IOACT_OOB:
-		auth_passkey_oob(conn_handle);
-		break;
-	case BLE_SM_IOACT_INPUT:
-		auth_passkey_entry(conn_handle);
-		break;
-	case BLE_SM_IOACT_DISP:
-		auth_passkey_display(conn_handle, params->numcmp);
-		break;
-	case BLE_SM_IOACT_NUMCMP:
-		auth_passkey_numcmp(conn_handle, params->numcmp);
-		break;
-	case BLE_SM_IOACT_OOB_SC:
-		auth_passkey_oob_sc(conn_handle);
-		break;
-	default:
-		assert(0);
-	}
-}
-
-static void le_identity_resolved(uint16_t conn_handle)
-{
-	struct ble_gap_conn_desc desc;
-	struct gap_identity_resolved_ev ev;
-	int rc;
-
-	SYS_LOG_DBG("");
-
-	rc = ble_gap_conn_find(conn_handle, &desc);
-	if (rc) {
-		return;
-	}
-
-	peer_id_addr = desc.peer_id_addr;
-	peer_ota_addr = desc.peer_ota_addr;
-
-	ev.address_type = desc.peer_ota_addr.type;
-	memcpy(ev.address, desc.peer_ota_addr.val, sizeof(ev.address));
-
-	ev.identity_address_type = desc.peer_id_addr.type;
-	memcpy(ev.identity_address, desc.peer_id_addr.val,
-	       sizeof(ev.identity_address));
-
-	tester_send(BTP_SERVICE_ID_GAP, GAP_EV_IDENTITY_RESOLVED,
-		    CONTROLLER_INDEX, (uint8_t *) &ev, sizeof(ev));
-}
-
-static void le_pairing_failed(uint16_t conn_handle, int reason)
+    connection_attempts = 0;
+    memset(&connected_ev, 0, sizeof(connected_ev));
+
+    memcpy(ev.address, addr->val, sizeof(ev.address));
+    ev.address_type = addr->type;
+
+    tester_send(BTP_SERVICE_ID_GAP, GAP_EV_DEVICE_DISCONNECTED,
+            CONTROLLER_INDEX, (uint8_t *) &ev, sizeof(ev));
+}
+
+static void
+auth_passkey_oob(uint16_t conn_handle)
+{
+    struct ble_gap_conn_desc desc;
+    struct ble_sm_io pk;
+    int rc;
+
+    SYS_LOG_DBG("");
+
+    rc = ble_gap_conn_find(conn_handle, &desc);
+    if (rc) {
+        return;
+    }
+
+    memcpy(pk.oob, oob, sizeof(oob));
+    pk.action = BLE_SM_IOACT_OOB;
+
+    rc = ble_sm_inject_io(conn_handle, &pk);
+    assert(rc == 0);
+}
+
+static void
+auth_passkey_display(uint16_t conn_handle, unsigned int passkey)
+{
+    struct ble_gap_conn_desc desc;
+    struct gap_passkey_display_ev ev;
+    ble_addr_t *addr;
+    struct ble_sm_io pk;
+    int rc;
+
+    SYS_LOG_DBG("");
+
+    rc = ble_gap_conn_find(conn_handle, &desc);
+    if (rc) {
+        return;
+    }
+
+    rc = ble_hs_hci_util_rand(&pk.passkey, sizeof(pk.passkey));
+    assert(rc == 0);
+    /* Max value is 999999 */
+    pk.passkey %= 1000000;
+    pk.action = BLE_SM_IOACT_DISP;
+
+    rc = ble_sm_inject_io(conn_handle, &pk);
+    assert(rc == 0);
+
+    addr = &desc.peer_ota_addr;
+
+    memcpy(ev.address, addr->val, sizeof(ev.address));
+    ev.address_type = addr->type;
+    ev.passkey = sys_cpu_to_le32(pk.passkey);
+
+    tester_send(BTP_SERVICE_ID_GAP, GAP_EV_PASSKEY_DISPLAY,
+            CONTROLLER_INDEX, (uint8_t *) &ev, sizeof(ev));
+}
+
+static void
+auth_passkey_entry(uint16_t conn_handle)
+{
+    struct ble_gap_conn_desc desc;
+    struct gap_passkey_entry_req_ev ev;
+    ble_addr_t *addr;
+    int rc;
+
+    SYS_LOG_DBG("");
+
+    rc = ble_gap_conn_find(conn_handle, &desc);
+    if (rc) {
+        return;
+    }
+
+    addr = &desc.peer_ota_addr;
+
+    memcpy(ev.address, addr->val, sizeof(ev.address));
+    ev.address_type = addr->type;
+
+    tester_send(BTP_SERVICE_ID_GAP, GAP_EV_PASSKEY_ENTRY_REQ,
+            CONTROLLER_INDEX, (uint8_t *) &ev, sizeof(ev));
+}
+
+static void
+auth_passkey_numcmp(uint16_t conn_handle, unsigned int passkey)
+{
+    struct ble_gap_conn_desc desc;
+    struct gap_passkey_confirm_req_ev ev;
+    ble_addr_t *addr;
+    int rc;
+
+    SYS_LOG_DBG("");
+
+    rc = ble_gap_conn_find(conn_handle, &desc);
+    if (rc) {
+        return;
+    }
+
+    addr = &desc.peer_ota_addr;
+
+    memcpy(ev.address, addr->val, sizeof(ev.address));
+    ev.address_type = addr->type;
+    ev.passkey = sys_cpu_to_le32(passkey);
+
+    tester_send(BTP_SERVICE_ID_GAP, GAP_EV_PASSKEY_CONFIRM_REQ,
+            CONTROLLER_INDEX, (uint8_t *) &ev, sizeof(ev));
+}
+
+static void
+auth_passkey_oob_sc(uint16_t conn_handle)
+{
+    int rc;
+    struct ble_sm_io pk;
+
+    SYS_LOG_DBG("");
+
+    memset(&pk, 0, sizeof(pk));
+
+    pk.oob_sc_data.local = &oob_data_local;
+
+    if (ble_hs_cfg.sm_oob_data_flag) {
+        pk.oob_sc_data.remote = &oob_data_remote;
+    }
+
+    pk.action = BLE_SM_IOACT_OOB_SC;
+    rc = ble_sm_inject_io(conn_handle, &pk);
+    if (rc != 0) {
+        console_printf("error providing oob; rc=%d\n", rc);
+    }
+}
+
+static void
+le_passkey_action(uint16_t conn_handle,
+                  struct ble_gap_passkey_params *params)
+{
+    SYS_LOG_DBG("");
+
+    switch (params->action) {
+    case BLE_SM_IOACT_NONE:
+        break;
+    case BLE_SM_IOACT_OOB:
+        auth_passkey_oob(conn_handle);
+        break;
+    case BLE_SM_IOACT_INPUT:
+        auth_passkey_entry(conn_handle);
+        break;
+    case BLE_SM_IOACT_DISP:
+        auth_passkey_display(conn_handle, params->numcmp);
+        break;
+    case BLE_SM_IOACT_NUMCMP:
+        auth_passkey_numcmp(conn_handle, params->numcmp);
+        break;
+    case BLE_SM_IOACT_OOB_SC:
+        auth_passkey_oob_sc(conn_handle);
+        break;
+    default:
+        assert(0);
+    }
+}
+
+static void
+le_identity_resolved(uint16_t conn_handle)
+{
+    struct ble_gap_conn_desc desc;
+    struct gap_identity_resolved_ev ev;
+    int rc;
+
+    SYS_LOG_DBG("");
+
+    rc = ble_gap_conn_find(conn_handle, &desc);
+    if (rc) {
+        return;
+    }
+
+    peer_id_addr = desc.peer_id_addr;
+    peer_ota_addr = desc.peer_ota_addr;
+
+    ev.address_type = desc.peer_ota_addr.type;
+    memcpy(ev.address, desc.peer_ota_addr.val, sizeof(ev.address));
+
+    ev.identity_address_type = desc.peer_id_addr.type;
+    memcpy(ev.identity_address, desc.peer_id_addr.val,
+           sizeof(ev.identity_address));
+
+    tester_send(BTP_SERVICE_ID_GAP, GAP_EV_IDENTITY_RESOLVED,
+            CONTROLLER_INDEX, (uint8_t *) &ev, sizeof(ev));
+}
+
+static void
+le_pairing_failed(uint16_t conn_handle, int reason)
 {
     struct ble_gap_conn_desc desc;
     struct gap_sec_pairing_failed_ev ev;
@@ -1005,804 +1034,834 @@
                 CONTROLLER_INDEX, (uint8_t *) &ev, sizeof(ev));
 }
 
-static void le_conn_param_update(struct ble_gap_conn_desc *desc)
-{
-	struct gap_conn_param_update_ev ev;
-
-	SYS_LOG_DBG("");
-
-	ev.address_type = desc->peer_ota_addr.type;
-	memcpy(ev.address, desc->peer_ota_addr.val, sizeof(ev.address));
-
-	ev.conn_itvl = desc->conn_itvl;
-	ev.conn_latency = desc->conn_latency;
-	ev.supervision_timeout = desc->supervision_timeout;
-
-	tester_send(BTP_SERVICE_ID_GAP, GAP_EV_CONN_PARAM_UPDATE,
-		    CONTROLLER_INDEX, (uint8_t *) &ev, sizeof(ev));
-}
-
-static void le_encryption_changed(struct ble_gap_conn_desc *desc)
-{
-	struct gap_sec_level_changed_ev ev;
-
-	SYS_LOG_DBG("");
-
-	encrypted = (bool) desc->sec_state.encrypted;
-
-	ev.address_type = desc->peer_ota_addr.type;
-	memcpy(ev.address, desc->peer_ota_addr.val, sizeof(ev.address));
-	ev.level = 0;
-
-	if (desc->sec_state.encrypted) {
-		if (desc->sec_state.authenticated) {
-			if (desc->sec_state.key_size == 16) {
-				ev.level = 3;
-			} else {
-				ev.level = 2;
-			}
-		} else {
-			ev.level = 1;
-		}
-	}
-
-	tester_send(BTP_SERVICE_ID_GAP, GAP_EV_SEC_LEVEL_CHANGED,
-		    CONTROLLER_INDEX, (uint8_t *) &ev, sizeof(ev));
-}
-
-static void print_bytes(const uint8_t *bytes, int len)
-{
-	int i;
-
-	for (i = 0; i < len; i++) {
-		console_printf("%s0x%02x", i != 0 ? ":" : "", bytes[i]);
-	}
-}
-
-static void print_mbuf(const struct os_mbuf *om)
-{
-	int colon;
-
-	colon = 0;
-	while (om != NULL) {
-		if (colon) {
-			console_printf(":");
-		} else {
-			colon = 1;
-		}
-		print_bytes(om->om_data, om->om_len);
-		om = SLIST_NEXT(om, om_next);
-	}
-}
-
-static void print_addr(const void *addr)
-{
-	const uint8_t *u8p;
-
-	u8p = addr;
-	console_printf("%02x:%02x:%02x:%02x:%02x:%02x",
-		       u8p[5], u8p[4], u8p[3], u8p[2], u8p[1], u8p[0]);
-}
-
-static void print_conn_desc(const struct ble_gap_conn_desc *desc)
-{
-	console_printf("handle=%d our_ota_addr_type=%d our_ota_addr=",
-		       desc->conn_handle, desc->our_ota_addr.type);
-	print_addr(desc->our_ota_addr.val);
-	console_printf(" our_id_addr_type=%d our_id_addr=",
-		       desc->our_id_addr.type);
-	print_addr(desc->our_id_addr.val);
-	console_printf(" peer_ota_addr_type=%d peer_ota_addr=",
-		       desc->peer_ota_addr.type);
-	print_addr(desc->peer_ota_addr.val);
-	console_printf(" peer_id_addr_type=%d peer_id_addr=",
-		       desc->peer_id_addr.type);
-	print_addr(desc->peer_id_addr.val);
-	console_printf(" conn_itvl=%d conn_latency=%d supervision_timeout=%d "
-		       "key_sz=%d encrypted=%d authenticated=%d bonded=%d\n",
-		       desc->conn_itvl, desc->conn_latency,
-		       desc->supervision_timeout,
-		       desc->sec_state.key_size,
-		       desc->sec_state.encrypted,
-		       desc->sec_state.authenticated,
-		       desc->sec_state.bonded);
-}
-
-static void adv_complete(void)
-{
-	struct gap_new_settings_ev ev;
-
-	current_settings &= ~BIT(GAP_SETTINGS_ADVERTISING);
-	ev.current_settings = sys_cpu_to_le32(current_settings);
-
-	tester_send(BTP_SERVICE_ID_GAP, GAP_EV_NEW_SETTINGS, CONTROLLER_INDEX,
-		    (uint8_t *) &ev, sizeof(ev));
-}
-
-static int gap_event_cb(struct ble_gap_event *event, void *arg)
-{
-	struct ble_gap_conn_desc desc;
-	int rc;
-
-	switch (event->type) {
-	case BLE_GAP_EVENT_ADV_COMPLETE:
-		console_printf("advertising complete; reason=%d\n",
-			       event->adv_complete.reason);
-		break;
-	case BLE_GAP_EVENT_CONNECT:
-		console_printf("connection %s; status=%d ",
-			       event->connect.status == 0 ? "established" : "failed",
-			       event->connect.status);
-		if (event->connect.status == 0) {
-			rc = ble_gap_conn_find(event->connect.conn_handle, &desc);
-			assert(rc == 0);
-			print_conn_desc(&desc);
-		}
-
-		if (desc.role == BLE_GAP_ROLE_SLAVE) {
-			adv_complete();
-		}
-
-		le_connected(event->connect.conn_handle,
-			     event->connect.status);
-		break;
-	case BLE_GAP_EVENT_DISCONNECT:
-		console_printf("disconnect; reason=%d ", event->disconnect.reason);
-		print_conn_desc(&event->disconnect.conn);
-		le_disconnected(&event->disconnect.conn,
-				event->disconnect.reason);
-		break;
-	case BLE_GAP_EVENT_ENC_CHANGE:
-		console_printf("encryption change event; status=%d ", event->enc_change.status);
-		rc = ble_gap_conn_find(event->enc_change.conn_handle, &desc);
-		assert(rc == 0);
-		print_conn_desc(&desc);
-		le_encryption_changed(&desc);
-		break;
-	case BLE_GAP_EVENT_PASSKEY_ACTION:
-		console_printf("passkey action event; action=%d",
-			       event->passkey.params.action);
-		if (event->passkey.params.action == BLE_SM_IOACT_NUMCMP) {
-			console_printf(" numcmp=%lu",
-				       (unsigned long)event->passkey.params.numcmp);
-		}
-		console_printf("\n");
-		le_passkey_action(event->passkey.conn_handle,
-				  &event->passkey.params);
-		break;
-	case BLE_GAP_EVENT_IDENTITY_RESOLVED:
-		console_printf("identity resolved ");
-		rc = ble_gap_conn_find(event->identity_resolved.conn_handle, &desc);
-		assert(rc == 0);
-		print_conn_desc(&desc);
-		le_identity_resolved(event->identity_resolved.conn_handle);
-		break;
-	case BLE_GAP_EVENT_NOTIFY_RX:
-		console_printf("notification rx event; attr_handle=%d indication=%d "
-			       "len=%d data=",
-			       event->notify_rx.attr_handle,
-			       event->notify_rx.indication,
-			       OS_MBUF_PKTLEN(event->notify_rx.om));
-
-		print_mbuf(event->notify_rx.om);
-		console_printf("\n");
-		tester_gattc_notify_rx_ev(event->notify_rx.conn_handle,
-					 event->notify_rx.attr_handle,
-					 event->notify_rx.indication,
-					 event->notify_rx.om);
-		break;
-	case BLE_GAP_EVENT_SUBSCRIBE:
-		console_printf("subscribe event; conn_handle=%d attr_handle=%d "
-			       "reason=%d prevn=%d curn=%d previ=%d curi=%d\n",
-			       event->subscribe.conn_handle,
-			       event->subscribe.attr_handle,
-			       event->subscribe.reason,
-			       event->subscribe.prev_notify,
-			       event->subscribe.cur_notify,
-			       event->subscribe.prev_indicate,
-			       event->subscribe.cur_indicate);
-		tester_gatt_subscribe_ev(event->subscribe.conn_handle,
-					 event->subscribe.attr_handle,
-					 event->subscribe.reason,
-					 event->subscribe.prev_notify,
-					 event->subscribe.cur_notify,
-					 event->subscribe.prev_indicate,
-					 event->subscribe.cur_indicate);
-		break;
-	case BLE_GAP_EVENT_REPEAT_PAIRING:
-		console_printf("repeat pairing event; conn_handle=%d "
-			       "cur_key_sz=%d cur_auth=%d cur_sc=%d "
-			       "new_key_sz=%d new_auth=%d new_sc=%d "
-			       "new_bonding=%d\n",
-			event->repeat_pairing.conn_handle,
-			event->repeat_pairing.cur_key_size,
-			event->repeat_pairing.cur_authenticated,
-			event->repeat_pairing.cur_sc,
-			event->repeat_pairing.new_key_size,
-			event->repeat_pairing.new_authenticated,
-			event->repeat_pairing.new_sc,
-			event->repeat_pairing.new_bonding);
-		rc = ble_gap_conn_find(event->repeat_pairing.conn_handle, &desc);
-		assert(rc == 0);
-		rc = ble_store_util_delete_peer(&desc.peer_id_addr);
-		assert(rc == 0);
-		return BLE_GAP_REPEAT_PAIRING_RETRY;
-	case BLE_GAP_EVENT_CONN_UPDATE:
-		console_printf("connection update event; status=%d ",
-			       event->conn_update.status);
-			rc = ble_gap_conn_find(event->conn_update.conn_handle, &desc);
-			assert(rc == 0);
-			print_conn_desc(&desc);
-			le_conn_param_update(&desc);
-		break;
-	case BLE_GAP_EVENT_CONN_UPDATE_REQ:
-		console_printf("connection update request event; "
-			       "conn_handle=%d itvl_min=%d itvl_max=%d "
-			       "latency=%d supervision_timoeut=%d "
-			       "min_ce_len=%d max_ce_len=%d\n",
-			       event->conn_update_req.conn_handle,
-			       event->conn_update_req.peer_params->itvl_min,
-			       event->conn_update_req.peer_params->itvl_max,
-			       event->conn_update_req.peer_params->latency,
-			       event->conn_update_req.peer_params->supervision_timeout,
-			       event->conn_update_req.peer_params->min_ce_len,
-			       event->conn_update_req.peer_params->max_ce_len);
-
-		*event->conn_update_req.self_params =
-			*event->conn_update_req.peer_params;
-		break;
-	case BLE_GAP_EVENT_L2CAP_UPDATE_REQ:
-		console_printf("connection update request event; "
-					   "conn_handle=%d itvl_min=%d itvl_max=%d "
-					   "latency=%d supervision_timoeut=%d "
-					   "min_ce_len=%d max_ce_len=%d\n",
-					   event->conn_update_req.conn_handle,
-					   event->conn_update_req.peer_params->itvl_min,
-					   event->conn_update_req.peer_params->itvl_max,
-					   event->conn_update_req.peer_params->latency,
-					   event->conn_update_req.peer_params->supervision_timeout,
-					   event->conn_update_req.peer_params->min_ce_len,
-					   event->conn_update_req.peer_params->max_ce_len);
-		if (event->conn_update_req.peer_params->itvl_min == REJECT_INTERVAL_MIN &&
-			event->conn_update_req.peer_params->itvl_max == REJECT_INTERVAL_MAX &&
-			event->conn_update_req.peer_params->latency == REJECT_LATENCY &&
-			event->conn_update_req.peer_params->supervision_timeout == REJECT_SUPERVISION_TIMEOUT) {
-			return EINVAL;
-		}
+static void
+le_conn_param_update(struct ble_gap_conn_desc *desc)
+{
+    struct gap_conn_param_update_ev ev;
+
+    SYS_LOG_DBG("");
+
+    ev.address_type = desc->peer_ota_addr.type;
+    memcpy(ev.address, desc->peer_ota_addr.val, sizeof(ev.address));
+
+    ev.conn_itvl = desc->conn_itvl;
+    ev.conn_latency = desc->conn_latency;
+    ev.supervision_timeout = desc->supervision_timeout;
+
+    tester_send(BTP_SERVICE_ID_GAP, GAP_EV_CONN_PARAM_UPDATE,
+            CONTROLLER_INDEX, (uint8_t *) &ev, sizeof(ev));
+}
+
+static void
+le_encryption_changed(struct ble_gap_conn_desc *desc)
+{
+    struct gap_sec_level_changed_ev ev;
+
+    SYS_LOG_DBG("");
+
+    encrypted = (bool) desc->sec_state.encrypted;
+
+    ev.address_type = desc->peer_ota_addr.type;
+    memcpy(ev.address, desc->peer_ota_addr.val, sizeof(ev.address));
+    ev.level = 0;
+
+    if (desc->sec_state.encrypted) {
+        if (desc->sec_state.authenticated) {
+            if (desc->sec_state.key_size == 16) {
+                ev.level = 3;
+            } else {
+                ev.level = 2;
+            }
+        } else {
+            ev.level = 1;
+        }
+    }
+
+    tester_send(BTP_SERVICE_ID_GAP, GAP_EV_SEC_LEVEL_CHANGED,
+            CONTROLLER_INDEX, (uint8_t *) &ev, sizeof(ev));
+}
+
+static void
+print_bytes(const uint8_t *bytes, int len)
+{
+    int i;
+
+    for (i = 0; i < len; i++) {
+        console_printf("%s0x%02x", i != 0 ? ":" : "", bytes[i]);
+    }
+}
+
+static void
+print_mbuf(const struct os_mbuf *om)
+{
+    int colon;
+
+    colon = 0;
+    while (om != NULL) {
+        if (colon) {
+            console_printf(":");
+        } else {
+            colon = 1;
+        }
+        print_bytes(om->om_data, om->om_len);
+        om = SLIST_NEXT(om, om_next);
+    }
+}
+
+static void
+print_addr(const void *addr)
+{
+    const uint8_t *u8p;
+
+    u8p = addr;
+    console_printf("%02x:%02x:%02x:%02x:%02x:%02x",
+               u8p[5], u8p[4], u8p[3], u8p[2], u8p[1], u8p[0]);
+}
+
+static void
+print_conn_desc(const struct ble_gap_conn_desc *desc)
+{
+    console_printf("handle=%d our_ota_addr_type=%d our_ota_addr=",
+               desc->conn_handle, desc->our_ota_addr.type);
+    print_addr(desc->our_ota_addr.val);
+    console_printf(" our_id_addr_type=%d our_id_addr=",
+               desc->our_id_addr.type);
+    print_addr(desc->our_id_addr.val);
+    console_printf(" peer_ota_addr_type=%d peer_ota_addr=",
+               desc->peer_ota_addr.type);
+    print_addr(desc->peer_ota_addr.val);
+    console_printf(" peer_id_addr_type=%d peer_id_addr=",
+               desc->peer_id_addr.type);
+    print_addr(desc->peer_id_addr.val);
+    console_printf(" conn_itvl=%d conn_latency=%d supervision_timeout=%d "
+               "key_sz=%d encrypted=%d authenticated=%d bonded=%d\n",
+               desc->conn_itvl, desc->conn_latency,
+               desc->supervision_timeout,
+               desc->sec_state.key_size,
+               desc->sec_state.encrypted,
+               desc->sec_state.authenticated,
+               desc->sec_state.bonded);
+}
+
+static void
+adv_complete(void)
+{
+    struct gap_new_settings_ev ev;
+
+    current_settings &= ~BIT(GAP_SETTINGS_ADVERTISING);
+    ev.current_settings = sys_cpu_to_le32(current_settings);
+
+    tester_send(BTP_SERVICE_ID_GAP, GAP_EV_NEW_SETTINGS, CONTROLLER_INDEX,
+                (uint8_t *) &ev, sizeof(ev));
+}
+
+static int
+gap_event_cb(struct ble_gap_event *event, void *arg)
+{
+    struct ble_gap_conn_desc desc;
+    int rc;
+
+    switch (event->type) {
+    case BLE_GAP_EVENT_ADV_COMPLETE:
+        console_printf("advertising complete; reason=%d\n",
+                   event->adv_complete.reason);
+        break;
+    case BLE_GAP_EVENT_CONNECT:
+        console_printf("connection %s; status=%d ",
+                   event->connect.status == 0 ? "established" : "failed",
+                   event->connect.status);
+        if (event->connect.status == 0) {
+            rc = ble_gap_conn_find(event->connect.conn_handle, &desc);
+            assert(rc == 0);
+            print_conn_desc(&desc);
+        }
+
+        if (desc.role == BLE_GAP_ROLE_SLAVE) {
+            adv_complete();
+        }
+
+        le_connected(event->connect.conn_handle,
+                 event->connect.status);
+        break;
+    case BLE_GAP_EVENT_DISCONNECT:
+        console_printf("disconnect; reason=%d ", event->disconnect.reason);
+        print_conn_desc(&event->disconnect.conn);
+        le_disconnected(&event->disconnect.conn,
+                event->disconnect.reason);
+        break;
+    case BLE_GAP_EVENT_ENC_CHANGE:
+        console_printf("encryption change event; status=%d ", event->enc_change.status);
+        rc = ble_gap_conn_find(event->enc_change.conn_handle, &desc);
+        assert(rc == 0);
+        print_conn_desc(&desc);
+        le_encryption_changed(&desc);
+        break;
+    case BLE_GAP_EVENT_PASSKEY_ACTION:
+        console_printf("passkey action event; action=%d",
+                   event->passkey.params.action);
+        if (event->passkey.params.action == BLE_SM_IOACT_NUMCMP) {
+            console_printf(" numcmp=%lu",
+                           (unsigned long)event->passkey.params.numcmp);
+        }
+        console_printf("\n");
+        le_passkey_action(event->passkey.conn_handle,
+                  &event->passkey.params);
+        break;
+    case BLE_GAP_EVENT_IDENTITY_RESOLVED:
+        console_printf("identity resolved ");
+        rc = ble_gap_conn_find(event->identity_resolved.conn_handle, &desc);
+        assert(rc == 0);
+        print_conn_desc(&desc);
+        le_identity_resolved(event->identity_resolved.conn_handle);
+        break;
+    case BLE_GAP_EVENT_NOTIFY_RX:
+        console_printf("notification rx event; attr_handle=%d indication=%d "
+                   "len=%d data=",
+                   event->notify_rx.attr_handle,
+                   event->notify_rx.indication,
+                   OS_MBUF_PKTLEN(event->notify_rx.om));
+
+        print_mbuf(event->notify_rx.om);
+        console_printf("\n");
+        tester_gattc_notify_rx_ev(event->notify_rx.conn_handle,
+                     event->notify_rx.attr_handle,
+                     event->notify_rx.indication,
+                     event->notify_rx.om);
+        break;
+    case BLE_GAP_EVENT_SUBSCRIBE:
+        console_printf("subscribe event; conn_handle=%d attr_handle=%d "
+                   "reason=%d prevn=%d curn=%d previ=%d curi=%d\n",
+                   event->subscribe.conn_handle,
+                   event->subscribe.attr_handle,
+                   event->subscribe.reason,
+                   event->subscribe.prev_notify,
+                   event->subscribe.cur_notify,
+                   event->subscribe.prev_indicate,
+                   event->subscribe.cur_indicate);
+        tester_gatt_subscribe_ev(event->subscribe.conn_handle,
+                     event->subscribe.attr_handle,
+                     event->subscribe.reason,
+                     event->subscribe.prev_notify,
+                     event->subscribe.cur_notify,
+                     event->subscribe.prev_indicate,
+                     event->subscribe.cur_indicate);
+        break;
+    case BLE_GAP_EVENT_REPEAT_PAIRING:
+        console_printf("repeat pairing event; conn_handle=%d "
+                   "cur_key_sz=%d cur_auth=%d cur_sc=%d "
+                   "new_key_sz=%d new_auth=%d new_sc=%d "
+                   "new_bonding=%d\n",
+            event->repeat_pairing.conn_handle,
+            event->repeat_pairing.cur_key_size,
+            event->repeat_pairing.cur_authenticated,
+            event->repeat_pairing.cur_sc,
+            event->repeat_pairing.new_key_size,
+            event->repeat_pairing.new_authenticated,
+            event->repeat_pairing.new_sc,
+            event->repeat_pairing.new_bonding);
+        rc = ble_gap_conn_find(event->repeat_pairing.conn_handle, &desc);
+        assert(rc == 0);
+        rc = ble_store_util_delete_peer(&desc.peer_id_addr);
+        assert(rc == 0);
+        return BLE_GAP_REPEAT_PAIRING_RETRY;
+    case BLE_GAP_EVENT_CONN_UPDATE:
+        console_printf("connection update event; status=%d ",
+                   event->conn_update.status);
+        rc = ble_gap_conn_find(event->conn_update.conn_handle, &desc);
+        assert(rc == 0);
+        print_conn_desc(&desc);
+        le_conn_param_update(&desc);
+        break;
+    case BLE_GAP_EVENT_CONN_UPDATE_REQ:
+        console_printf("connection update request event; "
+                   "conn_handle=%d itvl_min=%d itvl_max=%d "
+                   "latency=%d supervision_timoeut=%d "
+                   "min_ce_len=%d max_ce_len=%d\n",
+                   event->conn_update_req.conn_handle,
+                   event->conn_update_req.peer_params->itvl_min,
+                   event->conn_update_req.peer_params->itvl_max,
+                   event->conn_update_req.peer_params->latency,
+                   event->conn_update_req.peer_params->supervision_timeout,
+                   event->conn_update_req.peer_params->min_ce_len,
+                   event->conn_update_req.peer_params->max_ce_len);
+
+        *event->conn_update_req.self_params =
+            *event->conn_update_req.peer_params;
+        break;
+    case BLE_GAP_EVENT_L2CAP_UPDATE_REQ:
+        console_printf("connection update request event; "
+                       "conn_handle=%d itvl_min=%d itvl_max=%d "
+                       "latency=%d supervision_timoeut=%d "
+                       "min_ce_len=%d max_ce_len=%d\n",
+                       event->conn_update_req.conn_handle,
+                       event->conn_update_req.peer_params->itvl_min,
+                       event->conn_update_req.peer_params->itvl_max,
+                       event->conn_update_req.peer_params->latency,
+                       event->conn_update_req.peer_params->supervision_timeout,
+                       event->conn_update_req.peer_params->min_ce_len,
+                       event->conn_update_req.peer_params->max_ce_len);
+        if (event->conn_update_req.peer_params->itvl_min == REJECT_INTERVAL_MIN &&
+            event->conn_update_req.peer_params->itvl_max == REJECT_INTERVAL_MAX &&
+            event->conn_update_req.peer_params->latency == REJECT_LATENCY &&
+            event->conn_update_req.peer_params->supervision_timeout == REJECT_SUPERVISION_TIMEOUT) {
+            return EINVAL;
+        }
     case BLE_GAP_EVENT_PARING_COMPLETE:
         console_printf("received pairing complete: "
                        "conn_handle=%d status=%d\n",
                        event->pairing_complete.conn_handle,
                        event->pairing_complete.status);
         if (event->pairing_complete.status != BLE_SM_ERR_SUCCESS) {
-    	    le_pairing_failed(event->pairing_complete.conn_handle, event->pairing_complete.status);
-        }
-        break;
-	default:
-		break;
-	}
-
-	return 0;
-}
-
-static void connect(const uint8_t *data, uint16_t len)
-{
-	uint8_t status = BTP_STATUS_SUCCESS;
-	ble_addr_t *addr = (ble_addr_t *) data;
-
-	SYS_LOG_DBG("");
-
-	if (ble_addr_cmp(BLE_ADDR_ANY, addr) == 0) {
-		addr = NULL;
-	}
-
-	if (ble_gap_connect(own_addr_type, addr, 0,
-			    &dflt_conn_params, gap_event_cb, NULL)) {
-		status = BTP_STATUS_FAILED;
-	}
-
-	tester_rsp(BTP_SERVICE_ID_GAP, GAP_CONNECT, CONTROLLER_INDEX, status);
-}
-
-static void disconnect(const uint8_t *data, uint16_t len)
-{
-	struct ble_gap_conn_desc desc;
-	uint8_t status;
-	int rc;
-
-	SYS_LOG_DBG("");
-
-	rc = gap_conn_find_by_addr((ble_addr_t *)data, &desc);
-	if (rc) {
-		status = BTP_STATUS_FAILED;
-		goto rsp;
-	}
-
-	if (ble_gap_terminate(desc.conn_handle, BLE_ERR_REM_USER_CONN_TERM)) {
-		status = BTP_STATUS_FAILED;
-	} else {
-		status = BTP_STATUS_SUCCESS;
-	}
+            le_pairing_failed(event->pairing_complete.conn_handle, event->pairing_complete.status);
+        }
+        break;
+    default:
+        break;
+    }
+
+    return 0;
+}
+
+static void
+connect(const uint8_t *data, uint16_t len)
+{
+    uint8_t status = BTP_STATUS_SUCCESS;
+    ble_addr_t *addr = (ble_addr_t *) data;
+
+    SYS_LOG_DBG("");
+
+    if (ble_addr_cmp(BLE_ADDR_ANY, addr) == 0) {
+        addr = NULL;
+    }
+
+    if (ble_gap_connect(own_addr_type, addr, 0,
+                &dflt_conn_params, gap_event_cb, NULL)) {
+        status = BTP_STATUS_FAILED;
+    }
+
+    tester_rsp(BTP_SERVICE_ID_GAP, GAP_CONNECT, CONTROLLER_INDEX, status);
+}
+
+static void
+disconnect(const uint8_t *data, uint16_t len)
+{
+    struct ble_gap_conn_desc desc;
+    uint8_t status;
+    int rc;
+
+    SYS_LOG_DBG("");
+
+    rc = gap_conn_find_by_addr((ble_addr_t *)data, &desc);
+    if (rc) {
+        status = BTP_STATUS_FAILED;
+        goto rsp;
+    }
+
+    if (ble_gap_terminate(desc.conn_handle, BLE_ERR_REM_USER_CONN_TERM)) {
+        status = BTP_STATUS_FAILED;
+    } else {
+        status = BTP_STATUS_SUCCESS;
+    }
 
 rsp:
-	tester_rsp(BTP_SERVICE_ID_GAP, GAP_DISCONNECT, CONTROLLER_INDEX,
-		   status);
-}
-
-static void set_io_cap(const uint8_t *data, uint16_t len)
-{
-	const struct gap_set_io_cap_cmd *cmd = (void *) data;
-	uint8_t status;
-
-	SYS_LOG_DBG("");
-
-	switch (cmd->io_cap) {
-	case GAP_IO_CAP_DISPLAY_ONLY:
-		ble_hs_cfg.sm_io_cap = BLE_SM_IO_CAP_DISP_ONLY;
-		ble_hs_cfg.sm_mitm = 1;
-		break;
-	case GAP_IO_CAP_KEYBOARD_DISPLAY:
-		ble_hs_cfg.sm_io_cap = BLE_SM_IO_CAP_KEYBOARD_DISP;
-		ble_hs_cfg.sm_mitm = 1;
-		break;
-	case GAP_IO_CAP_NO_INPUT_OUTPUT:
-		ble_hs_cfg.sm_io_cap = BLE_SM_IO_CAP_NO_IO;
-		ble_hs_cfg.sm_mitm = 0;
-		break;
-	case GAP_IO_CAP_KEYBOARD_ONLY:
-		ble_hs_cfg.sm_io_cap = BLE_SM_IO_CAP_KEYBOARD_ONLY;
-		ble_hs_cfg.sm_mitm = 1;
-		break;
-	case GAP_IO_CAP_DISPLAY_YESNO:
-		ble_hs_cfg.sm_io_cap = BLE_SM_IO_CAP_DISP_YES_NO;
-		ble_hs_cfg.sm_mitm = 1;
-		break;
-	default:
-		status = BTP_STATUS_FAILED;
-		goto rsp;
-	}
-
-	status = BTP_STATUS_SUCCESS;
+    tester_rsp(BTP_SERVICE_ID_GAP, GAP_DISCONNECT, CONTROLLER_INDEX,
+           status);
+}
+
+static void
+set_io_cap(const uint8_t *data, uint16_t len)
+{
+    const struct gap_set_io_cap_cmd *cmd = (void *) data;
+    uint8_t status;
+
+    SYS_LOG_DBG("");
+
+    switch (cmd->io_cap) {
+    case GAP_IO_CAP_DISPLAY_ONLY:
+        ble_hs_cfg.sm_io_cap = BLE_SM_IO_CAP_DISP_ONLY;
+        ble_hs_cfg.sm_mitm = 1;
+        break;
+    case GAP_IO_CAP_KEYBOARD_DISPLAY:
+        ble_hs_cfg.sm_io_cap = BLE_SM_IO_CAP_KEYBOARD_DISP;
+        ble_hs_cfg.sm_mitm = 1;
+        break;
+    case GAP_IO_CAP_NO_INPUT_OUTPUT:
+        ble_hs_cfg.sm_io_cap = BLE_SM_IO_CAP_NO_IO;
+        ble_hs_cfg.sm_mitm = 0;
+        break;
+    case GAP_IO_CAP_KEYBOARD_ONLY:
+        ble_hs_cfg.sm_io_cap = BLE_SM_IO_CAP_KEYBOARD_ONLY;
+        ble_hs_cfg.sm_mitm = 1;
+        break;
+    case GAP_IO_CAP_DISPLAY_YESNO:
+        ble_hs_cfg.sm_io_cap = BLE_SM_IO_CAP_DISP_YES_NO;
+        ble_hs_cfg.sm_mitm = 1;
+        break;
+    default:
+        status = BTP_STATUS_FAILED;
+        goto rsp;
+    }
+
+    status = BTP_STATUS_SUCCESS;
 
 rsp:
-	tester_rsp(BTP_SERVICE_ID_GAP, GAP_SET_IO_CAP, CONTROLLER_INDEX,
-		   status);
-}
-
-static void pair(const uint8_t *data, uint16_t len)
-{
-	struct ble_gap_conn_desc desc;
-	uint8_t status;
-	int rc;
-
-	SYS_LOG_DBG("");
-
-	rc = gap_conn_find_by_addr((ble_addr_t *)data, &desc);
-	if (rc) {
-		status = BTP_STATUS_FAILED;
-		goto rsp;
-	}
-
-	if (ble_gap_security_initiate(desc.conn_handle)) {
-		status = BTP_STATUS_FAILED;
-		goto rsp;
-	}
-
-	status = BTP_STATUS_SUCCESS;
+    tester_rsp(BTP_SERVICE_ID_GAP, GAP_SET_IO_CAP, CONTROLLER_INDEX,
+           status);
+}
+
+static void
+pair(const uint8_t *data, uint16_t len)
+{
+    struct ble_gap_conn_desc desc;
+    uint8_t status;
+    int rc;
+
+    SYS_LOG_DBG("");
+
+    rc = gap_conn_find_by_addr((ble_addr_t *)data, &desc);
+    if (rc) {
+        status = BTP_STATUS_FAILED;
+        goto rsp;
+    }
+
+    if (ble_gap_security_initiate(desc.conn_handle)) {
+        status = BTP_STATUS_FAILED;
+        goto rsp;
+    }
+
+    status = BTP_STATUS_SUCCESS;
 
 rsp:
-	tester_rsp(BTP_SERVICE_ID_GAP, GAP_PAIR, CONTROLLER_INDEX, status);
-}
-
-static void unpair(const uint8_t *data, uint16_t len)
-{
-	uint8_t status;
-	int err;
-
-	SYS_LOG_DBG("");
-
-	err = ble_gap_unpair((ble_addr_t *) data);
-	status = (uint8_t) (err != 0 ? BTP_STATUS_FAILED : BTP_STATUS_SUCCESS);
-	tester_rsp(BTP_SERVICE_ID_GAP, GAP_UNPAIR, CONTROLLER_INDEX, status);
-}
-
-static void passkey_entry(const uint8_t *data, uint16_t len)
-{
-	const struct gap_passkey_entry_cmd *cmd = (void *) data;
-	struct ble_gap_conn_desc desc;
-	struct ble_sm_io pk;
-	uint8_t status;
-	int rc;
-
-	SYS_LOG_DBG("");
-
-	rc = gap_conn_find_by_addr((ble_addr_t *)data, &desc);
-	if (rc) {
-		status = BTP_STATUS_FAILED;
-		goto rsp;
-	}
-
-	pk.action = BLE_SM_IOACT_INPUT;
-	pk.passkey = sys_le32_to_cpu(cmd->passkey);
-
-	rc = ble_sm_inject_io(desc.conn_handle, &pk);
-	if (rc) {
-		status = BTP_STATUS_FAILED;
-		goto rsp;
-	}
-
-	status = BTP_STATUS_SUCCESS;
+    tester_rsp(BTP_SERVICE_ID_GAP, GAP_PAIR, CONTROLLER_INDEX, status);
+}
+
+static void
+unpair(const uint8_t *data, uint16_t len)
+{
+    uint8_t status;
+    int err;
+
+    SYS_LOG_DBG("");
+
+    err = ble_gap_unpair((ble_addr_t *) data);
+    status = (uint8_t) (err != 0 ? BTP_STATUS_FAILED : BTP_STATUS_SUCCESS);
+    tester_rsp(BTP_SERVICE_ID_GAP, GAP_UNPAIR, CONTROLLER_INDEX, status);
+}
+
+static void
+passkey_entry(const uint8_t *data, uint16_t len)
+{
+    const struct gap_passkey_entry_cmd *cmd = (void *) data;
+    struct ble_gap_conn_desc desc;
+    struct ble_sm_io pk;
+    uint8_t status;
+    int rc;
+
+    SYS_LOG_DBG("");
+
+    rc = gap_conn_find_by_addr((ble_addr_t *)data, &desc);
+    if (rc) {
+        status = BTP_STATUS_FAILED;
+        goto rsp;
+    }
+
+    pk.action = BLE_SM_IOACT_INPUT;
+    pk.passkey = sys_le32_to_cpu(cmd->passkey);
+
+    rc = ble_sm_inject_io(desc.conn_handle, &pk);
+    if (rc) {
+        status = BTP_STATUS_FAILED;
+        goto rsp;
+    }
+
+    status = BTP_STATUS_SUCCESS;
 
 rsp:
-	tester_rsp(BTP_SERVICE_ID_GAP, GAP_PASSKEY_ENTRY, CONTROLLER_INDEX,
-		   status);
-}
-
-static void passkey_confirm(const uint8_t *data, uint16_t len)
-{
-	const struct gap_passkey_confirm_cmd *cmd = (void *) data;
-	struct ble_gap_conn_desc desc;
-	struct ble_sm_io pk;
-	uint8_t status;
-	int rc;
-
-	SYS_LOG_DBG("");
-
-	rc = gap_conn_find_by_addr((ble_addr_t *)data, &desc);
-	if (rc) {
-		status = BTP_STATUS_FAILED;
-		goto rsp;
-	}
-
-	pk.action = BLE_SM_IOACT_NUMCMP;
-	pk.numcmp_accept = cmd->match;
-
-	rc = ble_sm_inject_io(desc.conn_handle, &pk);
-	if (rc) {
-		console_printf("sm inject io failed");
-		status = BTP_STATUS_FAILED;
-		goto rsp;
-	}
-
-	status = BTP_STATUS_SUCCESS;
+    tester_rsp(BTP_SERVICE_ID_GAP, GAP_PASSKEY_ENTRY, CONTROLLER_INDEX,
+           status);
+}
+
+static void
+passkey_confirm(const uint8_t *data, uint16_t len)
+{
+    const struct gap_passkey_confirm_cmd *cmd = (void *) data;
+    struct ble_gap_conn_desc desc;
+    struct ble_sm_io pk;
+    uint8_t status;
+    int rc;
+
+    SYS_LOG_DBG("");
+
+    rc = gap_conn_find_by_addr((ble_addr_t *)data, &desc);
+    if (rc) {
+        status = BTP_STATUS_FAILED;
+        goto rsp;
+    }
+
+    pk.action = BLE_SM_IOACT_NUMCMP;
+    pk.numcmp_accept = cmd->match;
+
+    rc = ble_sm_inject_io(desc.conn_handle, &pk);
+    if (rc) {
+        console_printf("sm inject io failed");
+        status = BTP_STATUS_FAILED;
+        goto rsp;
+    }
+
+    status = BTP_STATUS_SUCCESS;
 
 rsp:
-	tester_rsp(BTP_SERVICE_ID_GAP, GAP_PASSKEY_CONFIRM, CONTROLLER_INDEX,
-		   status);
-}
-
-static void start_direct_adv(const uint8_t *data, uint16_t len)
-{
-	const struct gap_start_direct_adv_cmd *cmd = (void *) data;
-	struct gap_start_advertising_rp rp;
-	static struct ble_gap_adv_params adv_params = {
-		.conn_mode = BLE_GAP_CONN_MODE_DIR,
-	};
-	int err;
-
-	SYS_LOG_DBG("");
-
-	adv_params.high_duty_cycle = cmd->high_duty;
-
-	err = ble_gap_adv_start(own_addr_type, (ble_addr_t *)data,
-				BLE_HS_FOREVER, &adv_params,
-				gap_event_cb, NULL);
-	if (err) {
-		SYS_LOG_ERR("Advertising failed: err %d", err);
-		goto fail;
-	}
-
-	current_settings |= BIT(GAP_SETTINGS_ADVERTISING);
-	rp.current_settings = sys_cpu_to_le32(current_settings);
-
-	tester_send(BTP_SERVICE_ID_GAP, GAP_START_DIRECT_ADV, CONTROLLER_INDEX,
-		    (uint8_t *) &rp, sizeof(rp));
-	return;
+    tester_rsp(BTP_SERVICE_ID_GAP, GAP_PASSKEY_CONFIRM, CONTROLLER_INDEX,
+           status);
+}
+
+static void
+start_direct_adv(const uint8_t *data, uint16_t len)
+{
+    const struct gap_start_direct_adv_cmd *cmd = (void *) data;
+    struct gap_start_advertising_rp rp;
+    static struct ble_gap_adv_params adv_params = {
+        .conn_mode = BLE_GAP_CONN_MODE_DIR,
+    };
+    int err;
+
+    SYS_LOG_DBG("");
+
+    adv_params.high_duty_cycle = cmd->high_duty;
+
+    err = ble_gap_adv_start(own_addr_type, (ble_addr_t *)data,
+                BLE_HS_FOREVER, &adv_params,
+                gap_event_cb, NULL);
+    if (err) {
+        SYS_LOG_ERR("Advertising failed: err %d", err);
+        goto fail;
+    }
+
+    current_settings |= BIT(GAP_SETTINGS_ADVERTISING);
+    rp.current_settings = sys_cpu_to_le32(current_settings);
+
+    tester_send(BTP_SERVICE_ID_GAP, GAP_START_DIRECT_ADV, CONTROLLER_INDEX,
+                (uint8_t *) &rp, sizeof(rp));
+    return;
 fail:
-	tester_rsp(BTP_SERVICE_ID_GAP, GAP_START_DIRECT_ADV, CONTROLLER_INDEX,
-		   BTP_STATUS_FAILED);
-}
-
-static void conn_param_update_cb(uint16_t conn_handle, int status, void *arg)
-{
-	console_printf("conn param update complete; conn_handle=%d status=%d\n",
-		       conn_handle, status);
-}
-
-static int conn_param_update_slave(uint16_t conn_handle,
-				   const struct gap_conn_param_update_cmd *cmd)
-{
-	int rc;
-	struct ble_l2cap_sig_update_params params;
-
-	params.itvl_min = cmd->conn_itvl_min;
-	params.itvl_max = cmd->conn_itvl_max;
-	params.slave_latency = cmd->conn_latency;
-	params.timeout_multiplier = cmd->supervision_timeout;
-
-	rc = ble_l2cap_sig_update(conn_handle, &params,
-				  conn_param_update_cb, NULL);
-	if (rc) {
-		SYS_LOG_ERR("Failed to send update params: rc=%d", rc);
-	}
-
-	return 0;
-}
-
-static int conn_param_update_master(uint16_t conn_handle,
-				    const struct gap_conn_param_update_cmd *cmd)
-{
-	int rc;
-	struct ble_gap_upd_params params;
-
-	params.itvl_min = cmd->conn_itvl_min;
-	params.itvl_max = cmd->conn_itvl_max;
-	params.latency = cmd->conn_latency;
-	params.supervision_timeout = cmd->supervision_timeout;
-	params.min_ce_len = 0;
-	params.max_ce_len = 0;
-	rc = ble_gap_update_params(conn_handle, &params);
-	if (rc) {
-		SYS_LOG_ERR("Failed to send update params: rc=%d", rc);
-	}
-
-	return rc;
-}
-
-static void conn_param_update(struct os_event *ev)
-{
-	struct ble_gap_conn_desc desc;
-	int rc;
-
-	SYS_LOG_DBG("");
-
-	rc = gap_conn_find_by_addr((ble_addr_t *)&update_params, &desc);
-	if (rc) {
-		goto rsp;
-	}
-
-	if ((desc.conn_itvl >= update_params.conn_itvl_min) &&
-	    (desc.conn_itvl <= update_params.conn_itvl_max) &&
-	    (desc.conn_latency == update_params.conn_latency) &&
-	    (desc.supervision_timeout == update_params.supervision_timeout)) {
-		goto rsp;
-	}
-
-	if (desc.role == BLE_GAP_ROLE_MASTER) {
-		rc = conn_param_update_master(desc.conn_handle, &update_params);
-	} else {
-		rc = conn_param_update_slave(desc.conn_handle, &update_params);
-	}
-
-	if (rc == 0) {
-		return;
-	}
+    tester_rsp(BTP_SERVICE_ID_GAP, GAP_START_DIRECT_ADV, CONTROLLER_INDEX,
+           BTP_STATUS_FAILED);
+}
+
+static void
+conn_param_update_cb(uint16_t conn_handle, int status, void *arg)
+{
+    console_printf("conn param update complete; conn_handle=%d status=%d\n",
+               conn_handle, status);
+}
+
+static int
+conn_param_update_slave(uint16_t conn_handle,
+                        const struct gap_conn_param_update_cmd *cmd)
+{
+    int rc;
+    struct ble_l2cap_sig_update_params params;
+
+    params.itvl_min = cmd->conn_itvl_min;
+    params.itvl_max = cmd->conn_itvl_max;
+    params.slave_latency = cmd->conn_latency;
+    params.timeout_multiplier = cmd->supervision_timeout;
+
+    rc = ble_l2cap_sig_update(conn_handle, &params,
+                  conn_param_update_cb, NULL);
+    if (rc) {
+        SYS_LOG_ERR("Failed to send update params: rc=%d", rc);
+    }
+
+    return 0;
+}
+
+static int
+conn_param_update_master(uint16_t conn_handle,
+                         const struct gap_conn_param_update_cmd *cmd)
+{
+    int rc;
+    struct ble_gap_upd_params params;
+
+    params.itvl_min = cmd->conn_itvl_min;
+    params.itvl_max = cmd->conn_itvl_max;
+    params.latency = cmd->conn_latency;
+    params.supervision_timeout = cmd->supervision_timeout;
+    params.min_ce_len = 0;
+    params.max_ce_len = 0;
+    rc = ble_gap_update_params(conn_handle, &params);
+    if (rc) {
+        SYS_LOG_ERR("Failed to send update params: rc=%d", rc);
+    }
+
+    return rc;
+}
+
+static void
+conn_param_update(struct os_event *ev)
+{
+    struct ble_gap_conn_desc desc;
+    int rc;
+
+    SYS_LOG_DBG("");
+
+    rc = gap_conn_find_by_addr((ble_addr_t *)&update_params, &desc);
+    if (rc) {
+        goto rsp;
+    }
+
+    if ((desc.conn_itvl >= update_params.conn_itvl_min) &&
+        (desc.conn_itvl <= update_params.conn_itvl_max) &&
+        (desc.conn_latency == update_params.conn_latency) &&
+        (desc.supervision_timeout == update_params.supervision_timeout)) {
+        goto rsp;
+    }
+
+    if (desc.role == BLE_GAP_ROLE_MASTER) {
+        rc = conn_param_update_master(desc.conn_handle, &update_params);
+    } else {
+        rc = conn_param_update_slave(desc.conn_handle, &update_params);
+    }
+
+    if (rc == 0) {
+        return;
+    }
 
 rsp:
-	SYS_LOG_ERR("Conn param update fail; rc=%d", rc);
-}
-
-static void conn_param_update_async(const uint8_t *data, uint16_t len)
-{
-	const struct gap_conn_param_update_cmd *cmd = (void *) data;
-	update_params = *cmd;
-
-	os_callout_reset(&update_params_co, 0);
-
-	tester_rsp(BTP_SERVICE_ID_GAP, GAP_CONN_PARAM_UPDATE, CONTROLLER_INDEX,
-		   BTP_STATUS_SUCCESS);
-}
-
-static void oob_legacy_set_data(const uint8_t *data, uint16_t len)
-{
-	const struct gap_oob_legacy_set_data_cmd *cmd = (void *) data;
-
-	ble_hs_cfg.sm_oob_data_flag = 1;
-	memcpy(oob, cmd->oob_data, sizeof(oob));
-
-	tester_rsp(BTP_SERVICE_ID_GAP, GAP_OOB_LEGACY_SET_DATA,
-		   CONTROLLER_INDEX, BTP_STATUS_SUCCESS);
-}
-
-static void oob_sc_get_local_data(const uint8_t *data, uint16_t len)
-{
-	struct gap_oob_sc_get_local_data_rp rp;
-
-	memcpy(rp.r, oob_data_local.r, 16);
-	memcpy(rp.c, oob_data_local.c, 16);
-
-	tester_send(BTP_SERVICE_ID_GAP, GAP_OOB_SC_GET_LOCAL_DATA,
-		    CONTROLLER_INDEX, (uint8_t *) &rp, sizeof(rp));
-}
-
-static void oob_sc_set_remote_data(const uint8_t *data, uint16_t len)
-{
-	const struct gap_oob_sc_set_remote_data_cmd *cmd = (void *) data;
-
-	ble_hs_cfg.sm_oob_data_flag = 1;
-	memcpy(oob_data_remote.r, cmd->r, 16);
-	memcpy(oob_data_remote.c, cmd->c, 16);
-
-	tester_rsp(BTP_SERVICE_ID_GAP, GAP_OOB_SC_SET_REMOTE_DATA,
-		   CONTROLLER_INDEX, BTP_STATUS_SUCCESS);
-}
-
-static void set_mitm(const uint8_t *data, uint16_t len)
-{
-	const struct gap_set_mitm_cmd *cmd = (void *) data;
-
-	ble_hs_cfg.sm_mitm = cmd->mitm;
-
-	tester_rsp(BTP_SERVICE_ID_GAP, GAP_SET_MITM,
-		   CONTROLLER_INDEX, BTP_STATUS_SUCCESS);
-}
-
-static void set_filter_accept_list(const uint8_t *data, uint16_t len)
-{
-	uint8_t status = BTP_STATUS_SUCCESS;
-	struct gap_set_filter_accept_list_cmd *tmp =
-			(struct gap_set_filter_accept_list_cmd *) data;
-
-	SYS_LOG_DBG("");
-
-	/*
-	 * Check if the nb of bytes received matches the len of addrs list.
-	 * Then set the filter accept list.
-	 */
-	if (((len - sizeof(tmp->list_len))/sizeof(ble_addr_t) !=
-		tmp->list_len) || ble_gap_wl_set(tmp->addrs, tmp->list_len)) {
-		status = BTP_STATUS_FAILED;
-	}
-
-	tester_rsp(BTP_SERVICE_ID_GAP, GAP_SET_FILTER_ACCEPT_LIST,
-		   			CONTROLLER_INDEX, status);
-}
-
-void tester_handle_gap(uint8_t opcode, uint8_t index, uint8_t *data,
-		       uint16_t len)
-{
-	switch (opcode) {
-	case GAP_READ_SUPPORTED_COMMANDS:
-	case GAP_READ_CONTROLLER_INDEX_LIST:
-		if (index != BTP_INDEX_NONE){
-			tester_rsp(BTP_SERVICE_ID_GAP, opcode, index,
-				   BTP_STATUS_FAILED);
-			return;
-		}
-		break;
-	default:
-		if (index != CONTROLLER_INDEX){
-			tester_rsp(BTP_SERVICE_ID_GAP, opcode, index,
-				   BTP_STATUS_FAILED);
-			return;
-		}
-		break;
-	}
-
-	switch (opcode) {
-	case GAP_READ_SUPPORTED_COMMANDS:
-		supported_commands(data, len);
-		return;
-	case GAP_READ_CONTROLLER_INDEX_LIST:
-		controller_index_list(data, len);
-		return;
-	case GAP_READ_CONTROLLER_INFO:
-		controller_info(data, len);
-		return;
-	case GAP_SET_CONNECTABLE:
-		set_connectable(data, len);
-		return;
-	case GAP_SET_DISCOVERABLE:
-		set_discoverable(data, len);
-		return;
-	case GAP_SET_BONDABLE:
-		set_bondable(data, len);
-		return;
-	case GAP_START_ADVERTISING:
-		start_advertising(data, len);
-		return;
-	case GAP_STOP_ADVERTISING:
-		stop_advertising(data, len);
-		return;
-	case GAP_START_DISCOVERY:
-		start_discovery(data, len);
-		return;
-	case GAP_STOP_DISCOVERY:
-		stop_discovery(data, len);
-		return;
-	case GAP_CONNECT:
-		connect(data, len);
-		return;
-	case GAP_DISCONNECT:
-		disconnect(data, len);
-		return;
-	case GAP_SET_IO_CAP:
-		set_io_cap(data, len);
-		return;
-	case GAP_PAIR:
-		pair(data, len);
-		return;
-	case GAP_UNPAIR:
-		unpair(data, len);
-		return;
-	case GAP_PASSKEY_ENTRY:
-		passkey_entry(data, len);
-		return;
-	case GAP_PASSKEY_CONFIRM:
-		passkey_confirm(data, len);
-		return;
-	case GAP_START_DIRECT_ADV:
-		start_direct_adv(data, len);
-		return;
-	case GAP_CONN_PARAM_UPDATE:
-		conn_param_update_async(data, len);
-		return;
-	case GAP_OOB_LEGACY_SET_DATA:
-		oob_legacy_set_data(data, len);
-		return;
-	case GAP_OOB_SC_GET_LOCAL_DATA:
-		oob_sc_get_local_data(data, len);
-		return;
-	case GAP_OOB_SC_SET_REMOTE_DATA:
-		oob_sc_set_remote_data(data, len);
-		return;
-	case GAP_SET_MITM:
-		set_mitm(data, len);
-		return;
-	case GAP_SET_FILTER_ACCEPT_LIST:
-		set_filter_accept_list(data, len);
-		return;
-	default:
-		tester_rsp(BTP_SERVICE_ID_GAP, opcode, index,
-			   BTP_STATUS_UNKNOWN_CMD);
-		return;
-	}
-}
-
-static void tester_init_gap_cb(int err)
-{
-	if (err) {
-		tester_rsp(BTP_SERVICE_ID_CORE, CORE_REGISTER_SERVICE,
-			   BTP_INDEX_NONE, BTP_STATUS_FAILED);
-		return;
-	}
-
-	current_settings = 0;
-	current_settings |= BIT(GAP_SETTINGS_POWERED);
-	current_settings |= BIT(GAP_SETTINGS_LE);
-
-	os_callout_init(&update_params_co, os_eventq_dflt_get(),
-			conn_param_update, NULL);
-
-	os_callout_init(&connected_ev_co, os_eventq_dflt_get(),
-			device_connected_ev_send, NULL);
-
-	tester_rsp(BTP_SERVICE_ID_CORE, CORE_REGISTER_SERVICE, BTP_INDEX_NONE,
-		   BTP_STATUS_SUCCESS);
-}
-
-uint8_t tester_init_gap(void)
+    SYS_LOG_ERR("Conn param update fail; rc=%d", rc);
+}
+
+static void
+conn_param_update_async(const uint8_t *data, uint16_t len)
+{
+    const struct gap_conn_param_update_cmd *cmd = (void *) data;
+    update_params = *cmd;
+
+    os_callout_reset(&update_params_co, 0);
+
+    tester_rsp(BTP_SERVICE_ID_GAP, GAP_CONN_PARAM_UPDATE, CONTROLLER_INDEX,
+           BTP_STATUS_SUCCESS);
+}
+
+static void
+oob_legacy_set_data(const uint8_t *data, uint16_t len)
+{
+    const struct gap_oob_legacy_set_data_cmd *cmd = (void *) data;
+
+    ble_hs_cfg.sm_oob_data_flag = 1;
+    memcpy(oob, cmd->oob_data, sizeof(oob));
+
+    tester_rsp(BTP_SERVICE_ID_GAP, GAP_OOB_LEGACY_SET_DATA,
+           CONTROLLER_INDEX, BTP_STATUS_SUCCESS);
+}
+
+static void
+oob_sc_get_local_data(const uint8_t *data, uint16_t len)
+{
+    struct gap_oob_sc_get_local_data_rp rp;
+
+    memcpy(rp.r, oob_data_local.r, 16);
+    memcpy(rp.c, oob_data_local.c, 16);
+
+    tester_send(BTP_SERVICE_ID_GAP, GAP_OOB_SC_GET_LOCAL_DATA,
+            CONTROLLER_INDEX, (uint8_t *) &rp, sizeof(rp));
+}
+
+static void
+oob_sc_set_remote_data(const uint8_t *data, uint16_t len)
+{
+    const struct gap_oob_sc_set_remote_data_cmd *cmd = (void *) data;
+
+    ble_hs_cfg.sm_oob_data_flag = 1;
+    memcpy(oob_data_remote.r, cmd->r, 16);
+    memcpy(oob_data_remote.c, cmd->c, 16);
+
+    tester_rsp(BTP_SERVICE_ID_GAP, GAP_OOB_SC_SET_REMOTE_DATA,
+           CONTROLLER_INDEX, BTP_STATUS_SUCCESS);
+}
+
+static void
+set_mitm(const uint8_t *data, uint16_t len)
+{
+    const struct gap_set_mitm_cmd *cmd = (void *) data;
+
+    ble_hs_cfg.sm_mitm = cmd->mitm;
+
+    tester_rsp(BTP_SERVICE_ID_GAP, GAP_SET_MITM,
+           CONTROLLER_INDEX, BTP_STATUS_SUCCESS);
+}
+
+static void
+set_filter_accept_list(const uint8_t *data, uint16_t len)
+{
+    uint8_t status = BTP_STATUS_SUCCESS;
+    struct gap_set_filter_accept_list_cmd *tmp =
+        (struct gap_set_filter_accept_list_cmd *) data;
+
+    SYS_LOG_DBG("");
+
+    /*
+     * Check if the nb of bytes received matches the len of addrs list.
+     * Then set the filter accept list.
+     */
+    if (((len - sizeof(tmp->list_len))/sizeof(ble_addr_t) !=
+         tmp->list_len) || ble_gap_wl_set(tmp->addrs, tmp->list_len)) {
+        status = BTP_STATUS_FAILED;
+    }
+
+    tester_rsp(BTP_SERVICE_ID_GAP, GAP_SET_FILTER_ACCEPT_LIST,
+                    CONTROLLER_INDEX, status);
+}
+
+void
+tester_handle_gap(uint8_t opcode, uint8_t index, uint8_t *data,
+                  uint16_t len)
+{
+    switch (opcode) {
+    case GAP_READ_SUPPORTED_COMMANDS:
+    case GAP_READ_CONTROLLER_INDEX_LIST:
+        if (index != BTP_INDEX_NONE) {
+            tester_rsp(BTP_SERVICE_ID_GAP, opcode, index,
+                   BTP_STATUS_FAILED);
+            return;
+        }
+        break;
+    default:
+        if (index != CONTROLLER_INDEX) {
+            tester_rsp(BTP_SERVICE_ID_GAP, opcode, index,
+                   BTP_STATUS_FAILED);
+            return;
+        }
+        break;
+    }
+
+    switch (opcode) {
+    case GAP_READ_SUPPORTED_COMMANDS:
+        supported_commands(data, len);
+        return;
+    case GAP_READ_CONTROLLER_INDEX_LIST:
+        controller_index_list(data, len);
+        return;
+    case GAP_READ_CONTROLLER_INFO:
+        controller_info(data, len);
+        return;
+    case GAP_SET_CONNECTABLE:
+        set_connectable(data, len);
+        return;
+    case GAP_SET_DISCOVERABLE:
+        set_discoverable(data, len);
+        return;
+    case GAP_SET_BONDABLE:
+        set_bondable(data, len);
+        return;
+    case GAP_START_ADVERTISING:
+        start_advertising(data, len);
+        return;
+    case GAP_STOP_ADVERTISING:
+        stop_advertising(data, len);
+        return;
+    case GAP_START_DISCOVERY:
+        start_discovery(data, len);
+        return;
+    case GAP_STOP_DISCOVERY:
+        stop_discovery(data, len);
+        return;
+    case GAP_CONNECT:
+        connect(data, len);
+        return;
+    case GAP_DISCONNECT:
+        disconnect(data, len);
+        return;
+    case GAP_SET_IO_CAP:
+        set_io_cap(data, len);
+        return;
+    case GAP_PAIR:
+        pair(data, len);
+        return;
+    case GAP_UNPAIR:
+        unpair(data, len);
+        return;
+    case GAP_PASSKEY_ENTRY:
+        passkey_entry(data, len);
+        return;
+    case GAP_PASSKEY_CONFIRM:
+        passkey_confirm(data, len);
+        return;
+    case GAP_START_DIRECT_ADV:
+        start_direct_adv(data, len);
+        return;
+    case GAP_CONN_PARAM_UPDATE:
+        conn_param_update_async(data, len);
+        return;
+    case GAP_OOB_LEGACY_SET_DATA:
+        oob_legacy_set_data(data, len);
+        return;
+    case GAP_OOB_SC_GET_LOCAL_DATA:
+        oob_sc_get_local_data(data, len);
+        return;
+    case GAP_OOB_SC_SET_REMOTE_DATA:
+        oob_sc_set_remote_data(data, len);
+        return;
+    case GAP_SET_MITM:
+        set_mitm(data, len);
+        return;
+    case GAP_SET_FILTER_ACCEPT_LIST:
+        set_filter_accept_list(data, len);
+        return;
+    default:
+        tester_rsp(BTP_SERVICE_ID_GAP, opcode, index,
+               BTP_STATUS_UNKNOWN_CMD);
+        return;
+    }
+}
+
+static void
+tester_init_gap_cb(int err)
+{
+    if (err) {
+        tester_rsp(BTP_SERVICE_ID_CORE, CORE_REGISTER_SERVICE,
+               BTP_INDEX_NONE, BTP_STATUS_FAILED);
+        return;
+    }
+
+    current_settings = 0;
+    current_settings |= BIT(GAP_SETTINGS_POWERED);
+    current_settings |= BIT(GAP_SETTINGS_LE);
+
+    os_callout_init(&update_params_co, os_eventq_dflt_get(),
+            conn_param_update, NULL);
+
+    os_callout_init(&connected_ev_co, os_eventq_dflt_get(),
+            device_connected_ev_send, NULL);
+
+    tester_rsp(BTP_SERVICE_ID_CORE, CORE_REGISTER_SERVICE, BTP_INDEX_NONE,
+           BTP_STATUS_SUCCESS);
+}
+
+uint8_t
+tester_init_gap(void)
 {
 #if MYNEWT_VAL(BLE_SM_SC)
-	int rc;
-
-	rc = ble_sm_sc_oob_generate_data(&oob_data_local);
-	if (rc) {
-		console_printf("Error: generating oob data; reason=%d\n", rc);
-		return BTP_STATUS_FAILED;
-	}
+    int rc;
+
+    rc = ble_sm_sc_oob_generate_data(&oob_data_local);
+    if (rc) {
+        console_printf("Error: generating oob data; reason=%d\n", rc);
+        return BTP_STATUS_FAILED;
+    }
 #endif
 #if MYNEWT_VAL(BTTESTER_PRIVACY_MODE) && MYNEWT_VAL(BTTESTER_USE_NRPA)
-	os_callout_init(&bttester_nrpa_rotate_timer, os_eventq_dflt_get(),
+    os_callout_init(&bttester_nrpa_rotate_timer, os_eventq_dflt_get(),
                     rotate_nrpa_cb, NULL);
 #endif
-	adv_buf = NET_BUF_SIMPLE(ADV_BUF_LEN);
-
-	tester_init_gap_cb(BTP_STATUS_SUCCESS);
-	return BTP_STATUS_SUCCESS;
-}
-
-uint8_t tester_unregister_gap(void)
-{
-	return BTP_STATUS_SUCCESS;
-}
+    adv_buf = NET_BUF_SIMPLE(ADV_BUF_LEN);
+
+    tester_init_gap_cb(BTP_STATUS_SUCCESS);
+    return BTP_STATUS_SUCCESS;
+}
+
+uint8_t
+tester_unregister_gap(void)
+{
+    return BTP_STATUS_SUCCESS;
+}

nimble/host/include/host/ble_gap.h

@@ -1001,28 +1001,28 @@
          *     o BLE_GAP_EVENT_TRANSMIT_POWER
          */
 
-	struct {
-	    /** BLE_ERR_SUCCESS on success or error code on failure */
-	    uint8_t status;
-
-	    /** Connection Handle */
-	    uint16_t conn_handle;
-
-	    /** Reason indicating why event was sent */
-	    uint8_t reason;
-
-	    /** Advertising PHY */
-	    uint8_t phy;
-
-	    /** Transmit power Level */
-	    uint8_t transmit_power_level;
-
-	    /** Transmit Power Level Flag */
-	    uint8_t transmit_power_level_flag;
-
-	    /** Delta indicating change in transmit Power Level */
-	    uint8_t delta;
-	} transmit_power;
+        struct {
+            /** BLE_ERR_SUCCESS on success or error code on failure */
+            uint8_t status;
+
+            /** Connection Handle */
+            uint16_t conn_handle;
+
+            /** Reason indicating why event was sent */
+            uint8_t reason;
+
+            /** Advertising PHY */
+            uint8_t phy;
+
+            /** Transmit power Level */
+            uint8_t transmit_power_level;
+
+            /** Transmit Power Level Flag */
+            uint8_t transmit_power_level_flag;
+
+            /** Delta indicating change in transmit Power Level */
+            uint8_t delta;
+        } transmit_power;
 #endif
         /**
          * Represents a received Pairing Complete message

nimble/host/src/ble_gap.c

@@ -5899,8 +5899,8 @@
 }
 
 /*****************************************************************************
- * $rssi                                                                     *
- *****************************************************************************/
+* $rssi                                                                     *
+*****************************************************************************/
 
 int
 ble_gap_conn_rssi(uint16_t conn_handle, int8_t *out_rssi)

nimble/host/src/ble_sm.c

@@ -2428,13 +2427,13 @@
         cmd = (struct ble_sm_pair_fail *)(*om)->om_data;
 
         res->app_status = BLE_HS_SM_PEER_ERR(cmd->reason);
-        res->sm_err =  cmd->reason;
+        res->sm_err = cmd->reason;
     }
 }
 
 /*****************************************************************************
- * $api                                                                      *
- *****************************************************************************/
+* $api                                                                      *
+*****************************************************************************/
 
 /**
  * Times out expired SM procedures.

Copy link
Contributor

@rymanluk rymanluk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

Added event to inform application via GAP event that peer completed
pairing with reason code. This is required by SM/CEN/KDU/BI-02-C.
Send event when peer fails pairing procedure with reason code.
This is required by SM/CEN/KDU/BI-02-C.
@michal-narajowski michal-narajowski merged commit f7ebfaf into apache:master Aug 25, 2022
@KKopyscinski KKopyscinski deleted the add_pairing_failed_ev branch February 13, 2024 07:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants