Re: [BlueZ PATCH v1 2/2] adapter: support Intel MGMT_EV_QUALITY_REPORT

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Joseph,

On Fri, Jan 21, 2022 at 3:24 AM Joseph Hwang <josephsih@xxxxxxxxxxxx> wrote:
>
> This patch supports a new MGMT event of Intel telemetry report.
>
> An ACL telemetry report looks like:
>
> quality: Intel Extended Telemetry Event
> quality:   ACL connection handle: 0x0100
> quality:   Rx HEC errors: 0
> quality:   Rx CRC errors: 0
> quality:   Packets from host: 424
> quality:   Tx packets: 425
> quality:   Tx packets 0 retries: 391
> quality:   Tx packets 1 retries: 33
> quality:   Tx packets 2 retries: 1
> quality:   Tx packets 3 retries: 0
> quality:   Tx packets 4 retries: 0
> quality:   Tx DH1 packets: 0
> quality:   Tx DH3 packets: 0
> quality:   Tx DH5 packets: 0
> quality:   Tx 2DH1 packets: 0
> quality:   Tx 2DH3 packets: 0
> quality:   Tx 2DH5 packets: 0
> quality:   Tx 3DH1 packets: 9
> quality:   Tx 3DH3 packets: 0
> quality:   Tx 3DH5 packets: 415
> quality:   Rx packets: 1568
> quality:   ACL link throughput: 34071
> quality:   ACL max packet latency: 44375
> quality:   ACL avg packet latency: 13
>
> A SCO telemetry report looks like:
>
> quality: Intel Extended Telemetry Event
> quality:   SCO connection handle: 0x010a
> quality:   Packets from host: 667
> quality:   Tx packets: 667
> quality:   Rx payload lost: 5
> quality:   Tx payload lost: 36
> quality:   Rx No SYNC errors (slot 0): 11
> quality:   Rx No SYNC errors (slot 1): 32
> quality:   Rx No SYNC errors (slot 2): 33
> quality:   Rx No SYNC errors (slot 3): 13
> quality:   Rx No SYNC errors (slot 4): 0
> quality:   Rx HEC errors (slot 0): 9
> quality:   Rx HEC errors (slot 1): 4
> quality:   Rx HEC errors (slot 2): 0
> quality:   Rx HEC errors (slot 3): 0
> quality:   Rx HEC errors (slot 4): 0
> quality:   Rx CRC errors (slot 0): 9
> quality:   Rx CRC errors (slot 1): 2
> quality:   Rx CRC errors (slot 2): 0
> quality:   Rx CRC errors (slot 3): 0
> quality:   Rx CRC errors (slot 4): 0
> quality:   Rx NAK errors (slot 0): 647
> quality:   Rx NAK errors (slot 1): 14
> quality:   Rx NAK errors (slot 2): 2
> quality:   Rx NAK errors (slot 3): 0
> quality:   Rx NAK errors (slot 4): 0
> quality:   Failed Tx due to Wifi coex (slot 0): 0
> quality:   Failed Tx due to Wifi coex (slot 1): 0
> quality:   Failed Tx due to Wifi coex (slot 2): 0
> quality:   Failed Tx due to Wifi coex (slot 3): 0
> quality:   Failed Tx due to Wifi coex (slot 4): 0
> quality:   Failed Rx due to Wifi coex (slot 0): 0
> quality:   Failed Rx due to Wifi coex (slot 1): 0
> quality:   Failed Rx due to Wifi coex (slot 2): 0
> quality:   Failed Rx due to Wifi coex (slot 3): 0
> quality:   Failed Rx due to Wifi coex (slot 4): 0
> quality:   Late samples inserted based on CDC: 0
> quality:   Samples dropped: 0
> quality:   Mute samples sent at initial connection: 0
> quality:   PLC injection data: 0
>
> Reviewed-by: Archie Pusaka <apusaka@xxxxxxxxxxxx>
> Signed-off-by: Joseph Hwang <josephsih@xxxxxxxxxxxx>
> ---
>
>  Makefile.am        |   3 +-
>  src/adapter.c      |   9 +-
>  src/shared/intel.c | 327 +++++++++++++++++++++++++++++++++++++++++++++
>  src/shared/intel.h | 155 +++++++++++++++++++++
>  4 files changed, 492 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 03f0e1ca6..6f3bf495d 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"
> @@ -9331,6 +9332,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);
> @@ -9929,7 +9933,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..87cc300dc
> --- /dev/null
> +++ b/src/shared/intel.c
> @@ -0,0 +1,327 @@
> +// 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 <stddef.h>
> +#include <stdio.h>
> +#include <stdint.h>
> +#include <string.h>
> +
> +#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;
> +
> +static char *bredr_packet_type[INTEL_NUM_PACKET_TYPES] = {
> +       "DH1",
> +       "DH3",
> +       "DH5",
> +       "2DH1",
> +       "2DH3",
> +       "2DH5",
> +       "3DH1",
> +       "3DH3",
> +       "3DH5",
> +};
> +
> +/* 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 void debug(const char *format, ...)
> +{
> +       va_list ap;
> +       char str[256];
> +
> +       if (!intel_debug.callback || !intel_debug.data)
> +               return;
> +
> +       va_start(ap, format);
> +       vsnprintf(str, sizeof(str), format, ap);
> +       intel_debug.callback(str, intel_debug.data);
> +       va_end(ap);
> +}
> +
> +static void print_intel_telemetry_evt(struct intel_ext_telemetry_event *tev)
> +{
> +       if (!tev)
> +               return;
> +
> +       if (tev->link_type == TELEMETRY_ACL_LINK) {
> +               struct intel_acl_event *acl = &tev->conn.acl;
> +               int i;
> +
> +               debug("Intel Extended Telemetry Event");
> +               debug("  ACL connection handle: 0x%4.4x", acl->conn_handle);
> +               debug("  Rx HEC errors: %u", acl->rx_hec_error);
> +               debug("  Rx CRC errors: %u", acl->rx_crc_error);
> +               debug("  Packets from host: %u", acl->packets_from_host);
> +               debug("  Tx packets: %u", acl->tx_packets);
> +
> +               for (i = 0; i < INTEL_NUM_RETRIES; i++)
> +                       debug("  Tx packets %u retries: %u",
> +                                               i, acl->tx_packets_retry[i]);
> +
> +               for (i = 0; i < INTEL_NUM_PACKET_TYPES; i++)
> +                       debug("  Tx %s packets: %u", bredr_packet_type[i],
> +                                               acl->tx_packets_by_type[i]);
> +
> +               debug("  Rx packets: %u", acl->rx_packets);
> +               debug("  ACL link throughput: %u", acl->link_throughput);
> +               debug("  ACL max packet latency: %u", acl->max_packet_letency);
> +               debug("  ACL avg packet latency: %u", acl->avg_packet_letency);
> +
> +       } else if (tev->link_type == TELEMETRY_SCO_LINK) {
> +               struct intel_sco_event *sco = &tev->conn.sco;
> +               int i;
> +
> +               debug("Intel Extended Telemetry Event");
> +               debug("  SCO connection handle: 0x%4.4x", sco->conn_handle);
> +               debug("  Packets from host: %u", sco->packets_from_host);
> +               debug("  Tx packets: %u", sco->tx_packets);
> +               debug("  Rx payload lost: %u", sco->rx_payload_lost);
> +               debug("  Tx payload lost: %u", sco->tx_payload_lost);
> +
> +               for (i = 0; i < INTEL_NUM_SLOTS; i++)
> +                       debug("  Rx No SYNC errors (slot %u): %u",
> +                                               i, sco->rx_no_sync_error[i]);
> +
> +               for (i = 0; i < INTEL_NUM_SLOTS; i++)
> +                       debug("  Rx HEC errors (slot %u): %u",
> +                                               i, sco->rx_hec_error[i]);
> +
> +               for (i = 0; i < INTEL_NUM_SLOTS; i++)
> +                       debug("  Rx CRC errors (slot %u): %u",
> +                                               i, sco->rx_crc_error[i]);
> +
> +               for (i = 0; i < INTEL_NUM_SLOTS; i++)
> +                       debug("  Rx NAK errors (slot %u): %u",
> +                                               i, sco->rx_nak_error[i]);
> +
> +               for (i = 0; i < INTEL_NUM_SLOTS; i++)
> +                       debug("  Failed Tx due to Wifi coex (slot %u): %u",
> +                                               i, sco->tx_failed_wifi_coex[i]);
> +
> +               for (i = 0; i < INTEL_NUM_SLOTS; i++)
> +                       debug("  Failed Rx due to Wifi coex (slot %u): %u",
> +                                               i, sco->rx_failed_wifi_coex[i]);
> +
> +               debug("  Late samples inserted based on CDC: %u",
> +                                               sco->samples_inserted_by_CDC);
> +               debug("  Samples dropped: %u", sco->samples_dropped);
> +               debug("  Mute samples sent at initial connection: %u",
> +                                               sco->mute_samples);
> +               debug("  PLC injection data: %u", sco->plc_injection);
> +       }
> +}
> +
> +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) {
> +               debug("error: unknown Intel telemetry subevent 0x%2.2x",
> +                       tlv->id);
> +               return NULL;
> +       }
> +
> +       if (tlv->length != subevent->size * subevent->elements) {
> +               debug("error: invalid length %d of subevent 0x%2.2x",
> +                       tlv->length, tlv->id);
> +               return NULL;
> +       }
> +
> +       if (next_tlv > last_tlv) {
> +               debug("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:
> +               debug("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;
> +}
> +
> +bool process_intel_telemetry_report(const struct mgmt_ev_quality_report *ev)
> +{
> +       /* The ev->report points to a number of consecutive tlv.*/
> +       const struct intel_tlv *tlv = (const struct intel_tlv *)ev->report;
> +       const struct intel_tlv *last_tlv =
> +                       (const struct intel_tlv *)(ev->report + ev->report_len);
> +
> +       /* 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 */
> +       if (tlv) {
> +               print_intel_telemetry_evt(&tev);
> +               return true;
> +       }
> +
> +       return false;
> +}
> 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 <stdbool.h>
> +
> +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);
>

Same thing here, not sure where you got this idea that it would be
nice to print the telemetry as bluetoothd output rather than on btmon
like everything else.

> +#endif /* __INTEL_H */
> --
> 2.35.0.rc0.227.g00780c9af4-goog
>


-- 
Luiz Augusto von Dentz



[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux