1 // SPDX-License-Identifier: LGPL-2.1-or-later
4 * BlueZ - Bluetooth protocol stack for Linux
6 * Copyright (C) 2011-2014 Intel Corporation
7 * Copyright (C) 2002-2010 Marcel Holtmann <marcel@holtmann.org>
19 #include "lib/bluetooth.h"
22 #include "src/shared/util.h"
30 #define COLOR_UNKNOWN_EVENT_MASK COLOR_WHITE_BG
31 #define COLOR_UNKNOWN_SCAN_STATUS COLOR_WHITE_BG
32 #define COLOR_UNKNOWN_EXT_EVENT COLOR_WHITE_BG
34 static void print_status(uint8_t status)
36 packet_print_error("Status", status);
39 static void print_module(uint8_t module)
85 print_field("Module: %s (0x%2.2x)", str, module);
88 static void null_cmd(const void *data, uint8_t size)
92 static void status_rsp(const void *data, uint8_t size)
94 uint8_t status = get_u8(data);
99 static void reset_cmd(const void *data, uint8_t size)
101 uint8_t reset_type = get_u8(data);
102 uint8_t patch_enable = get_u8(data + 1);
103 uint8_t ddc_reload = get_u8(data + 2);
104 uint8_t boot_option = get_u8(data + 3);
105 uint32_t boot_addr = get_le32(data + 4);
108 switch (reset_type) {
110 str = "Soft software reset";
113 str = "Hard software reset";
120 print_field("Reset type: %s (0x%2.2x)", str, reset_type);
122 switch (patch_enable) {
124 str = "Do not enable";
134 print_field("Patch vectors: %s (0x%2.2x)", str, patch_enable);
136 switch (ddc_reload) {
138 str = "Do not reload";
141 str = "Reload from OTP";
148 print_field("DDC parameters: %s (0x%2.2x)", str, ddc_reload);
150 switch (boot_option) {
152 str = "Current image";
155 str = "Specified address";
162 print_field("Boot option: %s (0x%2.2x)", str, boot_option);
163 print_field("Boot address: 0x%8.8x", boot_addr);
166 static void read_version_rsp(const void *data, uint8_t size)
168 uint8_t status = get_u8(data);
169 uint8_t hw_platform = get_u8(data + 1);
170 uint8_t hw_variant = get_u8(data + 2);
171 uint8_t hw_revision = get_u8(data + 3);
172 uint8_t fw_variant = get_u8(data + 4);
173 uint8_t fw_revision = get_u8(data + 5);
174 uint8_t fw_build_nn = get_u8(data + 6);
175 uint8_t fw_build_cw = get_u8(data + 7);
176 uint8_t fw_build_yy = get_u8(data + 8);
177 uint8_t fw_patch = get_u8(data + 9);
179 print_status(status);
180 print_field("Hardware platform: 0x%2.2x", hw_platform);
181 print_field("Hardware variant: 0x%2.2x", hw_variant);
182 print_field("Hardware revision: %u.%u", hw_revision >> 4,
184 print_field("Firmware variant: 0x%2.2x", fw_variant);
185 print_field("Firmware revision: %u.%u", fw_revision >> 4,
188 print_field("Firmware build: %u-%u.%u", fw_build_nn,
189 fw_build_cw, 2000 + fw_build_yy);
190 print_field("Firmware patch: %u", fw_patch);
193 static void set_uart_baudrate_cmd(const void *data, uint8_t size)
195 uint8_t baudrate = get_u8(data);
224 str = "1843200 Baud";
227 str = "3250000 baud";
230 str = "2000000 baud";
233 str = "3000000 baud";
236 str = "3714286 baud";
239 str = "4333333 baud";
242 str = "6500000 baud";
249 print_field("Baudrate: %s (0x%2.2x)", str, baudrate);
252 static void secure_send_cmd(const void *data, uint8_t size)
254 uint8_t type = get_u8(data);
275 print_field("Type: %s fragment (0x%2.2x)", str, type);
277 packet_hexdump(data + 1, size - 1);
280 static void manufacturer_mode_cmd(const void *data, uint8_t size)
282 uint8_t mode = get_u8(data);
283 uint8_t reset = get_u8(data + 1);
298 print_field("Mode switch: %s (0x%2.2x)", str, mode);
305 str = "Reset and deactivate patches";
308 str = "Reset and activate patches";
315 print_field("Reset behavior: %s (0x%2.2x)", str, reset);
318 static void write_bd_data_cmd(const void *data, uint8_t size)
322 packet_print_addr("Address", data, false);
323 packet_hexdump(data + 6, 6);
325 memcpy(features, data + 12, 8);
326 packet_print_features_lmp(features, 0);
328 memcpy(features, data + 20, 1);
329 memset(features + 1, 0, 7);
330 packet_print_features_ll(features);
332 packet_hexdump(data + 21, size - 21);
335 static void read_bd_data_rsp(const void *data, uint8_t size)
337 uint8_t status = get_u8(data);
339 print_status(status);
340 packet_print_addr("Address", data + 1, false);
341 packet_hexdump(data + 7, size - 7);
344 static void write_bd_address_cmd(const void *data, uint8_t size)
346 packet_print_addr("Address", data, false);
349 static void act_deact_traces_cmd(const void *data, uint8_t size)
351 uint8_t tx = get_u8(data);
352 uint8_t tx_arq = get_u8(data + 1);
353 uint8_t rx = get_u8(data + 2);
355 print_field("Transmit traces: 0x%2.2x", tx);
356 print_field("Transmit ARQ: 0x%2.2x", tx_arq);
357 print_field("Receive traces: 0x%2.2x", rx);
360 static void stimulate_exception_cmd(const void *data, uint8_t size)
362 uint8_t type = get_u8(data);
367 str = "Fatal Exception";
370 str = "Debug Exception";
377 print_field("Type: %s (0x%2.2x)", str, type);
380 static const struct {
385 { 1, "SCO Rejected via LMP" },
386 { 2, "PTT Switch Notification" },
387 { 7, "Scan Status" },
388 { 9, "Debug Exception" },
389 { 10, "Fatal Exception" },
390 { 11, "System Exception" },
391 { 13, "LE Link Established" },
392 { 14, "FW Trace String" },
396 static void set_event_mask_cmd(const void *data, uint8_t size)
398 const uint8_t *events_array = data;
399 uint64_t mask, events = 0;
402 for (i = 0; i < 8; i++)
403 events |= ((uint64_t) events_array[i]) << (i * 8);
405 print_field("Mask: 0x%16.16" PRIx64, events);
409 for (i = 0; events_table[i].str; i++) {
410 if (events & (((uint64_t) 1) << events_table[i].bit)) {
411 print_field(" %s", events_table[i].str);
412 mask &= ~(((uint64_t) 1) << events_table[i].bit);
417 print_text(COLOR_UNKNOWN_EVENT_MASK, " Unknown mask "
418 "(0x%16.16" PRIx64 ")", mask);
421 static void ddc_config_write_cmd(const void *data, uint8_t size)
424 uint8_t param_len = get_u8(data);
425 uint16_t param_id = get_le16(data + 1);
427 print_field("Identifier: 0x%4.4x", param_id);
428 packet_hexdump(data + 3, param_len - 2);
430 data += param_len + 1;
431 size -= param_len + 1;
435 static void ddc_config_write_rsp(const void *data, uint8_t size)
437 uint8_t status = get_u8(data);
438 uint16_t param_id = get_le16(data + 1);
440 print_status(status);
441 print_field("Identifier: 0x%4.4x", param_id);
444 static void memory_write_cmd(const void *data, uint8_t size)
446 uint32_t addr = get_le32(data);
447 uint8_t mode = get_u8(data + 4);
448 uint8_t length = get_u8(data + 5);
451 print_field("Address: 0x%8.8x", addr);
458 str = "Half word access";
468 print_field("Mode: %s (0x%2.2x)", str, mode);
469 print_field("Length: %u", length);
471 packet_hexdump(data + 6, size - 6);
474 static void read_supported_features_cmd(const void *data, uint8_t size)
476 uint8_t page = get_u8(data);
478 print_field("Page: 0x%2.2x", page);
481 static void read_supported_features_rsp(const void *data, uint8_t size)
483 uint8_t status = get_u8(data);
484 uint8_t page = get_u8(data + 1);
485 uint8_t max_pages = get_u8(data + 2);
487 print_status(status);
488 print_field("Page: 0x%2.2x", page);
489 print_field("Max Pages: 0x%2.2x", max_pages);
490 print_field("Supported Features:");
491 packet_hexdump(data + 3, size - 3);
494 static const struct vendor_ocf vendor_ocf_table[] = {
497 status_rsp, 1, true },
498 { 0x002, "No Operation" },
499 { 0x005, "Read Version",
501 read_version_rsp, 10, true },
502 { 0x006, "Set UART Baudrate",
503 set_uart_baudrate_cmd, 1, true,
504 status_rsp, 1, true },
505 { 0x007, "Enable LPM" },
506 { 0x008, "PCM Write Configuration" },
507 { 0x009, "Secure Send",
508 secure_send_cmd, 1, false,
509 status_rsp, 1, true },
510 { 0x00d, "Read Secure Boot Params",
512 { 0x00e, "Write Secure Boot Params" },
514 { 0x010, "Change UART Baudrate" },
515 { 0x011, "Manufacturer Mode",
516 manufacturer_mode_cmd, 2, true,
517 status_rsp, 1, true },
518 { 0x012, "Read Link RSSI" },
519 { 0x022, "Get Exception Info" },
520 { 0x024, "Clear Exception Info" },
521 { 0x02f, "Write BD Data",
522 write_bd_data_cmd, 6, false },
523 { 0x030, "Read BD Data",
525 read_bd_data_rsp, 7, false },
526 { 0x031, "Write BD Address",
527 write_bd_address_cmd, 6, true,
528 status_rsp, 1, true },
529 { 0x032, "Flow Specification" },
530 { 0x034, "Read Secure ID" },
531 { 0x038, "Set Synchronous USB Interface Type" },
532 { 0x039, "Config Synchronous Interface" },
533 { 0x03f, "SW RF Kill",
535 status_rsp, 1, true },
536 { 0x043, "Activate Deactivate Traces",
537 act_deact_traces_cmd, 3, true },
538 { 0x04d, "Stimulate Exception",
539 stimulate_exception_cmd, 1, true,
540 status_rsp, 1, true },
541 { 0x050, "Read HW Version" },
542 { 0x052, "Set Event Mask",
543 set_event_mask_cmd, 8, true,
544 status_rsp, 1, true },
545 { 0x053, "Config_Link_Controller" },
546 { 0x089, "DDC Write" },
547 { 0x08a, "DDC Read" },
548 { 0x08b, "DDC Config Write",
549 ddc_config_write_cmd, 3, false,
550 ddc_config_write_rsp, 3, true },
551 { 0x08c, "DDC Config Read" },
552 { 0x08d, "Memory Read" },
553 { 0x08e, "Memory Write",
554 memory_write_cmd, 6, false,
555 status_rsp, 1, true },
556 { 0x0a6, "Read Supported Features",
557 read_supported_features_cmd, 1, true,
558 read_supported_features_rsp, 19, true },
563 const struct vendor_ocf *intel_vendor_ocf(uint16_t ocf)
567 for (i = 0; vendor_ocf_table[i].str; i++) {
568 if (vendor_ocf_table[i].ocf == ocf)
569 return &vendor_ocf_table[i];
575 static void startup_evt(const void *data, uint8_t size)
579 static void fatal_exception_evt(const void *data, uint8_t size)
581 uint16_t line = get_le16(data);
582 uint8_t module = get_u8(data + 2);
583 uint8_t reason = get_u8(data + 3);
585 print_field("Line: %u", line);
586 print_module(module);
587 print_field("Reason: 0x%2.2x", reason);
590 static void bootup_evt(const void *data, uint8_t size)
592 uint8_t zero = get_u8(data);
593 uint8_t num_packets = get_u8(data + 1);
594 uint8_t source = get_u8(data + 2);
595 uint8_t reset_type = get_u8(data + 3);
596 uint8_t reset_reason = get_u8(data + 4);
597 uint8_t ddc_status = get_u8(data + 5);
600 print_field("Zero: 0x%2.2x", zero);
601 print_field("Number of packets: %d", num_packets);
608 str = "Operational firmware";
611 str = "Self test firmware";
618 print_field("Source: %s (0x%2.2x)", str, source);
620 switch (reset_type) {
622 str = "Hardware reset";
625 str = "Soft watchdog reset";
628 str = "Soft software reset";
631 str = "Hard watchdog reset";
634 str = "Hard software reset";
641 print_field("Reset type: %s (0x%2.2x)", str, reset_type);
643 switch (reset_reason) {
648 str = "Reset command";
651 str = "Intel reset command";
657 str = "Fatal exception";
660 str = "System exception";
670 print_field("Reset reason: %s (0x%2.2x)", str, reset_reason);
672 switch (ddc_status) {
674 str = "Firmware default";
677 str = "Firmware default plus OTP";
680 str = "Persistent RAM";
690 print_field("DDC status: %s (0x%2.2x)", str, ddc_status);
693 static void default_bd_data_evt(const void *data, uint8_t size)
695 uint8_t mem_status = get_u8(data);
698 switch (mem_status) {
700 str = "Invalid manufacturing data";
707 print_field("Memory status: %s (0x%2.2x)", str, mem_status);
710 static void secure_send_commands_result_evt(const void *data, uint8_t size)
712 uint8_t result = get_u8(data);
713 uint16_t opcode = get_le16(data + 1);
714 uint16_t ogf = cmd_opcode_ogf(opcode);
715 uint16_t ocf = cmd_opcode_ocf(opcode);
716 uint8_t status = get_u8(data + 3);
724 str = "General failure";
727 str = "Hardware failure";
730 str = "Signature verification failed";
733 str = "Parsing error of command buffer";
736 str = "Command execution failure";
739 str = "Command parameters error";
742 str = "Command missing";
749 print_field("Result: %s (0x%2.2x)", str, result);
750 print_field("Opcode: 0x%4.4x (0x%2.2x|0x%4.4x)", opcode, ogf, ocf);
751 print_status(status);
754 static void debug_exception_evt(const void *data, uint8_t size)
756 uint16_t line = get_le16(data);
757 uint8_t module = get_u8(data + 2);
758 uint8_t reason = get_u8(data + 3);
760 print_field("Line: %u", line);
761 print_module(module);
762 print_field("Reason: 0x%2.2x", reason);
765 static void le_link_established_evt(const void *data, uint8_t size)
767 uint16_t handle = get_le16(data);
768 uint32_t access_addr = get_le32(data + 10);
770 print_field("Handle: %u", handle);
772 packet_hexdump(data + 2, 8);
774 print_field("Access address: 0x%8.8x", access_addr);
776 packet_hexdump(data + 14, size - 14);
779 static void scan_status_evt(const void *data, uint8_t size)
781 uint8_t enable = get_u8(data);
783 print_field("Inquiry scan: %s",
784 (enable & 0x01) ? "Enabled" : "Disabled");
785 print_field("Page scan: %s",
786 (enable & 0x02) ? "Enabled" : "Disabled");
789 print_text(COLOR_UNKNOWN_SCAN_STATUS,
790 " Unknown status (0x%2.2x)", enable & 0xfc);
794 static void act_deact_traces_complete_evt(const void *data, uint8_t size)
796 uint8_t status = get_u8(data);
798 print_status(status);
801 static void lmp_pdu_trace_evt(const void *data, uint8_t size)
803 uint8_t type, len, id;
804 uint16_t handle, count;
809 handle = get_le16(data + 1);
835 print_field("Type: %s (0x%2.2x)", str, type);
836 print_field("Handle: %u", handle);
841 clock = get_le32(data + 4 + len);
843 packet_hexdump(data + 3, 1);
844 lmp_packet(data + 4, len, false);
845 print_field("Clock: 0x%8.8x", clock);
849 clock = get_le32(data + 4 + len);
850 id = get_u8(data + 4 + len + 4);
852 packet_hexdump(data + 3, 1);
853 lmp_packet(data + 4, len, false);
854 print_field("Clock: 0x%8.8x", clock);
855 print_field("ID: 0x%2.2x", id);
858 clock = get_le32(data + 3);
859 id = get_u8(data + 3 + 4);
861 print_field("Clock: 0x%8.8x", clock);
862 print_field("ID: 0x%2.2x", id);
866 count = get_le16(data + 3);
868 print_field("Count: 0x%4.4x", count);
869 packet_hexdump(data + 3 + 2 + 1, 2);
870 llcp_packet(data + 8, len, false);
874 count = get_le16(data + 3);
875 id = get_u8(data + 3 + 2);
877 print_field("Count: 0x%4.4x", count);
878 print_field("ID: 0x%2.2x", id);
879 packet_hexdump(data + 3 + 2 + 1, 2);
880 llcp_packet(data + 8, len, false);
883 count = get_le16(data + 3);
884 id = get_u8(data + 3 + 2);
886 print_field("Count: 0x%4.4x", count);
887 print_field("ID: 0x%2.2x", id);
890 packet_hexdump(data + 3, size - 3);
895 static void write_bd_data_complete_evt(const void *data, uint8_t size)
897 uint8_t status = get_u8(data);
899 print_status(status);
902 static void sco_rejected_via_lmp_evt(const void *data, uint8_t size)
904 uint8_t reason = get_u8(data + 6);
906 packet_print_addr("Address", data, false);
907 packet_print_error("Reason", reason);
910 static void ptt_switch_notification_evt(const void *data, uint8_t size)
912 uint16_t handle = get_le16(data);
913 uint8_t table = get_u8(data + 2);
916 print_field("Handle: %u", handle);
923 str = "Enhanced data rate";
930 print_field("Packet type table: %s (0x%2.2x)", str, table);
933 static void system_exception_evt(const void *data, uint8_t size)
935 uint8_t type = get_u8(data);
940 str = "No Exception";
943 str = "Undefined Instruction";
946 str = "Prefetch abort";
956 print_field("Type: %s (0x%2.2x)", str, type);
958 packet_hexdump(data + 1, size - 1);
961 static const struct vendor_evt vendor_evt_table[] = {
963 startup_evt, 0, true },
964 { 0x01, "Fatal Exception",
965 fatal_exception_evt, 4, true },
967 bootup_evt, 6, true },
968 { 0x05, "Default BD Data",
969 default_bd_data_evt, 1, true },
970 { 0x06, "Secure Send Commands Result",
971 secure_send_commands_result_evt, 4, true },
972 { 0x08, "Debug Exception",
973 debug_exception_evt, 4, true },
974 { 0x0f, "LE Link Established",
975 le_link_established_evt, 26, true },
976 { 0x11, "Scan Status",
977 scan_status_evt, 1, true },
978 { 0x16, "Activate Deactivate Traces Complete",
979 act_deact_traces_complete_evt, 1, true },
980 { 0x17, "LMP PDU Trace",
981 lmp_pdu_trace_evt, 3, false },
982 { 0x19, "Write BD Data Complete",
983 write_bd_data_complete_evt, 1, true },
984 { 0x25, "SCO Rejected via LMP",
985 sco_rejected_via_lmp_evt, 7, true },
986 { 0x26, "PTT Switch Notification",
987 ptt_switch_notification_evt, 3, true },
988 { 0x29, "System Exception",
989 system_exception_evt, 133, true },
990 { 0x2c, "FW Trace String" },
991 { 0x2e, "FW Trace Binary" },
996 * An Intel telemetry subevent is of the TLV format.
997 * - Type: takes 1 byte. This is the subevent_id.
998 * - Length: takes 1 byte.
999 * - Value: takes |Length| bytes.
1002 uint8_t subevent_id;
1007 #define TLV_SIZE(tlv) (*((const uint8_t *) tlv + 1) + 2 * sizeof(uint8_t))
1008 #define NEXT_TLV(tlv) (const struct intel_tlv *) \
1009 ((const uint8_t *) tlv + TLV_SIZE(tlv))
1011 static void ext_evt_type(const struct intel_tlv *tlv)
1013 uint8_t evt_type = get_u8(tlv->value);
1018 str = "System Exception";
1021 str = "Fatal Exception";
1024 str = "Debug Exception";
1027 str = "Connection Event for BR/EDR Link Type";
1030 str = "Disconnection Event";
1033 str = "Audio Link Quality Report Type";
1036 str = "Stats for BR/EDR Link Type";
1039 print_text(COLOR_UNKNOWN_EXT_EVENT,
1040 "Unknown extended telemetry event type (0x%2.2x)",
1042 packet_hexdump((const void *) tlv,
1043 tlv->length + 2 * sizeof(uint8_t));
1047 print_field("Extended event type (0x%2.2x): %s (0x%2.2x)",
1048 tlv->subevent_id, str, evt_type);
1051 static void ext_acl_evt_conn_handle(const struct intel_tlv *tlv)
1053 uint16_t conn_handle = get_le16(tlv->value);
1055 print_field("ACL connection handle (0x%2.2x): 0x%4.4x",
1056 tlv->subevent_id, conn_handle);
1059 static void ext_acl_evt_hec_errors(const struct intel_tlv *tlv)
1061 uint32_t num = get_le32(tlv->value);
1063 print_field("Rx HEC errors (0x%2.2x): %d", tlv->subevent_id, num);
1066 static void ext_acl_evt_crc_errors(const struct intel_tlv *tlv)
1068 uint32_t num = get_le32(tlv->value);
1070 print_field("Rx CRC errors (0x%2.2x): %d", tlv->subevent_id, num);
1073 static void ext_acl_evt_num_pkt_from_host(const struct intel_tlv *tlv)
1075 uint32_t num = get_le32(tlv->value);
1077 print_field("Packets from host (0x%2.2x): %d",
1078 tlv->subevent_id, num);
1081 static void ext_acl_evt_num_tx_pkt_to_air(const struct intel_tlv *tlv)
1083 uint32_t num = get_le32(tlv->value);
1085 print_field("Tx packets (0x%2.2x): %d", tlv->subevent_id, num);
1088 static void ext_acl_evt_num_tx_pkt_retry(const struct intel_tlv *tlv)
1091 uint32_t num = get_le32(tlv->value);
1093 switch (tlv->subevent_id) {
1095 subevent_str = "Tx packets 0 retries";
1098 subevent_str = "Tx packets 1 retries";
1101 subevent_str = "Tx packets 2 retries";
1104 subevent_str = "Tx packets 3 retries";
1107 subevent_str = "Tx packets 4 retries and more";
1110 subevent_str = "Unknown";
1114 print_field("%s (0x%2.2x): %d", subevent_str, tlv->subevent_id, num);
1117 static void ext_acl_evt_num_tx_pkt_type(const struct intel_tlv *tlv)
1119 char *packet_type_str;
1120 uint32_t num = get_le32(tlv->value);
1122 switch (tlv->subevent_id) {
1124 packet_type_str = "DH1";
1127 packet_type_str = "DH3";
1130 packet_type_str = "DH5";
1133 packet_type_str = "2DH1";
1136 packet_type_str = "2DH3";
1139 packet_type_str = "2DH5";
1142 packet_type_str = "3DH1";
1145 packet_type_str = "3DH3";
1148 packet_type_str = "3DH5";
1151 packet_type_str = "Unknown";
1155 print_field("Tx %s packets (0x%2.2x): %d",
1156 packet_type_str, tlv->subevent_id, num);
1159 static void ext_acl_evt_num_rx_pkt_from_air(const struct intel_tlv *tlv)
1161 uint32_t num = get_le32(tlv->value);
1163 print_field("Rx packets (0x%2.2x): %d",
1164 tlv->subevent_id, num);
1167 static void ext_acl_evt_link_throughput(const struct intel_tlv *tlv)
1169 uint32_t num = get_le32(tlv->value);
1171 print_field("ACL link throughput (KBps) (0x%2.2x): %d",
1172 tlv->subevent_id, num);
1175 static void ext_acl_evt_max_packet_latency(const struct intel_tlv *tlv)
1177 uint32_t num = get_le32(tlv->value);
1179 print_field("ACL max packet latency (ms) (0x%2.2x): %d",
1180 tlv->subevent_id, num);
1183 static void ext_acl_evt_avg_packet_latency(const struct intel_tlv *tlv)
1185 uint32_t num = get_le32(tlv->value);
1187 print_field("ACL avg packet latency (ms) (0x%2.2x): %d",
1188 tlv->subevent_id, num);
1191 static void ext_sco_evt_conn_handle(const struct intel_tlv *tlv)
1193 uint16_t conn_handle = get_le16(tlv->value);
1195 print_field("SCO/eSCO connection handle (0x%2.2x): 0x%4.4x",
1196 tlv->subevent_id, conn_handle);
1199 static void ext_sco_evt_num_rx_pkt_from_air(const struct intel_tlv *tlv)
1201 uint32_t num = get_le32(tlv->value);
1203 print_field("Packets from host (0x%2.2x): %d", tlv->subevent_id, num);
1206 static void ext_sco_evt_num_tx_pkt_to_air(const struct intel_tlv *tlv)
1208 uint32_t num = get_le32(tlv->value);
1210 print_field("Tx packets (0x%2.2x): %d", tlv->subevent_id, num);
1213 static void ext_sco_evt_num_rx_payloads_lost(const struct intel_tlv *tlv)
1215 uint32_t num = get_le32(tlv->value);
1217 print_field("Rx payload lost (0x%2.2x): %d", tlv->subevent_id, num);
1220 static void ext_sco_evt_num_tx_payloads_lost(const struct intel_tlv *tlv)
1223 uint32_t num = get_le32(tlv->value);
1225 print_field("Tx payload lost (0x%2.2x): %d", tlv->subevent_id, num);
1228 static void slots_errors(const struct intel_tlv *tlv, const char *type_str)
1230 /* The subevent has 5 slots where each slot is of the uint32_t type. */
1232 const uint8_t *data = tlv->value;
1235 if (tlv->length != 5 * sizeof(uint32_t)) {
1236 print_text(COLOR_UNKNOWN_EXT_EVENT,
1237 " Invalid subevent length (%d)", tlv->length);
1241 for (i = 0; i < 5; i++) {
1242 num[i] = get_le32(data);
1243 data += sizeof(uint32_t);
1246 print_field("%s (0x%2.2x): %d %d %d %d %d", type_str, tlv->subevent_id,
1247 num[0], num[1], num[2], num[3], num[4]);
1250 static void ext_sco_evt_num_no_sync_errors(const struct intel_tlv *tlv)
1252 slots_errors(tlv, "Rx No SYNC errors");
1255 static void ext_sco_evt_num_hec_errors(const struct intel_tlv *tlv)
1257 slots_errors(tlv, "Rx HEC errors");
1260 static void ext_sco_evt_num_crc_errors(const struct intel_tlv *tlv)
1262 slots_errors(tlv, "Rx CRC errors");
1265 static void ext_sco_evt_num_naks(const struct intel_tlv *tlv)
1267 slots_errors(tlv, "Rx NAK errors");
1270 static void ext_sco_evt_num_failed_tx_by_wifi(const struct intel_tlv *tlv)
1272 slots_errors(tlv, "Failed Tx due to Wifi coex");
1275 static void ext_sco_evt_num_failed_rx_by_wifi(const struct intel_tlv *tlv)
1277 slots_errors(tlv, "Failed Rx due to Wifi coex");
1280 static void ext_sco_evt_samples_inserted(const struct intel_tlv *tlv)
1282 uint32_t num = get_le32(tlv->value);
1284 print_field("Late samples inserted based on CDC (0x%2.2x): %d",
1285 tlv->subevent_id, num);
1288 static void ext_sco_evt_samples_dropped(const struct intel_tlv *tlv)
1290 uint32_t num = get_le32(tlv->value);
1292 print_field("Samples dropped (0x%2.2x): %d", tlv->subevent_id, num);
1295 static void ext_sco_evt_mute_samples(const struct intel_tlv *tlv)
1297 uint32_t num = get_le32(tlv->value);
1299 print_field("Mute samples sent at initial connection (0x%2.2x): %d",
1300 tlv->subevent_id, num);
1303 static void ext_sco_evt_plc_injection_data(const struct intel_tlv *tlv)
1305 uint32_t num = get_le32(tlv->value);
1307 print_field("PLC injection data (0x%2.2x): %d", tlv->subevent_id, num);
1310 static const struct intel_ext_subevent {
1311 uint8_t subevent_id;
1313 void (*func)(const struct intel_tlv *tlv);
1314 } intel_ext_subevent_table[] = {
1315 { 0x01, 1, ext_evt_type },
1317 /* ACL audio link quality subevents */
1318 { 0x4a, 2, ext_acl_evt_conn_handle },
1319 { 0x4b, 4, ext_acl_evt_hec_errors },
1320 { 0x4c, 4, ext_acl_evt_crc_errors },
1321 { 0x4d, 4, ext_acl_evt_num_pkt_from_host },
1322 { 0x4e, 4, ext_acl_evt_num_tx_pkt_to_air },
1323 { 0x4f, 4, ext_acl_evt_num_tx_pkt_retry },
1324 { 0x50, 4, ext_acl_evt_num_tx_pkt_retry },
1325 { 0x51, 4, ext_acl_evt_num_tx_pkt_retry },
1326 { 0x52, 4, ext_acl_evt_num_tx_pkt_retry },
1327 { 0x53, 4, ext_acl_evt_num_tx_pkt_retry },
1328 { 0x54, 4, ext_acl_evt_num_tx_pkt_type },
1329 { 0x55, 4, ext_acl_evt_num_tx_pkt_type },
1330 { 0x56, 4, ext_acl_evt_num_tx_pkt_type },
1331 { 0x57, 4, ext_acl_evt_num_tx_pkt_type },
1332 { 0x58, 4, ext_acl_evt_num_tx_pkt_type },
1333 { 0x59, 4, ext_acl_evt_num_tx_pkt_type },
1334 { 0x5a, 4, ext_acl_evt_num_tx_pkt_type },
1335 { 0x5b, 4, ext_acl_evt_num_tx_pkt_type },
1336 { 0x5c, 4, ext_acl_evt_num_tx_pkt_type },
1337 { 0x5d, 4, ext_acl_evt_num_rx_pkt_from_air },
1338 { 0x5e, 4, ext_acl_evt_link_throughput },
1339 { 0x5f, 4, ext_acl_evt_max_packet_latency },
1340 { 0x60, 4, ext_acl_evt_avg_packet_latency },
1342 /* SCO/eSCO audio link quality subevents */
1343 { 0x6a, 2, ext_sco_evt_conn_handle },
1344 { 0x6b, 4, ext_sco_evt_num_rx_pkt_from_air },
1345 { 0x6c, 4, ext_sco_evt_num_tx_pkt_to_air },
1346 { 0x6d, 4, ext_sco_evt_num_rx_payloads_lost },
1347 { 0x6e, 4, ext_sco_evt_num_tx_payloads_lost },
1348 { 0x6f, 20, ext_sco_evt_num_no_sync_errors },
1349 { 0x70, 20, ext_sco_evt_num_hec_errors },
1350 { 0x71, 20, ext_sco_evt_num_crc_errors },
1351 { 0x72, 20, ext_sco_evt_num_naks },
1352 { 0x73, 20, ext_sco_evt_num_failed_tx_by_wifi },
1353 { 0x74, 20, ext_sco_evt_num_failed_rx_by_wifi },
1354 { 0x75, 4, ext_sco_evt_samples_inserted },
1355 { 0x76, 4, ext_sco_evt_samples_dropped },
1356 { 0x77, 4, ext_sco_evt_mute_samples },
1357 { 0x78, 4, ext_sco_evt_plc_injection_data },
1363 static const struct intel_tlv *process_ext_subevent(const struct intel_tlv *tlv,
1364 const struct intel_tlv *last_tlv)
1366 const struct intel_tlv *next_tlv = NEXT_TLV(tlv);
1367 const struct intel_ext_subevent *subevent = NULL;
1370 for (i = 0; intel_ext_subevent_table[i].length > 0; i++) {
1371 if (intel_ext_subevent_table[i].subevent_id ==
1373 subevent = &intel_ext_subevent_table[i];
1379 print_text(COLOR_UNKNOWN_EXT_EVENT,
1380 "Unknown extended subevent 0x%2.2x",
1385 if (tlv->length != subevent->length) {
1386 print_text(COLOR_ERROR, "Invalid length %d of subevent 0x%2.2x",
1387 tlv->length, tlv->subevent_id);
1391 if (next_tlv > last_tlv) {
1392 print_text(COLOR_ERROR, "Subevent exceeds the buffer size.");
1396 subevent->func(tlv);
1401 static void intel_vendor_ext_evt(const void *data, uint8_t size)
1403 /* The data pointer points to a number of tlv.*/
1404 const struct intel_tlv *tlv = data;
1405 const struct intel_tlv *last_tlv = data + size;
1407 /* Process every tlv subevent until reaching last_tlv.
1408 * The decoding process terminates normally when tlv == last_tlv.
1410 while (tlv && tlv < last_tlv)
1411 tlv = process_ext_subevent(tlv, last_tlv);
1413 /* If an error occurs in decoding the subevents, hexdump the packet. */
1415 packet_hexdump(data, size);
1418 /* Vendor extended events with a vendor prefix. */
1419 static const struct vendor_evt vendor_prefix_evt_table[] = {
1420 { 0x03, "Extended Telemetry", intel_vendor_ext_evt },
1424 const uint8_t intel_vendor_prefix[] = {0x87, 0x80};
1425 #define INTEL_VENDOR_PREFIX_SIZE sizeof(intel_vendor_prefix)
1428 * The vendor event with Intel vendor prefix.
1429 * Its format looks like
1430 * 0xff <length> <vendor_prefix> <subopcode> <data>
1431 * where Intel's <vendor_prefix> is 0x8780.
1433 * When <subopcode> == 0x03, it is a telemetry event; and
1434 * <data> is a number of tlv data.
1436 struct vendor_prefix_evt {
1437 uint8_t prefix_data[INTEL_VENDOR_PREFIX_SIZE];
1441 static const struct vendor_evt *intel_vendor_prefix_evt(const void *data,
1445 const struct vendor_prefix_evt *vnd = data;
1446 char prefix_string[INTEL_VENDOR_PREFIX_SIZE * 2 + 1] = { 0 };
1448 /* Check if the vendor prefix matches. */
1449 for (i = 0; i < INTEL_VENDOR_PREFIX_SIZE; i++) {
1450 if (vnd->prefix_data[i] != intel_vendor_prefix[i])
1452 sprintf(prefix_string + i * 2, "%02x", vnd->prefix_data[i]);
1454 print_field("Vendor Prefix (0x%s)", prefix_string);
1457 * Handle the vendor event with a vendor prefix.
1458 * 0xff <length> <vendor_prefix> <subopcode> <data>
1459 * This loop checks whether the <subopcode> exists in the
1460 * vendor_prefix_evt_table.
1462 for (i = 0; vendor_prefix_evt_table[i].str; i++) {
1463 if (vendor_prefix_evt_table[i].evt == vnd->subopcode) {
1464 *consumed_size = sizeof(struct vendor_prefix_evt);
1465 return &vendor_prefix_evt_table[i];
1472 const struct vendor_evt *intel_vendor_evt(const void *data, int *consumed_size)
1474 uint8_t evt = *((const uint8_t *) data);
1478 * Handle the vendor event without a vendor prefix.
1479 * 0xff <length> <evt> <data>
1480 * This loop checks whether the <evt> exists in the vendor_evt_table.
1482 for (i = 0; vendor_evt_table[i].str; i++) {
1483 if (vendor_evt_table[i].evt == evt)
1484 return &vendor_evt_table[i];
1488 * It is not a regular event. Check whether it is a vendor extended
1489 * event that comes with a vendor prefix followed by a subopcode.
1491 return intel_vendor_prefix_evt(data, consumed_size);