From patchwork Wed Jan 8 00:33:22 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luiz Augusto von Dentz X-Patchwork-Id: 197521 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.6 required=3.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7E5F9C33C9E for ; Wed, 8 Jan 2020 00:33:48 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 4B896206F0 for ; Wed, 8 Jan 2020 00:33:48 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="qow/aPts" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726837AbgAHAds (ORCPT ); Tue, 7 Jan 2020 19:33:48 -0500 Received: from mail-pg1-f176.google.com ([209.85.215.176]:45099 "EHLO mail-pg1-f176.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726411AbgAHAdr (ORCPT ); Tue, 7 Jan 2020 19:33:47 -0500 Received: by mail-pg1-f176.google.com with SMTP id b9so653527pgk.12 for ; Tue, 07 Jan 2020 16:33:47 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:subject:date:message-id:in-reply-to:references:mime-version :content-transfer-encoding; bh=YQg2WNzj/S4xESCNpW4vqMS7o4sgCnxBsBwcCP7+PJc=; b=qow/aPtsCHtG4R1zoNBGpYxWbK3JZUnApueeLpztBYdx2rKRK02VB9VtACrBq/1CTi qxfjQN5Q7exx57cOA8dkVcqStsIAl9RL8GQdsVdN1SSZ8qP2ET8TJMumRd/GncScINP4 bekgKB/n3AU0wfwFc7lBW73hSzeHOs23T14PrJgzN6kSOVeAVzMLiooog/+qWNvqL82u SA1qeBSBABmIMgkUk7Vs38u1PGjZz7ZKMpAybP/+wNdNb0T6Q/jbOTu3zGqA43y3gfEi sS9rMO0KDx9vR34yfyDYmoeJRs/+t7kZKpmkkgDBdnhxMrx3erLawE/S0vItKuexdwzl rc+Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=YQg2WNzj/S4xESCNpW4vqMS7o4sgCnxBsBwcCP7+PJc=; b=V8KHIUQY3k4NxjnmD5PWzrSErC+iup4ipbKd/1ud5TEwWZI9VmA6+1UB2K8IbqWt3B sDY4P33/fEFWZ3z2rlKCsLvDZTJ0KNnYAN+0/vZuo9iV2PdrQaFf23vI4xOurlnrM6nE LPURFgxwDgqmh1aHwmI8Dq4Gl3Byw6bZnPkPnkEtFAxDC9wtzZDHhy/GKhqCH0BAZW8W D87c6S+dMb7g3BBYMLI6uBEQrzf8lfgomkdsaKPEhddCupCiGxmIDSarC8vHFSwHNpCX ijE7qxxYndo2HzPC06CMmuSEssI2pRRWMHDzqCib3dFDJDyCkEMtfiKWUFs7ZBtKIvtY R7XA== X-Gm-Message-State: APjAAAWx9di5pl4RsQevOtQvYYy1Q+0Pg7ZO8chpwWn29eHcQr2TErN/ ZwXKfAHXEayGqrP1DXvk+OrYv93qK/E= X-Google-Smtp-Source: APXvYqzJcJIWnvfjGR0MkrgKO7rj2HQzXd7nDzqxy0sQGXg36VOba+mrlfAGgMJQKPQohCLgprFi/w== X-Received: by 2002:a63:89c2:: with SMTP id v185mr2320357pgd.135.1578443625828; Tue, 07 Jan 2020 16:33:45 -0800 (PST) Received: from localhost.localdomain ([192.102.209.43]) by smtp.gmail.com with ESMTPSA id u10sm925805pgg.41.2020.01.07.16.33.45 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 07 Jan 2020 16:33:45 -0800 (PST) From: Luiz Augusto von Dentz To: linux-bluetooth@vger.kernel.org Subject: [PATCH BlueZ 02/22] monitor: Add decoding of ISO related Link Layer PDUs Date: Tue, 7 Jan 2020 16:33:22 -0800 Message-Id: <20200108003342.15458-3-luiz.dentz@gmail.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20200108003342.15458-1-luiz.dentz@gmail.com> References: <20200108003342.15458-1-luiz.dentz@gmail.com> MIME-Version: 1.0 Sender: linux-bluetooth-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org From: Luiz Augusto von Dentz This adds the decoding of ISO related Link Layer PDUs --- monitor/bt.h | 48 ++++++++++++++++++++++++- monitor/ll.c | 100 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 147 insertions(+), 1 deletion(-) diff --git a/monitor/bt.h b/monitor/bt.h index 04ad34ea9..0a88aff97 100644 --- a/monitor/bt.h +++ b/monitor/bt.h @@ -28,7 +28,7 @@ #define BT_HCI_BIT_5_2 (8 * 41) + 5 #define BT_HCI_SUBEVT_5_2 0x19 -#define BT_LL_CMD_MILAN 0x1f +#define BT_LL_CMD_5_2 0x1f struct bt_ll_hdr { uint8_t preamble; @@ -181,6 +181,52 @@ struct bt_ll_clock_acc { #define BT_LL_CLOCK_ACCURACY_RSP 0x1e +#define BT_LL_CIS_REQ BT_LL_CMD_5_2 +struct bt_ll_cis_req { + uint8_t cig; + uint8_t cis; + uint8_t m_phy; + uint8_t s_phy; + uint16_t m_sdu; + uint16_t s_sdu; + uint8_t m_interval[3]; + uint8_t s_interval[3]; + uint8_t m_pdu; + uint8_t s_pdu; + uint8_t nse; + uint8_t sub_interval[3]; + uint8_t bn; + uint8_t m_ft; + uint8_t s_ft; + uint16_t iso_interval; + uint8_t offset_min[3]; + uint8_t offset_max[3]; + uint16_t conn_event_count; +} __attribute__ ((packed)); + +#define BT_LL_CIS_RSP BT_LL_CMD_5_2 + 1 +struct bt_ll_cis_rsp { + uint8_t offset_min[3]; + uint8_t offset_max[3]; + uint16_t conn_event_count; +} __attribute__ ((packed)); + +#define BT_LL_CIS_IND BT_LL_CMD_5_2 + 2 +struct bt_ll_cis_ind { + uint32_t addr; + uint8_t cis_offset[3]; + uint8_t cig_sync_delay[3]; + uint8_t cis_sync_delay[3]; + uint16_t conn_event_count; +} __attribute__ ((packed)); + +#define BT_LL_CIS_TERMINATE_IND BT_LL_CMD_5_2 + 3 +struct bt_ll_cis_term_ind { + uint8_t cig; + uint8_t cis; + uint8_t reason; +} __attribute__ ((packed)); + #define LMP_ESC4(x) ((127 << 8) | (x)) #define BT_LMP_NAME_REQ 1 diff --git a/monitor/ll.c b/monitor/ll.c index 5141f2be6..4b3f567bd 100644 --- a/monitor/ll.c +++ b/monitor/ll.c @@ -601,6 +601,97 @@ static void clock_acc_req_rsp(const void *data, uint8_t size) print_field("SCA: 0x%2.2x", pdu->sca); } +static void cis_req(const void *data, uint8_t size) +{ + const struct bt_ll_cis_req *cmd = data; + uint32_t interval; + uint8_t mask; + + print_field("CIG ID: 0x%2.2x", cmd->cig); + print_field("CIS ID: 0x%2.2x", cmd->cis); + print_field("Master to Slave PHY: 0x%2.2x", cmd->m_phy); + + mask = print_bitfield(2, cmd->m_phy, le_phys); + if (mask) + print_text(COLOR_UNKNOWN_OPTIONS_BIT, " Reserved" + " (0x%2.2x)", mask); + + print_field("Slave To Master PHY: 0x%2.2x", cmd->s_phy); + + mask = print_bitfield(2, cmd->s_phy, le_phys); + if (mask) + print_text(COLOR_UNKNOWN_OPTIONS_BIT, " Reserved" + " (0x%2.2x)", mask); + + print_field("Master to Slave Maximum SDU: %u", cmd->m_sdu); + print_field("Slave to Master Maximum SDU: %u", cmd->s_sdu); + + memcpy(&interval, cmd->m_interval, sizeof(cmd->m_interval)); + print_field("Master to Slave Interval: 0x%6.6x", le32_to_cpu(interval)); + memcpy(&interval, cmd->s_interval, sizeof(cmd->s_interval)); + print_field("Slave to Master Interval: 0x%6.6x", le32_to_cpu(interval)); + + print_field("Master to Slave Maximum PDU: %u", cmd->m_pdu); + print_field("Slave to Master Maximum PDU: %u", cmd->s_pdu); + + print_field("Burst Number: %u us", cmd->bn); + + memcpy(&interval, cmd->sub_interval, sizeof(cmd->sub_interval)); + print_field("Sub-Interval: 0x%6.6x", le32_to_cpu(interval)); + + print_field("Master to Slave Flush Timeout: %u", cmd->m_ft); + print_field("Slave to Master Flush Timeout: %u", cmd->s_ft); + + print_field("ISO Interval: 0x%4.4x", le16_to_cpu(cmd->iso_interval)); + + memcpy(&interval, cmd->offset_min, sizeof(cmd->offset_min)); + print_field("CIS Offset Minimum: 0x%6.6x", le32_to_cpu(interval)); + memcpy(&interval, cmd->offset_max, sizeof(cmd->offset_max)); + print_field("CIS Offset Maximum: 0x%6.6x", le32_to_cpu(interval)); + + print_field("Connection Event Count: %u", cmd->conn_event_count); +} + +static void cis_rsp(const void *data, uint8_t size) +{ + const struct bt_ll_cis_rsp *rsp = data; + uint32_t interval; + + memcpy(&interval, rsp->offset_min, sizeof(rsp->offset_min)); + print_field("CIS Offset Minimum: 0x%6.6x", le32_to_cpu(interval)); + memcpy(&interval, rsp->offset_max, sizeof(rsp->offset_max)); + print_field("CIS Offset Maximum: 0x%6.6x", le32_to_cpu(interval)); + + print_field("Connection Event Count: %u", rsp->conn_event_count); +} + +static void cis_ind(const void *data, uint8_t size) +{ + const struct bt_ll_cis_ind *ind = data; + uint32_t interval; + + print_field("CIS Access Address: 0x%4.4x", le32_to_cpu(ind->addr)); + memcpy(&interval, ind->cis_offset, sizeof(ind->cis_offset)); + print_field("CIS Offset: 0x%6.6x", le32_to_cpu(interval)); + + memcpy(&interval, ind->cig_sync_delay, sizeof(ind->cig_sync_delay)); + print_field("CIG Synchronization Delay: 0x%6.6x", + le32_to_cpu(interval)); + memcpy(&interval, ind->cis_sync_delay, sizeof(ind->cis_sync_delay)); + print_field("CIS Synchronization Delay: %u us", + le32_to_cpu(interval)); + print_field("Connection Event Count: %u", ind->conn_event_count); +} + +static void cis_term_ind(const void *data, uint8_t size) +{ + const struct bt_ll_cis_term_ind *ind = data; + + print_field("CIG ID: 0x%2.2x", ind->cig); + print_field("CIS ID: 0x%2.2x", ind->cis); + packet_print_error("Reason", ind->reason); +} + struct llcp_data { uint8_t opcode; const char *str; @@ -641,6 +732,15 @@ static const struct llcp_data llcp_table[] = { { 0x1c, "LL_PERIODIC_SYNC_IND", periodic_sync_ind, 34, true }, { 0x1d, "LL_CLOCK_ACCURACY_REQ", clock_acc_req_rsp, 1, true }, { 0x1e, "LL_CLOCK_ACCURACY_RSP", clock_acc_req_rsp, 1, true }, + { BT_LL_CIS_REQ, "LL_CIS_REQ", cis_req, + sizeof(struct bt_ll_cis_req), true }, + { BT_LL_CIS_RSP, "LL_CIS_RSP", cis_rsp, + sizeof(struct bt_ll_cis_rsp), true }, + { BT_LL_CIS_IND, "LL_CIS_IND", cis_ind, + sizeof(struct bt_ll_cis_ind), true }, + { BT_LL_CIS_TERMINATE_IND, "LL_CIS_TERMINATE_IND", cis_term_ind, + sizeof(struct bt_ll_cis_term_ind), + true }, { } }; From patchwork Wed Jan 8 00:33:23 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luiz Augusto von Dentz X-Patchwork-Id: 197520 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.6 required=3.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id AB48CC33C9B for ; Wed, 8 Jan 2020 00:33:48 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 80EA72075A for ; Wed, 8 Jan 2020 00:33:48 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="JC6hEdzQ" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726852AbgAHAds (ORCPT ); Tue, 7 Jan 2020 19:33:48 -0500 Received: from mail-pl1-f196.google.com ([209.85.214.196]:34282 "EHLO mail-pl1-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726836AbgAHAdr (ORCPT ); Tue, 7 Jan 2020 19:33:47 -0500 Received: by mail-pl1-f196.google.com with SMTP id x17so387743pln.1 for ; Tue, 07 Jan 2020 16:33:47 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:subject:date:message-id:in-reply-to:references:mime-version :content-transfer-encoding; bh=j2ZCFATyIGjIUkx/0ER/kXgMfFAg7tvRILbBVi+IPog=; b=JC6hEdzQh/YA92JYxZDHlsT8Mg/FK+ZlagckdnjJxuJM8YgpADoagVexJ2knt1/X6V S9usrwtR5DntsefybCRIPkPizwUxOPNSXHCl+bOd756P8jRUF5J+CuvhlOaYh7x4NjwT YbbJ9/xMdXMjfUha5SmusYMPFiqqDN0qGRjq60PsOYGUOTSFxWlWoZUORSfpisGCkOFI MgMwDxcemCG7EMWhGV0oLcKPxKStrXHEQ47XFMRhHmflOWh5WxvXX2QuFvIs4VooTx+a 8T0x8e0FaXzULWQYPRqWP1BKj/23lmR+v6DqZUrtIYsaJWRzrmPjUQxHsER0Kjx0/KWi rgFg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=j2ZCFATyIGjIUkx/0ER/kXgMfFAg7tvRILbBVi+IPog=; b=csN/lhYjgWKdn+GpyoM5KBQsRMKoUkQ4Z6V4FXo31x2c9TMtD6ZMnuki3dKB1Ajz9D jgG4TVllCZeXZgQEpP0R7MjCUq4KQ1ehGhGyidAoNcjuIWM1xbF4K7xALGW9lvJt5yFD MPBsFfyxwRzw5zEQk0xsLAvTTAmN/fb+UOTwKGHBDdNfrtwxOo7r0P9UmRYOVYvcR/tD 8YnjicnpPswURPZnlvkjVZyoxa5lQzl8Zt4FkHTEbO3D4xzXINt3cozCHn+hnxVGpC7w qCNgVc1gME76PwXOwU79Kl5D2WNFGT/x1CVuyA6wrIKZV/iJhHZOMhY7tPOWQSJz+4OP zN2g== X-Gm-Message-State: APjAAAX3YeG8s/iK1X5+g0bV8kKLABjswcWyz9SxKvyjMnhB2jDphEz0 uEhVODyr7jKOAkuU9qgFHz1jekKeEN0= X-Google-Smtp-Source: APXvYqxY47XM3yVpNNuridM79aXkAv0lJCfNT2tG4eIzh8Lcv/BdQkOUk8mNcRGCaxrszDPSzqfQgw== X-Received: by 2002:a17:902:bd96:: with SMTP id q22mr2483912pls.94.1578443626617; Tue, 07 Jan 2020 16:33:46 -0800 (PST) Received: from localhost.localdomain ([192.102.209.43]) by smtp.gmail.com with ESMTPSA id u10sm925805pgg.41.2020.01.07.16.33.45 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 07 Jan 2020 16:33:46 -0800 (PST) From: Luiz Augusto von Dentz To: linux-bluetooth@vger.kernel.org Subject: [PATCH BlueZ 03/22] lib: Add definitions for ISO socket Date: Tue, 7 Jan 2020 16:33:23 -0800 Message-Id: <20200108003342.15458-4-luiz.dentz@gmail.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20200108003342.15458-1-luiz.dentz@gmail.com> References: <20200108003342.15458-1-luiz.dentz@gmail.com> MIME-Version: 1.0 Sender: linux-bluetooth-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org From: Luiz Augusto von Dentz --- lib/bluetooth.h | 14 ++++++++++++++ lib/iso.h | 45 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) create mode 100644 lib/iso.h diff --git a/lib/bluetooth.h b/lib/bluetooth.h index 756dce164..ec110f757 100644 --- a/lib/bluetooth.h +++ b/lib/bluetooth.h @@ -50,6 +50,7 @@ extern "C" { #define BTPROTO_CMTP 5 #define BTPROTO_HIDP 6 #define BTPROTO_AVDTP 7 +#define BTPROTO_ISO 8 #define SOL_HCI 0 #define SOL_L2CAP 6 @@ -120,6 +121,19 @@ struct bt_voice { #define BT_SNDMTU 12 #define BT_RCVMTU 13 +#define BT_ISO_IN_QOS 15 +#define BT_ISO_OUT_QOS 16 +struct bt_iso_qos { + uint8_t sca; + uint8_t packing; + uint8_t framing; + uint32_t interval; + uint16_t latency; + uint16_t mtu; + uint8_t phy; + uint8_t rtn; +}; + #define BT_VOICE_TRANSPARENT 0x0003 #define BT_VOICE_CVSD_16BIT 0x0060 diff --git a/lib/iso.h b/lib/iso.h new file mode 100644 index 000000000..2d427b417 --- /dev/null +++ b/lib/iso.h @@ -0,0 +1,45 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2019 Intel Corporation. + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef __ISO_H +#define __ISO_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* ISO defaults */ +#define ISO_DEFAULT_MTU 251 + +/* ISO socket address */ +struct sockaddr_iso { + sa_family_t iso_family; + bdaddr_t iso_bdaddr; + uint8_t iso_bdaddr_type; +}; + +#ifdef __cplusplus +} +#endif + +#endif /* __ISO_H */ From patchwork Wed Jan 8 00:33:25 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luiz Augusto von Dentz X-Patchwork-Id: 197518 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.6 required=3.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1D386C33C9E for ; Wed, 8 Jan 2020 00:33:52 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id C4F47206F0 for ; Wed, 8 Jan 2020 00:33:51 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="iX7UfAm0" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726932AbgAHAdv (ORCPT ); Tue, 7 Jan 2020 19:33:51 -0500 Received: from mail-pj1-f45.google.com ([209.85.216.45]:52848 "EHLO mail-pj1-f45.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726856AbgAHAdu (ORCPT ); Tue, 7 Jan 2020 19:33:50 -0500 Received: by mail-pj1-f45.google.com with SMTP id a6so296966pjh.2 for ; Tue, 07 Jan 2020 16:33:49 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:subject:date:message-id:in-reply-to:references:mime-version :content-transfer-encoding; bh=Jbm/HArERlf6ukM7/6poE8pGXCnkfvAHld3teK8r7nw=; b=iX7UfAm0bBb3Ra0u8JsXoGzHAmGpD1BT2km7bVvx8sydGDrUTj5mfFJoEb+sCzejxE b4tDllkh3cHgqTIoL8VNdtDuMuK3PiO0koy7OFBNlmv2bgoefR8qoK79ZBsX3LnHdz/f /BG9BJDXT8qgfNaFauKaGyP+JEl+ANFEhh/rVoKlvNMxra8+dDxXdiksBn5w3I2y4HZw Q5506J1u/qhPrQbKLHl9Au3wgASh70SLG8tiLu9sbQGH8c4eGx27BfvxgBRuOFBST2LC AVDzIFPAyMwUfgbrRaByL0QUS2nRyw2HRpc7RvAGxP4dOwNgZ5lDjifwoil7qEDpS7ns lE3w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=Jbm/HArERlf6ukM7/6poE8pGXCnkfvAHld3teK8r7nw=; b=mpmmJRJVBDVqpLWtoc7yPBGCwxi7A0k/7E/X7BCf40k+hpdQ6yB7+MGH9n0+eka6jz adNZkrKQZjXL9Epm2HRpR1fOfIF4Ns7DAP2bFHQEP+DfORgztmX2QvLgKTURiOZR/XN/ KtMAizMFm5zdXDIwal86OyB/zMtK0HfIbAqSCl57vPXIvDdUUveszZXiRPFHFsZCbLZj U1RpKwo+jXnD6KFHd9vRO2nEA9M1mU2ATX5YSC4VUTxhFeB++3viQOyEEbgcX1JQr+6r PH06Z3Aqi73hiA/kZan7HtvuOpVepmWvzEmX6x8xXqTNxxnI78WhuwMNVba5yGfBxf5v TTMA== X-Gm-Message-State: APjAAAWpHYMJ2L8NG3S8cCngYv8NY5k7B/2wUoQDsqab0vdMCoF+w6kX YlqngC18dZTVrazcy+Ti4zBTinXCwPo= X-Google-Smtp-Source: APXvYqxsnpa8eBn6rQyQD5nbpbjqUOKn2cG5+vkA5s61h2z+LxPrTFI45gGVqobZrtap8o1vF86trA== X-Received: by 2002:a17:902:6802:: with SMTP id h2mr2496887plk.233.1578443628704; Tue, 07 Jan 2020 16:33:48 -0800 (PST) Received: from localhost.localdomain ([192.102.209.43]) by smtp.gmail.com with ESMTPSA id u10sm925805pgg.41.2020.01.07.16.33.47 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 07 Jan 2020 16:33:48 -0800 (PST) From: Luiz Augusto von Dentz To: linux-bluetooth@vger.kernel.org Subject: [PATCH BlueZ 05/22] emulator: Add initial support for BT 5.2 Date: Tue, 7 Jan 2020 16:33:25 -0800 Message-Id: <20200108003342.15458-6-luiz.dentz@gmail.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20200108003342.15458-1-luiz.dentz@gmail.com> References: <20200108003342.15458-1-luiz.dentz@gmail.com> MIME-Version: 1.0 Sender: linux-bluetooth-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org From: Luiz Augusto von Dentz This adds the initial command/event decoding for 5.2. --- emulator/btdev.c | 271 +++++++++++++++++++++++++++++++++++++++------- emulator/btdev.h | 1 + emulator/hciemu.c | 3 + emulator/hciemu.h | 1 + emulator/vhci.c | 3 +- 5 files changed, 236 insertions(+), 43 deletions(-) diff --git a/emulator/btdev.c b/emulator/btdev.c index 38d5b3b1f..02f408dd5 100644 --- a/emulator/btdev.c +++ b/emulator/btdev.c @@ -47,6 +47,9 @@ #define has_bredr(btdev) (!((btdev)->features[4] & 0x20)) #define has_le(btdev) (!!((btdev)->features[4] & 0x40)) +#define ACL_HANDLE 42 +#define ISO_HANDLE 44 + struct hook { btdev_hook_func handler; void *user_data; @@ -92,6 +95,8 @@ struct btdev { uint8_t feat_page_2[8]; uint16_t acl_mtu; uint16_t acl_max_pkt; + uint16_t iso_mtu; + uint16_t iso_max_pkt; uint8_t country_code; uint8_t bdaddr[6]; uint8_t random_addr[6]; @@ -438,6 +443,30 @@ static void set_le_50_commands(struct btdev *btdev) btdev->commands[38] |= 0x40; /* LE Read Periodic Adv List Size */ } +static void set_le_60_commands(struct btdev *btdev) +{ + btdev->commands[41] |= 0x20; /* LE Read Buffer Size v2 */ + btdev->commands[41] |= 0x40; /* LE Read ISO TX Sync */ + btdev->commands[41] |= 0x80; /* LE Set CIG Parameters */ + btdev->commands[42] |= 0x01; /* LE Set CIG Parameters Test */ + btdev->commands[42] |= 0x02; /* LE Create CIS */ + btdev->commands[42] |= 0x04; /* LE Remove CIG */ + btdev->commands[42] |= 0x08; /* LE Accept CIS */ + btdev->commands[42] |= 0x10; /* LE Reject CIS */ + btdev->commands[42] |= 0x20; /* LE Create BIG */ + btdev->commands[42] |= 0x40; /* LE Create BIG Test */ + btdev->commands[42] |= 0x80; /* LE Terminate BIG */ + btdev->commands[43] |= 0x01; /* LE BIG Create Sync */ + btdev->commands[43] |= 0x02; /* LE BIG Terminate Sync */ + btdev->commands[43] |= 0x04; /* LE Request Peer SCA */ + btdev->commands[43] |= 0x08; /* LE Setup ISO Path */ + btdev->commands[43] |= 0x10; /* LE Remove ISO Path */ + btdev->commands[43] |= 0x20; /* LE ISO TX Test */ + btdev->commands[43] |= 0x40; /* LE ISO RX Test */ + btdev->commands[43] |= 0x80; /* LE ISO Read Test Counter */ + btdev->commands[44] |= 0x01; /* LE ISO Test End */ +} + static void set_le_commands(struct btdev *btdev) { set_common_commands_all(btdev); @@ -482,6 +511,10 @@ static void set_le_commands(struct btdev *btdev) /* Extra LE commands for >= 5.0 adapters */ if (btdev->type >= BTDEV_TYPE_BREDRLE50) set_le_50_commands(btdev); + + /* Extra LE commands for >= 6.0 adapters */ + if (btdev->type >= BTDEV_TYPE_BREDRLE60) + set_le_60_commands(btdev); } static void set_bredrle_commands(struct btdev *btdev) @@ -550,6 +583,14 @@ static void set_bredrle_features(struct btdev *btdev) btdev->le_features[1] |= 0x10; /* LE EXT ADV */ } + if (btdev->type >= BTDEV_TYPE_BREDRLE60) { + btdev->le_features[3] |= 0x10; /* LE CIS Master */ + btdev->le_features[3] |= 0x20; /* LE CIS Slave */ + btdev->le_features[3] |= 0x40; /* LE ISO Broadcaster */ + btdev->le_features[3] |= 0x80; /* LE Synchronized Receiver */ + btdev->le_features[4] |= 0x01; /* LE ISO channels */ + } + btdev->feat_page_2[0] |= 0x01; /* CSB - Master Operation */ btdev->feat_page_2[0] |= 0x02; /* CSB - Slave Operation */ btdev->feat_page_2[0] |= 0x04; /* Synchronization Train */ @@ -644,8 +685,9 @@ struct btdev *btdev_create(enum btdev_type type, uint16_t id) memset(btdev, 0, sizeof(*btdev)); - if (type == BTDEV_TYPE_BREDRLE || type == BTDEV_TYPE_LE - || type == BTDEV_TYPE_BREDRLE50) { + if (type == BTDEV_TYPE_BREDRLE || type == BTDEV_TYPE_LE || + type == BTDEV_TYPE_BREDRLE50 || + type == BTDEV_TYPE_BREDRLE60) { btdev->crypto = bt_crypto_new(); if (!btdev->crypto) { free(btdev); @@ -661,6 +703,7 @@ struct btdev *btdev_create(enum btdev_type type, uint16_t id) switch (btdev->type) { case BTDEV_TYPE_BREDRLE: case BTDEV_TYPE_BREDRLE50: + case BTDEV_TYPE_BREDRLE60: btdev->version = 0x09; set_bredrle_features(btdev); set_bredrle_commands(btdev); @@ -700,6 +743,9 @@ struct btdev *btdev_create(enum btdev_type type, uint16_t id) btdev->acl_mtu = 192; btdev->acl_max_pkt = 1; + btdev->iso_mtu = 251; + btdev->iso_max_pkt = 1; + btdev->country_code = 0x00; index = add_btdev(btdev); @@ -893,13 +939,13 @@ static void le_meta_event(struct btdev *btdev, uint8_t event, send_event(btdev, BT_HCI_EVT_LE_META_EVENT, pkt_data, 1 + len); } -static void num_completed_packets(struct btdev *btdev) +static void num_completed_packets(struct btdev *btdev, uint16_t handle) { if (btdev->conn) { struct bt_hci_evt_num_completed_packets ncp; ncp.num_handles = 1; - ncp.handle = cpu_to_le16(42); + ncp.handle = cpu_to_le16(handle); ncp.count = cpu_to_le16(1); send_event(btdev, BT_HCI_EVT_NUM_COMPLETED_PACKETS, @@ -1106,12 +1152,12 @@ static void conn_complete(struct btdev *btdev, memcpy(cc.bdaddr, btdev->bdaddr, 6); cc.encr_mode = 0x00; - cc.handle = cpu_to_le16(42); + cc.handle = cpu_to_le16(ACL_HANDLE); cc.link_type = 0x01; send_event(remote, BT_HCI_EVT_CONN_COMPLETE, &cc, sizeof(cc)); - cc.handle = cpu_to_le16(42); + cc.handle = cpu_to_le16(ACL_HANDLE); cc.link_type = 0x01; } else { cc.handle = cpu_to_le16(0x0000); @@ -1208,7 +1254,7 @@ static void le_conn_complete(struct btdev *btdev, memcpy(cc->peer_addr, btdev->bdaddr, 6); cc->role = 0x01; - cc->handle = cpu_to_le16(42); + cc->handle = cpu_to_le16(ACL_HANDLE); cc->interval = lecc->max_interval; cc->latency = lecc->latency; cc->supv_timeout = lecc->supv_timeout; @@ -1255,7 +1301,7 @@ static void le_ext_conn_complete(struct btdev *btdev, memcpy(cc->peer_addr, btdev->bdaddr, 6); cc->role = 0x01; - cc->handle = cpu_to_le16(42); + cc->handle = cpu_to_le16(ACL_HANDLE); cc->interval = lecc->max_interval; cc->latency = lecc->latency; cc->supv_timeout = lecc->supv_timeout; @@ -1356,6 +1402,46 @@ static void le_ext_conn_request(struct btdev *btdev, BT_HCI_ERR_CONN_FAILED_TO_ESTABLISH); } +static void le_cis_estabilished(struct btdev *dev, uint8_t status) +{ + struct bt_hci_evt_le_cis_established evt; + + memset(&evt, 0, sizeof(evt)); + + evt.status = status; + + if (!evt.status) { + evt.conn_handle = cpu_to_le16(ISO_HANDLE); + evt.m_phy = 0x01; + evt.m_phy = 0x01; + } + + le_meta_event(dev, BT_HCI_EVT_LE_CIS_ESTABLISHED, &evt, sizeof(evt)); + + if (dev->conn) + le_meta_event(dev->conn, BT_HCI_EVT_LE_CIS_ESTABLISHED, &evt, + sizeof(evt)); +} + +static void le_cis_request(struct btdev *dev, + const struct bt_hci_cmd_le_create_cis *leccis) +{ + struct btdev *remote = dev->conn; + + if (remote) { + struct bt_hci_evt_le_cis_req evt; + + evt.acl_handle = cpu_to_le16(ACL_HANDLE); + evt.cis_handle = cpu_to_le16(ISO_HANDLE); + evt.cis_id = 0x00; + evt.cis_id = 0x00; + + le_meta_event(remote, BT_HCI_EVT_LE_CIS_REQ, &evt, sizeof(evt)); + } else { + le_cis_estabilished(dev, BT_HCI_ERR_UNKNOWN_CONN_ID); + } +} + static void conn_request(struct btdev *btdev, const uint8_t *bdaddr) { struct btdev *remote = find_btdev_by_bdaddr(bdaddr); @@ -1464,8 +1550,10 @@ static void disconnect_complete(struct btdev *btdev, uint16_t handle, dc.handle = cpu_to_le16(handle); dc.reason = reason; - btdev->conn = NULL; - remote->conn = NULL; + if (dc.handle == ACL_HANDLE) { + btdev->conn = NULL; + remote->conn = NULL; + } send_event(btdev, BT_HCI_EVT_DISCONNECT_COMPLETE, &dc, sizeof(dc)); send_event(remote, BT_HCI_EVT_DISCONNECT_COMPLETE, &dc, sizeof(dc)); @@ -1492,7 +1580,7 @@ static void link_key_req_reply_complete(struct btdev *btdev, return; } - ev.handle = cpu_to_le16(42); + ev.handle = cpu_to_le16(ACL_HANDLE); if (!memcmp(btdev->link_key, remote->link_key, 16)) ev.status = BT_HCI_ERR_SUCCESS; @@ -1587,7 +1675,7 @@ static void encrypt_change(struct btdev *btdev, uint8_t mode, uint8_t status) struct bt_hci_evt_encrypt_change ev; ev.status = status; - ev.handle = cpu_to_le16(42); + ev.handle = cpu_to_le16(ACL_HANDLE); ev.encr_mode = mode; send_event(btdev, BT_HCI_EVT_ENCRYPT_CHANGE, &ev, sizeof(ev)); @@ -1628,7 +1716,7 @@ static void pin_code_req_reply_complete(struct btdev *btdev, } if (remote->conn) { - ev.handle = cpu_to_le16(42); + ev.handle = cpu_to_le16(ACL_HANDLE); send_event(remote, BT_HCI_EVT_AUTH_COMPLETE, &ev, sizeof(ev)); } else { conn_complete(remote, btdev->bdaddr, ev.status); @@ -1651,7 +1739,7 @@ static void pin_code_req_neg_reply_complete(struct btdev *btdev, } ev.status = BT_HCI_ERR_PIN_OR_KEY_MISSING; - ev.handle = cpu_to_le16(42); + ev.handle = cpu_to_le16(ACL_HANDLE); if (btdev->conn) send_event(btdev, BT_HCI_EVT_AUTH_COMPLETE, &ev, sizeof(ev)); @@ -1944,7 +2032,7 @@ static void ssp_complete(struct btdev *btdev, const uint8_t *bdaddr, } auth.status = status; - auth.handle = cpu_to_le16(42); + auth.handle = cpu_to_le16(ACL_HANDLE); send_event(init, BT_HCI_EVT_AUTH_COMPLETE, &auth, sizeof(auth)); } @@ -2207,7 +2295,7 @@ static void le_read_remote_features_complete(struct btdev *btdev) memset(buf, 0, sizeof(buf)); buf[0] = BT_HCI_EVT_LE_REMOTE_FEATURES_COMPLETE; ev->status = BT_HCI_ERR_SUCCESS; - ev->handle = cpu_to_le16(42); + ev->handle = cpu_to_le16(ACL_HANDLE); memcpy(ev->features, remote->le_features, 8); send_event(btdev, BT_HCI_EVT_LE_META_EVENT, buf, sizeof(buf)); @@ -2230,7 +2318,7 @@ static void le_start_encrypt_complete(struct btdev *btdev, uint16_t ediv, memset(buf, 0, sizeof(buf)); buf[0] = BT_HCI_EVT_LE_LONG_TERM_KEY_REQUEST; - ev->handle = cpu_to_le16(42); + ev->handle = cpu_to_le16(ACL_HANDLE); ev->ediv = ediv; ev->rand = rand; @@ -2244,7 +2332,7 @@ static void le_encrypt_complete(struct btdev *btdev) struct btdev *remote = btdev->conn; memset(&rp, 0, sizeof(rp)); - rp.handle = cpu_to_le16(42); + rp.handle = cpu_to_le16(ACL_HANDLE); if (!remote) { rp.status = BT_HCI_ERR_UNKNOWN_CONN_ID; @@ -2266,7 +2354,7 @@ static void le_encrypt_complete(struct btdev *btdev) ev.encr_mode = 0x01; } - ev.handle = cpu_to_le16(42); + ev.handle = cpu_to_le16(ACL_HANDLE); send_event(btdev, BT_HCI_EVT_ENCRYPT_CHANGE, &ev, sizeof(ev)); send_event(remote, BT_HCI_EVT_ENCRYPT_CHANGE, &ev, sizeof(ev)); @@ -2279,7 +2367,7 @@ static void ltk_neg_reply_complete(struct btdev *btdev) struct btdev *remote = btdev->conn; memset(&rp, 0, sizeof(rp)); - rp.handle = cpu_to_le16(42); + rp.handle = cpu_to_le16(ACL_HANDLE); if (!remote) { rp.status = BT_HCI_ERR_UNKNOWN_CONN_ID; @@ -2293,7 +2381,7 @@ static void ltk_neg_reply_complete(struct btdev *btdev) memset(&ev, 0, sizeof(ev)); ev.status = BT_HCI_ERR_PIN_OR_KEY_MISSING; - ev.handle = cpu_to_le16(42); + ev.handle = cpu_to_le16(ACL_HANDLE); send_event(remote, BT_HCI_EVT_ENCRYPT_CHANGE, &ev, sizeof(ev)); } @@ -2364,6 +2452,7 @@ static void default_cmd(struct btdev *btdev, uint16_t opcode, const struct bt_hci_cmd_le_set_ext_scan_params *lsesp; const struct bt_hci_le_scan_phy *lsp; const struct bt_hci_cmd_le_set_ext_scan_enable *lsese; + const struct bt_hci_cmd_le_reject_cis *lrcis; struct bt_hci_rsp_read_default_link_policy rdlp; struct bt_hci_rsp_read_stored_link_key rslk; struct bt_hci_rsp_write_stored_link_key wslk; @@ -2425,6 +2514,11 @@ static void default_cmd(struct btdev *btdev, uint16_t opcode, struct bt_hci_evt_le_generate_dhkey_complete dh_evt; struct bt_hci_rsp_le_read_num_supported_adv_sets rlrnsas; struct bt_hci_rsp_le_set_ext_adv_params rlseap; + struct bt_hci_rsp_le_read_buffer_size_v2 lrbsv2; + struct lescp { + struct bt_hci_rsp_le_set_cig_params params; + uint16_t handle; + } __attribute__ ((packed)) lscp; uint8_t status, page; switch (opcode) { @@ -2960,7 +3054,8 @@ static void default_cmd(struct btdev *btdev, uint16_t opcode, case BT_HCI_CMD_READ_LE_HOST_SUPPORTED: if (btdev->type != BTDEV_TYPE_BREDRLE && - btdev->type != BTDEV_TYPE_BREDRLE50) + btdev->type != BTDEV_TYPE_BREDRLE50 && + btdev->type != BTDEV_TYPE_BREDRLE60) goto unsupported; rlhs.status = BT_HCI_ERR_SUCCESS; rlhs.supported = btdev->le_supported; @@ -2971,7 +3066,8 @@ static void default_cmd(struct btdev *btdev, uint16_t opcode, case BT_HCI_CMD_WRITE_LE_HOST_SUPPORTED: if (btdev->type != BTDEV_TYPE_BREDRLE && btdev->type != BTDEV_TYPE_LE && - btdev->type != BTDEV_TYPE_BREDRLE50) + btdev->type != BTDEV_TYPE_BREDRLE50 && + btdev->type != BTDEV_TYPE_BREDRLE60) goto unsupported; wlhs = data; btdev->le_supported = wlhs->supported; @@ -2982,7 +3078,8 @@ static void default_cmd(struct btdev *btdev, uint16_t opcode, case BT_HCI_CMD_READ_SECURE_CONN_SUPPORT: if (btdev->type != BTDEV_TYPE_BREDRLE && - btdev->type != BTDEV_TYPE_BREDRLE50) + btdev->type != BTDEV_TYPE_BREDRLE50 && + btdev->type != BTDEV_TYPE_BREDRLE60) goto unsupported; rscs.status = BT_HCI_ERR_SUCCESS; rscs.support = btdev->secure_conn_support; @@ -2991,7 +3088,8 @@ static void default_cmd(struct btdev *btdev, uint16_t opcode, case BT_HCI_CMD_WRITE_SECURE_CONN_SUPPORT: if (btdev->type != BTDEV_TYPE_BREDRLE && - btdev->type != BTDEV_TYPE_BREDRLE50) + btdev->type != BTDEV_TYPE_BREDRLE50 && + btdev->type != BTDEV_TYPE_BREDRLE60) goto unsupported; wscs = data; btdev->secure_conn_support = wscs->support; @@ -3001,7 +3099,8 @@ static void default_cmd(struct btdev *btdev, uint16_t opcode, case BT_HCI_CMD_READ_LOCAL_OOB_EXT_DATA: if (btdev->type != BTDEV_TYPE_BREDRLE && - btdev->type != BTDEV_TYPE_BREDRLE50) + btdev->type != BTDEV_TYPE_BREDRLE50 && + btdev->type != BTDEV_TYPE_BREDRLE60) goto unsupported; rloed.status = BT_HCI_ERR_SUCCESS; cmd_complete(btdev, opcode, &rloed, sizeof(rloed)); @@ -3009,7 +3108,8 @@ static void default_cmd(struct btdev *btdev, uint16_t opcode, case BT_HCI_CMD_READ_SYNC_TRAIN_PARAMS: if (btdev->type != BTDEV_TYPE_BREDRLE && - btdev->type != BTDEV_TYPE_BREDRLE50) + btdev->type != BTDEV_TYPE_BREDRLE50 && + btdev->type != BTDEV_TYPE_BREDRLE60) goto unsupported; rstp.status = BT_HCI_ERR_SUCCESS; rstp.interval = cpu_to_le16(btdev->sync_train_interval); @@ -3160,7 +3260,8 @@ static void default_cmd(struct btdev *btdev, uint16_t opcode, case BT_HCI_CMD_READ_ENCRYPT_KEY_SIZE: if (btdev->type != BTDEV_TYPE_BREDRLE && btdev->type != BTDEV_TYPE_BREDR && - btdev->type != BTDEV_TYPE_BREDRLE50) + btdev->type != BTDEV_TYPE_BREDRLE50 && + btdev->type != BTDEV_TYPE_BREDRLE60) goto unsupported; reks = data; read_enc_key_size_complete(btdev, le16_to_cpu(reks->handle)); @@ -3535,7 +3636,8 @@ static void default_cmd(struct btdev *btdev, uint16_t opcode, cmd_complete(btdev, opcode, &lcprnr_rsp, sizeof(lcprnr_rsp)); break; case BT_HCI_CMD_LE_READ_NUM_SUPPORTED_ADV_SETS: - if (btdev->type != BTDEV_TYPE_BREDRLE50) + if (btdev->type != BTDEV_TYPE_BREDRLE50 && + btdev->type != BTDEV_TYPE_BREDRLE60) goto unsupported; rlrnsas.status = BT_HCI_ERR_SUCCESS; @@ -3544,7 +3646,8 @@ static void default_cmd(struct btdev *btdev, uint16_t opcode, cmd_complete(btdev, opcode, &rlrnsas, sizeof(rlrnsas)); break; case BT_HCI_CMD_LE_SET_ADV_SET_RAND_ADDR: - if (btdev->type != BTDEV_TYPE_BREDRLE50) + if (btdev->type != BTDEV_TYPE_BREDRLE50 && + btdev->type != BTDEV_TYPE_BREDRLE60) goto unsupported; lsasra = data; @@ -3553,7 +3656,8 @@ static void default_cmd(struct btdev *btdev, uint16_t opcode, cmd_complete(btdev, opcode, &status, sizeof(status)); break; case BT_HCI_CMD_LE_SET_EXT_ADV_PARAMS: - if (btdev->type != BTDEV_TYPE_BREDRLE50) + if (btdev->type != BTDEV_TYPE_BREDRLE50 && + btdev->type != BTDEV_TYPE_BREDRLE60) goto unsupported; if (btdev->le_adv_enable) { @@ -3573,7 +3677,8 @@ static void default_cmd(struct btdev *btdev, uint16_t opcode, cmd_complete(btdev, opcode, &rlseap, sizeof(rlseap)); break; case BT_HCI_CMD_LE_SET_EXT_ADV_ENABLE: - if (btdev->type != BTDEV_TYPE_BREDRLE50) + if (btdev->type != BTDEV_TYPE_BREDRLE50 && + btdev->type != BTDEV_TYPE_BREDRLE60) goto unsupported; lseae = data; @@ -3588,7 +3693,8 @@ static void default_cmd(struct btdev *btdev, uint16_t opcode, le_set_ext_adv_enable_complete(btdev); break; case BT_HCI_CMD_LE_SET_EXT_ADV_DATA: - if (btdev->type != BTDEV_TYPE_BREDRLE50) + if (btdev->type != BTDEV_TYPE_BREDRLE50 && + btdev->type != BTDEV_TYPE_BREDRLE60) goto unsupported; lsead = data; @@ -3598,7 +3704,8 @@ static void default_cmd(struct btdev *btdev, uint16_t opcode, cmd_complete(btdev, opcode, &status, sizeof(status)); break; case BT_HCI_CMD_LE_SET_EXT_SCAN_RSP_DATA: - if (btdev->type != BTDEV_TYPE_BREDRLE50) + if (btdev->type != BTDEV_TYPE_BREDRLE50 && + btdev->type != BTDEV_TYPE_BREDRLE60) goto unsupported; lsesrd = data; @@ -3608,14 +3715,16 @@ static void default_cmd(struct btdev *btdev, uint16_t opcode, cmd_complete(btdev, opcode, &status, sizeof(status)); break; case BT_HCI_CMD_LE_REMOVE_ADV_SET: - if (btdev->type != BTDEV_TYPE_BREDRLE50) + if (btdev->type != BTDEV_TYPE_BREDRLE50 && + btdev->type != BTDEV_TYPE_BREDRLE60) goto unsupported; status = BT_HCI_ERR_SUCCESS; cmd_complete(btdev, opcode, &status, sizeof(status)); break; case BT_HCI_CMD_LE_CLEAR_ADV_SETS: - if (btdev->type != BTDEV_TYPE_BREDRLE50) + if (btdev->type != BTDEV_TYPE_BREDRLE50 && + btdev->type != BTDEV_TYPE_BREDRLE60) goto unsupported; status = BT_HCI_ERR_SUCCESS; @@ -3636,7 +3745,8 @@ static void default_cmd(struct btdev *btdev, uint16_t opcode, cmd_complete(btdev, opcode, &status, sizeof(status)); break; case BT_HCI_CMD_LE_SET_EXT_SCAN_PARAMS: - if (btdev->type != BTDEV_TYPE_BREDRLE50) + if (btdev->type != BTDEV_TYPE_BREDRLE50 && + btdev->type != BTDEV_TYPE_BREDRLE60) goto unsupported; lsesp = data; @@ -3658,7 +3768,8 @@ static void default_cmd(struct btdev *btdev, uint16_t opcode, cmd_complete(btdev, opcode, &status, sizeof(status)); break; case BT_HCI_CMD_LE_SET_EXT_SCAN_ENABLE: - if (btdev->type != BTDEV_TYPE_BREDRLE50) + if (btdev->type != BTDEV_TYPE_BREDRLE50 && + btdev->type != BTDEV_TYPE_BREDRLE60) goto unsupported; lsese = data; @@ -3672,11 +3783,62 @@ static void default_cmd(struct btdev *btdev, uint16_t opcode, cmd_complete(btdev, opcode, &status, sizeof(status)); break; case BT_HCI_CMD_LE_EXT_CREATE_CONN: - if (btdev->type != BTDEV_TYPE_BREDRLE50) + if (btdev->type != BTDEV_TYPE_BREDRLE50 && + btdev->type != BTDEV_TYPE_BREDRLE60) + goto unsupported; + + cmd_status(btdev, BT_HCI_ERR_SUCCESS, opcode); + break; + + case BT_HCI_CMD_LE_READ_BUFFER_SIZE_V2: + if (btdev->type != BTDEV_TYPE_BREDRLE60) + goto unsupported; + lrbsv2.status = BT_HCI_ERR_SUCCESS; + lrbsv2.acl_mtu = cpu_to_le16(btdev->acl_mtu); + lrbsv2.acl_max_pkt = btdev->acl_max_pkt; + lrbsv2.iso_mtu = cpu_to_le16(btdev->iso_mtu); + lrbsv2.iso_max_pkt = btdev->iso_max_pkt; + cmd_complete(btdev, opcode, &lrbsv2, sizeof(lrbsv2)); + break; + + case BT_HCI_CMD_LE_SET_CIG_PARAMS: + if (btdev->type != BTDEV_TYPE_BREDRLE60) + goto unsupported; + lscp.params.status = BT_HCI_ERR_SUCCESS; + lscp.params.cig_id = 0x00; + lscp.params.num_handles = 1; + lscp.handle = cpu_to_le16(ISO_HANDLE); + cmd_complete(btdev, opcode, &lscp, sizeof(lscp)); + break; + + case BT_HCI_CMD_LE_CREATE_CIS: + if (btdev->type != BTDEV_TYPE_BREDRLE60) + goto unsupported; + + cmd_status(btdev, BT_HCI_ERR_SUCCESS, opcode); + + break; + + case BT_HCI_CMD_LE_ACCEPT_CIS: + if (btdev->type != BTDEV_TYPE_BREDRLE60) goto unsupported; cmd_status(btdev, BT_HCI_ERR_SUCCESS, opcode); + le_cis_estabilished(btdev, BT_HCI_ERR_SUCCESS); + break; + + case BT_HCI_CMD_LE_REJECT_CIS: + if (btdev->type != BTDEV_TYPE_BREDRLE60) + goto unsupported; + + cmd_status(btdev, BT_HCI_ERR_SUCCESS, opcode); + + lrcis = data; + le_cis_estabilished(btdev, lrcis->reason); + + break; + default: goto unsupported; } @@ -3716,6 +3878,7 @@ static void default_cmd_completion(struct btdev *btdev, uint16_t opcode, const struct bt_hci_cmd_le_set_scan_enable *lsse; const struct bt_hci_cmd_le_set_ext_scan_enable *lsese; const struct bt_hci_cmd_le_ext_create_conn *leecc; + const struct bt_hci_cmd_le_create_cis *leccis; switch (opcode) { case BT_HCI_CMD_INQUIRY: @@ -3912,19 +4075,28 @@ static void default_cmd_completion(struct btdev *btdev, uint16_t opcode, le_set_scan_enable_complete(btdev); break; case BT_HCI_CMD_LE_SET_EXT_SCAN_ENABLE: - if (btdev->type != BTDEV_TYPE_BREDRLE50) + if (btdev->type != BTDEV_TYPE_BREDRLE50 && + btdev->type != BTDEV_TYPE_BREDRLE60) return; lsese = data; if (btdev->le_scan_enable && lsese->enable) le_set_ext_scan_enable_complete(btdev); break; case BT_HCI_CMD_LE_EXT_CREATE_CONN: - if (btdev->type != BTDEV_TYPE_BREDRLE50) + if (btdev->type != BTDEV_TYPE_BREDRLE50 && + btdev->type != BTDEV_TYPE_BREDRLE60) return; leecc = data; btdev->le_scan_own_addr_type = leecc->own_addr_type; le_ext_conn_request(btdev, leecc); break; + case BT_HCI_CMD_LE_CREATE_CIS: + if (btdev->type != BTDEV_TYPE_BREDRLE50 && + btdev->type != BTDEV_TYPE_BREDRLE60) + return; + leccis = data; + le_cis_request(btdev, leccis); + break; } } @@ -4033,6 +4205,16 @@ static void send_acl(struct btdev *conn, const void *data, uint16_t len) send_packet(conn, iov, 3); } +static void send_iso(struct btdev *conn, const void *data, uint16_t len) +{ + struct iovec iov; + + iov.iov_base = (void *) (data); + iov.iov_len = len; + + send_packet(conn, &iov, 1); +} + void btdev_receive_h4(struct btdev *btdev, const void *data, uint16_t len) { uint8_t pkt_type; @@ -4052,7 +4234,12 @@ void btdev_receive_h4(struct btdev *btdev, const void *data, uint16_t len) case BT_H4_ACL_PKT: if (btdev->conn) send_acl(btdev->conn, data, len); - num_completed_packets(btdev); + num_completed_packets(btdev, ACL_HANDLE); + break; + case BT_H4_ISO_PKT: + num_completed_packets(btdev, ISO_HANDLE); + if (btdev->conn) + send_iso(btdev->conn, data, len); break; default: printf("Unsupported packet 0x%2.2x\n", pkt_type); diff --git a/emulator/btdev.h b/emulator/btdev.h index 362d1e7a2..b535930de 100644 --- a/emulator/btdev.h +++ b/emulator/btdev.h @@ -64,6 +64,7 @@ enum btdev_type { BTDEV_TYPE_AMP, BTDEV_TYPE_BREDR20, BTDEV_TYPE_BREDRLE50, + BTDEV_TYPE_BREDRLE60, }; enum btdev_hook_type { diff --git a/emulator/hciemu.c b/emulator/hciemu.c index 1045043f1..23891a2ee 100644 --- a/emulator/hciemu.c +++ b/emulator/hciemu.c @@ -335,6 +335,9 @@ struct hciemu *hciemu_new(enum hciemu_type type) case HCIEMU_TYPE_BREDRLE50: hciemu->btdev_type = BTDEV_TYPE_BREDRLE50; break; + case HCIEMU_TYPE_BREDRLE60: + hciemu->btdev_type = BTDEV_TYPE_BREDRLE60; + break; default: return NULL; } diff --git a/emulator/hciemu.h b/emulator/hciemu.h index e37c069e1..6f651cb98 100644 --- a/emulator/hciemu.h +++ b/emulator/hciemu.h @@ -32,6 +32,7 @@ enum hciemu_type { HCIEMU_TYPE_LE, HCIEMU_TYPE_LEGACY, HCIEMU_TYPE_BREDRLE50, + HCIEMU_TYPE_BREDRLE60, }; enum hciemu_hook_type { diff --git a/emulator/vhci.c b/emulator/vhci.c index 8dec20a08..7a69b484e 100644 --- a/emulator/vhci.c +++ b/emulator/vhci.c @@ -89,6 +89,7 @@ static void vhci_read_callback(int fd, uint32_t events, void *user_data) case BT_H4_CMD_PKT: case BT_H4_ACL_PKT: case BT_H4_SCO_PKT: + case BT_H4_ISO_PKT: btdev_receive_h4(vhci->btdev, buf, len); break; } @@ -104,7 +105,7 @@ struct vhci *vhci_open(enum vhci_type type) switch (type) { case VHCI_TYPE_BREDRLE: - btdev_type = BTDEV_TYPE_BREDRLE; + btdev_type = BTDEV_TYPE_BREDRLE60; ctrl_type = HCI_PRIMARY; break; case VHCI_TYPE_BREDR: From patchwork Wed Jan 8 00:33:26 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luiz Augusto von Dentz X-Patchwork-Id: 197519 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-3.8 required=3.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS,UNWANTED_LANGUAGE_BODY,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7C014C33C9B for ; Wed, 8 Jan 2020 00:33:51 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 50C35206F0 for ; Wed, 8 Jan 2020 00:33:51 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="bxVsNqi3" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726931AbgAHAdv (ORCPT ); Tue, 7 Jan 2020 19:33:51 -0500 Received: from mail-pj1-f68.google.com ([209.85.216.68]:38605 "EHLO mail-pj1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726836AbgAHAdu (ORCPT ); Tue, 7 Jan 2020 19:33:50 -0500 Received: by mail-pj1-f68.google.com with SMTP id l35so299505pje.3 for ; Tue, 07 Jan 2020 16:33:50 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:subject:date:message-id:in-reply-to:references:mime-version :content-transfer-encoding; bh=tj1sKdxQJv+tVbKXBUsODP4Bl9IqFnM4sCvQBEtKHs0=; b=bxVsNqi3yvcUGKh9BG4DI/vR6ZfQsJP6xYxwsk92ZBjJei4D847Ldt2S263nznWBQU qH/i1FzW5xcGs92duuQUgag7WwC359VS/Te80QFsf2yF+Qs+IVNu/aNiWIWrr0o8Tvph LN1ui0e+u0N9+nFW+J/hBNo8ZEWtclZZeF+V1whsP4JW4HwPJs8oxgqv1DBPWrmcQcno hlDDrIUFI7Bq/zK9YDyRsEB3ho/LPvn9wvp58Cpf+wpr3dpQ3FGGJJV1OCwLQK2Xz5GJ rZqZEfb61h7ml8SOtMfgJbNzA0L1U30FSgGtXFwjTfcIMpmuLMY3jACD6nCaTYRpMEfL AyxQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=tj1sKdxQJv+tVbKXBUsODP4Bl9IqFnM4sCvQBEtKHs0=; b=tQMIM8Np231k0EDnPwDdTe61Hg5ySxsq8jAH1UT1cTbaQq+3RFyhxqmSHIkxfIVs+Y S5WD6Q4g3JcfXRMTMws15EXcg1H9q/d+bbjidjt4bKfWWuiLuSQ0thDP6lUo6vjBMrfj RJOB4TNNDCGGE/Q6BVC0suR7CL+RNZVWNdUfMd7L8w0lrpkIAZ13EHn2NdVT4IQEffPd mVPpEcMjwOCG9SMgMu/0txxUjBgMglA86yy3aUeW3AmPJuaDDZOuXCqltYvsVOMY19Tl dRFGSPbCuj+RQ4CstRlCZvUlJ954z9CCAkDU+Ico5ydhRZPcKyfbLeJFxoID1/boYHmN +z5Q== X-Gm-Message-State: APjAAAWcsP4QxcOJZJo6cYUlBew0UhJecCOsQ7oVVcHr6z0WpaPE3c4v CJACtfW3+g7GU5KFeMJPKzEWKqhmfFg= X-Google-Smtp-Source: APXvYqzgq4weoNpkx4adsQBkpv3YnnPbSzvNJTkZMc8wje4pMISslF47J9AFtxZwVW6tb/YrC4n4lw== X-Received: by 2002:a17:902:6501:: with SMTP id b1mr2562627plk.121.1578443629543; Tue, 07 Jan 2020 16:33:49 -0800 (PST) Received: from localhost.localdomain ([192.102.209.43]) by smtp.gmail.com with ESMTPSA id u10sm925805pgg.41.2020.01.07.16.33.48 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 07 Jan 2020 16:33:49 -0800 (PST) From: Luiz Augusto von Dentz To: linux-bluetooth@vger.kernel.org Subject: [PATCH BlueZ 06/22] monitor: Add support for ISO packets Date: Tue, 7 Jan 2020 16:33:26 -0800 Message-Id: <20200108003342.15458-7-luiz.dentz@gmail.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20200108003342.15458-1-luiz.dentz@gmail.com> References: <20200108003342.15458-1-luiz.dentz@gmail.com> MIME-Version: 1.0 Sender: linux-bluetooth-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org From: Luiz Augusto von Dentz This enables decoding of ISO packets. --- monitor/bt.h | 12 +++++++-- monitor/packet.c | 63 +++++++++++++++++++++++++++++++++++++++++++- monitor/packet.h | 2 ++ src/shared/btsnoop.h | 2 ++ 4 files changed, 76 insertions(+), 3 deletions(-) diff --git a/monitor/bt.h b/monitor/bt.h index 0a88aff97..b08f145ab 100644 --- a/monitor/bt.h +++ b/monitor/bt.h @@ -514,7 +514,7 @@ struct bt_hci_sco_hdr { struct bt_hci_iso_hdr { uint16_t handle; - uint8_t dlen; + uint16_t dlen; } __attribute__ ((packed)); struct bt_hci_iso_data_start { @@ -3434,9 +3434,17 @@ struct bt_hci_evt_le_cis_established { uint16_t conn_handle; uint8_t cig_sync_delay[3]; uint8_t cis_sync_delay[3]; - uint8_t latency[3]; + uint8_t m_latency[3]; + uint8_t s_latency[3]; uint8_t m_phy; uint8_t s_phy; + uint8_t nse; + uint8_t m_bn; + uint8_t s_bn; + uint8_t m_ft; + uint8_t s_ft; + uint16_t m_mtu; + uint16_t s_mtu; } __attribute__ ((packed)); #define BT_HCI_EVT_LE_CIS_REQ BT_HCI_SUBEVT_5_2 + 1 diff --git a/monitor/packet.c b/monitor/packet.c index 8987ed703..0ef8a5b86 100644 --- a/monitor/packet.c +++ b/monitor/packet.c @@ -3934,6 +3934,12 @@ void packet_monitor(struct timeval *tv, struct ucred *cred, case BTSNOOP_OPCODE_SCO_RX_PKT: packet_hci_scodata(tv, cred, index, true, data, size); break; + case BTSNOOP_OPCODE_ISO_TX_PKT: + packet_hci_isodata(tv, cred, index, false, data, size); + break; + case BTSNOOP_OPCODE_ISO_RX_PKT: + packet_hci_isodata(tv, cred, index, true, data, size); + break; case BTSNOOP_OPCODE_OPEN_INDEX: if (index < MAX_INDEX) addr2str(index_list[index].bdaddr, str); @@ -10275,9 +10281,17 @@ static void le_cis_established_evt(const void *data, uint8_t size) print_field("Connection Handle: %d", le16_to_cpu(evt->status)); print_usec_interval("CIG Synchronization Delay", evt->cig_sync_delay); print_usec_interval("CIS Synchronization Delay", evt->cis_sync_delay); - print_usec_interval("Latency", evt->latency); + print_usec_interval("Master to Slave Latency", evt->m_latency); + print_usec_interval("Slave to Master Latency", evt->s_latency); print_le_phy("Master to Slave PHY", evt->m_phy); print_le_phy("Slave to Master PHY", evt->m_phy); + print_field("Number of Subevents: %u", evt->nse); + print_field("Master to Slave Burst Number: %u", evt->m_bn); + print_field("Slave to Master Burst Number: %u", evt->s_bn); + print_field("Master to Slave Flush Timeout: %u", evt->m_ft); + print_field("Slave to Master Flush Timeout: %u", evt->s_ft); + print_field("Master to Slave MTU: %u", evt->m_ft); + print_field("Slave to Master MTU: %u", evt->s_ft); } static void le_req_cis_evt(const void *data, uint8_t size) @@ -11134,6 +11148,53 @@ void packet_hci_scodata(struct timeval *tv, struct ucred *cred, uint16_t index, packet_hexdump(data, size); } +void packet_hci_isodata(struct timeval *tv, struct ucred *cred, uint16_t index, + bool in, const void *data, uint16_t size) +{ + const struct bt_hci_iso_hdr *hdr = data; + uint16_t handle = le16_to_cpu(hdr->handle); + uint8_t flags = acl_flags(handle); + char handle_str[16], extra_str[32]; + + if (index > MAX_INDEX) { + print_field("Invalid index (%d).", index); + return; + } + + index_list[index].frame++; + + if (size < sizeof(*hdr)) { + if (in) + print_packet(tv, cred, '*', index, NULL, COLOR_ERROR, + "Malformed ISO Data RX packet", NULL, NULL); + else + print_packet(tv, cred, '*', index, NULL, COLOR_ERROR, + "Malformed ISO Data TX packet", NULL, NULL); + packet_hexdump(data, size); + return; + } + + data += sizeof(*hdr); + size -= sizeof(*hdr); + + sprintf(handle_str, "Handle %d", acl_handle(handle)); + sprintf(extra_str, "flags 0x%2.2x dlen %d", flags, hdr->dlen); + + print_packet(tv, cred, in ? '>' : '<', index, NULL, COLOR_HCI_SCODATA, + in ? "ISO Data RX" : "ISO Data TX", + handle_str, extra_str); + + if (size != hdr->dlen) { + print_text(COLOR_ERROR, "invalid packet size (%d != %d)", + size, hdr->dlen); + packet_hexdump(data, size); + return; + } + + if (filter_mask & PACKET_FILTER_SHOW_SCO_DATA) + packet_hexdump(data, size); +} + void packet_ctrl_open(struct timeval *tv, struct ucred *cred, uint16_t index, const void *data, uint16_t size) { diff --git a/monitor/packet.h b/monitor/packet.h index 199e15e58..19ea04c68 100644 --- a/monitor/packet.h +++ b/monitor/packet.h @@ -94,6 +94,8 @@ void packet_hci_acldata(struct timeval *tv, struct ucred *cred, uint16_t index, bool in, const void *data, uint16_t size); void packet_hci_scodata(struct timeval *tv, struct ucred *cred, uint16_t index, bool in, const void *data, uint16_t size); +void packet_hci_isodata(struct timeval *tv, struct ucred *cred, uint16_t index, + bool in, const void *data, uint16_t size); void packet_ctrl_open(struct timeval *tv, struct ucred *cred, uint16_t index, const void *data, uint16_t size); diff --git a/src/shared/btsnoop.h b/src/shared/btsnoop.h index 3043d33e2..5fb084aa2 100644 --- a/src/shared/btsnoop.h +++ b/src/shared/btsnoop.h @@ -53,6 +53,8 @@ #define BTSNOOP_OPCODE_CTRL_CLOSE 15 #define BTSNOOP_OPCODE_CTRL_COMMAND 16 #define BTSNOOP_OPCODE_CTRL_EVENT 17 +#define BTSNOOP_OPCODE_ISO_TX_PKT 18 +#define BTSNOOP_OPCODE_ISO_RX_PKT 19 #define BTSNOOP_MAX_PACKET_SIZE (1486 + 4) From patchwork Wed Jan 8 00:33:29 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luiz Augusto von Dentz X-Patchwork-Id: 197517 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-3.8 required=3.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS,UNWANTED_LANGUAGE_BODY,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id A5318C33C9B for ; Wed, 8 Jan 2020 00:33:54 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 79417206F0 for ; Wed, 8 Jan 2020 00:33:54 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="KN8GygVc" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726987AbgAHAdy (ORCPT ); Tue, 7 Jan 2020 19:33:54 -0500 Received: from mail-pl1-f182.google.com ([209.85.214.182]:46281 "EHLO mail-pl1-f182.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726964AbgAHAdx (ORCPT ); Tue, 7 Jan 2020 19:33:53 -0500 Received: by mail-pl1-f182.google.com with SMTP id y8so364796pll.13 for ; Tue, 07 Jan 2020 16:33:53 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:subject:date:message-id:in-reply-to:references:mime-version :content-transfer-encoding; bh=Qylhapiw6j9mT7HBQGG+i/xdsf/ElNGXrCeMwI/nKbs=; b=KN8GygVcQLhuqcyPHxXUkNT/GWzIgYX5z5J9N0QyKaJ4MebB2WsWFhwl5eWScF4ey5 l52IK3T8QciLO6k8btyGl0bJrI2DdzHkAZQ2SYmQEOjdXnN9KqHV1LsSNa3lFkYFKkby +umC05CSLwvoa365mYLRIF9VS5JmJK8yot8QKSNikSknjPqjJTWfAxWgfraGaPI4mNep 0FQGMKG3wOakXP30CIxMrxhY0Uki6e04W3EOlCA6Jsy4ZMah5IKnF0oTcgouTVf+o+iV 6s2cbPE+ooaSfV8IPNAhre4UjnAbZmHtbXxTzdrZCGqIJL3GA+HUUZoZlgIYWuSmncXC v/IQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=Qylhapiw6j9mT7HBQGG+i/xdsf/ElNGXrCeMwI/nKbs=; b=U8p3ms5OVrh/ulOC3AFUtVBzCfSyJJClsEogmludY0KvMQWNUivZRpNTNSLewfDXVT GnX7EJezmfm5f2llkwW/FTHKztR7dh5CY5QRadQMyO/KxwjEKxN4hf94lQfkHVV2DAie JZO7luIZumFAHNZPfgRYvV5u4AkgkvPMsYbKS798T36fMGssqRxALcloV53OUWperfDq Wwl5c7yg6ntKeDZDgofucL9G6Qx+i7lRfqeJRCnwMourrIZK0Tn6x5Uvn8n3XEV8l5p7 FHMqtn51VuvYgJaZvrd2h/lVuB/ASr6C+Q088CkCou2OkQ+8Q7ZDbP74v/MiQEcT95s5 CbYA== X-Gm-Message-State: APjAAAU771EWR7jhVXKZI7TBYo7DXrqeC31fEn0nJxl6MOF5Ov66t9G5 fzCLTGyad0wuznjU+/tfv6gIDUtdnkY= X-Google-Smtp-Source: APXvYqwePlTQBLtcK9EhkRfO2UfwfAMr2QRI0vvnvicj3PAQWTByzgeHt28pdYyFHwae4/AAEriVpA== X-Received: by 2002:a17:90a:cb0f:: with SMTP id z15mr1370342pjt.131.1578443632573; Tue, 07 Jan 2020 16:33:52 -0800 (PST) Received: from localhost.localdomain ([192.102.209.43]) by smtp.gmail.com with ESMTPSA id u10sm925805pgg.41.2020.01.07.16.33.51 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 07 Jan 2020 16:33:52 -0800 (PST) From: Luiz Augusto von Dentz To: linux-bluetooth@vger.kernel.org Subject: [PATCH BlueZ 09/22] emulator/btdev: Add parameter to CIS Estabilished Date: Tue, 7 Jan 2020 16:33:29 -0800 Message-Id: <20200108003342.15458-10-luiz.dentz@gmail.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20200108003342.15458-1-luiz.dentz@gmail.com> References: <20200108003342.15458-1-luiz.dentz@gmail.com> MIME-Version: 1.0 Sender: linux-bluetooth-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org From: Luiz Augusto von Dentz Use Set CIG params to fill CIS Estabilished. --- emulator/btdev.c | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/emulator/btdev.c b/emulator/btdev.c index 02f408dd5..0de273e53 100644 --- a/emulator/btdev.c +++ b/emulator/btdev.c @@ -144,6 +144,10 @@ struct btdev { uint8_t le_filter_dup; uint8_t le_adv_enable; uint8_t le_ltk[16]; + struct { + struct bt_hci_cmd_le_set_cig_params params; + struct bt_hci_cis_params cis; + } __attribute__ ((packed)) le_cig; uint8_t le_local_sk256[32]; @@ -1412,8 +1416,25 @@ static void le_cis_estabilished(struct btdev *dev, uint8_t status) if (!evt.status) { evt.conn_handle = cpu_to_le16(ISO_HANDLE); - evt.m_phy = 0x01; - evt.m_phy = 0x01; + /* TODO: Figure out if these values makes sense */ + memcpy(evt.cig_sync_delay, dev->le_cig.params.m_interval, + sizeof(dev->le_cig.params.m_interval)); + memcpy(evt.cis_sync_delay, dev->le_cig.params.s_interval, + sizeof(dev->le_cig.params.s_interval)); + memcpy(evt.m_latency, &dev->le_cig.params.m_latency, + sizeof(dev->le_cig.params.m_latency)); + memcpy(evt.s_latency, &dev->le_cig.params.s_latency, + sizeof(dev->le_cig.params.s_latency)); + evt.m_phy = dev->le_cig.cis.m_phy; + evt.s_phy = dev->le_cig.cis.s_phy; + evt.nse = 0x01; + evt.m_bn = 0x01; + evt.s_bn = 0x01; + evt.m_ft = 0x01; + evt.s_ft = 0x01; + evt.m_mtu = dev->iso_mtu; + evt.s_mtu = dev->iso_mtu; + evt.interval = dev->le_cig.params.m_latency; } le_meta_event(dev, BT_HCI_EVT_LE_CIS_ESTABLISHED, &evt, sizeof(evt)); @@ -3804,6 +3825,7 @@ static void default_cmd(struct btdev *btdev, uint16_t opcode, case BT_HCI_CMD_LE_SET_CIG_PARAMS: if (btdev->type != BTDEV_TYPE_BREDRLE60) goto unsupported; + memcpy(&btdev->le_cig, data, len); lscp.params.status = BT_HCI_ERR_SUCCESS; lscp.params.cig_id = 0x00; lscp.params.num_handles = 1; From patchwork Wed Jan 8 00:33:31 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luiz Augusto von Dentz X-Patchwork-Id: 197516 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.6 required=3.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0F11BC33C9E for ; Wed, 8 Jan 2020 00:33:56 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id D7AEE206F0 for ; Wed, 8 Jan 2020 00:33:55 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="tdFWZBOC" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727006AbgAHAdz (ORCPT ); Tue, 7 Jan 2020 19:33:55 -0500 Received: from mail-pl1-f170.google.com ([209.85.214.170]:36870 "EHLO mail-pl1-f170.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726281AbgAHAdy (ORCPT ); Tue, 7 Jan 2020 19:33:54 -0500 Received: by mail-pl1-f170.google.com with SMTP id c23so381593plz.4 for ; Tue, 07 Jan 2020 16:33:54 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:subject:date:message-id:in-reply-to:references:mime-version :content-transfer-encoding; bh=zqKf6NypyrHZYTy26aLa9pjq4Ob1TC2wzN2VrzLQVVQ=; b=tdFWZBOCskklLE5DTdvvvsUwpERIhSxe0D1wNLdqcGhJnOv5muSLwU2dVBR+1keUce oJ8pQTvN34EjVGiQ14KxRx817cHyUclnMpWFkIQIp5V4Yca/1GY+vga7OFPCM2HTFUG5 QguOpk0xULU+RPybxcTyydF4EmE8r4NCKNUOac72ob2PHZSMt9TMfLOOokSHlbLHetTv Cxng60Za/+/Api6x+RWjgdbzlEPFSReweqaDf1dCesRsr5LTsS9oG2bA9y8okyRWil1I DqT9iU+o+JMhNABqAErW4SKnHrfDpFApbKCxhwjhYluPMZ6ZrTKXsDuu1Tzu+3j5cqkp JbIw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=zqKf6NypyrHZYTy26aLa9pjq4Ob1TC2wzN2VrzLQVVQ=; b=ajvwMZl1vOiWt2kcYUjjArdtMb38SpWkrtBU/iRLBSe2IACuWKBb9uu6O1189szG1k OfiZJfn21jz+plL1vga+1o45fjoOofh/S+KRUROjBRsZWf3vuS9mXqc9xj8mVVTSpZQz r+FO9HRRp+QRZmJrZd3h/DukBcG27UUjkOEYf/zdOuTE74v9XRWQ48DZV6LNpPP1g50Q pDrmwYNmZyyqEAOQFvF4rzc2XzQIyJSv/KsVhyk8wI3F0QR2yqKRoYZiie6twh4qsjxv x/tzoPo1NvY19lhGggVgBKwGNqgpdanCjBEhCjHus3mo2ZHz/c7ikKthKQ4QETfdlede O7iA== X-Gm-Message-State: APjAAAWOH53QNJQobgo0rYxDqVd89LfIzo6D0YTrdMiof/o79idfnD0w YGFJ7Yf4RjRG1CrCGOhmUwveNY3xIaY= X-Google-Smtp-Source: APXvYqz3YvNACbB62WEtqOG9u4gtL79NGMAwQlk1xDBeY8zu+GZkPCNPL10tBd4PnEnPq6fRw0Sd1g== X-Received: by 2002:a17:90a:d985:: with SMTP id d5mr1410275pjv.73.1578443634003; Tue, 07 Jan 2020 16:33:54 -0800 (PST) Received: from localhost.localdomain ([192.102.209.43]) by smtp.gmail.com with ESMTPSA id u10sm925805pgg.41.2020.01.07.16.33.53 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 07 Jan 2020 16:33:53 -0800 (PST) From: Luiz Augusto von Dentz To: linux-bluetooth@vger.kernel.org Subject: [PATCH BlueZ 11/22] btio: Add mode to for Enhanced Credit Mode Date: Tue, 7 Jan 2020 16:33:31 -0800 Message-Id: <20200108003342.15458-12-luiz.dentz@gmail.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20200108003342.15458-1-luiz.dentz@gmail.com> References: <20200108003342.15458-1-luiz.dentz@gmail.com> MIME-Version: 1.0 Sender: linux-bluetooth-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org From: Luiz Augusto von Dentz This adds BT_IO_MODE_ECRED which directly maps to L2CAP_MODE_ECRED. --- btio/btio.c | 2 +- btio/btio.h | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/btio/btio.c b/btio/btio.c index af2276db9..bd076b4c8 100644 --- a/btio/btio.c +++ b/btio/btio.c @@ -638,7 +638,7 @@ static gboolean l2cap_set(int sock, uint8_t src_type, int sec_level, if (imtu || omtu || mode) { gboolean ret; - if (src_type == BDADDR_BREDR) + if (src_type == BDADDR_BREDR || mode) ret = set_l2opts(sock, imtu, omtu, mode, err); else ret = set_le_imtu(sock, imtu, err); diff --git a/btio/btio.h b/btio/btio.h index 2dce9f0c1..91398f72d 100644 --- a/btio/btio.h +++ b/btio/btio.h @@ -70,7 +70,8 @@ typedef enum { BT_IO_MODE_RETRANS, BT_IO_MODE_FLOWCTL, BT_IO_MODE_ERTM, - BT_IO_MODE_STREAMING + BT_IO_MODE_STREAMING, + BT_IO_MODE_ECRED = 0x81 } BtIOMode; typedef void (*BtIOConfirm)(GIOChannel *io, gpointer user_data); From patchwork Wed Jan 8 00:33:33 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luiz Augusto von Dentz X-Patchwork-Id: 197515 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.6 required=3.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id A4FB4C33C9E for ; Wed, 8 Jan 2020 00:33:58 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 7A8F5206F0 for ; Wed, 8 Jan 2020 00:33:58 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="DurjhheM" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727069AbgAHAd6 (ORCPT ); Tue, 7 Jan 2020 19:33:58 -0500 Received: from mail-pf1-f193.google.com ([209.85.210.193]:38603 "EHLO mail-pf1-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726281AbgAHAd5 (ORCPT ); Tue, 7 Jan 2020 19:33:57 -0500 Received: by mail-pf1-f193.google.com with SMTP id x185so697727pfc.5 for ; Tue, 07 Jan 2020 16:33:57 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:subject:date:message-id:in-reply-to:references:mime-version :content-transfer-encoding; bh=LZNpc7rBm7qvJQzDH/uuUhS9F/c8VqZuyIaA2JyqPik=; b=DurjhheMHP6UppIeEYDVUWmPK1gQ1aNRJSd564SETaXH3OSv4dkjfYttywdETKksPC Z3x2mKSYVTYH/NV98DZcO69dlraysulo0yb+1aY0lZC0B3e5DBmpnrPjCB3ND7iTa+DS JDAPSmHFthFLDZnP3ZJuCEal9ojWM9Wi7GfdHgp1Hb/NSDaPkqXhatti3Sc/ZO3aF337 2Tb1UcMQvjPWuI7O7Df7Kbv3fcIUyVkUSh2so6b3ocG1BxngRVcTRpQWGqcvEQzGyMf7 0FWP37t8Syi3dc/7AXw4qzGsLMWTGZcH6YUJuqVZqgExWEyPX1X+ey5hE1CLoSK6aHvj KFww== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=LZNpc7rBm7qvJQzDH/uuUhS9F/c8VqZuyIaA2JyqPik=; b=lHm2WKO8h4u4uXkQ0T/VAxM6O2L1LQ97wUwq+Pevf1Uj7RkqW9TpfGRrjwwRveGtcA pXWNKq7immaQkmlhE8XOo9CeXKyhXqdwV9Eh8TM/lGlOBFXJzh4GkjtInut1B8n0rse8 vaQb/GG9JHqcwVzSdTR5+ajoE0Ub6DFYAnmWDUbIwyxZ6AbfnQHGF/NjaJNDJmoWthuq poB+seWVlqJEOG+WAZSdRZOP2ybeZRylbRrMLLqylYvn2QpYgaxJKggacqq+oUZ/8tyC 3HrSYbZqK4t61gquX2x/Zgul8zw4XKrRUPG3I4decbRknlHZkGNvRxt5xiVVUhE+AxnF UoFw== X-Gm-Message-State: APjAAAUK/l8OK6gpLrHjBiz7jLJk9rkiBk9eomVbsLNxMgIVDwty4sJM YY1lJsam28NNrSC2p++QwHUu+55VF0Y= X-Google-Smtp-Source: APXvYqz6Ic+KIySuMk0Xf2yLQLYbNdDmJJ/YwBI/Ze96ut90Q3ttNWvZYmbCYc/eob926wn4LL9saw== X-Received: by 2002:a63:a019:: with SMTP id r25mr2263199pge.400.1578443636924; Tue, 07 Jan 2020 16:33:56 -0800 (PST) Received: from localhost.localdomain ([192.102.209.43]) by smtp.gmail.com with ESMTPSA id u10sm925805pgg.41.2020.01.07.16.33.55 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 07 Jan 2020 16:33:56 -0800 (PST) From: Luiz Augusto von Dentz To: linux-bluetooth@vger.kernel.org Subject: [PATCH BlueZ 13/22] l2test: Add support for L2CAP_ECRED_MODE Date: Tue, 7 Jan 2020 16:33:33 -0800 Message-Id: <20200108003342.15458-14-luiz.dentz@gmail.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20200108003342.15458-1-luiz.dentz@gmail.com> References: <20200108003342.15458-1-luiz.dentz@gmail.com> MIME-Version: 1.0 Sender: linux-bluetooth-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org From: Luiz Augusto von Dentz This enables using l2test to connect or listen with L2CAP_ECRED_MODE. --- tools/l2test.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tools/l2test.c b/tools/l2test.c index e787c2ce2..317515e68 100644 --- a/tools/l2test.c +++ b/tools/l2test.c @@ -149,6 +149,7 @@ static struct lookup_table l2cap_modes[] = { */ { "ertm", L2CAP_MODE_ERTM }, { "streaming", L2CAP_MODE_STREAMING }, + { "ecred", L2CAP_MODE_ECRED }, { 0 } }; @@ -282,7 +283,7 @@ static int getopts(int sk, struct l2cap_options *opts, bool connected) memset(opts, 0, sizeof(*opts)); - if (bdaddr_type == BDADDR_BREDR) { + if (bdaddr_type == BDADDR_BREDR || rfcmode) { optlen = sizeof(*opts); return getsockopt(sk, SOL_L2CAP, L2CAP_OPTIONS, opts, &optlen); } @@ -298,7 +299,7 @@ static int getopts(int sk, struct l2cap_options *opts, bool connected) static int setopts(int sk, struct l2cap_options *opts) { - if (bdaddr_type == BDADDR_BREDR) + if (bdaddr_type == BDADDR_BREDR || rfcmode) return setsockopt(sk, SOL_L2CAP, L2CAP_OPTIONS, opts, sizeof(*opts)); From patchwork Wed Jan 8 00:33:34 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luiz Augusto von Dentz X-Patchwork-Id: 197514 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.6 required=3.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4D1CDC33C99 for ; Wed, 8 Jan 2020 00:34:01 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 02C292075A for ; Wed, 8 Jan 2020 00:34:01 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="eCP39mhK" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727091AbgAHAeA (ORCPT ); Tue, 7 Jan 2020 19:34:00 -0500 Received: from mail-pj1-f68.google.com ([209.85.216.68]:54568 "EHLO mail-pj1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727078AbgAHAeA (ORCPT ); Tue, 7 Jan 2020 19:34:00 -0500 Received: by mail-pj1-f68.google.com with SMTP id kx11so292383pjb.4 for ; Tue, 07 Jan 2020 16:33:59 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:subject:date:message-id:in-reply-to:references:mime-version :content-transfer-encoding; bh=65l5og7QfwBV48bljxDrofRCiwTHmzu5OznLDGQLxKw=; b=eCP39mhKwMhv31th8VzAe3hgCNpiAk37QoSvWQB6rbpkRp6DknIZNZ02tkzh/i9O+W XrDZGoyDqTekWVX5GyBsJTK7cm0v56VeQt3/lNaiJCknA6ag5058jU0gknM5sPBcAS3a oAGir9mALdiYAQ8FPn8wRg06FX0LLdn+F42/7rnDStjsfn0isPY/I9A1MHbEgSBpemYM gGXnQLCnzNyj3oI5D7S/Kw5PDoLQntXoQSWZV4P6WwmpPyEFrng3jA9eHumPwp94ccJw RZlJ+UJIrGHlhrh9VB8D6LjkrISJ4JtFOxqwm3rBn3cFVXTnGUTp/+mkdlcaUL0eOPoT 4xkg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=65l5og7QfwBV48bljxDrofRCiwTHmzu5OznLDGQLxKw=; b=fIE4TM2OmLqpYuWABSqi4sU8/A1iUAwyno48//KeL4sOC+HMEE7mJEDD9bznwEXEfN 6I5XpHhllwADt4yRmeFirnLf9127T4nVajvnbzlQ9p4PSDMeUQpXzyau4ltKvVIeW2Od Qqf//GeaAQ6f66CxiLdF6eZ9Ek36BWdc1ZQzpeDbGTcjabED48CB0m4eDTon8ymjPFq7 6MobjyaFOTt3L5pxiCttF05Hotonq8GAoX089tqjtBqrx8qnb557/8DFwl5vxeYzbRQQ OWnHFtS3xQJ3kuOvvocR1m+/5MWy8qktnpdMV7goasN2rlirG8pIHvrvKZk04eOWuJG8 GDpQ== X-Gm-Message-State: APjAAAUdKOFc9kt2ULwtKLlowIcTs+sfDIYS8g2A/Yp+yFwIB8+GnoYY 8r6fZgiKL0FQOK1wDTOF6TBGt5xoXzc= X-Google-Smtp-Source: APXvYqxyoRMnBqccYVBi3QZubWyPvhIDXDV4KWpXoLb3+9ZfVwGTEI3ftG2Ld1HpXCCzU0lVOB8DHw== X-Received: by 2002:a17:902:241:: with SMTP id 59mr2648018plc.36.1578443638014; Tue, 07 Jan 2020 16:33:58 -0800 (PST) Received: from localhost.localdomain ([192.102.209.43]) by smtp.gmail.com with ESMTPSA id u10sm925805pgg.41.2020.01.07.16.33.57 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 07 Jan 2020 16:33:57 -0800 (PST) From: Luiz Augusto von Dentz To: linux-bluetooth@vger.kernel.org Subject: [PATCH BlueZ 14/22] share/att: Add EATT support Date: Tue, 7 Jan 2020 16:33:34 -0800 Message-Id: <20200108003342.15458-15-luiz.dentz@gmail.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20200108003342.15458-1-luiz.dentz@gmail.com> References: <20200108003342.15458-1-luiz.dentz@gmail.com> MIME-Version: 1.0 Sender: linux-bluetooth-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org From: Luiz Augusto von Dentz This adds EATT support to bt_att, EATT bearers are handled as additional channels which auto allocated for queued requests. --- src/gatt-database.c | 4 +- src/shared/att-types.h | 16 +- src/shared/att.c | 566 +++++++++++++++++++++++++-------------- src/shared/att.h | 4 + src/shared/gatt-client.c | 2 +- 5 files changed, 389 insertions(+), 203 deletions(-) diff --git a/src/gatt-database.c b/src/gatt-database.c index 2bae8711a..419e4f9e1 100644 --- a/src/gatt-database.c +++ b/src/gatt-database.c @@ -2102,10 +2102,10 @@ static void append_options(DBusMessageIter *iter, void *user_data) uint16_t mtu; switch (op->link_type) { - case BT_ATT_LINK_BREDR: + case BT_ATT_BREDR: link = "BR/EDR"; break; - case BT_ATT_LINK_LE: + case BT_ATT_LE: link = "LE"; break; default: diff --git a/src/shared/att-types.h b/src/shared/att-types.h index 8a2658de3..7b88e7d92 100644 --- a/src/shared/att-types.h +++ b/src/shared/att-types.h @@ -27,6 +27,10 @@ #define __packed __attribute__((packed)) #endif +#define BT_ATT_CID 4 +#define BT_ATT_PSM 31 +#define BT_ATT_EATT_PSM 0x27 + #define BT_ATT_SECURITY_AUTO 0 #define BT_ATT_SECURITY_LOW 1 #define BT_ATT_SECURITY_MEDIUM 2 @@ -37,9 +41,10 @@ #define BT_ATT_MAX_LE_MTU 517 #define BT_ATT_MAX_VALUE_LEN 512 -#define BT_ATT_LINK_BREDR 0x00 -#define BT_ATT_LINK_LE 0x01 -#define BT_ATT_LINK_LOCAL 0xff +#define BT_ATT_BREDR 0x00 +#define BT_ATT_LE 0x01 +#define BT_ATT_EATT 0x02 +#define BT_ATT_LOCAL 0xff /* ATT protocol opcodes */ #define BT_ATT_OP_ERROR_RSP 0x01 @@ -159,3 +164,8 @@ struct bt_att_pdu_error_rsp { /* GATT Characteristic Client Features Bitfield values */ #define BT_GATT_CHRC_CLI_FEAT_ROBUST_CACHING 0x01 +#define BT_GATT_CHRC_CLI_FEAT_EATT 0x02 +#define BT_GATT_CHRC_CLI_FEAT_NFY_MULTI 0x04 + +/* GATT Characteristic Server Features Bitfield values */ +#define BT_GATT_CHRC_SERVER_FEAT_EATT 0x01 diff --git a/src/shared/att.c b/src/shared/att.c index 0ea6d55bd..1313703f9 100644 --- a/src/shared/att.c +++ b/src/shared/att.c @@ -49,32 +49,40 @@ struct att_send_op; -struct bt_att { - int ref_count; +struct bt_att_chan { + struct bt_att *att; int fd; struct io *io; - bool io_on_l2cap; - int io_sec_level; /* Only used for non-L2CAP */ - uint8_t enc_size; + uint8_t type; + int sec_level; /* Only used for non-L2CAP */ - struct queue *req_queue; /* Queued ATT protocol requests */ struct att_send_op *pending_req; - struct queue *ind_queue; /* Queued ATT protocol indications */ struct att_send_op *pending_ind; - struct queue *write_queue; /* Queue of PDUs ready to send */ bool writer_active; - struct queue *notify_list; /* List of registered callbacks */ - struct queue *disconn_list; /* List of disconnect handlers */ - bool in_req; /* There's a pending incoming request */ uint8_t *buf; uint16_t mtu; +}; + +struct bt_att { + int ref_count; + bool close_on_unref; + struct queue *chans; + uint8_t enc_size; + uint16_t mtu; /* Biggest possible MTU */ + + struct queue *notify_list; /* List of registered callbacks */ + struct queue *disconn_list; /* List of disconnect handlers */ unsigned int next_send_id; /* IDs for "send" ops */ unsigned int next_reg_id; /* IDs for registered callbacks */ + struct queue *req_queue; /* Queued ATT protocol requests */ + struct queue *ind_queue; /* Queued ATT protocol indications */ + struct queue *write_queue; /* Queue of PDUs ready to send */ + bt_att_timeout_func_t timeout_callback; bt_att_destroy_func_t timeout_destroy; void *timeout_data; @@ -362,8 +370,9 @@ static struct att_send_op *create_att_send_op(struct bt_att *att, return op; } -static struct att_send_op *pick_next_send_op(struct bt_att *att) +static struct att_send_op *pick_next_send_op(struct bt_att_chan *chan) { + struct bt_att *att = chan->att; struct att_send_op *op; /* See if any operations are already in the write queue */ @@ -374,7 +383,7 @@ static struct att_send_op *pick_next_send_op(struct bt_att *att) /* If there is no pending request, pick an operation from the * request queue. */ - if (!att->pending_req) { + if (!chan->pending_req) { op = queue_pop_head(att->req_queue); if (op) return op; @@ -383,7 +392,7 @@ static struct att_send_op *pick_next_send_op(struct bt_att *att) /* There is either a request pending or no requests queued. If there is * no pending indication, pick an operation from the indication queue. */ - if (!att->pending_ind) { + if (!chan->pending_ind) { op = queue_pop_head(att->ind_queue); if (op) return op; @@ -393,22 +402,23 @@ static struct att_send_op *pick_next_send_op(struct bt_att *att) } struct timeout_data { - struct bt_att *att; + struct bt_att_chan *chan; unsigned int id; }; static bool timeout_cb(void *user_data) { struct timeout_data *timeout = user_data; - struct bt_att *att = timeout->att; + struct bt_att_chan *chan = timeout->chan; + struct bt_att *att = chan->att; struct att_send_op *op = NULL; - if (att->pending_req && att->pending_req->id == timeout->id) { - op = att->pending_req; - att->pending_req = NULL; - } else if (att->pending_ind && att->pending_ind->id == timeout->id) { - op = att->pending_ind; - att->pending_ind = NULL; + if (chan->pending_req && chan->pending_req->id == timeout->id) { + op = chan->pending_req; + chan->pending_req = NULL; + } else if (chan->pending_ind && chan->pending_ind->id == timeout->id) { + op = chan->pending_ind; + chan->pending_ind = NULL; } if (!op) @@ -428,27 +438,28 @@ static bool timeout_cb(void *user_data) * This should trigger an io disconnect event which will clean up the * io and notify the upper layer. */ - io_shutdown(att->io); + io_shutdown(chan->io); return false; } static void write_watch_destroy(void *user_data) { - struct bt_att *att = user_data; + struct bt_att_chan *chan = user_data; - att->writer_active = false; + chan->writer_active = false; } static bool can_write_data(struct io *io, void *user_data) { - struct bt_att *att = user_data; + struct bt_att_chan *chan = user_data; + struct bt_att *att = chan->att; struct att_send_op *op; struct timeout_data *timeout; ssize_t ret; struct iovec iov; - op = pick_next_send_op(att); + op = pick_next_send_op(chan); if (!op) return false; @@ -478,14 +489,14 @@ static bool can_write_data(struct io *io, void *user_data) */ switch (op->type) { case ATT_OP_TYPE_REQ: - att->pending_req = op; + chan->pending_req = op; break; case ATT_OP_TYPE_IND: - att->pending_ind = op; + chan->pending_ind = op; break; case ATT_OP_TYPE_RSP: /* Set in_req to false to indicate that no request is pending */ - att->in_req = false; + chan->in_req = false; /* fall through */ case ATT_OP_TYPE_CMD: case ATT_OP_TYPE_NOT: @@ -497,7 +508,7 @@ static bool can_write_data(struct io *io, void *user_data) } timeout = new0(struct timeout_data, 1); - timeout->att = att; + timeout->chan = chan; timeout->id = op->id; op->timeout_id = timeout_add(ATT_TIMEOUT_INTERVAL, timeout_cb, timeout, free); @@ -506,25 +517,33 @@ static bool can_write_data(struct io *io, void *user_data) return true; } -static void wakeup_writer(struct bt_att *att) +static void wakeup_chan_writer(void *data, void *user_data) { - if (att->writer_active) + struct bt_att_chan *chan = data; + struct bt_att *att = chan->att; + + if (chan->writer_active) return; /* Set the write handler only if there is anything that can be sent * at all. */ if (queue_isempty(att->write_queue)) { - if ((att->pending_req || queue_isempty(att->req_queue)) && - (att->pending_ind || queue_isempty(att->ind_queue))) + if ((chan->pending_req || queue_isempty(att->req_queue)) && + (chan->pending_ind || queue_isempty(att->ind_queue))) return; } - if (!io_set_write_handler(att->io, can_write_data, att, + if (!io_set_write_handler(chan->io, can_write_data, chan, write_watch_destroy)) return; - att->writer_active = true; + chan->writer_active = true; +} + +static void wakeup_writer(struct bt_att *att) +{ + queue_foreach(att->chans, wakeup_chan_writer, NULL); } static void disconn_handler(void *data, void *user_data) @@ -549,44 +568,66 @@ static void disc_att_send_op(void *data) destroy_att_send_op(op); } +static void bt_att_chan_free(void *data) +{ + struct bt_att_chan *chan = data; + + if (chan->pending_req) + destroy_att_send_op(chan->pending_req); + + if (chan->pending_ind) + destroy_att_send_op(chan->pending_ind); + + io_destroy(chan->io); + + free(chan->buf); + free(chan); +} + static bool disconnect_cb(struct io *io, void *user_data) { - struct bt_att *att = user_data; + struct bt_att_chan *chan = user_data; + struct bt_att *att = chan->att; int err; socklen_t len; len = sizeof(err); - if (getsockopt(att->fd, SOL_SOCKET, SO_ERROR, &err, &len) < 0) { - util_debug(att->debug_callback, att->debug_data, + if (getsockopt(chan->fd, SOL_SOCKET, SO_ERROR, &err, &len) < 0) { + util_debug(chan->att->debug_callback, chan->att->debug_data, "Failed to obtain disconnect error: %s", strerror(errno)); err = 0; } - util_debug(att->debug_callback, att->debug_data, - "Physical link disconnected: %s", - strerror(err)); + util_debug(chan->att->debug_callback, chan->att->debug_data, + "Channel %p disconnected: %s", + chan, strerror(err)); - io_destroy(att->io); - att->io = NULL; - att->fd = -1; + /* Dettach channel */ + queue_remove(att->chans, chan); /* Notify request callbacks */ queue_remove_all(att->req_queue, NULL, NULL, disc_att_send_op); queue_remove_all(att->ind_queue, NULL, NULL, disc_att_send_op); queue_remove_all(att->write_queue, NULL, NULL, disc_att_send_op); - if (att->pending_req) { - disc_att_send_op(att->pending_req); - att->pending_req = NULL; + if (chan->pending_req) { + disc_att_send_op(chan->pending_req); + chan->pending_req = NULL; } - if (att->pending_ind) { - disc_att_send_op(att->pending_ind); - att->pending_ind = NULL; + if (chan->pending_ind) { + disc_att_send_op(chan->pending_ind); + chan->pending_ind = NULL; } + bt_att_chan_free(chan); + + /* Don't run disconnect callback if there are channels left */ + if (!queue_isempty(att->chans)) + return false; + bt_att_ref(att); queue_foreach(att->disconn_list, disconn_handler, INT_TO_PTR(err)); @@ -597,14 +638,49 @@ static bool disconnect_cb(struct io *io, void *user_data) return false; } -static bool change_security(struct bt_att *att, uint8_t ecode) +static int bt_att_chan_get_security(struct bt_att_chan *chan) +{ + struct bt_security sec; + socklen_t len; + + if (chan->type == BT_ATT_LOCAL) + return chan->sec_level; + + memset(&sec, 0, sizeof(sec)); + len = sizeof(sec); + if (getsockopt(chan->fd, SOL_BLUETOOTH, BT_SECURITY, &sec, &len) < 0) + return -EIO; + + return sec.level; +} + +static bool bt_att_chan_set_security(struct bt_att_chan *chan, int level) +{ + struct bt_security sec; + + if (chan->type == BT_ATT_LOCAL) { + chan->sec_level = level; + return true; + } + + memset(&sec, 0, sizeof(sec)); + sec.level = level; + + if (setsockopt(chan->fd, SOL_BLUETOOTH, BT_SECURITY, &sec, + sizeof(sec)) < 0) + return false; + + return true; +} + +static bool change_security(struct bt_att_chan *chan, uint8_t ecode) { int security; - if (att->io_sec_level != BT_ATT_SECURITY_AUTO) + if (chan->sec_level != BT_ATT_SECURITY_AUTO) return false; - security = bt_att_get_security(att, NULL); + security = bt_att_chan_get_security(chan); if (ecode == BT_ATT_ERROR_INSUFFICIENT_ENCRYPTION && security < BT_ATT_SECURITY_MEDIUM) { @@ -622,14 +698,15 @@ static bool change_security(struct bt_att *att, uint8_t ecode) return false; } - return bt_att_set_security(att, security); + return bt_att_chan_set_security(chan, security); } -static bool handle_error_rsp(struct bt_att *att, uint8_t *pdu, +static bool handle_error_rsp(struct bt_att_chan *chan, uint8_t *pdu, ssize_t pdu_len, uint8_t *opcode) { + struct bt_att *att = chan->att; const struct bt_att_pdu_error_rsp *rsp; - struct att_send_op *op = att->pending_req; + struct att_send_op *op = chan->pending_req; if (pdu_len != sizeof(*rsp)) { *opcode = 0; @@ -641,7 +718,7 @@ static bool handle_error_rsp(struct bt_att *att, uint8_t *pdu, *opcode = rsp->opcode; /* Attempt to change security */ - if (!change_security(att, rsp->ecode)) + if (!change_security(chan, rsp->ecode)) return false; /* Remove timeout_id if outstanding */ @@ -653,16 +730,17 @@ static bool handle_error_rsp(struct bt_att *att, uint8_t *pdu, util_debug(att->debug_callback, att->debug_data, "Retrying operation %p", op); - att->pending_req = NULL; + chan->pending_req = NULL; /* Push operation back to request queue */ return queue_push_head(att->req_queue, op); } -static void handle_rsp(struct bt_att *att, uint8_t opcode, uint8_t *pdu, +static void handle_rsp(struct bt_att_chan *chan, uint8_t opcode, uint8_t *pdu, ssize_t pdu_len) { - struct att_send_op *op = att->pending_req; + struct bt_att *att = chan->att; + struct att_send_op *op = chan->pending_req; uint8_t req_opcode; uint8_t rsp_opcode; uint8_t *rsp_pdu = NULL; @@ -675,7 +753,7 @@ static void handle_rsp(struct bt_att *att, uint8_t opcode, uint8_t *pdu, if (!op) { util_debug(att->debug_callback, att->debug_data, "Received unexpected ATT response"); - io_shutdown(att->io); + io_shutdown(chan->io); return; } @@ -685,8 +763,8 @@ static void handle_rsp(struct bt_att *att, uint8_t opcode, uint8_t *pdu, */ if (opcode == BT_ATT_OP_ERROR_RSP) { /* Return if error response cause a retry */ - if (handle_error_rsp(att, pdu, pdu_len, &req_opcode)) { - wakeup_writer(att); + if (handle_error_rsp(chan, pdu, pdu_len, &req_opcode)) { + wakeup_chan_writer(chan, NULL); return; } } else if (!(req_opcode = get_req_opcode(opcode))) @@ -715,14 +793,15 @@ done: op->callback(rsp_opcode, rsp_pdu, rsp_pdu_len, op->user_data); destroy_att_send_op(op); - att->pending_req = NULL; + chan->pending_req = NULL; - wakeup_writer(att); + wakeup_chan_writer(chan, NULL); } -static void handle_conf(struct bt_att *att, uint8_t *pdu, ssize_t pdu_len) +static void handle_conf(struct bt_att_chan *chan, uint8_t *pdu, ssize_t pdu_len) { - struct att_send_op *op = att->pending_ind; + struct bt_att *att = chan->att; + struct att_send_op *op = chan->pending_ind; /* * Disconnect the bearer if the confirmation is unexpected or the PDU is @@ -731,7 +810,7 @@ static void handle_conf(struct bt_att *att, uint8_t *pdu, ssize_t pdu_len) if (!op || pdu_len) { util_debug(att->debug_callback, att->debug_data, "Received unexpected/invalid ATT confirmation"); - io_shutdown(att->io); + io_shutdown(chan->io); return; } @@ -739,9 +818,9 @@ static void handle_conf(struct bt_att *att, uint8_t *pdu, ssize_t pdu_len) op->callback(BT_ATT_OP_HANDLE_VAL_CONF, NULL, 0, op->user_data); destroy_att_send_op(op); - att->pending_ind = NULL; + chan->pending_ind = NULL; - wakeup_writer(att); + wakeup_chan_writer(chan, NULL); } struct notify_data { @@ -811,9 +890,10 @@ fail: return false; } -static void handle_notify(struct bt_att *att, uint8_t opcode, uint8_t *pdu, - ssize_t pdu_len) +static void handle_notify(struct bt_att_chan *chan, uint8_t opcode, + uint8_t *pdu, ssize_t pdu_len) { + struct bt_att *att = chan->att; const struct queue_entry *entry; bool found; @@ -845,7 +925,7 @@ static void handle_notify(struct bt_att *att, uint8_t opcode, uint8_t *pdu, * link since the MTU size is negotiated using L2CAP channel * configuration procedures. */ - if (bt_att_get_link_type(att) == BT_ATT_LINK_BREDR) { + if (bt_att_get_link_type(att) == BT_ATT_BREDR) { switch (opcode) { case BT_ATT_OP_MTU_REQ: goto not_supported; @@ -876,22 +956,23 @@ not_supported: static bool can_read_data(struct io *io, void *user_data) { - struct bt_att *att = user_data; + struct bt_att_chan *chan = user_data; + struct bt_att *att = chan->att; uint8_t opcode; uint8_t *pdu; ssize_t bytes_read; - bytes_read = read(att->fd, att->buf, att->mtu); + bytes_read = read(chan->fd, chan->buf, chan->mtu); if (bytes_read < 0) return false; - util_hexdump('>', att->buf, bytes_read, - att->debug_callback, att->debug_data); + util_hexdump('>', chan->buf, bytes_read, + att->debug_callback, att->debug_data); if (bytes_read < ATT_MIN_PDU_LEN) return true; - pdu = att->buf; + pdu = chan->buf; opcode = pdu[0]; bt_att_ref(att); @@ -901,12 +982,12 @@ static bool can_read_data(struct io *io, void *user_data) case ATT_OP_TYPE_RSP: util_debug(att->debug_callback, att->debug_data, "ATT response received: 0x%02x", opcode); - handle_rsp(att, opcode, pdu + 1, bytes_read - 1); + handle_rsp(chan, opcode, pdu + 1, bytes_read - 1); break; case ATT_OP_TYPE_CONF: util_debug(att->debug_callback, att->debug_data, "ATT confirmation received: 0x%02x", opcode); - handle_conf(att, pdu + 1, bytes_read - 1); + handle_conf(chan, pdu + 1, bytes_read - 1); break; case ATT_OP_TYPE_REQ: /* @@ -914,17 +995,17 @@ static bool can_read_data(struct io *io, void *user_data) * protocol was violated. Disconnect the bearer, which will * promptly notify the upper layer via disconnect handlers. */ - if (att->in_req) { + if (chan->in_req) { util_debug(att->debug_callback, att->debug_data, "Received request while another is " "pending: 0x%02x", opcode); - io_shutdown(att->io); - bt_att_unref(att); + io_shutdown(chan->io); + bt_att_unref(chan->att); return false; } - att->in_req = true; + chan->in_req = true; /* fall through */ case ATT_OP_TYPE_CMD: case ATT_OP_TYPE_NOT: @@ -937,7 +1018,7 @@ static bool can_read_data(struct io *io, void *user_data) */ util_debug(att->debug_callback, att->debug_data, "ATT PDU received: 0x%02x", opcode); - handle_notify(att, opcode, pdu + 1, bytes_read - 1); + handle_notify(chan, opcode, pdu + 1, bytes_read - 1); break; } @@ -973,21 +1054,8 @@ static bool is_io_l2cap_based(int fd) static void bt_att_free(struct bt_att *att) { - if (att->pending_req) - destroy_att_send_op(att->pending_req); - - if (att->pending_ind) - destroy_att_send_op(att->pending_ind); - - io_destroy(att->io); bt_crypto_unref(att->crypto); - queue_destroy(att->req_queue, NULL); - queue_destroy(att->ind_queue, NULL); - queue_destroy(att->write_queue, NULL); - queue_destroy(att->notify_list, NULL); - queue_destroy(att->disconn_list, NULL); - if (att->timeout_destroy) att->timeout_destroy(att->timeout_data); @@ -997,7 +1065,12 @@ static void bt_att_free(struct bt_att *att) free(att->local_sign); free(att->remote_sign); - free(att->buf); + queue_destroy(att->req_queue, NULL); + queue_destroy(att->ind_queue, NULL); + queue_destroy(att->write_queue, NULL); + queue_destroy(att->notify_list, NULL); + queue_destroy(att->disconn_list, NULL); + queue_destroy(att->chans, bt_att_chan_free); free(att); } @@ -1014,60 +1087,101 @@ static uint16_t get_l2cap_mtu(int fd) return l2o.omtu; } -struct bt_att *bt_att_new(int fd, bool ext_signed) +static uint8_t io_get_type(int fd) { - struct bt_att *att; + struct sockaddr_l2 src; + socklen_t len; - if (fd < 0) - return NULL; + if (!is_io_l2cap_based(fd)) + return BT_ATT_LOCAL; - att = new0(struct bt_att, 1); - att->fd = fd; + len = sizeof(src); + memset(&src, 0, len); + if (getsockname(fd, (void *)&src, &len) < 0) + return -errno; - att->io = io_new(fd); - if (!att->io) - goto fail; + if (src.l2_bdaddr_type == BDADDR_BREDR) + return BT_ATT_BREDR; - /* crypto is optional, if not available leave it NULL */ - if (!ext_signed) - att->crypto = bt_crypto_new(); + return BT_ATT_LE; +} - att->req_queue = queue_new(); - att->ind_queue = queue_new(); - att->write_queue = queue_new(); - att->notify_list = queue_new(); - att->disconn_list = queue_new(); +static struct bt_att_chan *bt_att_chan_new(int fd, uint8_t type) +{ + struct bt_att_chan *chan; - if (!io_set_read_handler(att->io, can_read_data, att, NULL)) + if (fd < 0) + return NULL; + + chan = new0(struct bt_att_chan, 1); + chan->fd = fd; + + chan->io = io_new(fd); + if (!chan->io) goto fail; - if (!io_set_disconnect_handler(att->io, disconnect_cb, att, NULL)) + if (!io_set_read_handler(chan->io, can_read_data, chan, NULL)) goto fail; - att->io_on_l2cap = is_io_l2cap_based(att->fd); - if (!att->io_on_l2cap) - att->io_sec_level = BT_ATT_SECURITY_LOW; + if (!io_set_disconnect_handler(chan->io, disconnect_cb, chan, NULL)) + goto fail; - if (bt_att_get_link_type(att) == BT_ATT_LINK_BREDR) - att->mtu = get_l2cap_mtu(att->fd); - else - att->mtu = BT_ATT_DEFAULT_LE_MTU; + chan->type = type; + switch (chan->type) { + case BT_ATT_LOCAL: + chan->sec_level = BT_ATT_SECURITY_LOW; + /* fall through */ + case BT_ATT_LE: + chan->mtu = BT_ATT_DEFAULT_LE_MTU; + break; + default: + chan->mtu = get_l2cap_mtu(chan->fd); + } - if (att->mtu < BT_ATT_DEFAULT_LE_MTU) + if (chan->mtu < BT_ATT_DEFAULT_LE_MTU) goto fail; - att->buf = malloc(att->mtu); - if (!att->buf) + chan->buf = malloc(chan->mtu); + if (!chan->buf) goto fail; - return bt_att_ref(att); + return chan; fail: - bt_att_free(att); + bt_att_chan_free(chan); return NULL; } +struct bt_att *bt_att_new(int fd, bool ext_signed) +{ + struct bt_att *att; + struct bt_att_chan *chan; + + chan = bt_att_chan_new(fd, io_get_type(fd)); + if (!chan) + return NULL; + + att = new0(struct bt_att, 1); + att->chans = queue_new(); + att->mtu = chan->mtu; + + queue_push_head(att->chans, chan); + chan->att = att; + + /* crypto is optional, if not available leave it NULL */ + if (!ext_signed) + att->crypto = bt_crypto_new(); + + att->req_queue = queue_new(); + att->ind_queue = queue_new(); + att->write_queue = queue_new(); + att->notify_list = queue_new(); + att->disconn_list = queue_new(); + + return bt_att_ref(att); +} + struct bt_att *bt_att_ref(struct bt_att *att) { if (!att) @@ -1094,18 +1208,67 @@ void bt_att_unref(struct bt_att *att) bool bt_att_set_close_on_unref(struct bt_att *att, bool do_close) { - if (!att || !att->io) + const struct queue_entry *entry; + + if (!att) return false; - return io_set_close_on_destroy(att->io, do_close); + att->close_on_unref = do_close; + + for (entry = queue_get_entries(att->chans); entry; + entry = entry->next) { + struct bt_att_chan *chan = entry->data; + + if (!io_set_close_on_destroy(chan->io, do_close)) + return false; + } + + return true; +} + +int bt_att_attach_fd(struct bt_att *att, int fd) +{ + struct bt_att_chan *chan; + + if (!att || fd < 0) + return -EINVAL; + + chan = bt_att_chan_new(fd, BT_ATT_EATT); + if (!chan) + return -EINVAL; + + queue_push_tail(att->chans, chan); + chan->att = att; + + if (chan->mtu > att->mtu) + att->mtu = chan->mtu; + + io_set_close_on_destroy(chan->io, att->close_on_unref); + + return 0; } int bt_att_get_fd(struct bt_att *att) { + struct bt_att_chan *chan; + if (!att) return -1; - return att->fd; + if (queue_isempty(att->chans)) + return -ENOTCONN; + + chan = queue_peek_head(att->chans); + + return chan->fd; +} + +int bt_att_get_channels(struct bt_att *att) +{ + if (!att) + return 0; + + return queue_length(att->chans); } bool bt_att_set_debug(struct bt_att *att, bt_att_debug_func_t callback, @@ -1134,6 +1297,7 @@ uint16_t bt_att_get_mtu(struct bt_att *att) bool bt_att_set_mtu(struct bt_att *att, uint16_t mtu) { + struct bt_att_chan *chan; void *buf; if (!att) @@ -1142,38 +1306,37 @@ bool bt_att_set_mtu(struct bt_att *att, uint16_t mtu) if (mtu < BT_ATT_DEFAULT_LE_MTU) return false; + chan = queue_peek_head(att->chans); + if (!chan) + return -ENOTCONN; + buf = malloc(mtu); if (!buf) return false; - free(att->buf); + free(chan->buf); + + chan->mtu = mtu; + chan->buf = buf; - att->mtu = mtu; - att->buf = buf; + if (chan->mtu > att->mtu) + att->mtu = chan->mtu; return true; } uint8_t bt_att_get_link_type(struct bt_att *att) { - struct sockaddr_l2 src; - socklen_t len; + struct bt_att_chan *chan; if (!att) return -EINVAL; - if (!att->io_on_l2cap) - return BT_ATT_LINK_LOCAL; + chan = queue_peek_head(att->chans); + if (!chan) + return -ENOTCONN; - len = sizeof(src); - memset(&src, 0, len); - if (getsockname(att->fd, (void *)&src, &len) < 0) - return -errno; - - if (src.l2_bdaddr_type == BDADDR_BREDR) - return BT_ATT_LINK_BREDR; - - return BT_ATT_LINK_LE; + return chan->type; } bool bt_att_set_timeout_cb(struct bt_att *att, bt_att_timeout_func_t callback, @@ -1200,7 +1363,7 @@ unsigned int bt_att_register_disconnect(struct bt_att *att, { struct att_disconn *disconn; - if (!att || !att->io) + if (!att || queue_isempty(att->chans)) return 0; disconn = new0(struct att_disconn, 1); @@ -1229,7 +1392,7 @@ bool bt_att_unregister_disconnect(struct bt_att *att, unsigned int id) return false; /* Check if disconnect is running */ - if (!att->io) { + if (!queue_isempty(att->chans)) { disconn = queue_find(att->disconn_list, match_disconn_id, UINT_TO_PTR(id)); if (!disconn) @@ -1256,7 +1419,7 @@ unsigned int bt_att_send(struct bt_att *att, uint8_t opcode, struct att_send_op *op; bool result; - if (!att || !att->io) + if (!att || queue_isempty(att->chans)) return 0; op = create_att_send_op(att, opcode, pdu, length, callback, user_data, @@ -1308,21 +1471,31 @@ static bool match_op_id(const void *a, const void *b) bool bt_att_cancel(struct bt_att *att, unsigned int id) { + const struct queue_entry *entry; struct att_send_op *op; if (!att || !id) return false; - if (att->pending_req && att->pending_req->id == id) { - /* Don't cancel the pending request; remove it's handlers */ - cancel_att_send_op(att->pending_req); - return true; - } + for (entry = queue_get_entries(att->chans); entry; + entry = entry->next) { + struct bt_att_chan *chan = entry->data; - if (att->pending_ind && att->pending_ind->id == id) { - /* Don't cancel the pending indication; remove it's handlers */ - cancel_att_send_op(att->pending_ind); - return true; + if (chan->pending_req && chan->pending_req->id == id) { + /* Don't cancel the pending request; remove it's + * handlers + */ + cancel_att_send_op(chan->pending_req); + return true; + } + + if (chan->pending_ind && chan->pending_ind->id == id) { + /* Don't cancel the pending indication; remove it's + * handlers. + */ + cancel_att_send_op(chan->pending_ind); + return true; + } } op = queue_remove_if(att->req_queue, match_op_id, UINT_TO_PTR(id)); @@ -1350,6 +1523,8 @@ done: bool bt_att_cancel_all(struct bt_att *att) { + const struct queue_entry *entry; + if (!att) return false; @@ -1357,13 +1532,22 @@ bool bt_att_cancel_all(struct bt_att *att) queue_remove_all(att->ind_queue, NULL, NULL, destroy_att_send_op); queue_remove_all(att->write_queue, NULL, NULL, destroy_att_send_op); - if (att->pending_req) - /* Don't cancel the pending request; remove it's handlers */ - cancel_att_send_op(att->pending_req); - - if (att->pending_ind) - /* Don't cancel the pending request; remove it's handlers */ - cancel_att_send_op(att->pending_ind); + for (entry = queue_get_entries(att->chans); entry; + entry = entry->next) { + struct bt_att_chan *chan = entry->data; + + if (chan->pending_req) + /* Don't cancel the pending request; remove it's + * handlers + */ + cancel_att_send_op(chan->pending_req); + + if (chan->pending_ind) + /* Don't cancel the pending request; remove it's + * handlers + */ + cancel_att_send_op(chan->pending_ind); + } return true; } @@ -1424,7 +1608,7 @@ unsigned int bt_att_register(struct bt_att *att, uint8_t opcode, { struct att_notify *notify; - if (!att || !callback || !att->io) + if (!att || !callback || queue_isempty(att->chans)) return 0; notify = new0(struct att_notify, 1); @@ -1475,51 +1659,39 @@ bool bt_att_unregister_all(struct bt_att *att) int bt_att_get_security(struct bt_att *att, uint8_t *enc_size) { - struct bt_security sec; - socklen_t len; + struct bt_att_chan *chan; + int ret; if (!att) return -EINVAL; - if (!att->io_on_l2cap) { - if (enc_size) - *enc_size = att->enc_size; + chan = queue_peek_head(att->chans); + if (!chan) + return -ENOTCONN; - return att->io_sec_level; - } - - memset(&sec, 0, sizeof(sec)); - len = sizeof(sec); - if (getsockopt(att->fd, SOL_BLUETOOTH, BT_SECURITY, &sec, &len) < 0) - return -EIO; + ret = bt_att_chan_get_security(chan); + if (ret < 0) + return ret; if (enc_size) *enc_size = att->enc_size; - return sec.level; + return ret; } bool bt_att_set_security(struct bt_att *att, int level) { - struct bt_security sec; + struct bt_att_chan *chan; if (!att || level < BT_ATT_SECURITY_AUTO || level > BT_ATT_SECURITY_HIGH) return false; - if (!att->io_on_l2cap) { - att->io_sec_level = level; - return true; - } + chan = queue_peek_head(att->chans); + if (!chan) + return -ENOTCONN; - memset(&sec, 0, sizeof(sec)); - sec.level = level; - - if (setsockopt(att->fd, SOL_BLUETOOTH, BT_SECURITY, &sec, - sizeof(sec)) < 0) - return false; - - return true; + return bt_att_chan_set_security(chan, level); } void bt_att_set_enc_key_size(struct bt_att *att, uint8_t enc_size) diff --git a/src/shared/att.h b/src/shared/att.h index 49d93269b..110700846 100644 --- a/src/shared/att.h +++ b/src/shared/att.h @@ -37,6 +37,10 @@ bool bt_att_set_close_on_unref(struct bt_att *att, bool do_close); int bt_att_get_fd(struct bt_att *att); +int bt_att_attach_fd(struct bt_att *att, int fd); + +int bt_att_get_channels(struct bt_att *att); + typedef void (*bt_att_response_func_t)(uint8_t opcode, const void *pdu, uint16_t length, void *user_data); typedef void (*bt_att_notify_func_t)(uint8_t opcode, const void *pdu, diff --git a/src/shared/gatt-client.c b/src/shared/gatt-client.c index 29254cb61..3ce126485 100644 --- a/src/shared/gatt-client.c +++ b/src/shared/gatt-client.c @@ -1909,7 +1909,7 @@ static bool gatt_client_init(struct bt_gatt_client *client, uint16_t mtu) * the MTU size is negotiated using L2CAP channel configuration * procedures. */ - if (bt_att_get_link_type(client->att) == BT_ATT_LINK_BREDR) + if (bt_att_get_link_type(client->att) == BT_ATT_BREDR) goto discover; /* Check if MTU needs to be send */ From patchwork Wed Jan 8 00:33:38 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luiz Augusto von Dentz X-Patchwork-Id: 197513 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.6 required=3.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8881EC33C99 for ; Wed, 8 Jan 2020 00:34:04 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 5FB6E206F0 for ; Wed, 8 Jan 2020 00:34:04 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="HhJhZ6Jb" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727135AbgAHAeE (ORCPT ); Tue, 7 Jan 2020 19:34:04 -0500 Received: from mail-pg1-f196.google.com ([209.85.215.196]:41322 "EHLO mail-pg1-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726281AbgAHAeD (ORCPT ); Tue, 7 Jan 2020 19:34:03 -0500 Received: by mail-pg1-f196.google.com with SMTP id x8so666766pgk.8 for ; Tue, 07 Jan 2020 16:34:03 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:subject:date:message-id:in-reply-to:references:mime-version :content-transfer-encoding; bh=mdvyyyvPpQFaJbQGLewzvFtpyc9kHqej1Sc18Z5t20Y=; b=HhJhZ6JbtVbTc9Z3tWPTrBC7dYlGj5VUuKuN1jDpB31phyLcrf212m6XwP9fs9iy6b gRh7cnjqBfx2/3a6fbNgWvj+FN5OEKRgpEgeUO+RkPLTuRc+ptrbuAj3lx3II4RRXhFc 7e8sUG5e/7wdcfSpHtIH4Ng2PYqbb2/ajPwGQoNBslks8jWBzZdvAjIzy6ipuiQkui62 THBw3AtTah9vMJm8sHN85L7f3EfKhaFQ9b8iDIeBc3IlxbrGgP3QChXCygKjMowNiviz UF/sVFLnR750BXNxIgfbzbDm02RMqb7u1e9Tk5UR4KE3sdmWPENavXKdmCsQZzbY+Tjh MW2A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=mdvyyyvPpQFaJbQGLewzvFtpyc9kHqej1Sc18Z5t20Y=; b=f0hQoawuQUHF3jcKWRQUT5j8XTempco80Nip58pOn12vjROl94dcCXn3Z+FUBV87VG 3+CbshifVWrm+47wguQ9ihVnD5CNicox9C7R6FiK2H31xZGWhxCOQP5yINyq+8bjr7S3 YG0PDMw1bFJThImKyJtiolX0GCS0Q7Ayeb6hiOducxDifH9EqkKKXVh8eR8JmCb+YOzx MgBBBesvTVozKbAD/dAArw2UtfEmlyqKUmhOPgsGxbuHUTlaBOtGUm4o9DkNaOCkdqii 84da4OAHarFfnuHRzncZdCp8nITKYQFAOJR8bPOhfLtbXtS39pSVdXvGQIXvcR53dC6+ fSvg== X-Gm-Message-State: APjAAAW1uUgqXzYoJplX7HGwJmjKc+Nq48z4oJcWQJPWpi67YsZf6drB 9c/gy0LwW5dn8LvGdxeFP8MPURB8qno= X-Google-Smtp-Source: APXvYqwJNi/eVNHx7riRPoOneDcoz6fCxAYsk/vcjVtJ3dB05F54H07u2edvo37QPp1Uomk0NbdsxA== X-Received: by 2002:a63:b141:: with SMTP id g1mr2543433pgp.168.1578443642630; Tue, 07 Jan 2020 16:34:02 -0800 (PST) Received: from localhost.localdomain ([192.102.209.43]) by smtp.gmail.com with ESMTPSA id u10sm925805pgg.41.2020.01.07.16.34.01 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 07 Jan 2020 16:34:01 -0800 (PST) From: Luiz Augusto von Dentz To: linux-bluetooth@vger.kernel.org Subject: [PATCH BlueZ 18/22] shared/gatt-client: Add support for Read Multiple Variable Length Date: Tue, 7 Jan 2020 16:33:38 -0800 Message-Id: <20200108003342.15458-19-luiz.dentz@gmail.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20200108003342.15458-1-luiz.dentz@gmail.com> References: <20200108003342.15458-1-luiz.dentz@gmail.com> MIME-Version: 1.0 Sender: linux-bluetooth-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org From: Luiz Augusto von Dentz The Read Multiple Variable Length Request is used to request that the server read two or more values of a set of attributes that have a variable or unknown value length and return their values in a Read Multiple Variable Length Response. --- src/shared/gatt-client.c | 37 +++++++++++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/src/shared/gatt-client.c b/src/shared/gatt-client.c index d4758c2de..aecf0ca5a 100644 --- a/src/shared/gatt-client.c +++ b/src/shared/gatt-client.c @@ -2639,7 +2639,9 @@ static void read_multiple_cb(uint8_t opcode, const void *pdu, uint16_t length, uint8_t att_ecode; bool success; - if (opcode != BT_ATT_OP_READ_MULT_RSP || (!pdu && length)) { + if ((opcode != BT_ATT_OP_READ_MULT_RSP && + opcode != BT_ATT_OP_READ_MULT_VL_RSP) || + (!pdu && length)) { success = false; if (opcode == BT_ATT_OP_ERROR_RSP) @@ -2654,8 +2656,31 @@ static void read_multiple_cb(uint8_t opcode, const void *pdu, uint16_t length, att_ecode = 0; } - if (op->callback) + if (!op->callback) + return; + + if (opcode == BT_ATT_OP_READ_MULT_RSP) { op->callback(success, att_ecode, pdu, length, op->user_data); + return; + } + + /* Parse response */ + while (length >= 2) { + uint16_t len; + + len = get_le16(pdu); + length -= 2; + pdu += 2; + + /* The Length Value Tuple List may be truncated within the + * first two octets of a tuple due to the size limits of the + * current ATT_MTU. + */ + if (len > length) + length = len; + + op->callback(success, att_ecode, pdu, len, op->user_data); + } } unsigned int bt_gatt_client_read_multiple(struct bt_gatt_client *client, @@ -2667,6 +2692,7 @@ unsigned int bt_gatt_client_read_multiple(struct bt_gatt_client *client, uint8_t pdu[num_handles * 2]; struct request *req; struct read_op *op; + uint8_t opcode; int i; if (!client) @@ -2696,8 +2722,11 @@ unsigned int bt_gatt_client_read_multiple(struct bt_gatt_client *client, for (i = 0; i < num_handles; i++) put_le16(handles[i], pdu + (2 * i)); - req->att_id = bt_att_send(client->att, BT_ATT_OP_READ_MULT_REQ, - pdu, sizeof(pdu), + opcode = bt_gatt_client_get_features(client) & + BT_GATT_CHRC_CLI_FEAT_EATT ? BT_ATT_OP_READ_MULT_VL_REQ : + BT_GATT_CHRC_CLI_FEAT_EATT; + + req->att_id = bt_att_send(client->att, opcode, pdu, sizeof(pdu), read_multiple_cb, req, request_unref); if (!req->att_id) { From patchwork Wed Jan 8 00:33:39 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luiz Augusto von Dentz X-Patchwork-Id: 197512 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.6 required=3.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8A9BAC33C99 for ; Wed, 8 Jan 2020 00:34:06 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 54B62206F0 for ; Wed, 8 Jan 2020 00:34:06 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="G56RdSZG" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727142AbgAHAeG (ORCPT ); Tue, 7 Jan 2020 19:34:06 -0500 Received: from mail-pg1-f178.google.com ([209.85.215.178]:46712 "EHLO mail-pg1-f178.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726281AbgAHAeF (ORCPT ); Tue, 7 Jan 2020 19:34:05 -0500 Received: by mail-pg1-f178.google.com with SMTP id z124so650707pgb.13 for ; Tue, 07 Jan 2020 16:34:05 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:subject:date:message-id:in-reply-to:references:mime-version :content-transfer-encoding; bh=EXDlj0f4Fin4tduOJKMQpnxsBYpqgsV+gU/r2GsW0qk=; b=G56RdSZGdc/XdqWtQjlJvhWKgA3NeKME+Tnif0KTsAi4UB/U1IDCszqfssUjsfXBSs i1HoMzhPF75XqPGKoZmCERjewK4+uyb0lEMoclCpoUvBUPUgS7iV7RX/4AzSPnq5E4C4 Pcn3RPX/kcNhm0xMpzt5YAdZ/hCjNdvFTUeph7ZZbIKBQOuANEhN6Ug3LlRmZbWT1kxe t9teTOvpt6CP+fXVg/QQKZSiSOtts7raAN8H9JGgC/N6mbg5tl//AUlUAbvCQ6AcyJPd lKhfACY2pfdqGhZuht1uYJ7lingLwtjYEv7bp3wyuEJtC2IjIkFwCfB2sdQBU98YboWJ bRQA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=EXDlj0f4Fin4tduOJKMQpnxsBYpqgsV+gU/r2GsW0qk=; b=jOC6UqjgSjAzYJpVEK4EA/Kdx2nOaPN5Zcu//hthCkeupaPzV5GUH2YJQiHMlCqJqb icHh/yUq9Bhny48p2oF9J37/K1PDplP2AYTgl5dI5YB8D4G0HEYSXtT1prKcZRVgWmdN QQB7D/xTgKGGPusb5PhcsEZvpS0WTpxlnwdsOZSxFhgM8p1driUSxRdOeSMNNxIzAqx+ 06wiz6GhW9Uitf0lSG2zdP3cSJtRWUvlSAkeADnL/NV1cVWpqTM0/jQ6W5HDP66bcNv3 Zv1cHzQEPh9mTCo+enXNiM2WSCwPeCtRfVZtSnuuhu8SwVZqd7+3r/qbeyI3+PQEM4Vl c8mg== X-Gm-Message-State: APjAAAVwLGP/xR0LNcS9wOpoX2UbWMFG7S/8VwqZoO3sMi7XZkAULG4k qn6ItCgKmst0zeZm0PWAqtzlcmL75NE= X-Google-Smtp-Source: APXvYqyCBjOjDeLkOqdNdEpK4SqIA9RVPsBwbaY3Nbpb5nigIox8W80YnDmrJfU0n04x212MiSdwoQ== X-Received: by 2002:a63:1210:: with SMTP id h16mr2350727pgl.171.1578443644044; Tue, 07 Jan 2020 16:34:04 -0800 (PST) Received: from localhost.localdomain ([192.102.209.43]) by smtp.gmail.com with ESMTPSA id u10sm925805pgg.41.2020.01.07.16.34.02 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 07 Jan 2020 16:34:02 -0800 (PST) From: Luiz Augusto von Dentz To: linux-bluetooth@vger.kernel.org Subject: [PATCH BlueZ 19/22] shared/gatt: Add support for Handle Value Multiple Notifications Date: Tue, 7 Jan 2020 16:33:39 -0800 Message-Id: <20200108003342.15458-20-luiz.dentz@gmail.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20200108003342.15458-1-luiz.dentz@gmail.com> References: <20200108003342.15458-1-luiz.dentz@gmail.com> MIME-Version: 1.0 Sender: linux-bluetooth-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org From: Luiz Augusto von Dentz Handle Value Multiple Notification can be used to notify multiple values at once. --- src/shared/att-types.h | 7 ++-- src/shared/att.c | 16 ++++----- src/shared/gatt-client.c | 76 ++++++++++++++++++++++++++-------------- src/shared/gatt-server.c | 4 +-- 4 files changed, 64 insertions(+), 39 deletions(-) diff --git a/src/shared/att-types.h b/src/shared/att-types.h index cc9cc9fd6..99b108990 100644 --- a/src/shared/att-types.h +++ b/src/shared/att-types.h @@ -72,11 +72,12 @@ #define BT_ATT_OP_PREP_WRITE_RSP 0x17 #define BT_ATT_OP_EXEC_WRITE_REQ 0x18 #define BT_ATT_OP_EXEC_WRITE_RSP 0x19 -#define BT_ATT_OP_HANDLE_VAL_NOT 0x1B -#define BT_ATT_OP_HANDLE_VAL_IND 0x1D -#define BT_ATT_OP_HANDLE_VAL_CONF 0x1E +#define BT_ATT_OP_HANDLE_NFY 0x1B +#define BT_ATT_OP_HANDLE_IND 0x1D +#define BT_ATT_OP_HANDLE_CONF 0x1E #define BT_ATT_OP_READ_MULT_VL_REQ 0x20 #define BT_ATT_OP_READ_MULT_VL_RSP 0x21 +#define BT_ATT_OP_HANDLE_NFY_MULT 0x23 /* Packed struct definitions for ATT protocol PDUs */ /* TODO: Complete these definitions for all opcodes */ diff --git a/src/shared/att.c b/src/shared/att.c index 56ea40c46..6fa16e422 100644 --- a/src/shared/att.c +++ b/src/shared/att.c @@ -110,7 +110,7 @@ enum att_op_type { ATT_OP_TYPE_RSP, ATT_OP_TYPE_CMD, ATT_OP_TYPE_IND, - ATT_OP_TYPE_NOT, + ATT_OP_TYPE_NFY, ATT_OP_TYPE_CONF, ATT_OP_TYPE_UNKNOWN, }; @@ -144,9 +144,9 @@ static const struct { { BT_ATT_OP_PREP_WRITE_RSP, ATT_OP_TYPE_RSP }, { BT_ATT_OP_EXEC_WRITE_REQ, ATT_OP_TYPE_REQ }, { BT_ATT_OP_EXEC_WRITE_RSP, ATT_OP_TYPE_RSP }, - { BT_ATT_OP_HANDLE_VAL_NOT, ATT_OP_TYPE_NOT }, - { BT_ATT_OP_HANDLE_VAL_IND, ATT_OP_TYPE_IND }, - { BT_ATT_OP_HANDLE_VAL_CONF, ATT_OP_TYPE_CONF }, + { BT_ATT_OP_HANDLE_NFY, ATT_OP_TYPE_NFY }, + { BT_ATT_OP_HANDLE_IND, ATT_OP_TYPE_IND }, + { BT_ATT_OP_HANDLE_CONF, ATT_OP_TYPE_CONF }, { } }; @@ -530,7 +530,7 @@ static bool can_write_data(struct io *io, void *user_data) chan->in_req = false; /* fall through */ case ATT_OP_TYPE_CMD: - case ATT_OP_TYPE_NOT: + case ATT_OP_TYPE_NFY: case ATT_OP_TYPE_CONF: case ATT_OP_TYPE_UNKNOWN: default: @@ -842,7 +842,7 @@ static void handle_conf(struct bt_att_chan *chan, uint8_t *pdu, ssize_t pdu_len) } if (op->callback) - op->callback(BT_ATT_OP_HANDLE_VAL_CONF, NULL, 0, op->user_data); + op->callback(BT_ATT_OP_HANDLE_NFY, NULL, 0, op->user_data); destroy_att_send_op(op); chan->pending_ind = NULL; @@ -1042,7 +1042,7 @@ static bool can_read_data(struct io *io, void *user_data) chan->in_req = true; /* fall through */ case ATT_OP_TYPE_CMD: - case ATT_OP_TYPE_NOT: + case ATT_OP_TYPE_NFY: case ATT_OP_TYPE_UNKNOWN: case ATT_OP_TYPE_IND: /* fall through */ @@ -1492,7 +1492,7 @@ unsigned int bt_att_send(struct bt_att *att, uint8_t opcode, result = queue_push_tail(att->ind_queue, op); break; case ATT_OP_TYPE_CMD: - case ATT_OP_TYPE_NOT: + case ATT_OP_TYPE_NFY: case ATT_OP_TYPE_UNKNOWN: case ATT_OP_TYPE_RSP: case ATT_OP_TYPE_CONF: diff --git a/src/shared/gatt-client.c b/src/shared/gatt-client.c index aecf0ca5a..8c563cdcc 100644 --- a/src/shared/gatt-client.c +++ b/src/shared/gatt-client.c @@ -95,7 +95,7 @@ struct bt_gatt_client { struct queue *notify_list; struct queue *notify_chrcs; int next_reg_id; - unsigned int disc_id, notify_id, ind_id; + unsigned int disc_id, nfy_id, nfy_mult_id, ind_id; /* * Handles of the GATT Service and the Service Changed characteristic @@ -2069,9 +2069,10 @@ done: return true; } -struct pdu_data { - const void *pdu; - uint16_t length; +struct value_data { + uint16_t handle; + uint16_t len; + const void *data; }; static void disable_ccc_callback(uint8_t opcode, const void *pdu, @@ -2122,25 +2123,18 @@ done: static void notify_handler(void *data, void *user_data) { struct notify_data *notify_data = data; - struct pdu_data *pdu_data = user_data; - uint16_t value_handle; - const uint8_t *value = NULL; - - value_handle = get_le16(pdu_data->pdu); + struct value_data *value_data = user_data; - if (notify_data->chrc->value_handle != value_handle) + if (notify_data->chrc->value_handle != value_data->handle) return; - if (pdu_data->length > 2) - value = pdu_data->pdu + 2; - /* * Even if the notify data has a pending ATT request to write to the * CCC, there is really no reason not to notify the handlers. */ if (notify_data->notify) - notify_data->notify(value_handle, value, pdu_data->length - 2, - notify_data->user_data); + notify_data->notify(value_data->handle, value_data->data, + value_data->len, notify_data->user_data); } static void notify_cb(struct bt_att_chan *chan, uint8_t opcode, @@ -2148,18 +2142,42 @@ static void notify_cb(struct bt_att_chan *chan, uint8_t opcode, void *user_data) { struct bt_gatt_client *client = user_data; - struct pdu_data pdu_data; + struct value_data data; bt_gatt_client_ref(client); - memset(&pdu_data, 0, sizeof(pdu_data)); - pdu_data.pdu = pdu; - pdu_data.length = length; + memset(&data, 0, sizeof(data)); + + if (opcode == BT_ATT_OP_HANDLE_NFY_MULT) { + while (length >= 4) { + data.handle = get_le16(pdu); + length -= 2; + pdu += 2; + + data.len = get_le16(pdu); + length -= 2; + pdu += 2; + + data.data = pdu; + + queue_foreach(client->notify_list, notify_handler, + &data); - queue_foreach(client->notify_list, notify_handler, &pdu_data); + length -= data.len; + } + } else { + data.handle = get_le16(pdu); + length -= 2; + pdu += 2; + + data.len = length; + data.data = pdu; - if (opcode == BT_ATT_OP_HANDLE_VAL_IND && !client->parent) - bt_att_chan_send(chan, BT_ATT_OP_HANDLE_VAL_CONF, NULL, 0, + queue_foreach(client->notify_list, notify_handler, &data); + } + + if (opcode == BT_ATT_OP_HANDLE_IND && !client->parent) + bt_att_chan_send(chan, BT_ATT_OP_HANDLE_CONF, NULL, 0, NULL, NULL, NULL); bt_gatt_client_unref(client); @@ -2178,7 +2196,8 @@ static void bt_gatt_client_free(struct bt_gatt_client *client) if (client->att) { bt_att_unregister_disconnect(client->att, client->disc_id); - bt_att_unregister(client->att, client->notify_id); + bt_att_unregister(client->att, client->nfy_id); + bt_att_unregister(client->att, client->nfy_mult_id); bt_att_unregister(client->att, client->ind_id); bt_att_unref(client->att); } @@ -2236,12 +2255,17 @@ static struct bt_gatt_client *gatt_client_new(struct gatt_db *db, client->notify_chrcs = queue_new(); client->pending_requests = queue_new(); - client->notify_id = bt_att_register(att, BT_ATT_OP_HANDLE_VAL_NOT, + client->nfy_id = bt_att_register(att, BT_ATT_OP_HANDLE_NFY, + notify_cb, client, NULL); + if (!client->nfy_id) + goto fail; + + client->nfy_mult_id = bt_att_register(att, BT_ATT_OP_HANDLE_NFY_MULT, notify_cb, client, NULL); - if (!client->notify_id) + if (!client->nfy_mult_id) goto fail; - client->ind_id = bt_att_register(att, BT_ATT_OP_HANDLE_VAL_IND, + client->ind_id = bt_att_register(att, BT_ATT_OP_HANDLE_IND, notify_cb, client, NULL); if (!client->ind_id) goto fail; diff --git a/src/shared/gatt-server.c b/src/shared/gatt-server.c index 55535abdf..0711f1d75 100644 --- a/src/shared/gatt-server.c +++ b/src/shared/gatt-server.c @@ -1748,7 +1748,7 @@ bool bt_gatt_server_send_notification(struct bt_gatt_server *server, put_le16(handle, pdu); memcpy(pdu + 2, value, pdu_len - 2); - result = !!bt_att_send(server->att, BT_ATT_OP_HANDLE_VAL_NOT, pdu, + result = !!bt_att_send(server->att, BT_ATT_OP_HANDLE_NFY, pdu, pdu_len, NULL, NULL, NULL); free(pdu); @@ -1809,7 +1809,7 @@ bool bt_gatt_server_send_indication(struct bt_gatt_server *server, put_le16(handle, pdu); memcpy(pdu + 2, value, pdu_len - 2); - result = !!bt_att_send(server->att, BT_ATT_OP_HANDLE_VAL_IND, pdu, + result = !!bt_att_send(server->att, BT_ATT_OP_HANDLE_IND, pdu, pdu_len, conf_cb, data, destroy_ind_data); if (!result) From patchwork Wed Jan 8 00:33:41 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luiz Augusto von Dentz X-Patchwork-Id: 197511 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-3.8 required=3.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS,UNWANTED_LANGUAGE_BODY,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 44C4DC33C9B for ; Wed, 8 Jan 2020 00:34:08 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 1BDE8206F0 for ; Wed, 8 Jan 2020 00:34:08 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="cgR2MRHj" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727149AbgAHAeH (ORCPT ); Tue, 7 Jan 2020 19:34:07 -0500 Received: from mail-pg1-f195.google.com ([209.85.215.195]:43349 "EHLO mail-pg1-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727139AbgAHAeH (ORCPT ); Tue, 7 Jan 2020 19:34:07 -0500 Received: by mail-pg1-f195.google.com with SMTP id k197so660112pga.10 for ; Tue, 07 Jan 2020 16:34:07 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:subject:date:message-id:in-reply-to:references:mime-version :content-transfer-encoding; bh=asgOSiO3en3MKirTF13/FJXqhGCOjS4KYj7aip7vEMk=; b=cgR2MRHjczWnaS1aW48i4voSB3UOGaH+Eav1yu3hM52L1qu9Y5fGt5llo/tq79LuNl HrEkTVikTy/yi8wVmDZfloe0vnCIbCQArUrZK4aFMB/pJGP4cEhzAg/iZAECKpzxAwcu ofwOtKl1Sjhv/qYr0VkzIP3ZxJE6TeiLc0k8ogBKAb9EmXUUM2vOXcr5gpTiwBTMM9Sc 8BQW4Ee9xkTar96uyMkRLfiaH1GSGYGGsfUdmaMSerwPoesK4vKP5QTnM7rjbRSUhU2j gQZfMuIqpLv2bIJpuvnfrZurd2JEO80gMH+8N4aXsdrKw3IsRJqhrKzddW8cwZ+rOfQm TEbQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=asgOSiO3en3MKirTF13/FJXqhGCOjS4KYj7aip7vEMk=; b=WWZzKjczr/ZjnRTHsdzPBbpu5Gv+5ePTcjnqlA7U/sGBvcEW5vI0Yz851kjhA/ot6i Xhr+0JJU1pKyZfrG3/YZoUFjH24gXaWT6eEit1dn+8BSWrKsKPmT2jda5anIFbwWrI+t XYCKXOkTfJYH7SAEsl/iyL0J0XjW81B3eBqFlh2dW82+HpvNwjKzqHGFTekkGredn7Ou euiEDRWpZIZ51z4o2pTS0hv6dod05RiHmvegymFQWt9+EEF0zETj3qM0ZyAKrmPx10Ei OTE4zzSXtu394t0msjuPOVTCy68VMPJSlX9ADrTRYUAO+fv97ULzRT3B5ADDcqpp5ypz T2vA== X-Gm-Message-State: APjAAAWTYEMMRsx6jnwWQ0wagIUf03kFCK+Ry7PLzCOPNkS+uHd6mb72 mcSHbMdN6tUe+pNq7O4OTYjDsG3srJY= X-Google-Smtp-Source: APXvYqxYlFjixI2EP3BpUEnzOSUqX6uTRXNsvgrI3B9plpIEFRs7qlC/95r+2w27WHnZb45Hiz9/Fg== X-Received: by 2002:a63:e309:: with SMTP id f9mr2347223pgh.391.1578443646161; Tue, 07 Jan 2020 16:34:06 -0800 (PST) Received: from localhost.localdomain ([192.102.209.43]) by smtp.gmail.com with ESMTPSA id u10sm925805pgg.41.2020.01.07.16.34.05 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 07 Jan 2020 16:34:05 -0800 (PST) From: Luiz Augusto von Dentz To: linux-bluetooth@vger.kernel.org Subject: [PATCH BlueZ 21/22] core: Add support for setting the number of GATT bearers Date: Tue, 7 Jan 2020 16:33:41 -0800 Message-Id: <20200108003342.15458-22-luiz.dentz@gmail.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20200108003342.15458-1-luiz.dentz@gmail.com> References: <20200108003342.15458-1-luiz.dentz@gmail.com> MIME-Version: 1.0 Sender: linux-bluetooth-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org From: Luiz Augusto von Dentz This adds option to set the numbers of GATT Channels/Bearers to be connected in main.conf. --- src/device.c | 5 +++++ src/gatt-client.c | 8 +++++--- src/gatt-database.c | 12 ++++++++++-- src/hcid.h | 1 + src/main.c | 14 ++++++++++++++ src/main.conf | 5 +++++ 6 files changed, 40 insertions(+), 5 deletions(-) diff --git a/src/device.c b/src/device.c index f7f0bc789..828fe9810 100644 --- a/src/device.c +++ b/src/device.c @@ -5049,6 +5049,11 @@ bool device_attach_att(struct btd_device *dev, GIOChannel *io) } if (dev->att) { + if (main_opts.gatt_channels == bt_att_get_channels(dev->att)) { + DBG("EATT channel limit reached"); + return false; + } + if (!bt_att_attach_fd(dev->att, g_io_channel_unix_get_fd(io))) { DBG("EATT channel connected"); g_io_channel_set_close_on_unref(io, FALSE); diff --git a/src/gatt-client.c b/src/gatt-client.c index 04a7e5319..203af709b 100644 --- a/src/gatt-client.c +++ b/src/gatt-client.c @@ -59,8 +59,6 @@ #define GATT_CHARACTERISTIC_IFACE "org.bluez.GattCharacteristic1" #define GATT_DESCRIPTOR_IFACE "org.bluez.GattDescriptor1" -#define EATT_MAX_BEARERS 2 - struct btd_gatt_client { struct btd_device *device; uint8_t features; @@ -2171,6 +2169,7 @@ static void eatt_connect_cb(GIOChannel *io, GError *gerr, gpointer user_data) static void eatt_connect(struct btd_gatt_client *client) { + struct bt_att *att = bt_gatt_client_get_att(client->gatt); struct btd_device *dev = client->device; struct btd_adapter *adapter = device_get_adapter(dev); GIOChannel *io; @@ -2178,11 +2177,14 @@ static void eatt_connect(struct btd_gatt_client *client) char addr[18]; int i; + if (bt_att_get_channels(att) == main_opts.gatt_channels) + return; + ba2str(device_get_address(dev), addr); DBG("Connection attempt to: %s", addr); - for (i = 0; i < EATT_MAX_BEARERS; i++) { + for (i = bt_att_get_channels(att); i < main_opts.gatt_channels; i++) { io = bt_io_connect(eatt_connect_cb, client, NULL, NULL, BT_IO_OPT_SOURCE_BDADDR, btd_adapter_get_address(adapter), diff --git a/src/gatt-database.c b/src/gatt-database.c index d4c892113..455201efd 100644 --- a/src/gatt-database.c +++ b/src/gatt-database.c @@ -1215,10 +1215,13 @@ static void populate_gatt_service(struct btd_gatt_database *database) &uuid, BT_ATT_PERM_READ, BT_GATT_CHRC_PROP_READ, db_hash_read_cb, NULL, database); - bt_uuid16_create(&uuid, GATT_CHARAC_SERVER_FEAT); - database->eatt = gatt_db_service_add_characteristic(service, + /* Only enable EATT if there is a socket listening */ + if (database->eatt_io) { + bt_uuid16_create(&uuid, GATT_CHARAC_SERVER_FEAT); + database->eatt = gatt_db_service_add_characteristic(service, &uuid, BT_ATT_PERM_READ, BT_GATT_CHRC_PROP_READ, server_feat_read_cb, NULL, database); + } gatt_db_service_set_active(service, true); @@ -3564,6 +3567,10 @@ struct btd_gatt_database *btd_gatt_database_new(struct btd_adapter *adapter) goto fail; } + /* If just just 1 channel is enabled EATT is not required */ + if (main_opts.gatt_channels == 1) + goto bredr; + /* EATT socket */ database->eatt_io = bt_io_listen(connect_cb, NULL, NULL, NULL, NULL, BT_IO_OPT_SOURCE_BDADDR, addr, @@ -3591,6 +3598,7 @@ struct btd_gatt_database *btd_gatt_database_new(struct btd_adapter *adapter) } } +bredr: /* BR/EDR socket */ database->bredr_io = bt_io_listen(connect_cb, NULL, NULL, NULL, &gerr, BT_IO_OPT_SOURCE_BDADDR, addr, diff --git a/src/hcid.h b/src/hcid.h index adea85ce2..083f70c5b 100644 --- a/src/hcid.h +++ b/src/hcid.h @@ -56,6 +56,7 @@ struct main_opts { bt_mode_t mode; bt_gatt_cache_t gatt_cache; uint16_t gatt_mtu; + uint8_t gatt_channels; uint8_t key_size; }; diff --git a/src/main.c b/src/main.c index 1a6ab36a3..701cd279c 100644 --- a/src/main.c +++ b/src/main.c @@ -108,6 +108,7 @@ static const char *gatt_options[] = { "Cache", "KeySize", "ExchangeMTU", + "EATTChannels", NULL }; @@ -444,6 +445,18 @@ static void parse_config(GKeyFile *config) DBG("ExchangeMTU=%d", val); main_opts.gatt_mtu = val; } + + val = g_key_file_get_integer(config, "GATT", "Channels", &err); + if (err) { + DBG("%s", err->message); + g_clear_error(&err); + } else { + DBG("Channels=%d", val); + /* Ensure the channels is within a valid range. */ + val = MIN(val, 5); + val = MAX(val, 1); + main_opts.gatt_channels = val; + } } static void init_defaults(void) @@ -470,6 +483,7 @@ static void init_defaults(void) main_opts.gatt_cache = BT_GATT_CACHE_ALWAYS; main_opts.gatt_mtu = BT_ATT_MAX_LE_MTU; + main_opts.gatt_channels = 3; } static void log_handler(const gchar *log_domain, GLogLevelFlags log_level, diff --git a/src/main.conf b/src/main.conf index 40687a755..35e4238f2 100644 --- a/src/main.conf +++ b/src/main.conf @@ -94,6 +94,11 @@ # Defaults to 517 #ExchangeMTU = 517 +# Number of ATT channels +# Possible values: 1-5 (1 disables EATT) +# Default to 3 +#Channels = 3 + [Policy] # # The ReconnectUUIDs defines the set of remote services that should try