From patchwork Thu Jan 27 10:16:06 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Joseph Hwang X-Patchwork-Id: 12726528 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5DEF0C433FE for ; Thu, 27 Jan 2022 10:16:27 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235212AbiA0KQ0 (ORCPT ); Thu, 27 Jan 2022 05:16:26 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45702 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238944AbiA0KQ0 (ORCPT ); Thu, 27 Jan 2022 05:16:26 -0500 Received: from mail-pj1-x102a.google.com (mail-pj1-x102a.google.com [IPv6:2607:f8b0:4864:20::102a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E3636C061714 for ; Thu, 27 Jan 2022 02:16:25 -0800 (PST) Received: by mail-pj1-x102a.google.com with SMTP id s2-20020a17090ad48200b001b501977b23so7105010pju.2 for ; Thu, 27 Jan 2022 02:16:25 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=Bct+9uJXCp9AR4JZv//NgLkcqYHpNSr+0PKnUweua4g=; b=IINhtUv7Q56jAtl+GQEZujoNP1Y2erydYgb82WDuNCXEPQdgihxzmv59XWG2cFS9+P sxwEZiGibV2ZADw2teYh03HSSpGWfiX2NwL52/mG0IhRQ5/fbwJymIe8Hkj4nIPprDRY a72eZhA3qLyJKpFNCzy5IP8dq4TpdHT52DVcA= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=Bct+9uJXCp9AR4JZv//NgLkcqYHpNSr+0PKnUweua4g=; b=oDhnwrVdrj2KbCW7Z6VJGpVfoIsrpe6sacre3sSlVDnCNYWiBzjpfn2v4P6yb/k69L wYefgH9+DtHxQxDmjjzs6zPOJo+Z31ws19Pxw73Y2UIqvXwHv2b+LECtNZ0x0LtXkXYr WS+zts7He6I548UKgUT4bLaj5vJ/mkh7PU042SBBZU38EPCRD0Mfs1vC+DU5oNOSPI/I 7llheIssZi4zfaUM4+9dQurOsbUZlDA6rv+DNIbX+O6KPPZVvo3oGbppKntumQgcvklP EvW8VJeCP7Z0qeTB22Kb1bDujpKYyTERJpXz/kVoFtwCmN27OgK338hXroaqOfCiuxmU LQHw== X-Gm-Message-State: AOAM532aerIeqbYSSA+t/UYat4b1aiwV9o/7HvljiE5Yp+WvOIVGyVrz 3q42uGawHwmUUOP+wHyvD4FMs7g/xFj4MQ== X-Google-Smtp-Source: ABdhPJzII5yJLLnhrZ+KJTxEjiSJ6gell3puHJ3wSI85bggW5uopoayP+JgCq7omgbP6dvBeiZewlw== X-Received: by 2002:a17:90b:1c89:: with SMTP id oo9mr3464302pjb.146.1643278585094; Thu, 27 Jan 2022 02:16:25 -0800 (PST) Received: from localhost (174.71.80.34.bc.googleusercontent.com. [34.80.71.174]) by smtp.gmail.com with UTF8SMTPSA id h6sm5192692pfc.35.2022.01.27.02.16.23 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Thu, 27 Jan 2022 02:16:24 -0800 (PST) From: Joseph Hwang To: linux-bluetooth@vger.kernel.org, marcel@holtmann.org, luiz.dentz@gmail.com, pali@kernel.org Cc: chromeos-bluetooth-upstreaming@chromium.org, josephsih@google.com, Joseph Hwang Subject: [BlueZ PATCH v2 1/4] doc: Add Bluetooth quality report event Date: Thu, 27 Jan 2022 18:16:06 +0800 Message-Id: <20220127101609.3646316-1-josephsih@chromium.org> X-Mailer: git-send-email 2.35.0.rc0.227.g00780c9af4-goog MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org Add the Bluetooth quality report event in doc/mgmt-api.txt. Signed-off-by: Joseph Hwang --- Changes in v2: - This is a new patch for adding the event in doc/mgmt-api.txt doc/mgmt-api.txt | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/doc/mgmt-api.txt b/doc/mgmt-api.txt index ebe56afa4..a0e71a732 100644 --- a/doc/mgmt-api.txt +++ b/doc/mgmt-api.txt @@ -4978,3 +4978,23 @@ Advertisement Monitor Device Lost Event 2 LE Random This event will be sent to all management sockets. + + +Bluetooth Quality Report Event +============================== + + Event code: 0x0031 + Controller Index: + Event Parameters: Quality_Spec (1 Octet) + Report_Len (2 Octets) + Report (0-65535 Octets) + + This event carries the Bluetooth quality report sent by the + controller. + + Possible values for the Quality_Spec parameter: + 0 Not Available + 1 Intel Telemetry Event + 2 AOSP Bluetooth Quality Report Event + + This event will be sent to all management sockets. From patchwork Thu Jan 27 10:16:07 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Joseph Hwang X-Patchwork-Id: 12726529 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 03E15C433F5 for ; Thu, 27 Jan 2022 10:16:30 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238960AbiA0KQ3 (ORCPT ); Thu, 27 Jan 2022 05:16:29 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45720 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238944AbiA0KQ2 (ORCPT ); Thu, 27 Jan 2022 05:16:28 -0500 Received: from mail-pl1-x629.google.com (mail-pl1-x629.google.com [IPv6:2607:f8b0:4864:20::629]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 72A97C061714 for ; Thu, 27 Jan 2022 02:16:28 -0800 (PST) Received: by mail-pl1-x629.google.com with SMTP id d18so2093643plg.2 for ; Thu, 27 Jan 2022 02:16:28 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=UQfqUCe52Kc/dWWcenFdwSJogZh4zY4n1Nupyj466uE=; b=h2xlW6kSG0RJn9cqixXAmX93/B3ebK15KcU1NzbdvLlETBKdRDtXNDU/dq5rI5K3/u FB1TrsiYB9d8LxiEIrg70yMOl0Lsdlq/P9LnmWC83T/gvDd90Cff3F1nTJJim9nBNw4f ItPpFubkY4EwQfNqx3Gh/Q+i3j5ELddHhT1js= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=UQfqUCe52Kc/dWWcenFdwSJogZh4zY4n1Nupyj466uE=; b=LhAp6wjBMGWgXyET3VPO7wPqdudxiD+xe6T9GKkZWkpHhfoIRlXfmI2jqFBOVMIpej FKC7or/tOUcXhirNJYXe2zn53RiNgfjJK9vcEJwJrM852LwFYZuETIlGXoztG7bODYec 9NiomxK8QB9AWqqZgJZH7NHs0fd0aAKBzKtWKvhFszTRsEilHvWLjfV1pLshc2ns6Myz dktWLFPKc9lLqHK+jbhFjJLpS7YfeFN8F3cHal/Df450x1SsSoMJlH3A4ew0CadnHenx M2kYgZfhVP375vpQy0tYWe393gifyKCQYgTO8ie1hmRG9eNkoJI3ZGpK3EY8rwbzq4ZE iiWw== X-Gm-Message-State: AOAM530Zv8So7UZ9/hwGIzmWODjFPSKiUAQF6OfNZGpte3FkcjT+YfeB WcxTnAdOw7MRkgJv01+OJngWuR/hvkIOzQ== X-Google-Smtp-Source: ABdhPJz72nTFqUqH8wm4dO+kcEaNuDghqjMgq+sJQ75wKB70jNGlN1Dy0aYS15brzwB9aguPaPQqXQ== X-Received: by 2002:a17:903:2352:: with SMTP id c18mr3199673plh.104.1643278587720; Thu, 27 Jan 2022 02:16:27 -0800 (PST) Received: from localhost (174.71.80.34.bc.googleusercontent.com. [34.80.71.174]) by smtp.gmail.com with UTF8SMTPSA id s42sm5475105pfg.146.2022.01.27.02.16.26 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Thu, 27 Jan 2022 02:16:27 -0800 (PST) From: Joseph Hwang To: linux-bluetooth@vger.kernel.org, marcel@holtmann.org, luiz.dentz@gmail.com, pali@kernel.org Cc: chromeos-bluetooth-upstreaming@chromium.org, josephsih@google.com, Joseph Hwang Subject: [BlueZ PATCH v2 2/4] lib: Add structures and constants for quality report Date: Thu, 27 Jan 2022 18:16:07 +0800 Message-Id: <20220127101609.3646316-2-josephsih@chromium.org> X-Mailer: git-send-email 2.35.0.rc0.227.g00780c9af4-goog In-Reply-To: <20220127101609.3646316-1-josephsih@chromium.org> References: <20220127101609.3646316-1-josephsih@chromium.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org Add the new struct and constants to lib/mgmt.h. Signed-off-by: Joseph Hwang --- Changes in v2: - This is a new patch for adding the new struct and constants. lib/mgmt.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/lib/mgmt.h b/lib/mgmt.h index 922a24367..92c682a8c 100644 --- a/lib/mgmt.h +++ b/lib/mgmt.h @@ -1032,6 +1032,16 @@ struct mgmt_ev_adv_monitor_device_lost { struct mgmt_addr_info addr; } __packed; +#define MGMT_EV_QUALITY_REPORT 0x0031 +#define QUALITY_SPEC_NA 0x0 +#define QUALITY_SPEC_INTEL_TELEMETRY 0x1 +#define QUALITY_SPEC_AOSP_BQR 0x2 +struct mgmt_ev_quality_report { + uint8_t quality_spec; + uint32_t report_len; + uint8_t report[]; +} __packed; + static const char *mgmt_op[] = { "<0x0000>", "Read Version", @@ -1172,6 +1182,7 @@ static const char *mgmt_ev[] = { "Controller Resume", "Advertisement Monitor Device Found", /* 0x002f */ "Advertisement Monitor Device Lost", + "Bluetooth Quality Report", /* 0x0031 */ }; static const char *mgmt_status[] = { From patchwork Thu Jan 27 10:16:08 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Joseph Hwang X-Patchwork-Id: 12726530 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0FBBCC433EF for ; Thu, 27 Jan 2022 10:16:33 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238967AbiA0KQc (ORCPT ); Thu, 27 Jan 2022 05:16:32 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45732 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238979AbiA0KQb (ORCPT ); Thu, 27 Jan 2022 05:16:31 -0500 Received: from mail-pg1-x52d.google.com (mail-pg1-x52d.google.com [IPv6:2607:f8b0:4864:20::52d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 64AB9C061714 for ; Thu, 27 Jan 2022 02:16:31 -0800 (PST) Received: by mail-pg1-x52d.google.com with SMTP id p125so1894644pga.2 for ; Thu, 27 Jan 2022 02:16:31 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=Qz2qCwI+jwk3DR7g7+LzAPUcwVOyPlMvpqkYYHwwfBc=; b=VnmNMvybojAhLVpdsP8nuSIXwNohY6vdzq1hcRUObwdC9gQX2yAAZb6bfV0Lq2zJCH HtJeDtO+Ixm0307lIwjdPTd/ZfhQTsnv9cgitdE29afHflJk+opxMkYinugAYF8cOc+P Vv+GCVhdgJyDWZSTpS/ARUOFrETdHxg8l3qxE= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=Qz2qCwI+jwk3DR7g7+LzAPUcwVOyPlMvpqkYYHwwfBc=; b=yB6HmQxUJTBwYljBzj3dJ6TuTsyrn+oKJlB3TeQaB4s5cio1LQxlzMAoUJ2FmkDbHR 7YfaBpJyG93Oy/mClRV+5+G153pDCXDLCPdN6AVDV36k/5nxN+DPCR13ozYXC2HIDcYq eVYTRClXmBQZUqfuEtzRPEJGyEIZnqwxj/CQv34RuS6gXTU9UBt4/3K29MkA1KXa+2A+ SpPgr5OGOJccC2edm08aeueeMxQdlPii7zIhLb85Q+2IfsCY1b5pt6pit78F9Z8k5M3N fWvt6hS/k4ybSqts5e0Fa8j5kmsmVJFp+0P2yV4bNkmAhucjxY1O9rszCCWXUYGZvTo/ 5aug== X-Gm-Message-State: AOAM530vuCUcHZujBzkz1SPxKg1iuamuakB4BuAH4uRu+Mw36+Y3zbUH zWs/uXGEoOPkxAgJnNY9wegXQxYfZ++lLQ== X-Google-Smtp-Source: ABdhPJyfbqg5+0GHe61NuJn3VRojiti/2EjsdgbyzxURa6Y62uyw2vmU0KcYl2aSxo4MZ1D3nVcBJg== X-Received: by 2002:a62:b618:: with SMTP id j24mr2320990pff.42.1643278590540; Thu, 27 Jan 2022 02:16:30 -0800 (PST) Received: from localhost (174.71.80.34.bc.googleusercontent.com. [34.80.71.174]) by smtp.gmail.com with UTF8SMTPSA id x17sm5001246pfa.105.2022.01.27.02.16.28 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Thu, 27 Jan 2022 02:16:30 -0800 (PST) From: Joseph Hwang To: linux-bluetooth@vger.kernel.org, marcel@holtmann.org, luiz.dentz@gmail.com, pali@kernel.org Cc: chromeos-bluetooth-upstreaming@chromium.org, josephsih@google.com, Joseph Hwang , Archie Pusaka Subject: [BlueZ PATCH v2 3/4] adapter: support AOSP MGMT_EV_QUALITY_REPORT Date: Thu, 27 Jan 2022 18:16:08 +0800 Message-Id: <20220127181537.BlueZ.v2.3.Ie4d1be8ced51f0aa92ee6d8eacf9666a121a1292@changeid> X-Mailer: git-send-email 2.35.0.rc0.227.g00780c9af4-goog In-Reply-To: <20220127101609.3646316-1-josephsih@chromium.org> References: <20220127101609.3646316-1-josephsih@chromium.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org This patch supports a new MGMT event of AOSP bluetooth quality report. Reviewed-by: Archie Pusaka Signed-off-by: Joseph Hwang --- Changes in v2: - The new structs and constants are moved to separate patches: * doc: Add Bluetooth quality report event * lib: Add structures and constants for quality report - The btmon decoding patches, about 500 lines of code, are ready and will be submitted immediately after these patches are accepted. - Use util_debug instead of defining a new debug function. - Remove the event printing function. - The plan about the BQR events is to further expose them to other daemons, e.g., an audio daemon to make some smart control, or to an UI daemon to display alerts to users. Makefile.am | 3 +- lib/mgmt.h | 4 +-- src/adapter.c | 56 +++++++++++++++++++++++++++++ src/adapter.h | 2 ++ src/shared/aosp.c | 90 +++++++++++++++++++++++++++++++++++++++++++++++ src/shared/aosp.h | 58 ++++++++++++++++++++++++++++++ 6 files changed, 210 insertions(+), 3 deletions(-) create mode 100644 src/shared/aosp.c create mode 100644 src/shared/aosp.h diff --git a/Makefile.am b/Makefile.am index e391d7ae8..baab40369 100644 --- a/Makefile.am +++ b/Makefile.am @@ -230,7 +230,8 @@ shared_sources = src/shared/io.h src/shared/timeout.h \ src/shared/gatt-db.h src/shared/gatt-db.c \ src/shared/gap.h src/shared/gap.c \ src/shared/log.h src/shared/log.c \ - src/shared/tty.h + src/shared/tty.h \ + src/shared/aosp.h src/shared/aosp.c if READLINE shared_sources += src/shared/shell.c src/shared/shell.h diff --git a/lib/mgmt.h b/lib/mgmt.h index 92c682a8c..137010d9b 100644 --- a/lib/mgmt.h +++ b/lib/mgmt.h @@ -1038,8 +1038,8 @@ struct mgmt_ev_adv_monitor_device_lost { #define QUALITY_SPEC_AOSP_BQR 0x2 struct mgmt_ev_quality_report { uint8_t quality_spec; - uint32_t report_len; - uint8_t report[]; + uint32_t data_len; + uint8_t data[]; } __packed; static const char *mgmt_op[] = { diff --git a/src/adapter.c b/src/adapter.c index 9772e843a..58f8c0298 100644 --- a/src/adapter.c +++ b/src/adapter.c @@ -47,6 +47,7 @@ #include "src/shared/att.h" #include "src/shared/gatt-db.h" #include "src/shared/timeout.h" +#include "src/shared/aosp.h" #include "btio/btio.h" #include "btd.h" @@ -9312,6 +9313,28 @@ static void controller_resume_callback(uint16_t index, uint16_t length, controller_resume_notify(adapter); } +static void quality_report_callback(uint16_t index, uint16_t length, + const void *param, void *user_data) +{ + const struct mgmt_ev_quality_report *ev = param; + + if (!ev) + return; + + if (length < sizeof(*ev)) { + error("MGMT_EV_QUALITY_REPORT event too small"); + return; + } + + if (ev->quality_spec == QUALITY_SPEC_AOSP_BQR) { + if (!process_aosp_quality_report(ev)) + error("processing aosp quality report"); + } else { + error("quality report spec %u not supported.", + ev->quality_spec); + } +} + static void device_blocked_callback(uint16_t index, uint16_t length, const void *param, void *user_data) { @@ -9727,6 +9750,19 @@ static void le_simult_central_peripheral_func(struct btd_adapter *adapter, (void *)le_simult_central_peripheral_uuid.val); } +static bool is_exp_feature_uuid_the_same(const void *data, + const void *match_data) +{ + return memcmp(data, match_data, + sizeof(((struct mgmt_exp_uuid *)NULL)->val)) == 0; +} + +bool is_quality_report_supported(struct btd_adapter *adapter) +{ + return queue_find(adapter->exps, is_exp_feature_uuid_the_same, + (void *)quality_report_uuid.val) != NULL; +} + static void quality_report_func(struct btd_adapter *adapter, uint8_t action) { if (action) @@ -9882,6 +9918,18 @@ static void read_exp_features(struct btd_adapter *adapter) btd_error(adapter->dev_id, "Failed to read exp features info"); } +static void quality_report_debug(const char *str, void *user_data) +{ + const char *prefix = user_data; + + info("%s%s", prefix, str); +} + +static void quality_set_debug(struct btd_adapter *adapter) +{ + aosp_set_debug(quality_report_debug, "quality: "); +} + static void read_info_complete(uint8_t status, uint16_t length, const void *param, void *user_data) { @@ -10110,6 +10158,11 @@ static void read_info_complete(uint8_t status, uint16_t length, controller_resume_callback, adapter, NULL); + mgmt_register(adapter->mgmt, MGMT_EV_QUALITY_REPORT, + adapter->dev_id, + quality_report_callback, + adapter, NULL); + set_dev_class(adapter); set_name(adapter, btd_adapter_get_name(adapter)); @@ -10137,6 +10190,9 @@ static void read_info_complete(uint8_t status, uint16_t length, if (btd_adapter_get_powered(adapter)) adapter_start(adapter); + if (is_quality_report_supported(adapter) && getenv("QUALITY_DEBUG")) + quality_set_debug(adapter); + return; failed: diff --git a/src/adapter.h b/src/adapter.h index 35deb1d11..c199e358a 100644 --- a/src/adapter.h +++ b/src/adapter.h @@ -266,6 +266,8 @@ enum kernel_features { bool btd_has_kernel_features(uint32_t feature); +bool is_quality_report_supported(struct btd_adapter *adapter); + bool btd_adapter_set_allowed_uuids(struct btd_adapter *adapter, struct queue *uuids); bool btd_adapter_is_uuid_allowed(struct btd_adapter *adapter, diff --git a/src/shared/aosp.c b/src/shared/aosp.c new file mode 100644 index 000000000..838babea4 --- /dev/null +++ b/src/shared/aosp.c @@ -0,0 +1,90 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2021 Google LLC + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 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 + * Lesser General Public License for more details. + * + */ + +#include +#include +#include +#include + +#include "lib/bluetooth.h" +#include "lib/mgmt.h" + +#include "src/shared/aosp.h" +#include "src/shared/util.h" + +static struct { + aosp_debug_func_t callback; + void *data; +} aosp_debug; + +void aosp_set_debug(aosp_debug_func_t callback, void *user_data) +{ + aosp_debug.callback = callback; + aosp_debug.data = user_data; +} + +bool process_aosp_quality_report(const struct mgmt_ev_quality_report *ev) +{ + const struct aosp_bqr *edata = (struct aosp_bqr *)ev->data; + struct aosp_bqr bqr; + + if (edata->subevent_code != 0x58) { + util_debug(aosp_debug.callback, aosp_debug.data, + "error: %u not AOSP Bluetooth quality report subevent", + edata->subevent_code); + return false; + } + + if (ev->data_len < sizeof(struct aosp_bqr)) { + util_debug(aosp_debug.callback, aosp_debug.data, + "error: AOSP report size %u too small (expect >= %lu).", + ev->data_len, sizeof(struct aosp_bqr)); + return false; + } + + /* Ignore the Vendor Specific Parameter (VSP) field for now + * due to the lack of standard way of reading it. + */ + bqr.quality_report_id = edata->quality_report_id; + bqr.packet_type = edata->packet_type; + bqr.conn_handle = btohs(edata->conn_handle); + bqr.conn_role = edata->conn_role; + bqr.tx_power_level = edata->tx_power_level; + bqr.rssi = edata->rssi; + bqr.snr = edata->snr; + bqr.unused_afh_channel_count = edata->unused_afh_channel_count; + bqr.afh_select_unideal_channel_count = + edata->afh_select_unideal_channel_count; + bqr.lsto = btohs(edata->lsto); + bqr.conn_piconet_clock = btohl(edata->conn_piconet_clock); + bqr.retransmission_count = btohl(edata->retransmission_count); + bqr.no_rx_count = btohl(edata->no_rx_count); + bqr.nak_count = btohl(edata->nak_count); + bqr.last_tx_ack_timestamp = btohl(edata->last_tx_ack_timestamp); + bqr.flow_off_count = btohl(edata->flow_off_count); + bqr.last_flow_on_timestamp = btohl(edata->last_flow_on_timestamp); + bqr.buffer_overflow_bytes = btohl(edata->buffer_overflow_bytes); + bqr.buffer_underflow_bytes = btohl(edata->buffer_underflow_bytes); + + util_debug(aosp_debug.callback, aosp_debug.data, + "AOSP report of connection hanle %u received", bqr.conn_handle); + + return true; +} diff --git a/src/shared/aosp.h b/src/shared/aosp.h new file mode 100644 index 000000000..b58aa5e3a --- /dev/null +++ b/src/shared/aosp.h @@ -0,0 +1,58 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2021 Google LLC + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 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 + * Lesser General Public License for more details. + * + */ + +#ifndef __AOSP_H +#define __AOSP_H + +#include + +struct mgmt_ev_quality_report; + +struct aosp_bqr { + uint8_t subevent_code; + uint8_t quality_report_id; + uint8_t packet_type; + uint16_t conn_handle; + uint8_t conn_role; + int8_t tx_power_level; /* -30 to 20 dbm */ + int8_t rssi; /* -127 to 20 dbm */ + uint8_t snr; /* db */ + uint8_t unused_afh_channel_count; + uint8_t afh_select_unideal_channel_count; + uint16_t lsto; + uint32_t conn_piconet_clock; + uint32_t retransmission_count; + uint32_t no_rx_count; + uint32_t nak_count; + uint32_t last_tx_ack_timestamp; + uint32_t flow_off_count; + uint32_t last_flow_on_timestamp; + uint32_t buffer_overflow_bytes; + uint32_t buffer_underflow_bytes; + + uint8_t vsp[0]; /* Vendor Specific Parameter */ +} __packed; + +typedef void (*aosp_debug_func_t)(const char *str, void *user_data); +void aosp_set_debug(aosp_debug_func_t callback, void *user_data); + +bool process_aosp_quality_report(const struct mgmt_ev_quality_report *ev); + +#endif /* __AOSP_H */ From patchwork Thu Jan 27 10:16:09 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Joseph Hwang X-Patchwork-Id: 12726531 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id C386EC433EF for ; Thu, 27 Jan 2022 10:16:35 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238970AbiA0KQf (ORCPT ); Thu, 27 Jan 2022 05:16:35 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45748 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238979AbiA0KQe (ORCPT ); Thu, 27 Jan 2022 05:16:34 -0500 Received: from mail-pf1-x431.google.com (mail-pf1-x431.google.com [IPv6:2607:f8b0:4864:20::431]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5A836C061714 for ; Thu, 27 Jan 2022 02:16:34 -0800 (PST) Received: by mail-pf1-x431.google.com with SMTP id i30so2205961pfk.8 for ; Thu, 27 Jan 2022 02:16:34 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=aZtrLA6y3xBxE7AuHU+cZRGCsPa0d+YxEsLpiRLe268=; b=NMQk5uDPRliKr9nUJBL4DnKOhLAVZTWLHPCsLWLELtVJ4G3wiWKHoneloXHPSkKRzo Mn9MJnhFc2+qrg7tiTDSXoFFgDC/gBBSj+EzfT9PJOVvgIBqXmRZH/1kq+V7qQRD+yYT ATLRJa5NJ6LvgF0RcSgeb2L7qG/7BigjI825Y= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=aZtrLA6y3xBxE7AuHU+cZRGCsPa0d+YxEsLpiRLe268=; b=vATWuRdWyHjTgA388YIorw35sJ1J0OTap8GXylpO/A5jVI9Kcf7EHSXs9pbEwPEE7t VXG5WZjoIZl7bnH990+czNDYC/3NOZaX6+TkBsvUIEHkUe37Q/BkbbxUs3C5HN3LuYht lJYeM5jCWll+b3TvAtAbAAUS8AiTn+xArPHW2lQL3tqe49ZxBVEgevPUSynovUpWDyns WfhG9SgU13bnIfakV1dVVhQHfR7AfgiXI1vYI+dEpezsZmRMGpIXlmbvvj4Pf1E4A8hl CvrhvAR9FHWyu8Gju5vcXA223NQ1pg+gIJJXKX7dgp4fnmOq4P6IoRFBkKHNId8pahAN d/dw== X-Gm-Message-State: AOAM531yzATypKqJk1w5dcbdi0QJfnY/lvbG09ATgif6+kNsO8MZ0+EI cJx85SL92UQSG8Skbyccms0Q9n4Ffz40qw== X-Google-Smtp-Source: ABdhPJyW+UfoXc3s5NK4wsPzTjZJK0CstQH85jPeK50OBtQ6I/M2J4FFNVcvIckA7fXXfAA6KxLQhQ== X-Received: by 2002:a62:bd0e:: with SMTP id a14mr2320264pff.32.1643278593402; Thu, 27 Jan 2022 02:16:33 -0800 (PST) Received: from localhost (174.71.80.34.bc.googleusercontent.com. [34.80.71.174]) by smtp.gmail.com with UTF8SMTPSA id mn2sm2130248pjb.38.2022.01.27.02.16.31 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Thu, 27 Jan 2022 02:16:33 -0800 (PST) From: Joseph Hwang To: linux-bluetooth@vger.kernel.org, marcel@holtmann.org, luiz.dentz@gmail.com, pali@kernel.org Cc: chromeos-bluetooth-upstreaming@chromium.org, josephsih@google.com, Joseph Hwang , Archie Pusaka Subject: [BlueZ PATCH v2 4/4] adapter: support Intel MGMT_EV_QUALITY_REPORT Date: Thu, 27 Jan 2022 18:16:09 +0800 Message-Id: <20220127181537.BlueZ.v2.4.Ifdf5cf89a14b4f293d868910c6cb85e802f7eb9e@changeid> X-Mailer: git-send-email 2.35.0.rc0.227.g00780c9af4-goog In-Reply-To: <20220127101609.3646316-1-josephsih@chromium.org> References: <20220127101609.3646316-1-josephsih@chromium.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org This patch supports a new MGMT event of Intel telemetry report. Reviewed-by: Archie Pusaka Signed-off-by: Joseph Hwang --- Changes in v2: - Remove the event printing function. The btmon decoding patches are ready and will be submitted after these are accepted. Makefile.am | 3 +- src/adapter.c | 9 +- src/shared/intel.c | 243 +++++++++++++++++++++++++++++++++++++++++++++ src/shared/intel.h | 155 +++++++++++++++++++++++++++++ 4 files changed, 408 insertions(+), 2 deletions(-) create mode 100644 src/shared/intel.c create mode 100644 src/shared/intel.h diff --git a/Makefile.am b/Makefile.am index baab40369..abbe3897b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -231,7 +231,8 @@ shared_sources = src/shared/io.h src/shared/timeout.h \ src/shared/gap.h src/shared/gap.c \ src/shared/log.h src/shared/log.c \ src/shared/tty.h \ - src/shared/aosp.h src/shared/aosp.c + src/shared/aosp.h src/shared/aosp.c \ + src/shared/intel.h src/shared/intel.c if READLINE shared_sources += src/shared/shell.c src/shared/shell.h diff --git a/src/adapter.c b/src/adapter.c index 58f8c0298..9816235ec 100644 --- a/src/adapter.c +++ b/src/adapter.c @@ -48,6 +48,7 @@ #include "src/shared/gatt-db.h" #include "src/shared/timeout.h" #include "src/shared/aosp.h" +#include "src/shared/intel.h" #include "btio/btio.h" #include "btd.h" @@ -9329,6 +9330,9 @@ static void quality_report_callback(uint16_t index, uint16_t length, if (ev->quality_spec == QUALITY_SPEC_AOSP_BQR) { if (!process_aosp_quality_report(ev)) error("processing aosp quality report"); + } else if (ev->quality_spec == QUALITY_SPEC_INTEL_TELEMETRY) { + if (!process_intel_telemetry_report(ev)) + error("processing intel telemetry report"); } else { error("quality report spec %u not supported.", ev->quality_spec); @@ -9927,7 +9931,10 @@ static void quality_report_debug(const char *str, void *user_data) static void quality_set_debug(struct btd_adapter *adapter) { - aosp_set_debug(quality_report_debug, "quality: "); + if (is_manufacturer_intel(adapter->manufacturer)) + intel_set_debug(quality_report_debug, "quality: "); + else + aosp_set_debug(quality_report_debug, "quality: "); } static void read_info_complete(uint8_t status, uint16_t length, diff --git a/src/shared/intel.c b/src/shared/intel.c new file mode 100644 index 000000000..5d7c0d0ad --- /dev/null +++ b/src/shared/intel.c @@ -0,0 +1,243 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2021 Google LLC + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 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 + * Lesser General Public License for more details. + * + */ + +#include +#include +#include +#include + +#include "lib/bluetooth.h" +#include "lib/mgmt.h" + +#include "src/shared/intel.h" +#include "src/shared/util.h" + +#define COMPANY_ID_INTEL 0x0002 + +struct intel_ext_telemetry_event tev; + +static struct { + intel_debug_func_t callback; + void *data; +} intel_debug; + +/* Use offsetof to access the attributes of structures. This makes + * simple traversing and assigning values to the attributes. + */ +#define TELEM_OFFSET(a) offsetof(struct intel_ext_telemetry_event, a) +#define TELEM_ATTR(a) (((uint8_t *)&tev) + TELEM_OFFSET(a)) + +#define ACL_OFFSET(a) offsetof(struct intel_acl_event, a) +#define ACL_ATTR(a) (((uint8_t *)&tev.conn.acl) + ACL_OFFSET(a)) +#define ACL_ATTR_ARRAY(a, i) (ACL_ATTR(a) + i * sizeof(tev.conn.acl.a[0])) + +#define SCO_OFFSET(a) offsetof(struct intel_sco_event, a) +#define SCO_ATTR(a) (((uint8_t *)&tev.conn.sco) + SCO_OFFSET(a)) + +static const struct intel_ext_subevent { + uint8_t id; + uint8_t size; + uint8_t elements; + uint8_t *attr; /* address of the attribute in tev */ +} intel_ext_subevent_table[] = { + { 0x01, 1, 1, TELEM_ATTR(telemetry_ev_type) }, + + /* ACL audio link quality subevents */ + { 0x4a, 2, 1, ACL_ATTR(conn_handle) }, + { 0x4b, 4, 1, ACL_ATTR(rx_hec_error) }, + { 0x4c, 4, 1, ACL_ATTR(rx_crc_error) }, + { 0x4d, 4, 1, ACL_ATTR(packets_from_host) }, + { 0x4e, 4, 1, ACL_ATTR(tx_packets) }, + { 0x4f, 4, 1, ACL_ATTR_ARRAY(tx_packets_retry, 0) }, + { 0x50, 4, 1, ACL_ATTR_ARRAY(tx_packets_retry, 1) }, + { 0x51, 4, 1, ACL_ATTR_ARRAY(tx_packets_retry, 2) }, + { 0x52, 4, 1, ACL_ATTR_ARRAY(tx_packets_retry, 3) }, + { 0x53, 4, 1, ACL_ATTR_ARRAY(tx_packets_retry, 4) }, + { 0x54, 4, 1, ACL_ATTR_ARRAY(tx_packets_by_type, 0) }, + { 0x55, 4, 1, ACL_ATTR_ARRAY(tx_packets_by_type, 1) }, + { 0x56, 4, 1, ACL_ATTR_ARRAY(tx_packets_by_type, 2) }, + { 0x57, 4, 1, ACL_ATTR_ARRAY(tx_packets_by_type, 3) }, + { 0x58, 4, 1, ACL_ATTR_ARRAY(tx_packets_by_type, 4) }, + { 0x59, 4, 1, ACL_ATTR_ARRAY(tx_packets_by_type, 5) }, + { 0x5a, 4, 1, ACL_ATTR_ARRAY(tx_packets_by_type, 6) }, + { 0x5b, 4, 1, ACL_ATTR_ARRAY(tx_packets_by_type, 7) }, + { 0x5c, 4, 1, ACL_ATTR_ARRAY(tx_packets_by_type, 8) }, + { 0x5d, 4, 1, ACL_ATTR(rx_packets) }, + { 0x5e, 4, 1, ACL_ATTR(link_throughput) }, + { 0x5f, 4, 1, ACL_ATTR(max_packet_letency) }, + { 0x60, 4, 1, ACL_ATTR(avg_packet_letency) }, + + /* SCO/eSCO audio link quality subevents */ + { 0x6a, 2, 1, SCO_ATTR(conn_handle) }, + { 0x6b, 4, 1, SCO_ATTR(packets_from_host) }, + { 0x6c, 4, 1, SCO_ATTR(tx_packets) }, + { 0x6d, 4, 1, SCO_ATTR(rx_payload_lost) }, + { 0x6e, 4, 1, SCO_ATTR(tx_payload_lost) }, + { 0x6f, 4, 5, SCO_ATTR(rx_no_sync_error) }, + { 0x70, 4, 5, SCO_ATTR(rx_hec_error) }, + { 0x71, 4, 5, SCO_ATTR(rx_crc_error) }, + { 0x72, 4, 5, SCO_ATTR(rx_nak_error) }, + { 0x73, 4, 5, SCO_ATTR(tx_failed_wifi_coex) }, + { 0x74, 4, 5, SCO_ATTR(rx_failed_wifi_coex) }, + { 0x75, 4, 1, SCO_ATTR(samples_inserted_by_CDC) }, + { 0x76, 4, 1, SCO_ATTR(samples_dropped) }, + { 0x77, 4, 1, SCO_ATTR(mute_samples) }, + { 0x78, 4, 1, SCO_ATTR(plc_injection) }, + + /* end */ + { 0x0, 0, 0 } +}; + +bool is_manufacturer_intel(uint16_t manufacturer) +{ + return manufacturer == COMPANY_ID_INTEL; +} + +void intel_set_debug(intel_debug_func_t callback, void *user_data) +{ + intel_debug.callback = callback; + intel_debug.data = user_data; +} + +static const struct intel_tlv *process_ext_subevent( + struct intel_ext_telemetry_event *tev, + const struct intel_tlv *tlv, + const struct intel_tlv *last_tlv) +{ + const struct intel_tlv *next_tlv = NEXT_TLV(tlv); + const struct intel_ext_subevent *subevent = NULL; + int i; + + for (i = 0; intel_ext_subevent_table[i].size > 0; i++) { + if (intel_ext_subevent_table[i].id == tlv->id) { + subevent = &intel_ext_subevent_table[i]; + break; + } + } + + if (!subevent) { + util_debug(intel_debug.callback, intel_debug.data, + "error: unknown Intel telemetry subevent 0x%2.2x", + tlv->id); + return NULL; + } + + if (tlv->length != subevent->size * subevent->elements) { + util_debug(intel_debug.callback, intel_debug.data, + "error: invalid length %d of subevent 0x%2.2x", + tlv->length, tlv->id); + return NULL; + } + + if (next_tlv > last_tlv) { + util_debug(intel_debug.callback, intel_debug.data, + "error: subevent 0x%2.2x exceeds the buffer size.", + tlv->id); + return NULL; + } + + /* Assign tlv value to the corresponding attribute of acl/sco struct. */ + switch (subevent->size) { + case 1: + *subevent->attr = get_u8(tlv->value); + break; + + case 2: + *((uint16_t *)subevent->attr) = get_le16(tlv->value); + break; + + case 4: + if (subevent->elements == 1) { + *((uint32_t *)subevent->attr) = get_le32(tlv->value); + break; + } + + for (i = 0; i < subevent->elements; i++) { + /* Both acl and sco structs are __packed such that + * the addresses of array elements can be calculated. + */ + *((uint32_t *)(subevent->attr + i * subevent->size)) = + get_le32((uint32_t *)tlv->value + i); + } + break; + + default: + util_debug(intel_debug.callback, intel_debug.data, + "error: subevent id %u: size %u not supported", + subevent->id, subevent->size); + break; + + } + + switch (subevent->id) { + case EXT_EVT_TYPE: + /* Only interested in the LINK_QUALITY_REPORT type for now. */ + if (*subevent->attr != LINK_QUALITY_REPORT) + return NULL; + break; + + case ACL_CONNECTION_HANDLE: + tev->link_type = TELEMETRY_ACL_LINK; + break; + + case SCO_CONNECTION_HANDLE: + tev->link_type = TELEMETRY_SCO_LINK; + break; + + default: + break; + } + + return next_tlv; +} + +struct intel_telemetry_data { + uint16_t vendor_prefix; + uint8_t code; + uint8_t data[]; /* a number of struct intel_tlv subevents */ +} __packed; + +bool process_intel_telemetry_report(const struct mgmt_ev_quality_report *ev) +{ + struct intel_telemetry_data *telemetry = + (struct intel_telemetry_data *)ev->data; + + /* The telemetry->data points to a number of consecutive tlv.*/ + const struct intel_tlv *tlv = (const struct intel_tlv *)telemetry->data; + const struct intel_tlv *last_tlv = + (const struct intel_tlv *)(ev->data + ev->data_len); + + if (telemetry->code != 0x03) { + util_debug(intel_debug.callback, intel_debug.data, + "error: %u not Intel telemetry sub-opcode", + telemetry->code); + return false; + } + + /* Read every tlv subevent into tev. + * The decoding process terminates normally when tlv == last_tlv. + */ + memset(&tev, 0, sizeof(tev)); + while (tlv && tlv < last_tlv) + tlv = process_ext_subevent(&tev, tlv, last_tlv); + + /* If the decoding completes successfully, tlv would be non-NULL */ + return !!tlv; +} diff --git a/src/shared/intel.h b/src/shared/intel.h new file mode 100644 index 000000000..2b20f803e --- /dev/null +++ b/src/shared/intel.h @@ -0,0 +1,155 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2021 Google LLC + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 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 + * Lesser General Public License for more details. + * + */ + +#ifndef __INTEL_H +#define __INTEL_H + +#include + +struct mgmt_ev_quality_report; + +enum intel_telemetry_event_type { + SYSTEM_EXCEPTION, + FATAL_EXCEPTION, + DEBUG_EXCEPTION, + CONNECTION_EVENT, + DISCONNECTION_EVENT, + LINK_QUALITY_REPORT, +}; + +enum intel_telemetry_link_type { + TELEMETRY_UNKNOWN_LINK, + TELEMETRY_ACL_LINK, + TELEMETRY_SCO_LINK, +}; + +/* The subevent indices of the complete list of Intel telemetry subevents. */ +enum intel_subevt_list { + EXT_EVT_TYPE = 0x01, + + ACL_CONNECTION_HANDLE = 0x4a, + ACL_HEC_ERRORS, + ACL_CRC_ERRORS, + ACL_PACKETS_FROM_HOST, + ACL_TX_PACKETS_TO_AIR, + ACL_TX_PACKETS_0_RETRY, + ACL_TX_PACKETS_1_RETRY, + ACL_TX_PACKETS_2_RETRY, + ACL_TX_PACKETS_3_RETRY, + ACL_TX_PACKETS_MORE_RETRY, + ACL_TX_PACKETS_DH1, + ACL_TX_PACKETS_DH3, + ACL_TX_PACKETS_DH5, + ACL_TX_PACKETS_2DH1, + ACL_TX_PACKETS_2DH3, + ACL_TX_PACKETS_2DH5, + ACL_TX_PACKETS_3DH1, + ACL_TX_PACKETS_3DH3, + ACL_TX_PACKETS_3DH5, + ACL_RX_PACKETS, + ACL_LINK_THROUGHPUT, + ACL_MAX_PACKET_LATENCY, + ACL_AVG_PACKET_LATENCY, + + SCO_CONNECTION_HANDLE = 0x6a, + SCO_RX_PACKETS, + SCO_TX_PACKETS, + SCO_RX_PACKETS_LOST, + SCO_TX_PACKETS_LOST, + SCO_RX_NO_SYNC_ERROR, + SCO_RX_HEC_ERROR, + SCO_RX_CRC_ERROR, + SCO_RX_NAK_ERROR, + SCO_TX_FAILED_BY_WIFI, + SCO_RX_FAILED_BY_WIFI, + SCO_SAMPLES_INSERTED, + SCO_SAMPLES_DROPPED, + SCO_MUTE_SAMPLES, + SCO_PLC_INJECTION_DATA, +}; + +#define INTEL_NUM_SLOTS 5 +#define INTEL_NUM_RETRIES 5 +#define INTEL_NUM_PACKET_TYPES 9 + +/* An Intel telemetry subevent is of the TLV format. + * - id: takes 1 byte. This is the subevent id. + * - length: takes 1 byte. + * - value: takes |length| bytes. + */ +struct intel_tlv { + uint8_t id; + uint8_t length; + uint8_t value[0]; +}; + +#define TLV_SIZE(tlv) (*((const uint8_t *) tlv + 1) + 2 * sizeof(uint8_t)) +#define NEXT_TLV(tlv) ((const struct intel_tlv *)\ + ((const uint8_t *)tlv + TLV_SIZE(tlv))) + +struct intel_acl_event { + uint16_t conn_handle; + uint32_t rx_hec_error; + uint32_t rx_crc_error; + uint32_t packets_from_host; + uint32_t tx_packets; + uint32_t tx_packets_retry[INTEL_NUM_RETRIES]; + uint32_t tx_packets_by_type[INTEL_NUM_PACKET_TYPES]; + uint32_t rx_packets; + uint32_t link_throughput; + uint32_t max_packet_letency; + uint32_t avg_packet_letency; +} __packed; + +struct intel_sco_event { + uint16_t conn_handle; + uint32_t packets_from_host; + uint32_t tx_packets; + uint32_t rx_payload_lost; + uint32_t tx_payload_lost; + uint32_t rx_no_sync_error[INTEL_NUM_SLOTS]; + uint32_t rx_hec_error[INTEL_NUM_SLOTS]; + uint32_t rx_crc_error[INTEL_NUM_SLOTS]; + uint32_t rx_nak_error[INTEL_NUM_SLOTS]; + uint32_t tx_failed_wifi_coex[INTEL_NUM_SLOTS]; + uint32_t rx_failed_wifi_coex[INTEL_NUM_SLOTS]; + uint32_t samples_inserted_by_CDC; + uint32_t samples_dropped; + uint32_t mute_samples; + uint32_t plc_injection; +} __packed; + +struct intel_ext_telemetry_event { + uint8_t telemetry_ev_type; /* one in enum intel_telemetry_event_type */ + uint8_t link_type; + union { + struct intel_sco_event sco; + struct intel_acl_event acl; + } conn; +} __packed; + +typedef void (*intel_debug_func_t)(const char *str, void *user_data); + +bool is_manufacturer_intel(uint16_t manufacturer); +void intel_set_debug(intel_debug_func_t callback, void *user_data); + +bool process_intel_telemetry_report(const struct mgmt_ev_quality_report *ev); + +#endif /* __INTEL_H */