Diff between f5653c83e84d36b0745355d35a9741e0cb0c7901 and 4003a333dc4484dd68671ffecda894f57149ff07

Changed Files

File Additions Deletions Status
emulator/bthost.c +13 -0 modified
emulator/bthost.h +2 -0 modified
emulator/smp.c +37 -0 modified

Full Patch

diff --git a/emulator/bthost.c b/emulator/bthost.c
index 7792a71..6c616e8 100644
--- a/emulator/bthost.c
+++ b/emulator/bthost.c
@@ -1522,6 +1522,8 @@ static bool l2cap_info_rsp(struct bthost *bthost, struct btconn *conn,
 		if (len < sizeof(*rsp) + 8)
 			return false;
 		conn->fixed_chan = get_le64(rsp->data);
+		if (conn->smp_data && conn->encr_mode)
+			smp_conn_encrypted(conn->smp_data, conn->encr_mode);
 		break;
 	default:
 		break;
@@ -2318,6 +2320,17 @@ void bthost_le_start_encrypt(struct bthost *bthost, uint16_t handle,
 	send_command(bthost, BT_HCI_CMD_LE_START_ENCRYPT, &cmd, sizeof(cmd));
 }
 
+uint64_t bthost_conn_get_fixed_chan(struct bthost *bthost, uint16_t handle)
+{
+	struct btconn *conn;
+
+	conn = bthost_find_conn(bthost, handle);
+	if (!conn)
+		return 0;
+
+	return conn->fixed_chan;
+}
+
 void bthost_add_l2cap_server(struct bthost *bthost, uint16_t psm,
 				bthost_l2cap_connect_cb func, void *user_data)
 {
diff --git a/emulator/bthost.h b/emulator/bthost.h
index 207ce77..6beb1f4 100644
--- a/emulator/bthost.h
+++ b/emulator/bthost.h
@@ -107,6 +107,8 @@ uint8_t bthost_get_auth_req(struct bthost *bthost);
 void bthost_set_reject_user_confirm(struct bthost *bthost, bool reject);
 bool bthost_get_reject_user_confirm(struct bthost *bthost);
 
+uint64_t bthost_conn_get_fixed_chan(struct bthost *bthost, uint16_t handle);
+
 typedef void (*bthost_rfcomm_connect_cb) (uint16_t handle, uint16_t cid,
 						void *user_data, bool status);
 
diff --git a/emulator/smp.c b/emulator/smp.c
index 5d338b7..4f527e9 100644
--- a/emulator/smp.c
+++ b/emulator/smp.c
@@ -47,6 +47,8 @@
 #define SMP_CID		0x0006
 #define SMP_BREDR_CID	0x0007
 
+#define L2CAP_FC_SMP_BREDR	0x80
+
 #define SMP_PASSKEY_ENTRY_FAILED	0x01
 #define SMP_OOB_NOT_AVAIL		0x02
 #define SMP_AUTH_REQUIREMENTS		0x03
@@ -462,6 +464,13 @@ static void pairing_rsp(struct smp_conn *conn, const void *data, uint16_t len)
 	conn->local_key_dist = conn->prsp[5];
 	conn->remote_key_dist = conn->prsp[6];
 
+	if (conn->addr_type == BDADDR_BREDR) {
+		conn->local_key_dist &= ~SC_NO_DIST;
+		conn->remote_key_dist &= ~SC_NO_DIST;
+		distribute_keys(conn);
+		return;
+	}
+
 	if (((conn->prsp[3] & 0x08) && (conn->preq[3] & 0x08)) ||
 					conn->addr_type == BDADDR_BREDR) {
 		conn->sc = true;
@@ -788,6 +797,29 @@ int smp_get_ltk(void *smp_data, uint64_t rand, uint16_t ediv, uint8_t *ltk)
 	return 0;
 }
 
+static void smp_conn_bredr(struct smp_conn *conn, uint8_t encrypt)
+{
+	struct smp *smp = conn->smp;
+	struct bt_l2cap_smp_pairing_request req;
+	uint64_t fixed_chan;
+
+	if (encrypt != 0x02)
+		return;
+
+	conn->sc = true;
+
+	fixed_chan = bthost_conn_get_fixed_chan(smp->bthost, conn->handle);
+	if (!(fixed_chan & L2CAP_FC_SMP_BREDR))
+		return;
+
+	memset(&req, 0, sizeof(req));
+	req.max_key_size = 0x10;
+	req.init_key_dist = KEY_DIST;
+	req.resp_key_dist = KEY_DIST;
+
+	smp_send(conn, BT_L2CAP_SMP_PAIRING_REQUEST, &req, sizeof(req));
+}
+
 void smp_conn_encrypted(void *conn_data, uint8_t encrypt)
 {
 	struct smp_conn *conn = conn_data;
@@ -795,6 +827,11 @@ void smp_conn_encrypted(void *conn_data, uint8_t encrypt)
 	if (!encrypt)
 		return;
 
+	if (conn->addr_type == BDADDR_BREDR) {
+		smp_conn_bredr(conn, encrypt);
+		return;
+	}
+
 	if (conn->out && conn->remote_key_dist)
 		return;