Diff between 670d0ed2fd762b5ad2ea6d6a290404b7cd0e37d7 and 07306b872efe221be7e9474fb9923ae5a3d535af

Changed Files

File Additions Deletions Status
emulator/bthost.c +92 -0 modified

Full Patch

diff --git a/emulator/bthost.c b/emulator/bthost.c
index ab055bb..c6e58e5 100644
--- a/emulator/bthost.c
+++ b/emulator/bthost.c
@@ -875,6 +875,95 @@ reject:
 							&rej, sizeof(rej));
 }
 
+static bool l2cap_conn_param_req(struct bthost *bthost, uint16_t handle,
+				uint8_t ident, const void *data, uint16_t len)
+{
+	const struct bt_l2cap_pdu_conn_param_req *req = data;
+	struct bt_l2cap_pdu_conn_param_rsp rsp;
+	struct bt_hci_cmd_le_conn_update hci_cmd;
+
+	if (len < sizeof(*req))
+		return false;
+
+	memset(&hci_cmd, 0, sizeof(hci_cmd));
+	hci_cmd.handle = cpu_to_le16(handle);
+	hci_cmd.min_interval = req->min_interval;
+	hci_cmd.max_interval = req->max_interval;
+	hci_cmd.latency = req->latency;
+	hci_cmd.supv_timeout = req->timeout;
+	hci_cmd.min_length = cpu_to_le16(0x0001);
+	hci_cmd.max_length = cpu_to_le16(0x0001);
+
+	send_command(bthost, BT_HCI_CMD_LE_CONN_UPDATE,
+						&hci_cmd, sizeof(hci_cmd));
+
+	memset(&rsp, 0, sizeof(rsp));
+	l2cap_sig_send(bthost, handle, BT_L2CAP_PDU_CONN_PARAM_RSP, ident,
+							&rsp, sizeof(rsp));
+
+	return true;
+}
+
+static bool l2cap_conn_param_rsp(struct bthost *bthost, uint16_t handle,
+				uint8_t ident, const void *data, uint16_t len)
+{
+	const struct bt_l2cap_pdu_conn_param_req *rsp = data;
+
+	if (len < sizeof(*rsp))
+		return false;
+
+	return true;
+}
+
+static void l2cap_le_sig(struct bthost *bthost, uint16_t handle,
+						const void *data, uint16_t len)
+{
+	const struct bt_l2cap_hdr_sig *hdr = data;
+	struct bt_l2cap_pdu_cmd_reject rej;
+	uint16_t hdr_len;
+	bool ret;
+
+	if (len < sizeof(*hdr))
+		goto reject;
+
+	hdr_len = le16_to_cpu(hdr->len);
+
+	if (sizeof(*hdr) + hdr_len != len)
+		goto reject;
+
+	switch (hdr->code) {
+	case BT_L2CAP_PDU_CMD_REJECT:
+		ret = l2cap_cmd_rej(bthost, handle, hdr->ident,
+						data + sizeof(*hdr), hdr_len);
+		break;
+
+	case BT_L2CAP_PDU_CONN_PARAM_REQ:
+		ret = l2cap_conn_param_req(bthost, handle, hdr->ident,
+						data + sizeof(*hdr), hdr_len);
+		break;
+
+	case BT_L2CAP_PDU_CONN_PARAM_RSP:
+		ret = l2cap_conn_param_rsp(bthost, handle, hdr->ident,
+						data + sizeof(*hdr), hdr_len);
+		break;
+
+	default:
+		printf("Unknown L2CAP code 0x%02x\n", hdr->code);
+		ret = false;
+	}
+
+	handle_pending_l2reqs(bthost, handle, hdr->ident, hdr->code,
+						data + sizeof(*hdr), hdr_len);
+
+	if (ret)
+		return;
+
+reject:
+	memset(&rej, 0, sizeof(rej));
+	l2cap_sig_send(bthost, handle, BT_L2CAP_PDU_CMD_REJECT, 0,
+							&rej, sizeof(rej));
+}
+
 static void process_acl(struct bthost *bthost, const void *data, uint16_t len)
 {
 	const struct bt_hci_acl_hdr *acl_hdr = data;
@@ -903,6 +992,9 @@ static void process_acl(struct bthost *bthost, const void *data, uint16_t len)
 	case 0x0001:
 		l2cap_sig(bthost, handle, l2_data, l2_len);
 		break;
+	case 0x0005:
+		l2cap_le_sig(bthost, handle, l2_data, l2_len);
+		break;
 	default:
 		printf("Packet for unknown CID 0x%04x (%u)\n", cid, cid);
 		break;