This set adds support for decoding Bluetooth 5 commands as listed below.
Changes since v1:
-squash patches as requested
-fix coding style issues and review comments
-add legacy pdu decoding
Changes since v2:
-commit message cleanups
Changes since v3:
-fix decoding of LE Extended Advertising Report Event
-add support for missing error codes
-fix decoding of LE Set Periodic Advertising Data
Changes since v4:
-fix decoding of LE Set Extended Scan Parameters
-fix decoding of LE Set Extended Scan Enable
-fix decoding of LE Set Extended Advertising Data
-fix decoding of LE Set Extended Scan Response Data
-fix decoding of LE Set Periodic Advertising commands
-fix decoding of LE Extended Create Connection
-fix decoding of LE Set Extended Scan Parameters
-fix decoding of LE Set Extended Scan Enable
-fix decoding of connection latency
-refactor printing enable field
-refactor printing advertising channel map and filter policy
-fix coding style issues
-rename Directed Advertising Timeout to Advertising Timeout
Michał Narajowski (11):
monitor: Add LE Enhanced Test commands decoding
monitor: Add LE Extended Advertising commands decoding
monitor: Add LE Set Periodic Advertising commands decoding
monitor: Add LE Extended Scan commands decoding
monitor: Add LE Periodic Advertising commands decoding
monitor: Add LE RF commands decoding
monitor: Add LE Set Privacy Mode decoding
monitor: Fix connection latency decoding
monitor: Add support for missing error codes
monitor: Rename Directed Advertising Timeout
monitor: Refactor print_enable function
monitor/bt.h | 256 +++++++++
monitor/packet.c | 1666 ++++++++++++++++++++++++++++++++++++++++--------------
2 files changed, 1483 insertions(+), 439 deletions(-)
--
2.11.0
< HCI Command: LE Set Privacy Mode (0x08|0x004e) plen 8
Peer Identity address type: Random (0x01)
Peer Identity address: 01:01:01:01:01:01 (Non-Resolvable)
Privacy Mode: Use Device Privacy (0x01)
---
monitor/bt.h | 7 +++++++
monitor/packet.c | 28 +++++++++++++++++++++++++++-
2 files changed, 34 insertions(+), 1 deletion(-)
diff --git a/monitor/bt.h b/monitor/bt.h
index 481b82a5a..595b6a737 100644
--- a/monitor/bt.h
+++ b/monitor/bt.h
@@ -2376,6 +2376,13 @@ struct bt_hci_cmd_le_write_rf_path_comp {
uint16_t rf_rx_path_comp;
} __attribute__ ((packed));
+#define BT_HCI_CMD_LE_SET_PRIV_MODE 0x204e
+struct bt_hci_cmd_le_set_priv_mode {
+ uint8_t peer_id_addr_type;
+ uint8_t peer_id_addr[6];
+ uint8_t priv_mode;
+} __attribute__ ((packed));
+
#define BT_HCI_EVT_INQUIRY_COMPLETE 0x01
struct bt_hci_evt_inquiry_complete {
uint8_t status;
diff --git a/monitor/packet.c b/monitor/packet.c
index 577310505..fec952a12 100644
--- a/monitor/packet.c
+++ b/monitor/packet.c
@@ -7831,6 +7831,30 @@ static void le_write_rf_path_comp_cmd(const void *data, uint8_t size)
cmd->rf_rx_path_comp);
}
+static void le_set_priv_mode_cmd(const void *data, uint8_t size)
+{
+ const struct bt_hci_cmd_le_set_priv_mode *cmd = data;
+ const char *str;
+
+ print_addr_type("Peer Identity address type", cmd->peer_id_addr_type);
+ print_addr("Peer Identity address", cmd->peer_id_addr,
+ cmd->peer_id_addr_type);
+
+ switch (cmd->priv_mode) {
+ case 0x00:
+ str = "Use Network Privacy";
+ break;
+ case 0x01:
+ str = "Use Device Privacy";
+ break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ print_field("Privacy Mode: %s (0x%2.2x)", str, cmd->priv_mode);
+}
+
struct opcode_data {
uint16_t opcode;
int bit;
@@ -8615,7 +8639,9 @@ static const struct opcode_data opcode_table[] = {
{ 0x204d, 313, "LE Write RF Path Compensation",
le_write_rf_path_comp_cmd, 4, true,
status_rsp, 1, true },
- { 0x204e, 314, "LE Set Privacy Mode" },
+ { 0x204e, 314, "LE Set Privacy Mode",
+ le_set_priv_mode_cmd, 8, true,
+ status_rsp, 1, true },
{ }
};
--
2.11.0
This patch adds decoding for following commands:
LE Enhanced Receiver Test
LE Enhanced Transmitter Test
< HCI Command: LE Enhanced Receiver Test (0x08|0x0033) plen 3
RX channel: 0x01
PHY: LE 1M (0x01)
Modulation index: Stable (0x01)
< HCI Command: LE Enhanced Transmitter Test (0x08|0x0034) plen 4
TX channel frequency: 2402 MHz (0x00)
Test data length: 255 bytes
Packet payload: 0x01
PHY: LE Coded with S=8 (0x03)
---
monitor/bt.h | 15 +++++++++++++
monitor/packet.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 77 insertions(+), 2 deletions(-)
diff --git a/monitor/bt.h b/monitor/bt.h
index c2045bbf9..a877b2c13 100644
--- a/monitor/bt.h
+++ b/monitor/bt.h
@@ -2161,6 +2161,21 @@ struct bt_hci_cmd_le_set_phy {
uint16_t phy_opts;
} __attribute__((packed));
+#define BT_HCI_CMD_LE_ENHANCED_RECEIVER_TEST 0x2033
+struct bt_hci_cmd_le_enhanced_receiver_test {
+ uint8_t rx_channel;
+ uint8_t phy;
+ uint8_t modulation_index;
+} __attribute__((packed));
+
+#define BT_HCI_CMD_LE_ENHANCED_TRANSMITTER_TEST 0x2034
+struct bt_hci_cmd_le_enhanced_transmitter_test {
+ uint8_t tx_channel;
+ uint8_t data_len;
+ uint8_t payload;
+ uint8_t phy;
+} __attribute__((packed));
+
#define BT_HCI_EVT_INQUIRY_COMPLETE 0x01
struct bt_hci_evt_inquiry_complete {
uint8_t status;
diff --git a/monitor/packet.c b/monitor/packet.c
index 39823691f..1f6cd3699 100644
--- a/monitor/packet.c
+++ b/monitor/packet.c
@@ -7086,6 +7086,62 @@ static void le_set_phy_cmd(const void *data, uint8_t size)
print_field("PHY options preference: %s (0x%4.4x)", str, cmd->phy_opts);
}
+static void le_enhanced_receiver_test_cmd(const void *data, uint8_t size)
+{
+ const struct bt_hci_cmd_le_enhanced_receiver_test *cmd = data;
+ const char *str;
+
+ print_field("RX channel frequency: %d MHz (0x%2.2x)",
+ (cmd->rx_channel * 2) + 2402, cmd->rx_channel);
+ print_le_phy("PHY", cmd->phy);
+
+ switch (cmd->modulation_index) {
+ case 0x00:
+ str = "Standard";
+ break;
+ case 0x01:
+ str = "Stable";
+ break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ print_field("Modulation index: %s (0x%2.2x)", str,
+ cmd->modulation_index);
+}
+
+static void le_enhanced_transmitter_test_cmd(const void *data, uint8_t size)
+{
+ const struct bt_hci_cmd_le_enhanced_transmitter_test *cmd = data;
+ const char *str;
+
+ print_field("TX channel frequency: %d MHz (0x%2.2x)",
+ (cmd->tx_channel * 2) + 2402, cmd->tx_channel);
+ print_field("Test data length: %d bytes", cmd->data_len);
+ print_field("Packet payload: 0x%2.2x", cmd->payload);
+
+ switch (cmd->phy) {
+ case 0x01:
+ str = "LE 1M";
+ break;
+ case 0x02:
+ str = "LE 2M";
+ break;
+ case 0x03:
+ str = "LE Coded with S=8";
+ break;
+ case 0x04:
+ str = "LE Coded with S=2";
+ break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ print_field("PHY: %s (0x%2.2x)", str, cmd->phy);
+}
+
struct opcode_data {
uint16_t opcode;
int bit;
@@ -7789,8 +7845,12 @@ static const struct opcode_data opcode_table[] = {
status_rsp, 1, true },
{ 0x2032, 286, "LE Set PHY",
le_set_phy_cmd, 7, true},
- { 0x2033, 287, "LE Enhanced Receiver Test" },
- { 0x2034, 288, "LE Enhanced Transmitter Test" },
+ { 0x2033, 287, "LE Enhanced Receiver Test",
+ le_enhanced_receiver_test_cmd, 3, true,
+ status_rsp, 1, true },
+ { 0x2034, 288, "LE Enhanced Transmitter Test",
+ le_enhanced_transmitter_test_cmd, 4, true,
+ status_rsp, 1, true },
{ 0x2035, 289, "LE Set Advertising Set Random Address" },
{ 0x2036, 290, "LE Set Extended Advertising Parameters" },
{ 0x2037, 291, "LE Set Extended Advertising Data" },
--
2.11.0
This patch adds decoding for following commands:
LE Read Transmit Power
LE Read RF Path Compensation
LE Write RF Path Compensation
< HCI Command: LE Write RF Path Compensation (0x08|0x004d) plen 4
RF Tx Path Compensation Value: 0x0201
RF Rx Path Compensation Value: 0x0403
---
monitor/bt.h | 20 ++++++++++++++++++++
monitor/packet.c | 42 +++++++++++++++++++++++++++++++++++++++---
2 files changed, 59 insertions(+), 3 deletions(-)
diff --git a/monitor/bt.h b/monitor/bt.h
index 757adfa18..481b82a5a 100644
--- a/monitor/bt.h
+++ b/monitor/bt.h
@@ -2356,6 +2356,26 @@ struct bt_hci_rsp_le_read_dev_periodic_adv_list_size {
uint8_t list_size;
} __attribute__ ((packed));
+#define BT_HCI_CMD_LE_READ_TX_POWER 0x204b
+struct bt_hci_rsp_le_read_tx_power {
+ uint8_t status;
+ uint8_t min_tx_power;
+ uint8_t max_tx_power;
+} __attribute__ ((packed));
+
+#define BT_HCI_CMD_LE_READ_RF_PATH_COMPENSATION 0x204c
+struct bt_hci_rsp_le_read_rf_path_comp {
+ uint8_t status;
+ uint16_t rf_tx_path_comp;
+ uint16_t rf_rx_path_comp;
+} __attribute__ ((packed));
+
+#define BT_HCI_CMD_LE_WRITE_RF_PATH_COMPENSATION 0x204d
+struct bt_hci_cmd_le_write_rf_path_comp {
+ uint16_t rf_tx_path_comp;
+ uint16_t rf_rx_path_comp;
+} __attribute__ ((packed));
+
#define BT_HCI_EVT_INQUIRY_COMPLETE 0x01
struct bt_hci_evt_inquiry_complete {
uint8_t status;
diff --git a/monitor/packet.c b/monitor/packet.c
index 56d935a3c..577310505 100644
--- a/monitor/packet.c
+++ b/monitor/packet.c
@@ -7801,6 +7801,36 @@ static void le_read_periodic_adv_list_size_rsp(const void *data, uint8_t size)
print_field("List size: 0x%2.2x", rsp->list_size);
}
+static void le_read_tx_power_rsp(const void *data, uint8_t size)
+{
+ const struct bt_hci_rsp_le_read_tx_power *rsp = data;
+
+ print_status(rsp->status);
+ print_field("Min Tx power: %d dBm", rsp->min_tx_power);
+ print_field("Max Tx power: %d dBm", rsp->max_tx_power);
+}
+
+static void le_read_rf_path_comp_rsp(const void *data, uint8_t size)
+{
+ const struct bt_hci_rsp_le_read_rf_path_comp *rsp = data;
+
+ print_status(rsp->status);
+ print_field("RF Tx Path Compensation Value: 0x%4.4x",
+ rsp->rf_tx_path_comp);
+ print_field("RF Rx Path Compensation Value: 0x%4.4x",
+ rsp->rf_rx_path_comp);
+}
+
+static void le_write_rf_path_comp_cmd(const void *data, uint8_t size)
+{
+ const struct bt_hci_cmd_le_write_rf_path_comp *cmd = data;
+
+ print_field("RF Tx Path Compensation Value: 0x%4.4x",
+ cmd->rf_tx_path_comp);
+ print_field("RF Rx Path Compensation Value: 0x%4.4x",
+ cmd->rf_rx_path_comp);
+}
+
struct opcode_data {
uint16_t opcode;
int bit;
@@ -8576,9 +8606,15 @@ static const struct opcode_data opcode_table[] = {
{ 0x204a, 310, "LE Read Periodic Advertiser List Size",
null_cmd, 0, true,
le_read_periodic_adv_list_size_rsp, 2, true },
- { 0x204b, 311, "LE Read Transmit Power" },
- { 0x204c, 312, "LE Read RF Path Compensation" },
- { 0x204d, 313, "LE Write RF Path Compensation" },
+ { 0x204b, 311, "LE Read Transmit Power",
+ null_cmd, 0, true,
+ le_read_tx_power_rsp, 3, true },
+ { 0x204c, 312, "LE Read RF Path Compensation",
+ null_cmd, 0, true,
+ le_read_rf_path_comp_rsp, 5, true },
+ { 0x204d, 313, "LE Write RF Path Compensation",
+ le_write_rf_path_comp_cmd, 4, true,
+ status_rsp, 1, true },
{ 0x204e, 314, "LE Set Privacy Mode" },
{ }
};
--
2.11.0
---
monitor/packet.c | 321 +++++++------------------------------------------------
1 file changed, 37 insertions(+), 284 deletions(-)
diff --git a/monitor/packet.c b/monitor/packet.c
index e1f69b145..c697890cf 100644
--- a/monitor/packet.c
+++ b/monitor/packet.c
@@ -557,6 +557,25 @@ void packet_print_error(const char *label, uint8_t error)
print_error(label, error);
}
+static void print_enable(const char *label, uint8_t enable)
+{
+ const char *str;
+
+ switch (enable) {
+ case 0x00:
+ str = "Disable";
+ break;
+ case 0x01:
+ str = "Enabled";
+ break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ print_field("%s: %s (0x%2.2x)", label, str, enable);
+}
+
static void print_addr_type(const char *label, uint8_t addr_type)
{
const char *str;
@@ -1198,21 +1217,7 @@ static void print_power_level(int8_t level, const char *type)
static void print_sync_flow_control(uint8_t enable)
{
- const char *str;
-
- switch (enable) {
- case 0x00:
- str = "Disabled";
- break;
- case 0x01:
- str = "Enabled";
- break;
- default:
- str = "Reserved";
- break;
- }
-
- print_field("Flow control: %s (0x%2.2x)", str, enable);
+ print_enable("Flow control", enable);
}
static void print_host_flow_control(uint8_t enable)
@@ -1506,40 +1511,12 @@ static void print_pscan_type(uint8_t type)
static void print_afh_mode(uint8_t mode)
{
- const char *str;
-
- switch (mode) {
- case 0x00:
- str = "Disabled";
- break;
- case 0x01:
- str = "Enabled";
- break;
- default:
- str = "Reserved";
- break;
- }
-
- print_field("Mode: %s (0x%2.2x)", str, mode);
+ print_enable("Mode", mode);
}
static void print_erroneous_reporting(uint8_t mode)
{
- const char *str;
-
- switch (mode) {
- case 0x00:
- str = "Disabled";
- break;
- case 0x01:
- str = "Enabled";
- break;
- default:
- str = "Reserved";
- break;
- }
-
- print_field("Mode: %s (0x%2.2x)", str, mode);
+ print_enable("Mode", mode);
}
static void print_loopback_mode(uint8_t mode)
@@ -1566,59 +1543,17 @@ static void print_loopback_mode(uint8_t mode)
static void print_simple_pairing_mode(uint8_t mode)
{
- const char *str;
-
- switch (mode) {
- case 0x00:
- str = "Disabled";
- break;
- case 0x01:
- str = "Enabled";
- break;
- default:
- str = "Reserved";
- break;
- }
-
- print_field("Mode: %s (0x%2.2x)", str, mode);
+ print_enable("Mode", mode);
}
static void print_ssp_debug_mode(uint8_t mode)
{
- const char *str;
-
- switch (mode) {
- case 0x00:
- str = "Disabled";
- break;
- case 0x01:
- str = "Enabled";
- break;
- default:
- str = "Reserved";
- break;
- }
-
- print_field("Debug mode: %s (0x%2.2x)", str, mode);
+ print_enable("Debug Mode", mode);
}
static void print_secure_conn_support(uint8_t support)
{
- const char *str;
-
- switch (support) {
- case 0x00:
- str = "Disabled";
- break;
- case 0x01:
- str = "Enabled";
- break;
- default:
- str = "Reserved";
- break;
- }
-
- print_field("Support: %s (0x%2.2x)", str, support);
+ print_enable("Support", support);
}
static void print_auth_payload_timeout(uint16_t timeout)
@@ -1791,21 +1726,7 @@ static void print_link_type(uint8_t link_type)
static void print_encr_mode(uint8_t encr_mode)
{
- const char *str;
-
- switch (encr_mode) {
- case 0x00:
- str = "Disabled";
- break;
- case 0x01:
- str = "Enabled";
- break;
- default:
- str = "Reserved";
- break;
- }
-
- print_field("Encryption: %s (0x%2.2x)", str, encr_mode);
+ print_enable("Encryption", encr_mode);
}
static void print_encr_mode_change(uint8_t encr_mode, uint16_t handle)
@@ -2248,21 +2169,7 @@ static void print_flow_spec(const char *label, const uint8_t *data)
static void print_short_range_mode(uint8_t mode)
{
- const char *str;
-
- switch (mode) {
- case 0x00:
- str = "Disabled";
- break;
- case 0x01:
- str = "Enabled";
- break;
- default:
- str = "Reserved";
- break;
- }
-
- print_field("Short range mode: %s (0x%2.2x)", str, mode);
+ print_enable("Short range mode", mode);
}
static void print_amp_status(uint8_t amp_status)
@@ -6358,24 +6265,9 @@ static void get_mws_transport_config_rsp(const void *data, uint8_t size)
static void set_triggered_clock_capture_cmd(const void *data, uint8_t size)
{
const struct bt_hci_cmd_set_triggered_clock_capture *cmd = data;
- const char *str;
print_handle(cmd->handle);
-
- switch (cmd->enable) {
- case 0x00:
- str = "Disabled";
- break;
- case 0x01:
- str = "Enabled";
- break;
- default:
- str = "Reserved";
- break;
- }
-
- print_field("Capture: %s (0x%2.2x)", str, cmd->enable);
-
+ print_enable("Capture", cmd->enable);
print_clock_type(cmd->type);
print_lpo_allowed(cmd->lpo_allowed);
print_field("Clock captures to filter: %u", cmd->num_filter);
@@ -6499,21 +6391,8 @@ static void le_set_scan_rsp_data_cmd(const void *data, uint8_t size)
static void le_set_adv_enable_cmd(const void *data, uint8_t size)
{
const struct bt_hci_cmd_le_set_adv_enable *cmd = data;
- const char *str;
- switch (cmd->enable) {
- case 0x00:
- str = "Disabled";
- break;
- case 0x01:
- str = "Enabled";
- break;
- default:
- str = "Reserved";
- break;
- }
-
- print_field("Advertising: %s (0x%2.2x)", str, cmd->enable);
+ print_enable("Advertising", cmd->enable);
}
static void print_scan_type(const char *label, uint8_t type)
@@ -6574,35 +6453,9 @@ static void le_set_scan_parameters_cmd(const void *data, uint8_t size)
static void le_set_scan_enable_cmd(const void *data, uint8_t size)
{
const struct bt_hci_cmd_le_set_scan_enable *cmd = data;
- const char *str;
-
- switch (cmd->enable) {
- case 0x00:
- str = "Disabled";
- break;
- case 0x01:
- str = "Enabled";
- break;
- default:
- str = "Reserved";
- break;
- }
-
- print_field("Scanning: %s (0x%2.2x)", str, cmd->enable);
-
- switch (cmd->filter_dup) {
- case 0x00:
- str = "Disabled";
- break;
- case 0x01:
- str = "Enabled";
- break;
- default:
- str = "Reserved";
- break;
- }
- print_field("Filter duplicates: %s (0x%2.2x)", str, cmd->filter_dup);
+ print_enable("Scanning", cmd->enable);
+ print_enable("Filter duplicates", cmd->filter_dup);
}
static void le_create_conn_cmd(const void *data, uint8_t size)
@@ -6950,21 +6803,8 @@ static void le_read_local_resolv_addr_rsp(const void *data, uint8_t size)
static void le_set_resolv_enable_cmd(const void *data, uint8_t size)
{
const struct bt_hci_cmd_le_set_resolv_enable *cmd = data;
- const char *str;
- switch (cmd->enable) {
- case 0x00:
- str = "Disabled";
- break;
- case 0x01:
- str = "Enabled";
- break;
- default:
- str = "Reserved";
- break;
- }
-
- print_field("Address resolution: %s (0x%2.2x)", str, cmd->enable);
+ print_enable("Address resolution", cmd->enable);
}
static void le_set_resolv_timeout_cmd(const void *data, uint8_t size)
@@ -7298,21 +7138,7 @@ static void le_set_ext_adv_params_cmd(const void *data, uint8_t size)
print_field("Secondary max skip: 0x%2.2x", cmd->secondary_max_skip);
print_le_phy("Secondary PHY", cmd->secondary_phy);
print_field("SID: 0x%2.2x", cmd->sid);
-
- switch (cmd->notif_enable) {
- case 0x00:
- str = "Disabled";
- break;
- case 0x01:
- str = "Enabled";
- break;
- default:
- str = "Reserved";
- break;
- }
-
- print_field("Scan request notifications: %s (0x%2.2x)",
- str, cmd->notif_enable);
+ print_enable("Scan request notifications", cmd->notif_enable);
}
static void le_set_ext_adv_params_rsp(const void *data, uint8_t size)
@@ -7423,22 +7249,9 @@ static void le_set_ext_adv_enable_cmd(const void *data, uint8_t size)
{
const struct bt_hci_cmd_le_set_ext_adv_enable *cmd = data;
const struct bt_hci_cmd_ext_adv_set *adv_set;
- const char *str;
int i;
- switch (cmd->enable) {
- case 0x00:
- str = "Disable";
- break;
- case 0x01:
- str = "Enabled";
- break;
- default:
- str = "Reserved";
- break;
- }
-
- print_field("Extended advertising: %s (0x%2.2x)", str, cmd->enable);
+ print_enable("Extended advertising", cmd->enable);
if (cmd->num_of_sets == 0)
print_field("Number of sets: Disable all sets (0x%2.2x)",
@@ -7555,21 +7368,8 @@ static void le_set_periodic_adv_data_cmd(const void *data, uint8_t size)
static void le_set_periodic_adv_enable_cmd(const void *data, uint8_t size)
{
const struct bt_hci_cmd_le_set_periodic_adv_enable *cmd = data;
- const char *str;
- switch (cmd->enable) {
- case 0x00:
- str = "Disable";
- break;
- case 0x01:
- str = "Enabled";
- break;
- default:
- str = "Reserved";
- break;
- }
-
- print_field("Periodic advertising: %s (0x%2.2x)", str, cmd->enable);
+ print_enable("Periodic advertising", cmd->enable);
print_handle(cmd->handle);
}
@@ -7620,42 +7420,9 @@ static void le_set_ext_scan_params_cmd(const void *data, uint8_t size)
print_ext_scan_phys(cmd->data, cmd->num_phys);
}
-static void print_enable(const char *label, uint8_t enable)
-{
- const char *str;
-
- switch (enable) {
- case 0x00:
- str = "Disable";
- break;
- case 0x01:
- str = "Enabled";
- break;
- default:
- str = "Reserved";
- break;
- }
-
- print_field("%s: %s (0x%2.2x)", label, str, enable);
-}
-
static void print_filter_dup(uint8_t filter_dup)
{
- const char *str;
-
- switch (filter_dup) {
- case 0x00:
- str = "Disabled";
- break;
- case 0x01:
- str = "Enabled";
- break;
- default:
- str = "Reserved";
- break;
- }
-
- print_field("Filter duplicates: %s (0x%2.2x)", str, filter_dup);
+ print_enable("Filter duplicates", filter_dup);
}
static void le_set_ext_scan_enable_cmd(const void *data, uint8_t size)
@@ -11009,21 +10776,7 @@ static void mgmt_print_uuid(const void *data)
static void mgmt_print_enable(const char *label, uint8_t enable)
{
- const char *str;
-
- switch (enable) {
- case 0x00:
- str = "Disabled";
- break;
- case 0x01:
- str = "Enabled";
- break;
- default:
- str = "Reserved";
- break;
- }
-
- print_field("%s: %s (0x%2.2x)", label, str, enable);
+ print_enable(label, enable);
}
static void mgmt_print_io_capability(uint8_t capability)
--
2.11.0
Connection Latency is a number, not time
---
monitor/packet.c | 27 ++++++++++++++++-----------
1 file changed, 16 insertions(+), 11 deletions(-)
diff --git a/monitor/packet.c b/monitor/packet.c
index fec952a12..fb299084d 100644
--- a/monitor/packet.c
+++ b/monitor/packet.c
@@ -2431,6 +2431,12 @@ static void print_window(uint16_t window)
print_slot_625("Window", window);
}
+static void print_conn_latency(const char *label, uint16_t value)
+{
+ print_field("%s: %u (0x%4.4x)", label, le16_to_cpu(value),
+ le16_to_cpu(value));
+}
+
static void print_role(uint8_t role)
{
const char *str;
@@ -6623,7 +6629,7 @@ static void le_create_conn_cmd(const void *data, uint8_t size)
print_slot_125("Min connection interval", cmd->min_interval);
print_slot_125("Max connection interval", cmd->max_interval);
- print_field("Connection latency: 0x%4.4x", le16_to_cpu(cmd->latency));
+ print_conn_latency("Connection latency", cmd->latency);
print_field("Supervision timeout: %d msec (0x%4.4x)",
le16_to_cpu(cmd->supv_timeout) * 10,
le16_to_cpu(cmd->supv_timeout));
@@ -6662,7 +6668,7 @@ static void le_conn_update_cmd(const void *data, uint8_t size)
print_handle(cmd->handle);
print_slot_125("Min connection interval", cmd->min_interval);
print_slot_125("Max connection interval", cmd->max_interval);
- print_field("Connection latency: 0x%4.4x", le16_to_cpu(cmd->latency));
+ print_conn_latency("Connection latency", cmd->latency);
print_field("Supervision timeout: %d msec (0x%4.4x)",
le16_to_cpu(cmd->supv_timeout) * 10,
le16_to_cpu(cmd->supv_timeout));
@@ -6806,7 +6812,7 @@ static void le_conn_param_req_reply_cmd(const void *data, uint8_t size)
print_handle(cmd->handle);
print_slot_125("Min connection interval", cmd->min_interval);
print_slot_125("Max connection interval", cmd->max_interval);
- print_field("Connection latency: 0x%4.4x", le16_to_cpu(cmd->latency));
+ print_conn_latency("Connection latency", cmd->latency);
print_field("Supervision timeout: %d msec (0x%4.4x)",
le16_to_cpu(cmd->supv_timeout) * 10,
le16_to_cpu(cmd->supv_timeout));
@@ -7695,9 +7701,8 @@ static void print_ext_conn_phys(const void *data, uint8_t flags)
entry->min_interval);
print_slot_125(" Max connection interval",
entry->max_interval);
- print_field(" Connection latency: %u (0x%4.4x)",
- le16_to_cpu(entry->latency),
- le16_to_cpu(entry->latency));
+ print_conn_latency(" Connection latency",
+ entry->latency);
print_field(" Supervision timeout: %d msec (0x%4.4x)",
le16_to_cpu(entry->supv_timeout) * 10,
le16_to_cpu(entry->supv_timeout));
@@ -9587,7 +9592,7 @@ static void le_conn_complete_evt(const void *data, uint8_t size)
print_peer_addr_type("Peer address type", evt->peer_addr_type);
print_addr("Peer address", evt->peer_addr, evt->peer_addr_type);
print_slot_125("Connection interval", evt->interval);
- print_slot_125("Connection latency", evt->latency);
+ print_conn_latency("Connection latency", evt->latency);
print_field("Supervision timeout: %d msec (0x%4.4x)",
le16_to_cpu(evt->supv_timeout) * 10,
le16_to_cpu(evt->supv_timeout));
@@ -9632,7 +9637,7 @@ static void le_conn_update_complete_evt(const void *data, uint8_t size)
print_status(evt->status);
print_handle(evt->handle);
print_slot_125("Connection interval", evt->interval);
- print_slot_125("Connection latency", evt->latency);
+ print_conn_latency("Connection latency", evt->latency);
print_field("Supervision timeout: %d msec (0x%4.4x)",
le16_to_cpu(evt->supv_timeout) * 10,
le16_to_cpu(evt->supv_timeout));
@@ -9663,7 +9668,7 @@ static void le_conn_param_request_evt(const void *data, uint8_t size)
print_handle(evt->handle);
print_slot_125("Min connection interval", evt->min_interval);
print_slot_125("Max connection interval", evt->max_interval);
- print_field("Connection latency: 0x%4.4x", le16_to_cpu(evt->latency));
+ print_conn_latency("Connection latency", evt->latency);
print_field("Supervision timeout: %d msec (0x%4.4x)",
le16_to_cpu(evt->supv_timeout) * 10,
le16_to_cpu(evt->supv_timeout));
@@ -9708,7 +9713,7 @@ static void le_enhanced_conn_complete_evt(const void *data, uint8_t size)
print_addr("Local resolvable private address", evt->local_rpa, 0x01);
print_addr("Peer resolvable private address", evt->peer_rpa, 0x01);
print_slot_125("Connection interval", evt->interval);
- print_slot_125("Connection latency", evt->latency);
+ print_conn_latency("Connection latency", evt->latency);
print_field("Supervision timeout: %d msec (0x%4.4x)",
le16_to_cpu(evt->supv_timeout) * 10,
le16_to_cpu(evt->supv_timeout));
@@ -11159,7 +11164,7 @@ static void mgmt_print_connection_parameter(const void *data)
mgmt_print_address(data, address_type);
print_field("Min connection interval: %u", min_conn_interval);
print_field("Max connection interval: %u", max_conn_interval);
- print_field("Connection latency: %u", conn_latency);
+ print_conn_latency("Connection latency", conn_latency);
print_field("Supervision timeout: %u", supv_timeout);
}
--
2.11.0
In Bluetooth 5.0 spec this error code is named "Advertising Timeout"
---
monitor/packet.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/monitor/packet.c b/monitor/packet.c
index f0efd78cd..e1f69b145 100644
--- a/monitor/packet.c
+++ b/monitor/packet.c
@@ -496,7 +496,7 @@ static const struct {
{ 0x39, "Connection Rejected due to No Suitable Channel Found" },
{ 0x3a, "Controller Busy" },
{ 0x3b, "Unacceptable Connection Parameters" },
- { 0x3c, "Directed Advertising Timeout" },
+ { 0x3c, "Advertising Timeout" },
{ 0x3d, "Connection Terminated due to MIC Failure" },
{ 0x3e, "Connection Failed to be Established" },
{ 0x3f, "MAC Connection Failed" },
--
2.11.0
These codes were added in Bluetooth 5
---
monitor/packet.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/monitor/packet.c b/monitor/packet.c
index fb299084d..f0efd78cd 100644
--- a/monitor/packet.c
+++ b/monitor/packet.c
@@ -502,6 +502,10 @@ static const struct {
{ 0x3f, "MAC Connection Failed" },
{ 0x40, "Coarse Clock Adjustment Rejected "
"but Will Try to Adjust Using Clock Dragging" },
+ { 0x41, "Type0 Submap Not Defined" },
+ { 0x42, "Unknown Advertising Identifier" },
+ { 0x43, "Limit Reached" },
+ { 0x44, "Operation Cancelled by Host" },
{ }
};
--
2.11.0
This patch adds decoding for following commands:
LE Periodic Advertising Create Sync
LE Periodic Advertising Create Sync Cancel
LE Periodic Advertising Terminate Sync
LE Add Device To Periodic Advertiser List
LE Remove Device From Periodic Advertiser List
LE Clear Periodic Advertiser List
LE Read Periodic Advertiser List Size
< HCI Command: LE Periodic Advertising Create Sync (0x08|0x0044) plen 14
Filter policy: Use Periodic Advertiser List (0x01)
SID: 0x02
Adv address type: Random (0x01)
Adv address: 00:00:00:00:00:00 (Non-Resolvable)
Skip: 0x0201
Sync timeout: 30 msec (0x0003)
Unused: 0x0a
< HCI Command: LE Periodic Advertising Terminate Sync (0x08|0x0046) plen 2
Sync handle: 0x0201
< HCI Command: LE Add Device To Periodic Advertiser List (0x08|0x0047) plen 8
Adv address type: Random (0x01)
Adv address: 07:06:05:04:03:02 (Non-Resolvable)
SID: 0x08
< HCI Command: LE Add Device To Periodic Advertiser List (0x08|0x0047) plen 8
Adv address type: Random (0x01)
Adv address: 07:06:05:04:03:02 (Non-Resolvable)
SID: 0x08
---
monitor/bt.h | 40 +++++++++++++++++++++++++
monitor/packet.c | 89 +++++++++++++++++++++++++++++++++++++++++++++++++++-----
2 files changed, 122 insertions(+), 7 deletions(-)
diff --git a/monitor/bt.h b/monitor/bt.h
index 74439b9e5..757adfa18 100644
--- a/monitor/bt.h
+++ b/monitor/bt.h
@@ -2316,6 +2316,46 @@ struct bt_hci_le_ext_create_conn {
uint16_t max_length;
} __attribute__ ((packed));
+#define BT_HCI_CMD_LE_PERIODIC_ADV_CREATE_SYNC 0x2044
+struct bt_hci_cmd_le_periodic_adv_create_sync {
+ uint8_t filter_policy;
+ uint8_t sid;
+ uint8_t addr_type;
+ uint8_t addr[6];
+ uint16_t skip;
+ uint16_t sync_timeout;
+ uint8_t unused;
+} __attribute__ ((packed));
+
+#define BT_HCI_CMD_LE_PERIODIC_ADV_CREATE_SYNC_CANCEL 0x2045
+
+#define BT_HCI_CMD_LE_PERIODIC_ADV_TERM_SYNC 0x2046
+struct bt_hci_cmd_le_periodic_adv_term_sync {
+ uint16_t sync_handle;
+} __attribute__ ((packed));
+
+#define BT_HCI_CMD_LE_ADD_DEV_PERIODIC_ADV_LIST 0x2047
+struct bt_hci_cmd_le_add_dev_periodic_adv_list {
+ uint8_t addr_type;
+ uint8_t addr[6];
+ uint8_t sid;
+} __attribute__ ((packed));
+
+#define BT_HCI_CMD_LE_REMOVE_DEV_PERIODIC_ADV_LIST 0x2048
+struct bt_hci_cmd_le_remove_dev_periodic_adv_list {
+ uint8_t addr_type;
+ uint8_t addr[6];
+ uint8_t sid;
+} __attribute__ ((packed));
+
+#define BT_HCI_CMD_LE_CLEAR_PERIODIC_ADV_LIST 0x2049
+
+#define BT_HCI_CMD_LE_READ_PERIODIC_ADV_LIST_SIZE 0x204a
+struct bt_hci_rsp_le_read_dev_periodic_adv_list_size {
+ uint8_t status;
+ uint8_t list_size;
+} __attribute__ ((packed));
+
#define BT_HCI_EVT_INQUIRY_COMPLETE 0x01
struct bt_hci_evt_inquiry_complete {
uint8_t status;
diff --git a/monitor/packet.c b/monitor/packet.c
index 6a602d8a8..56d935a3c 100644
--- a/monitor/packet.c
+++ b/monitor/packet.c
@@ -7740,6 +7740,67 @@ static void le_ext_create_conn_cmd(const void *data, uint8_t size)
print_ext_conn_phys(cmd->data, cmd->phys);
}
+static void le_periodic_adv_create_sync_cmd(const void *data, uint8_t size)
+{
+ const struct bt_hci_cmd_le_periodic_adv_create_sync *cmd = data;
+ const char *str;
+
+ switch (cmd->filter_policy) {
+ case 0x00:
+ str = "Use specified advertising parameters";
+ break;
+ case 0x01:
+ str = "Use Periodic Advertiser List";
+ break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ print_field("Filter policy: %s (0x%2.2x)", str, cmd->filter_policy);
+ print_field("SID: 0x%2.2x", cmd->sid);
+ print_addr_type("Adv address type", cmd->addr_type);
+ print_addr("Adv address", cmd->addr, cmd->addr_type);
+ print_field("Skip: 0x%4.4x", cmd->skip);
+ print_field("Sync timeout: %d msec (0x%4.4x)",
+ le16_to_cpu(cmd->sync_timeout) * 10,
+ le16_to_cpu(cmd->sync_timeout));
+ print_field("Unused: 0x%2.2x", cmd->unused);
+}
+
+static void le_periodic_adv_term_sync_cmd(const void *data, uint8_t size)
+{
+ const struct bt_hci_cmd_le_periodic_adv_term_sync *cmd = data;
+
+ print_field("Sync handle: 0x%4.4x", cmd->sync_handle);
+}
+
+static void le_add_dev_periodic_adv_list_cmd(const void *data, uint8_t size)
+{
+ const struct bt_hci_cmd_le_add_dev_periodic_adv_list *cmd = data;
+
+ print_addr_type("Adv address type", cmd->addr_type);
+ print_addr("Adv address", cmd->addr, cmd->addr_type);
+ print_field("SID: 0x%2.2x", cmd->sid);
+}
+
+static void le_remove_dev_periodic_adv_list_cmd(const void *data, uint8_t size)
+{
+ const struct bt_hci_cmd_le_remove_dev_periodic_adv_list *cmd = data;
+
+ print_addr_type("Adv address type", cmd->addr_type);
+ print_addr("Adv address", cmd->addr, cmd->addr_type);
+ print_field("SID: 0x%2.2x", cmd->sid);
+}
+
+static void le_read_periodic_adv_list_size_rsp(const void *data, uint8_t size)
+{
+ const struct bt_hci_rsp_le_read_dev_periodic_adv_list_size *rsp = data;
+
+ print_status(rsp->status);
+ print_field("List size: 0x%2.2x", rsp->list_size);
+}
+
struct opcode_data {
uint16_t opcode;
int bit;
@@ -8494,13 +8555,27 @@ static const struct opcode_data opcode_table[] = {
{ 0x2043, 303, "LE Extended Create Connection",
le_ext_create_conn_cmd, 10, false,
status_rsp, 1, true },
- { 0x2044, 304, "LE Periodic Advertising Create Sync" },
- { 0x2045, 305, "LE Periodic Advertising Create Sync Cancel" },
- { 0x2046, 306, "LE Periodic Advertising Terminate Sync" },
- { 0x2047, 307, "LE Add Device To Periodic Advertiser List" },
- { 0x2048, 308, "LE Remove Device From Periodic Advertiser List" },
- { 0x2049, 309, "LE Clear Periodic Advertiser List" },
- { 0x204a, 310, "LE Read Periodic Advertiser List Size" },
+ { 0x2044, 304, "LE Periodic Advertising Create Sync",
+ le_periodic_adv_create_sync_cmd, 14, true,
+ status_rsp, 1, true },
+ { 0x2045, 305, "LE Periodic Advertising Create Sync Cancel",
+ null_cmd, 0, true,
+ status_rsp, 1, true },
+ { 0x2046, 306, "LE Periodic Advertising Terminate Sync",
+ le_periodic_adv_term_sync_cmd, 2, true,
+ status_rsp, 1, true },
+ { 0x2047, 307, "LE Add Device To Periodic Advertiser List",
+ le_add_dev_periodic_adv_list_cmd, 8, true,
+ status_rsp, 1, true },
+ { 0x2048, 308, "LE Remove Device From Periodic Advertiser List",
+ le_remove_dev_periodic_adv_list_cmd, 8, true,
+ status_rsp, 1, true },
+ { 0x2049, 309, "LE Clear Periodic Advertiser List",
+ null_cmd, 0, true,
+ status_rsp, 1, true },
+ { 0x204a, 310, "LE Read Periodic Advertiser List Size",
+ null_cmd, 0, true,
+ le_read_periodic_adv_list_size_rsp, 2, true },
{ 0x204b, 311, "LE Read Transmit Power" },
{ 0x204c, 312, "LE Read RF Path Compensation" },
{ 0x204d, 313, "LE Write RF Path Compensation" },
--
2.11.0
This patch adds decoding for following commands:
LE Set Extended Scan Parameters
LE Set Extended Scan Enable
LE Extended Create Connection
LE Extended Advertising Report Event
< HCI Command: LE Set Extended Scan Parameters (0x08|0x0041) plen 13
Own address type: Public (0x00)
Filter policy: Accept all advertisement (0x00)
PHYs: 0x05
Entry 0: LE 1M
Type: Active (0x01)
Interval: 30.000 msec (0x0030)
Window: 30.000 msec (0x0030)
Entry 1: LE Coded
Type: Active (0x01)
Interval: 30.000 msec (0x0030)
Window: 30.000 msec (0x0030)
< HCI Command: LE Set Extended Scan Enable (0x08|0x0042) plen 6
Extended scan: Enabled (0x01)
Filter duplicates: Disabled (0x00)
Duration: 0 msec (0x0000)
Period: 0.00 sec (0x0000)
< HCI Command: LE Extended Create Connection (0x08|0x0043) plen 29
Filter policy: White list is not used (0x00)
Own address type: Public (0x00)
Peer address type: Public (0x00)
Peer address: 11:22:33:C0:DE:C0 (OUI 11-22-33)
Initiating PHYs: 0x04
Entry 0: LE Coded
Scan interval: 10.000 msec (0x0010)
Scan window: 10.000 msec (0x0010)
Min connection interval: 30.00 msec (0x0018)
Max connection interval: 50.00 msec (0x0028)
Connection latency: 0 (0x0000)
Supervision timeout: 2560 msec (0x0100)
Min connection length: 10.000 msec (0x0010)
Max connection length: 480.000 msec (0x0300)
---
monitor/bt.h | 60 ++++++++
monitor/packet.c | 406 ++++++++++++++++++++++++++++++++++++++++++++++++++++---
2 files changed, 449 insertions(+), 17 deletions(-)
diff --git a/monitor/bt.h b/monitor/bt.h
index 0160dcc7f..74439b9e5 100644
--- a/monitor/bt.h
+++ b/monitor/bt.h
@@ -2275,6 +2275,47 @@ struct bt_hci_cmd_le_set_periodic_adv_enable {
uint8_t handle;
} __attribute__ ((packed));
+#define BT_HCI_CMD_LE_SET_EXT_SCAN_PARAMS 0x2041
+struct bt_hci_cmd_le_set_ext_scan_params {
+ uint8_t own_addr_type;
+ uint8_t filter_policy;
+ uint8_t num_phys;
+ uint8_t data[0];
+} __attribute__ ((packed));
+struct bt_hci_le_scan_phy {
+ uint8_t type;
+ uint16_t interval;
+ uint16_t window;
+} __attribute__ ((packed));
+
+#define BT_HCI_CMD_LE_SET_EXT_SCAN_ENABLE 0x2042
+struct bt_hci_cmd_le_set_ext_scan_enable {
+ uint8_t enable;
+ uint8_t filter_dup;
+ uint16_t duration;
+ uint16_t period;
+} __attribute__ ((packed));
+
+#define BT_HCI_CMD_LE_EXT_CREATE_CONN 0x2043
+struct bt_hci_cmd_le_ext_create_conn {
+ uint8_t filter_policy;
+ uint8_t own_addr_type;
+ uint8_t peer_addr_type;
+ uint8_t peer_addr[6];
+ uint8_t phys;
+ uint8_t data[0];
+} __attribute__ ((packed));
+struct bt_hci_le_ext_create_conn {
+ uint16_t scan_interval;
+ uint16_t scan_window;
+ uint16_t min_interval;
+ uint16_t max_interval;
+ uint16_t latency;
+ uint16_t supv_timeout;
+ uint16_t min_length;
+ uint16_t max_length;
+} __attribute__ ((packed));
+
#define BT_HCI_EVT_INQUIRY_COMPLETE 0x01
struct bt_hci_evt_inquiry_complete {
uint8_t status;
@@ -2885,6 +2926,25 @@ struct bt_hci_evt_le_phy_update_complete {
uint8_t rx_phy;
} __attribute__ ((packed));
+#define BT_HCI_EVT_LE_EXT_ADV_REPORT 0x0d
+struct bt_hci_evt_le_ext_adv_report {
+ uint8_t num_reports;
+} __attribute__ ((packed));
+struct bt_hci_le_ext_adv_report {
+ uint16_t event_type;
+ uint8_t addr_type;
+ uint8_t addr[6];
+ uint8_t primary_phy;
+ uint8_t secondary_phy;
+ uint8_t sid;
+ uint8_t tx_power;
+ int8_t rssi;
+ uint16_t interval;
+ uint8_t direct_addr_type;
+ uint8_t direct_addr[6];
+ uint8_t data_len;
+} __attribute__ ((packed));
+
#define BT_HCI_EVT_LE_ADV_SET_TERM 0x12
struct bt_hci_evt_le_adv_set_term {
uint8_t status;
diff --git a/monitor/packet.c b/monitor/packet.c
index f43be9adb..6a602d8a8 100644
--- a/monitor/packet.c
+++ b/monitor/packet.c
@@ -2305,7 +2305,7 @@ static void print_num_reports(uint8_t num_reports)
print_field("Num reports: %d", num_reports);
}
-static void print_adv_event_type(uint8_t type)
+static void print_adv_event_type(const char *label, uint8_t type)
{
const char *str;
@@ -2330,7 +2330,7 @@ static void print_adv_event_type(uint8_t type)
break;
}
- print_field("Event type: %s (0x%2.2x)", str, type);
+ print_field("%s: %s (0x%2.2x)", label, str, type);
}
static void print_adv_channel_map(const char *label, uint8_t value)
@@ -6506,12 +6506,11 @@ static void le_set_adv_enable_cmd(const void *data, uint8_t size)
print_field("Advertising: %s (0x%2.2x)", str, cmd->enable);
}
-static void le_set_scan_parameters_cmd(const void *data, uint8_t size)
+static void print_scan_type(const char *label, uint8_t type)
{
- const struct bt_hci_cmd_le_set_scan_parameters *cmd = data;
const char *str;
- switch (cmd->type) {
+ switch (type) {
case 0x00:
str = "Passive";
break;
@@ -6523,13 +6522,14 @@ static void le_set_scan_parameters_cmd(const void *data, uint8_t size)
break;
}
- print_field("Type: %s (0x%2.2x)", str, cmd->type);
+ print_field("%s: %s (0x%2.2x)", label, str, type);
+}
- print_interval(cmd->interval);
- print_window(cmd->window);
- print_own_addr_type(cmd->own_addr_type);
+static void print_scan_filter_policy(uint8_t policy)
+{
+ const char *str;
- switch (cmd->filter_policy) {
+ switch (policy) {
case 0x00:
str = "Accept all advertisement";
break;
@@ -6547,7 +6547,18 @@ static void le_set_scan_parameters_cmd(const void *data, uint8_t size)
break;
}
- print_field("Filter policy: %s (0x%2.2x)", str, cmd->filter_policy);
+ print_field("Filter policy: %s (0x%2.2x)", str, policy);
+}
+
+static void le_set_scan_parameters_cmd(const void *data, uint8_t size)
+{
+ const struct bt_hci_cmd_le_set_scan_parameters *cmd = data;
+
+ print_scan_type("Type", cmd->type);
+ print_interval(cmd->interval);
+ print_window(cmd->window);
+ print_own_addr_type(cmd->own_addr_type);
+ print_scan_filter_policy(cmd->filter_policy);
}
static void le_set_scan_enable_cmd(const void *data, uint8_t size)
@@ -7552,6 +7563,183 @@ static void le_set_periodic_adv_enable_cmd(const void *data, uint8_t size)
print_handle(cmd->handle);
}
+static const struct {
+ uint8_t bit;
+ const char *str;
+} ext_scan_phys_table[] = {
+ { 0, "LE 1M" },
+ { 2, "LE Coded" },
+ { }
+};
+
+static void print_ext_scan_phys(const void *data, uint8_t flags)
+{
+ const struct bt_hci_le_scan_phy *scan_phy;
+ uint8_t mask = flags;
+ int bits_set = 0;
+ int i;
+
+ print_field("PHYs: 0x%2.2x", flags);
+
+ for (i = 0; ext_scan_phys_table[i].str; i++) {
+ if (flags & (1 << ext_scan_phys_table[i].bit)) {
+ scan_phy = data + bits_set * sizeof(*scan_phy);
+ mask &= ~(1 << ext_scan_phys_table[i].bit);
+
+ print_field("Entry %d: %s", bits_set,
+ ext_scan_phys_table[i].str);
+ print_scan_type(" Type", scan_phy->type);
+ print_slot_625(" Interval", scan_phy->interval);
+ print_slot_625(" Window", scan_phy->window);
+
+ ++bits_set;
+ }
+ }
+
+ if (mask)
+ print_text(COLOR_UNKNOWN_ADV_FLAG, " Unknown scanning PHYs"
+ " (0x%2.2x)", mask);
+}
+
+static void le_set_ext_scan_params_cmd(const void *data, uint8_t size)
+{
+ const struct bt_hci_cmd_le_set_ext_scan_params *cmd = data;
+
+ print_own_addr_type(cmd->own_addr_type);
+ print_scan_filter_policy(cmd->filter_policy);
+ print_ext_scan_phys(cmd->data, cmd->num_phys);
+}
+
+static void print_enable(const char *label, uint8_t enable)
+{
+ const char *str;
+
+ switch (enable) {
+ case 0x00:
+ str = "Disable";
+ break;
+ case 0x01:
+ str = "Enabled";
+ break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ print_field("%s: %s (0x%2.2x)", label, str, enable);
+}
+
+static void print_filter_dup(uint8_t filter_dup)
+{
+ const char *str;
+
+ switch (filter_dup) {
+ case 0x00:
+ str = "Disabled";
+ break;
+ case 0x01:
+ str = "Enabled";
+ break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ print_field("Filter duplicates: %s (0x%2.2x)", str, filter_dup);
+}
+
+static void le_set_ext_scan_enable_cmd(const void *data, uint8_t size)
+{
+ const struct bt_hci_cmd_le_set_ext_scan_enable *cmd = data;
+
+ print_enable("Extended scan", cmd->enable);
+ print_filter_dup(cmd->filter_dup);
+
+ print_field("Duration: %d msec (0x%4.4x)",
+ le16_to_cpu(cmd->duration) * 10,
+ le16_to_cpu(cmd->duration));
+ print_field("Period: %.2f sec (0x%4.4x)",
+ le16_to_cpu(cmd->period) * 1.28,
+ le16_to_cpu(cmd->period));
+}
+
+static const struct {
+ uint8_t bit;
+ const char *str;
+} ext_conn_phys_table[] = {
+ { 0, "LE 1M" },
+ { 1, "LE 2M" },
+ { 2, "LE Coded" },
+ { }
+};
+
+static void print_ext_conn_phys(const void *data, uint8_t flags)
+{
+ const struct bt_hci_le_ext_create_conn *entry;
+ uint8_t mask = flags;
+ int bits_set = 0;
+ int i;
+
+ print_field("Initiating PHYs: 0x%2.2x", flags);
+
+ for (i = 0; ext_conn_phys_table[i].str; i++) {
+ if (flags & (1 << ext_conn_phys_table[i].bit)) {
+ entry = data + bits_set * sizeof(*entry);
+ mask &= ~(1 << ext_conn_phys_table[i].bit);
+
+ print_field("Entry %d: %s", bits_set,
+ ext_conn_phys_table[i].str);
+ print_slot_625(" Scan interval", entry->scan_interval);
+ print_slot_625(" Scan window", entry->scan_window);
+ print_slot_125(" Min connection interval",
+ entry->min_interval);
+ print_slot_125(" Max connection interval",
+ entry->max_interval);
+ print_field(" Connection latency: %u (0x%4.4x)",
+ le16_to_cpu(entry->latency),
+ le16_to_cpu(entry->latency));
+ print_field(" Supervision timeout: %d msec (0x%4.4x)",
+ le16_to_cpu(entry->supv_timeout) * 10,
+ le16_to_cpu(entry->supv_timeout));
+ print_slot_625(" Min connection length",
+ entry->min_length);
+ print_slot_625(" Max connection length",
+ entry->max_length);
+
+ ++bits_set;
+ }
+ }
+
+ if (mask)
+ print_text(COLOR_UNKNOWN_ADV_FLAG, " Unknown scanning PHYs"
+ " (0x%2.2x)", mask);
+}
+
+static void le_ext_create_conn_cmd(const void *data, uint8_t size)
+{
+ const struct bt_hci_cmd_le_ext_create_conn *cmd = data;
+ const char *str;
+
+ switch (cmd->filter_policy) {
+ case 0x00:
+ str = "White list is not used";
+ break;
+ case 0x01:
+ str = "White list is used";
+ break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ print_field("Filter policy: %s (0x%2.2x)", str, cmd->filter_policy);
+
+ print_own_addr_type(cmd->own_addr_type);
+ print_peer_addr_type("Peer address type", cmd->peer_addr_type);
+ print_addr("Peer address", cmd->peer_addr, cmd->peer_addr_type);
+ print_ext_conn_phys(cmd->data, cmd->phys);
+}
+
struct opcode_data {
uint16_t opcode;
int bit;
@@ -8297,9 +8485,15 @@ static const struct opcode_data opcode_table[] = {
{ 0x2040, 300, "LE Set Periodic Advertising Enable",
le_set_periodic_adv_enable_cmd, 2, true,
status_rsp, 1, true },
- { 0x2041, 301, "LE Set Extended Scan Parameters" },
- { 0x2042, 302, "LE Set Extended Scan Enable" },
- { 0x2043, 303, "LE Extended Create Connection" },
+ { 0x2041, 301, "LE Set Extended Scan Parameters",
+ le_set_ext_scan_params_cmd, 3, false,
+ status_rsp, 1, true },
+ { 0x2042, 302, "LE Set Extended Scan Enable",
+ le_set_ext_scan_enable_cmd, 6, true,
+ status_rsp, 1, true },
+ { 0x2043, 303, "LE Extended Create Connection",
+ le_ext_create_conn_cmd, 10, false,
+ status_rsp, 1, true },
{ 0x2044, 304, "LE Periodic Advertising Create Sync" },
{ 0x2045, 305, "LE Periodic Advertising Create Sync Cancel" },
{ 0x2046, 306, "LE Periodic Advertising Terminate Sync" },
@@ -9275,7 +9469,7 @@ static void le_adv_report_evt(const void *data, uint8_t size)
print_num_reports(evt->num_reports);
report:
- print_adv_event_type(evt->event_type);
+ print_adv_event_type("Event type", evt->event_type);
print_peer_addr_type("Address type", evt->addr_type);
print_addr("Address", evt->addr, evt->addr_type);
print_field("Data length: %d", evt->data_len);
@@ -9393,7 +9587,7 @@ static void le_direct_adv_report_evt(const void *data, uint8_t size)
print_num_reports(evt->num_reports);
- print_adv_event_type(evt->event_type);
+ print_adv_event_type("Event type", evt->event_type);
print_peer_addr_type("Address type", evt->addr_type);
print_addr("Address", evt->addr, evt->addr_type);
print_addr_type("Direct address type", evt->direct_addr_type);
@@ -9414,6 +9608,183 @@ static void le_phy_update_complete_evt(const void *data, uint8_t size)
print_le_phy("RX PHY", evt->rx_phy);
}
+static const struct {
+ uint8_t bit;
+ const char *str;
+} ext_adv_report_evt_type[] = {
+ { 0, "Connectable" },
+ { 1, "Scannable" },
+ { 2, "Directed" },
+ { 3, "Scan response" },
+ { 4, "Use legacy advertising PDUs" },
+ { }
+};
+
+static void print_ext_adv_report_evt_type(const char *indent, uint16_t flags)
+{
+ uint16_t mask = flags;
+ uint16_t props = flags;
+ uint8_t data_status;
+ const char *str;
+ int i;
+
+ print_field("%sEvent type: 0x%4.4x", indent, flags);
+
+ props &= 0x1f;
+ print_field("%s Props: 0x%4.4x", indent, props);
+ for (i = 0; ext_adv_report_evt_type[i].str; i++) {
+ if (flags & (1 << ext_adv_report_evt_type[i].bit)) {
+ print_field("%s %s", indent,
+ ext_adv_report_evt_type[i].str);
+ mask &= ~(1 << ext_adv_report_evt_type[i].bit);
+ }
+ }
+
+ data_status = (flags >> 5) & 3;
+ mask &= ~(data_status << 5);
+
+ switch (data_status) {
+ case 0x00:
+ str = "Complete";
+ break;
+ case 0x01:
+ str = "Incomplete, more data to come";
+ break;
+ case 0x02:
+ str = "Incomplete, data truncated, no more to come";
+ break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ print_field("%s Data status: %s", indent, str);
+
+ if (mask)
+ print_text(COLOR_UNKNOWN_ADV_FLAG,
+ "%s Reserved (0x%4.4x)", indent, mask);
+}
+
+static void print_legacy_adv_report_pdu(uint16_t flags)
+{
+ const char *str;
+
+ if (!(flags & (1 << 4)))
+ return;
+
+ switch (flags) {
+ case 0x10:
+ str = "ADV_NONCONN_IND";
+ break;
+ case 0x12:
+ str = "ADV_SCAN_IND";
+ break;
+ case 0x13:
+ str = "ADV_IND";
+ break;
+ case 0x15:
+ str = "ADV_DIRECT_IND";
+ break;
+ case 0x1a:
+ str = "SCAN_RSP to an ADV_IND";
+ break;
+ case 0x1b:
+ str = "SCAN_RSP to an ADV_SCAN_IND";
+ break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ print_field(" Legacy PDU Type: %s (0x%4.4x)", str, flags);
+}
+
+static void le_ext_adv_report_evt(const void *data, uint8_t size)
+{
+ const struct bt_hci_evt_le_ext_adv_report *evt = data;
+ const struct bt_hci_le_ext_adv_report *report;
+ const char *str;
+ int i;
+
+ print_num_reports(evt->num_reports);
+
+ data += sizeof(evt->num_reports);
+
+ for (i = 0; i < evt->num_reports; ++i) {
+ report = data;
+ print_field("Entry %d", i);
+ print_ext_adv_report_evt_type(" ", report->event_type);
+ print_legacy_adv_report_pdu(report->event_type);
+ print_peer_addr_type(" Address type", report->addr_type);
+ print_addr(" Address", report->addr, report->addr_type);
+
+ switch (report->primary_phy) {
+ case 0x01:
+ str = "LE 1M";
+ break;
+ case 0x03:
+ str = "LE Coded";
+ break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ print_field(" Primary PHY: %s", str);
+
+ switch (report->secondary_phy) {
+ case 0x00:
+ str = "No packets";
+ break;
+ case 0x01:
+ str = "LE 1M";
+ break;
+ case 0x02:
+ str = "LE 2M";
+ break;
+ case 0x03:
+ str = "LE Coded";
+ break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ print_field(" Secondary PHY: %s", str);
+
+ if (report->sid == 0xff)
+ print_field(" SID: no ADI field (0x%2.2x)",
+ report->sid);
+ else if (report->sid > 0x0f)
+ print_field(" SID: Reserved (0x%2.2x)", report->sid);
+ else
+ print_field(" SID: 0x%2.2x", report->sid);
+
+ print_field(" TX power: %d dBm", report->tx_power);
+
+ if (report->rssi == 127)
+ print_field(" RSSI: not available (0x%2.2x)",
+ (uint8_t) report->rssi);
+ else if (report->rssi >= -127 && report->rssi <= 20)
+ print_field(" RSSI: %d dBm (0x%2.2x)",
+ report->rssi, (uint8_t) report->rssi);
+ else
+ print_field(" RSSI: reserved (0x%2.2x)",
+ (uint8_t) report->rssi);
+
+ print_slot_125(" Periodic advertising invteral",
+ report->interval);
+ print_peer_addr_type(" Direct address type",
+ report->direct_addr_type);
+ print_addr(" Direct address", report->direct_addr,
+ report->direct_addr_type);
+ print_field(" Data length: 0x%2.2x", report->data_len);
+ data += sizeof(struct bt_hci_le_ext_adv_report);
+ packet_hexdump(data, report->data_len);
+ data += report->data_len;
+ }
+}
+
static void le_adv_set_term_evt(const void *data, uint8_t size)
{
const struct bt_hci_evt_le_adv_set_term *evt = data;
@@ -9525,7 +9896,8 @@ static const struct subevent_data le_meta_event_table[] = {
le_direct_adv_report_evt, 1, false },
{ 0x0c, "LE PHY Update Complete",
le_phy_update_complete_evt, 5, true},
- { 0x0d, "LE Extended Advertising Report" },
+ { 0x0d, "LE Extended Advertising Report",
+ le_ext_adv_report_evt, 1, false},
{ 0x0e, "LE Periodic Advertising Sync Established" },
{ 0x0f, "LE Periodic Advertising Report" },
{ 0x10, "LE Periodic Advertising Sync Lost" },
--
2.11.0
This patch adds decoding for following commands:
LE Set Periodic Advertising Parameters
LE Set Periodic Advertising Data
LE Set Periodic Advertising Enable
< HCI Command: LE Set Periodic Advertising Parameters (0x08|0x003e) plen 7
Handle: 1
Min interval: 2.50 msec (0x0002)
Max interval: 318.75 msec (0x00ff)
Properties: 0x00ff
Include TxPower
Unknown advertising properties (0x00bf)
< HCI Command: LE Set Periodic Advertising Data (0x08|0x003f) plen 7
Handle: 1
Operation: Last fragment (0x02)
Data length: 0x04
ff 00 ff 00 ....
< HCI Command: LE Set Periodic Advertising Enable (0x08|0x0040) plen 2
Periodic advertising: Enabled (0x01)
Handle: 2
---
monitor/bt.h | 22 ++++++++++++
monitor/packet.c | 102 +++++++++++++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 121 insertions(+), 3 deletions(-)
diff --git a/monitor/bt.h b/monitor/bt.h
index aa55579bf..0160dcc7f 100644
--- a/monitor/bt.h
+++ b/monitor/bt.h
@@ -2253,6 +2253,28 @@ struct bt_hci_cmd_le_remove_adv_set {
#define BT_HCI_CMD_LE_CLEAR_ADV_SETS 0x203d
+#define BT_HCI_CMD_LE_SET_PERIODIC_ADV_PARAMS 0x203e
+struct bt_hci_cmd_le_set_periodic_adv_params {
+ uint8_t handle;
+ uint16_t min_interval;
+ uint16_t max_interval;
+ uint16_t properties;
+} __attribute__ ((packed));
+
+#define BT_HCI_CMD_LE_SET_PERIODIC_ADV_DATA 0x203f
+struct bt_hci_cmd_le_set_periodic_adv_data {
+ uint8_t handle;
+ uint8_t operation;
+ uint8_t data_len;
+ uint8_t data[0];
+} __attribute__ ((packed));
+
+#define BT_HCI_CMD_LE_SET_PERIODIC_ADV_ENABLE 0x2040
+struct bt_hci_cmd_le_set_periodic_adv_enable {
+ uint8_t enable;
+ uint8_t handle;
+} __attribute__ ((packed));
+
#define BT_HCI_EVT_INQUIRY_COMPLETE 0x01
struct bt_hci_evt_inquiry_complete {
uint8_t status;
diff --git a/monitor/packet.c b/monitor/packet.c
index 4c1ba1cbe..f43be9adb 100644
--- a/monitor/packet.c
+++ b/monitor/packet.c
@@ -7462,6 +7462,96 @@ static void le_remove_adv_set_cmd(const void *data, uint8_t size)
print_handle(cmd->handle);
}
+static const struct {
+ uint8_t bit;
+ const char *str;
+} periodic_adv_properties_table[] = {
+ { 6, "Include TxPower" },
+ { }
+};
+
+static void print_periodic_adv_properties(uint16_t flags)
+{
+ uint16_t mask = flags;
+ int i;
+
+ print_field("Properties: 0x%4.4x", flags);
+
+ for (i = 0; periodic_adv_properties_table[i].str; i++) {
+ if (flags & (1 << periodic_adv_properties_table[i].bit)) {
+ print_field(" %s",
+ periodic_adv_properties_table[i].str);
+ mask &= ~(1 << periodic_adv_properties_table[i].bit);
+ }
+ }
+
+ if (mask)
+ print_text(COLOR_UNKNOWN_ADV_FLAG,
+ " Unknown advertising properties (0x%4.4x)",
+ mask);
+}
+
+static void le_set_periodic_adv_params_cmd(const void *data, uint8_t size)
+{
+ const struct bt_hci_cmd_le_set_periodic_adv_params *cmd = data;
+
+ print_handle(cmd->handle);
+ print_slot_125("Min interval", cmd->min_interval);
+ print_slot_125("Max interval", cmd->max_interval);
+ print_periodic_adv_properties(cmd->properties);
+}
+
+static void le_set_periodic_adv_data_cmd(const void *data, uint8_t size)
+{
+ const struct bt_hci_cmd_le_set_periodic_adv_data *cmd = data;
+ const char *str;
+
+ print_handle(cmd->handle);
+
+ switch (cmd->operation) {
+ case 0x00:
+ str = "Immediate fragment";
+ break;
+ case 0x01:
+ str = "First fragment";
+ break;
+ case 0x02:
+ str = "Last fragment";
+ break;
+ case 0x03:
+ str = "Complete ext advertising data";
+ break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ print_field("Operation: %s (0x%2.2x)", str, cmd->operation);
+ print_field("Data length: 0x%2.2x", cmd->data_len);
+ print_eir(cmd->data, cmd->data_len, true);
+}
+
+static void le_set_periodic_adv_enable_cmd(const void *data, uint8_t size)
+{
+ const struct bt_hci_cmd_le_set_periodic_adv_enable *cmd = data;
+ const char *str;
+
+ switch (cmd->enable) {
+ case 0x00:
+ str = "Disable";
+ break;
+ case 0x01:
+ str = "Enabled";
+ break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ print_field("Periodic advertising: %s (0x%2.2x)", str, cmd->enable);
+ print_handle(cmd->handle);
+}
+
struct opcode_data {
uint16_t opcode;
int bit;
@@ -8198,9 +8288,15 @@ static const struct opcode_data opcode_table[] = {
{ 0x203d, 297, "LE Clear Advertising Sets",
null_cmd, 0, true,
status_rsp, 1, true },
- { 0x203e, 298, "LE Set Periodic Advertising Parameters" },
- { 0x203f, 299, "LE Set Periodic Advertising Data" },
- { 0x2040, 300, "LE Set Periodic Advertising Enable" },
+ { 0x203e, 298, "LE Set Periodic Advertising Parameters",
+ le_set_periodic_adv_params_cmd, 7, true,
+ status_rsp, 1, true },
+ { 0x203f, 299, "LE Set Periodic Advertising Data",
+ le_set_periodic_adv_data_cmd, 3, false,
+ status_rsp, 1, true },
+ { 0x2040, 300, "LE Set Periodic Advertising Enable",
+ le_set_periodic_adv_enable_cmd, 2, true,
+ status_rsp, 1, true },
{ 0x2041, 301, "LE Set Extended Scan Parameters" },
{ 0x2042, 302, "LE Set Extended Scan Enable" },
{ 0x2043, 303, "LE Extended Create Connection" },
--
2.11.0
This patch adds decoding for following commands:
LE Set Advertising Set Random Address
LE Set Extended Advertising Parameters
LE Set Extended Advertising Data
LE Set Extended Scan Response Data
LE Set Extended Advertising Enable
LE Read Maximum Advertising Data Length
LE Read Number of Supported Advertising Sets
LE Remove Advertising Set
LE Clear Advertising Sets
LE Advertising Set Terminated Event
LE Scan Request Received Event
< HCI Command: LE Set Advertising Set Random Address (0x08|0x0035) plen 7
Advertising handle: 0x00
Advertising random address: 0A:0B:0C:0D:0E:0F (OUI 0A-0B-0C)
< HCI Command: LE Set Extended Advertising Parameters (0x08|0x0036) plen 25
Handle: 0x00
Properties: 0x0005
Connectable
Directed
Min advertising interval: 30.000 msec (0x0030)
Max advertising interval: 60.000 msec (0x0060)
Channel map: 37, 38, 39 (0x07)
Own address type: Public (0x00)
Peer address type: Public (0x00)
Peer address: 00:11:22:33:44:55 (CIMSYS Inc)
Filter policy: Allow Scan Request from Any, Allow Connect Request from Any (0x00)
TX power: 127 dbm (0x7f)
Primary PHY: LE Coded (0x03)
Secondary max skip: 0x00
Secondary PHY: LE Coded (0x03)
SID: 0x00
Scan request notifications: Disabled (0x00)
< HCI Command: LE Set Extended Advertising Data (0x08|0x0037) plen 39
Handle: 0x00
Operation: Complete extended advertising data (0x03)
Fragment preference: Fragment all (0x00)
Data length: 0x23
16-bit Service UUIDs (partial): 1 entry
Unknown (0x1234)
128-bit Service UUIDs (partial): 1 entry
Vendor specific (0f0e0d0c-0b0a-0908-0706-050403020100)
Name (short): device-name
< HCI Command: LE Set Extended Scan Response Data (0x08|0x0037) plen 39
Handle: 0x00
Operation: Complete extended advertising data (0x03)
Fragment preference: Fragment all (0x00)
Data length: 0x23
16-bit Service UUIDs (partial): 1 entry
Unknown (0x1234)
128-bit Service UUIDs (partial): 1 entry
Vendor specific (0f0e0d0c-0b0a-0908-0706-050403020100)
Name (short): device-name
< HCI Command: LE Set Extended Advertising Enable (0x08|0x0039) plen 24
Extended advertising: Enabled (0x01)
Number of sets: 2 (0x02)
Entry 0
Handle: 0xff
Duration: 0 ms (0x00)
Max ext adv events: 0
Entry 1
Handle: 0x00
Duration: 0 ms (0x00)
Max ext adv events: 1
< HCI Command: LE Remove Advertising Set (0x08|0x003c) plen 1
Handle: 1
---
monitor/bt.h | 92 +++++++++++
monitor/packet.c | 493 +++++++++++++++++++++++++++++++++++++++++++++++--------
2 files changed, 519 insertions(+), 66 deletions(-)
diff --git a/monitor/bt.h b/monitor/bt.h
index a877b2c13..aa55579bf 100644
--- a/monitor/bt.h
+++ b/monitor/bt.h
@@ -2176,6 +2176,83 @@ struct bt_hci_cmd_le_enhanced_transmitter_test {
uint8_t phy;
} __attribute__((packed));
+#define BT_HCI_CMD_LE_SET_ADV_SET_RAND_ADDR 0x2035
+struct bt_hci_cmd_le_set_adv_set_rand_addr {
+ uint8_t handle;
+ uint8_t bdaddr[6];
+} __attribute__ ((packed));
+
+#define BT_HCI_CMD_LE_SET_EXT_ADV_PARAMS 0x2036
+struct bt_hci_cmd_le_set_ext_adv_params {
+ uint8_t handle;
+ uint16_t evt_properties;
+ uint8_t min_interval[3];
+ uint8_t max_interval[3];
+ uint8_t channel_map;
+ uint8_t own_addr_type;
+ uint8_t peer_addr_type;
+ uint8_t peer_addr[6];
+ uint8_t filter_policy;
+ uint8_t tx_power;
+ uint8_t primary_phy;
+ uint8_t secondary_max_skip;
+ uint8_t secondary_phy;
+ uint8_t sid;
+ uint8_t notif_enable;
+} __attribute__ ((packed));
+struct bt_hci_rsp_le_set_ext_adv_params {
+ uint8_t status;
+ uint8_t tx_power;
+} __attribute__ ((packed));
+
+#define BT_HCI_CMD_LE_SET_EXT_ADV_DATA 0x2037
+struct bt_hci_cmd_le_set_ext_adv_data {
+ uint8_t handle;
+ uint8_t operation;
+ uint8_t fragment_preference;
+ uint8_t data_len;
+ uint8_t data[0];
+} __attribute__ ((packed));
+
+#define BT_HCI_CMD_LE_SET_EXT_SCAN_RSP_DATA 0x2038
+struct bt_hci_cmd_le_set_ext_scan_rsp_data {
+ uint8_t handle;
+ uint8_t operation;
+ uint8_t fragment_preference;
+ uint8_t data_len;
+ uint8_t data[0];
+} __attribute__ ((packed));
+
+#define BT_HCI_CMD_LE_SET_EXT_ADV_ENABLE 0x2039
+struct bt_hci_cmd_le_set_ext_adv_enable {
+ uint8_t enable;
+ uint8_t num_of_sets;
+} __attribute__ ((packed));
+struct bt_hci_cmd_ext_adv_set {
+ uint8_t handle;
+ uint16_t duration;
+ uint8_t max_events;
+} __attribute__ ((packed));
+
+#define BT_HCI_CMD_LE_READ_MAX_ADV_DATA_LEN 0x203a
+struct bt_hci_rsp_le_read_max_adv_data_len {
+ uint8_t status;
+ uint16_t max_len;
+} __attribute__ ((packed));
+
+#define BT_HCI_CMD_LE_READ_NUM_SUPPORTED_ADV_SETS 0x203b
+struct bt_hci_rsp_le_read_num_supported_adv_sets {
+ uint8_t status;
+ uint8_t num_of_sets;
+} __attribute__ ((packed));
+
+#define BT_HCI_CMD_LE_REMOVE_ADV_SET 0x203c
+struct bt_hci_cmd_le_remove_adv_set {
+ uint8_t handle;
+} __attribute__ ((packed));
+
+#define BT_HCI_CMD_LE_CLEAR_ADV_SETS 0x203d
+
#define BT_HCI_EVT_INQUIRY_COMPLETE 0x01
struct bt_hci_evt_inquiry_complete {
uint8_t status;
@@ -2786,6 +2863,21 @@ struct bt_hci_evt_le_phy_update_complete {
uint8_t rx_phy;
} __attribute__ ((packed));
+#define BT_HCI_EVT_LE_ADV_SET_TERM 0x12
+struct bt_hci_evt_le_adv_set_term {
+ uint8_t status;
+ uint8_t handle;
+ uint16_t conn_handle;
+ uint8_t num_evts;
+} __attribute__ ((packed));
+
+#define BT_HCI_EVT_LE_SCAN_REQ_RECEIVED 0x13
+struct bt_hci_evt_le_scan_req_received {
+ uint8_t handle;
+ uint8_t scanner_addr_type;
+ uint8_t scanner_addr[6];
+} __attribute__ ((packed));
+
#define BT_HCI_EVT_LE_CHAN_SELECT_ALG 0x14
struct bt_hci_evt_le_chan_select_alg {
uint16_t handle;
diff --git a/monitor/packet.c b/monitor/packet.c
index 1f6cd3699..4c1ba1cbe 100644
--- a/monitor/packet.c
+++ b/monitor/packet.c
@@ -1187,8 +1187,9 @@ static void print_power_type(uint8_t type)
static void print_power_level(int8_t level, const char *type)
{
- print_field("TX power%s%s%s: %d dBm",
- type ? " (" : "", type ? type : "", type ? ")" : "", level);
+ print_field("TX power%s%s%s: %d dbm (0x%2.2x)",
+ type ? " (" : "", type ? type : "", type ? ")" : "",
+ level, level);
}
static void print_sync_flow_control(uint8_t enable)
@@ -2332,6 +2333,69 @@ static void print_adv_event_type(uint8_t type)
print_field("Event type: %s (0x%2.2x)", str, type);
}
+static void print_adv_channel_map(const char *label, uint8_t value)
+{
+ const char *str;
+
+ switch (value) {
+ case 0x01:
+ str = "37";
+ break;
+ case 0x02:
+ str = "38";
+ break;
+ case 0x03:
+ str = "37, 38";
+ break;
+ case 0x04:
+ str = "39";
+ break;
+ case 0x05:
+ str = "37, 39";
+ break;
+ case 0x06:
+ str = "38, 39";
+ break;
+ case 0x07:
+ str = "37, 38, 39";
+ break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ print_field("%s: %s (0x%2.2x)", label, str, value);
+}
+
+static void print_adv_filter_policy(const char *label, uint8_t value)
+{
+ const char *str;
+
+ switch (value) {
+ case 0x00:
+ str = "Allow Scan Request from Any, "
+ "Allow Connect Request from Any";
+ break;
+ case 0x01:
+ str = "Allow Scan Request from White List Only, "
+ "Allow Connect Request from Any";
+ break;
+ case 0x02:
+ str = "Allow Scan Request from Any, "
+ "Allow Connect Request from White List Only";
+ break;
+ case 0x03:
+ str = "Allow Scan Request from White List Only, "
+ "Allow Connect Request from White List Only";
+ break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ print_field("%s: %s (0x%2.2x)", label, str, value);
+}
+
static void print_rssi(int8_t rssi)
{
if ((uint8_t) rssi == 0x99 || rssi == 127)
@@ -6394,59 +6458,8 @@ static void le_set_adv_parameters_cmd(const void *data, uint8_t size)
print_own_addr_type(cmd->own_addr_type);
print_addr_type("Direct address type", cmd->direct_addr_type);
print_addr("Direct address", cmd->direct_addr, cmd->direct_addr_type);
-
- switch (cmd->channel_map) {
- case 0x01:
- str = "37";
- break;
- case 0x02:
- str = "38";
- break;
- case 0x03:
- str = "37, 38";
- break;
- case 0x04:
- str = "39";
- break;
- case 0x05:
- str = "37, 39";
- break;
- case 0x06:
- str = "38, 39";
- break;
- case 0x07:
- str = "37, 38, 39";
- break;
- default:
- str = "Reserved";
- break;
- }
-
- print_field("Channel map: %s (0x%2.2x)", str, cmd->channel_map);
-
- switch (cmd->filter_policy) {
- case 0x00:
- str = "Allow Scan Request from Any, "
- "Allow Connect Request from Any";
- break;
- case 0x01:
- str = "Allow Scan Request from White List Only, "
- "Allow Connect Request from Any";
- break;
- case 0x02:
- str = "Allow Scan Request from Any, "
- "Allow Connect Request from White List Only";
- break;
- case 0x03:
- str = "Allow Scan Request from White List Only, "
- "Allow Connect Request from White List Only";
- break;
- default:
- str = "Reserved";
- break;
- }
-
- print_field("Filter policy: %s (0x%2.2x)", str, cmd->filter_policy);
+ print_adv_channel_map("Channel map", cmd->channel_map);
+ print_adv_filter_policy("Filter policy", cmd->filter_policy);
}
static void le_read_adv_tx_power_rsp(const void *data, uint8_t size)
@@ -7142,6 +7155,313 @@ static void le_enhanced_transmitter_test_cmd(const void *data, uint8_t size)
print_field("PHY: %s (0x%2.2x)", str, cmd->phy);
}
+static void le_set_adv_set_rand_addr(const void *data, uint8_t size)
+{
+ const struct bt_hci_cmd_le_set_adv_set_rand_addr *cmd = data;
+
+ print_field("Advertising handle: 0x%2.2x", cmd->handle);
+ print_addr("Advertising random address", cmd->bdaddr, 0x00);
+}
+
+static const struct {
+ uint8_t bit;
+ const char *str;
+} ext_adv_properties_table[] = {
+ { 0, "Connectable" },
+ { 1, "Scannable" },
+ { 2, "Directed" },
+ { 3, "High Duty Cycle Directed Connectable" },
+ { 4, "Use legacy advertising PDUs" },
+ { 5, "Anonymous advertising" },
+ { 6, "Include TxPower" },
+ { }
+};
+
+static const char *get_adv_pdu_desc(uint16_t flags)
+{
+ const char *str;
+
+ switch (flags) {
+ case 0x10:
+ str = "ADV_NONCONN_IND";
+ break;
+ case 0x12:
+ str = "ADV_SCAN_IND";
+ break;
+ case 0x13:
+ str = "ADV_IND";
+ break;
+ case 0x15:
+ str = "ADV_DIRECT_IND (low duty cycle)";
+ break;
+ case 0x1d:
+ str = "ADV_DIRECT_IND (high duty cycle)";
+ break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ return str;
+}
+
+static void print_ext_adv_properties(uint16_t flags)
+{
+ uint16_t mask = flags;
+ const char *property;
+ int i;
+
+ print_field("Properties: 0x%4.4x", flags);
+
+ for (i = 0; ext_adv_properties_table[i].str; i++) {
+ if (flags & (1 << ext_adv_properties_table[i].bit)) {
+ property = ext_adv_properties_table[i].str;
+
+ if (ext_adv_properties_table[i].bit == 4) {
+ print_field(" %s: %s", property,
+ get_adv_pdu_desc(flags));
+ } else {
+ print_field(" %s", property);
+ }
+ mask &= ~(1 << ext_adv_properties_table[i].bit);
+ }
+ }
+
+ if (mask)
+ print_text(COLOR_UNKNOWN_ADV_FLAG,
+ " Unknown advertising properties (0x%4.4x)",
+ mask);
+}
+
+static void print_ext_slot_625(const char *label, const uint8_t value[3])
+{
+ uint32_t value_cpu = value[0];
+
+ value_cpu |= value[1] << 8;
+ value_cpu |= value[2] << 16;
+
+ print_field("%s: %.3f msec (0x%4.4x)", label,
+ value_cpu * 0.625, value_cpu);
+}
+
+static void le_set_ext_adv_params_cmd(const void *data, uint8_t size)
+{
+ const struct bt_hci_cmd_le_set_ext_adv_params *cmd = data;
+ const char *str;
+
+ print_field("Handle: 0x%2.2x", cmd->handle);
+ print_ext_adv_properties(le16_to_cpu(cmd->evt_properties));
+
+ print_ext_slot_625("Min advertising interval", cmd->min_interval);
+ print_ext_slot_625("Max advertising interval", cmd->max_interval);
+ print_adv_channel_map("Channel map", cmd->channel_map);
+ print_own_addr_type(cmd->own_addr_type);
+ print_peer_addr_type("Peer address type", cmd->peer_addr_type);
+ print_addr("Peer address", cmd->peer_addr, cmd->peer_addr_type);
+ print_adv_filter_policy("Filter policy", cmd->filter_policy);
+ print_power_level(cmd->tx_power, NULL);
+
+ switch (cmd->primary_phy) {
+ case 0x01:
+ str = "LE 1M";
+ break;
+ case 0x03:
+ str = "LE Coded";
+ break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ print_field("Primary PHY: %s (0x%2.2x)", str, cmd->primary_phy);
+ print_field("Secondary max skip: 0x%2.2x", cmd->secondary_max_skip);
+ print_le_phy("Secondary PHY", cmd->secondary_phy);
+ print_field("SID: 0x%2.2x", cmd->sid);
+
+ switch (cmd->notif_enable) {
+ case 0x00:
+ str = "Disabled";
+ break;
+ case 0x01:
+ str = "Enabled";
+ break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ print_field("Scan request notifications: %s (0x%2.2x)",
+ str, cmd->notif_enable);
+}
+
+static void le_set_ext_adv_params_rsp(const void *data, uint8_t size)
+{
+ const struct bt_hci_rsp_le_set_ext_adv_params *rsp = data;
+
+ print_status(rsp->status);
+ print_power_level(rsp->tx_power, "selected");
+}
+
+static void le_set_ext_adv_data_cmd(const void *data, uint8_t size)
+{
+ const struct bt_hci_cmd_le_set_ext_adv_data *cmd = data;
+ const char *str;
+
+ print_field("Handle: 0x%2.2x", cmd->handle);
+
+ switch (cmd->operation) {
+ case 0x00:
+ str = "Immediate fragment";
+ break;
+ case 0x01:
+ str = "First fragment";
+ break;
+ case 0x02:
+ str = "Last fragment";
+ break;
+ case 0x03:
+ str = "Complete extended advertising data";
+ break;
+ case 0x04:
+ str = "Unchanged data";
+ break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ print_field("Operation: %s (0x%2.2x)", str, cmd->operation);
+
+ switch (cmd->fragment_preference) {
+ case 0x00:
+ str = "Fragment all";
+ break;
+ case 0x01:
+ str = "Minimize fragmentation";
+ break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ print_field("Fragment preference: %s (0x%2.2x)", str,
+ cmd->fragment_preference);
+ print_field("Data length: 0x%2.2x", cmd->data_len);
+ packet_print_ad(cmd->data, size - sizeof(*cmd));
+}
+
+static void le_set_ext_scan_rsp_data_cmd(const void *data, uint8_t size)
+{
+ const struct bt_hci_cmd_le_set_ext_scan_rsp_data *cmd = data;
+ const char *str;
+
+ print_field("Handle: 0x%2.2x", cmd->handle);
+
+ switch (cmd->operation) {
+ case 0x00:
+ str = "Immediate fragment";
+ break;
+ case 0x01:
+ str = "First fragment";
+ break;
+ case 0x02:
+ str = "Last fragment";
+ break;
+ case 0x03:
+ str = "Complete scan response data";
+ break;
+ case 0x04:
+ str = "Unchanged data";
+ break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ print_field("Operation: %s (0x%2.2x)", str, cmd->operation);
+
+ switch (cmd->fragment_preference) {
+ case 0x00:
+ str = "Fragment all";
+ break;
+ case 0x01:
+ str = "Minimize fragmentation";
+ break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ print_field("Fragment preference: %s (0x%2.2x)", str,
+ cmd->fragment_preference);
+ print_field("Data length: 0x%2.2x", cmd->data_len);
+ packet_print_ad(cmd->data, size - sizeof(*cmd));
+}
+
+static void le_set_ext_adv_enable_cmd(const void *data, uint8_t size)
+{
+ const struct bt_hci_cmd_le_set_ext_adv_enable *cmd = data;
+ const struct bt_hci_cmd_ext_adv_set *adv_set;
+ const char *str;
+ int i;
+
+ switch (cmd->enable) {
+ case 0x00:
+ str = "Disable";
+ break;
+ case 0x01:
+ str = "Enabled";
+ break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ print_field("Extended advertising: %s (0x%2.2x)", str, cmd->enable);
+
+ if (cmd->num_of_sets == 0)
+ print_field("Number of sets: Disable all sets (0x%2.2x)",
+ cmd->num_of_sets);
+ else if (cmd->num_of_sets > 0x3f)
+ print_field("Number of sets: Reserved (0x%2.2x)",
+ cmd->num_of_sets);
+ else
+ print_field("Number of sets: %u (0x%2.2x)", cmd->num_of_sets,
+ cmd->num_of_sets);
+
+ for (i = 0; i < cmd->num_of_sets; ++i) {
+ adv_set = data + 2 + i * sizeof(struct bt_hci_cmd_ext_adv_set);
+ print_field("Entry %d", i);
+ print_field(" Handle: 0x%2.2x", adv_set->handle);
+ print_field(" Duration: %d ms (0x%2.2x)",
+ adv_set->duration * 10, adv_set->duration);
+ print_field(" Max ext adv events: %d", adv_set->max_events);
+ }
+}
+
+static void le_read_max_adv_data_len_rsp(const void *data, uint8_t size)
+{
+ const struct bt_hci_rsp_le_read_max_adv_data_len *rsp = data;
+
+ print_status(rsp->status);
+ print_field("Max length: %d", rsp->max_len);
+}
+
+static void le_read_num_supported_adv_sets_rsp(const void *data, uint8_t size)
+{
+ const struct bt_hci_rsp_le_read_num_supported_adv_sets *rsp = data;
+
+ print_status(rsp->status);
+ print_field("Num supported adv sets: %d", rsp->num_of_sets);
+}
+
+static void le_remove_adv_set_cmd(const void *data, uint8_t size)
+{
+ const struct bt_hci_cmd_le_remove_adv_set *cmd = data;
+
+ print_handle(cmd->handle);
+}
+
struct opcode_data {
uint16_t opcode;
int bit;
@@ -7851,15 +8171,33 @@ static const struct opcode_data opcode_table[] = {
{ 0x2034, 288, "LE Enhanced Transmitter Test",
le_enhanced_transmitter_test_cmd, 4, true,
status_rsp, 1, true },
- { 0x2035, 289, "LE Set Advertising Set Random Address" },
- { 0x2036, 290, "LE Set Extended Advertising Parameters" },
- { 0x2037, 291, "LE Set Extended Advertising Data" },
- { 0x2038, 292, "LE Set Extended Scan Response Data" },
- { 0x2039, 293, "LE Set Extended Advertising Enable" },
- { 0x203a, 294, "LE Read Maximum Advertising Data Length" },
- { 0x203b, 295, "LE Read Number of Supported Advertising Sets" },
- { 0x203c, 296, "LE Remove Advertising Set" },
- { 0x203d, 297, "LE Clear Advertising Sets" },
+ { 0x2035, 289, "LE Set Advertising Set Random Address",
+ le_set_adv_set_rand_addr, 7, true,
+ status_rsp, 1, true },
+ { 0x2036, 290, "LE Set Extended Advertising Parameters",
+ le_set_ext_adv_params_cmd, 25, true,
+ le_set_ext_adv_params_rsp, 2, true },
+ { 0x2037, 291, "LE Set Extended Advertising Data",
+ le_set_ext_adv_data_cmd, 4, false,
+ status_rsp, 1, true },
+ { 0x2038, 292, "LE Set Extended Scan Response Data",
+ le_set_ext_scan_rsp_data_cmd, 4, false,
+ status_rsp, 1, true },
+ { 0x2039, 293, "LE Set Extended Advertising Enable",
+ le_set_ext_adv_enable_cmd, 2, false,
+ status_rsp, 1, true },
+ { 0x203a, 294, "LE Read Maximum Advertising Data Length",
+ null_cmd, 0, true,
+ le_read_max_adv_data_len_rsp, 3, true },
+ { 0x203b, 295, "LE Read Number of Supported Advertising Sets",
+ null_cmd, 0, true,
+ le_read_num_supported_adv_sets_rsp, 2, true },
+ { 0x203c, 296, "LE Remove Advertising Set",
+ le_remove_adv_set_cmd, 1, true,
+ status_rsp, 1, true },
+ { 0x203d, 297, "LE Clear Advertising Sets",
+ null_cmd, 0, true,
+ status_rsp, 1, true },
{ 0x203e, 298, "LE Set Periodic Advertising Parameters" },
{ 0x203f, 299, "LE Set Periodic Advertising Data" },
{ 0x2040, 300, "LE Set Periodic Advertising Enable" },
@@ -8980,6 +9318,27 @@ static void le_phy_update_complete_evt(const void *data, uint8_t size)
print_le_phy("RX PHY", evt->rx_phy);
}
+static void le_adv_set_term_evt(const void *data, uint8_t size)
+{
+ const struct bt_hci_evt_le_adv_set_term *evt = data;
+
+ print_status(evt->status);
+ print_field("Handle: %d", evt->handle);
+ print_field("Connection handle: %d", evt->conn_handle);
+ print_field("Number of completed extended advertising events: %d",
+ evt->num_evts);
+}
+
+static void le_scan_req_received_evt(const void *data, uint8_t size)
+{
+ const struct bt_hci_evt_le_scan_req_received *evt = data;
+
+ print_field("Handle: %d", evt->handle);
+ print_peer_addr_type("Scanner address type", evt->scanner_addr_type);
+ print_addr("Scanner address", evt->scanner_addr,
+ evt->scanner_addr_type);
+}
+
static void le_chan_select_alg_evt(const void *data, uint8_t size)
{
const struct bt_hci_evt_le_chan_select_alg *evt = data;
@@ -9075,8 +9434,10 @@ static const struct subevent_data le_meta_event_table[] = {
{ 0x0f, "LE Periodic Advertising Report" },
{ 0x10, "LE Periodic Advertising Sync Lost" },
{ 0x11, "LE Scan Timeout" },
- { 0x12, "LE Advertising Set Terminated" },
- { 0x13, "LE Scan Request Received" },
+ { 0x12, "LE Advertising Set Terminated",
+ le_adv_set_term_evt, 5, true},
+ { 0x13, "LE Scan Request Received",
+ le_scan_req_received_evt, 8, true},
{ 0x14, "LE Channel Selection Algorithm",
le_chan_select_alg_evt, 3, true},
{ }
--
2.11.0
Hi Marcel,
I added this global new generic in the last patch. I will fix the typo
here and in the last patch.
Best regards
Micha=C5=82
2017-08-04 16:27 GMT+02:00 Marcel Holtmann <[email protected]>:
> Hi Michal,
>
>> This patch adds decoding for following commands:
>>
>> LE Set Extended Scan Parameters
>> LE Set Extended Scan Enable
>> LE Extended Create Connection
>> LE Extended Advertising Report Event
>>
>> < HCI Command: LE Set Extended Scan Parameters (0x08|0x0041) plen 13
>> Own address type: Public (0x00)
>> Filter policy: Accept all advertisement (0x00)
>> PHYs: 0x05
>> Entry 0: LE 1M
>> Type: Active (0x01)
>> Interval: 30.000 msec (0x0030)
>> Window: 30.000 msec (0x0030)
>> Entry 1: LE Coded
>> Type: Active (0x01)
>> Interval: 30.000 msec (0x0030)
>> Window: 30.000 msec (0x0030)
>>
>> < HCI Command: LE Set Extended Scan Enable (0x08|0x0042) plen 6
>> Extended scan: Enabled (0x01)
>> Filter duplicates: Disabled (0x00)
>> Duration: 0 msec (0x0000)
>> Period: 0.00 sec (0x0000)
>>
>> < HCI Command: LE Extended Create Connection (0x08|0x0043) plen 29
>> Filter policy: White list is not used (0x00)
>> Own address type: Public (0x00)
>> Peer address type: Public (0x00)
>> Peer address: 11:22:33:C0:DE:C0 (OUI 11-22-33)
>> Initiating PHYs: 0x04
>> Entry 0: LE Coded
>> Scan interval: 10.000 msec (0x0010)
>> Scan window: 10.000 msec (0x0010)
>> Min connection interval: 30.00 msec (0x0018)
>> Max connection interval: 50.00 msec (0x0028)
>> Connection latency: 0 (0x0000)
>> Supervision timeout: 2560 msec (0x0100)
>> Min connection length: 10.000 msec (0x0010)
>> Max connection length: 480.000 msec (0x0300)
>> ---
>> monitor/bt.h | 60 ++++++++
>> monitor/packet.c | 406 +++++++++++++++++++++++++++++++++++++++++++++++++=
+++---
>> 2 files changed, 449 insertions(+), 17 deletions(-)
>>
>> diff --git a/monitor/bt.h b/monitor/bt.h
>> index 0160dcc7f..74439b9e5 100644
>> --- a/monitor/bt.h
>> +++ b/monitor/bt.h
>> @@ -2275,6 +2275,47 @@ struct bt_hci_cmd_le_set_periodic_adv_enable {
>> uint8_t handle;
>> } __attribute__ ((packed));
>>
>> +#define BT_HCI_CMD_LE_SET_EXT_SCAN_PARAMS 0x2041
>> +struct bt_hci_cmd_le_set_ext_scan_params {
>> + uint8_t own_addr_type;
>> + uint8_t filter_policy;
>> + uint8_t num_phys;
>> + uint8_t data[0];
>> +} __attribute__ ((packed));
>> +struct bt_hci_le_scan_phy {
>> + uint8_t type;
>> + uint16_t interval;
>> + uint16_t window;
>> +} __attribute__ ((packed));
>> +
>> +#define BT_HCI_CMD_LE_SET_EXT_SCAN_ENABLE 0x2042
>> +struct bt_hci_cmd_le_set_ext_scan_enable {
>> + uint8_t enable;
>> + uint8_t filter_dup;
>> + uint16_t duration;
>> + uint16_t period;
>> +} __attribute__ ((packed));
>> +
>> +#define BT_HCI_CMD_LE_EXT_CREATE_CONN 0x2043
>> +struct bt_hci_cmd_le_ext_create_conn {
>> + uint8_t filter_policy;
>> + uint8_t own_addr_type;
>> + uint8_t peer_addr_type;
>> + uint8_t peer_addr[6];
>> + uint8_t phys;
>> + uint8_t data[0];
>> +} __attribute__ ((packed));
>> +struct bt_hci_le_ext_create_conn {
>> + uint16_t scan_interval;
>> + uint16_t scan_window;
>> + uint16_t min_interval;
>> + uint16_t max_interval;
>> + uint16_t latency;
>> + uint16_t supv_timeout;
>> + uint16_t min_length;
>> + uint16_t max_length;
>> +} __attribute__ ((packed));
>> +
>> #define BT_HCI_EVT_INQUIRY_COMPLETE 0x01
>> struct bt_hci_evt_inquiry_complete {
>> uint8_t status;
>> @@ -2885,6 +2926,25 @@ struct bt_hci_evt_le_phy_update_complete {
>> uint8_t rx_phy;
>> } __attribute__ ((packed));
>>
>> +#define BT_HCI_EVT_LE_EXT_ADV_REPORT 0x0d
>> +struct bt_hci_evt_le_ext_adv_report {
>> + uint8_t num_reports;
>> +} __attribute__ ((packed));
>> +struct bt_hci_le_ext_adv_report {
>> + uint16_t event_type;
>> + uint8_t addr_type;
>> + uint8_t addr[6];
>> + uint8_t primary_phy;
>> + uint8_t secondary_phy;
>> + uint8_t sid;
>> + uint8_t tx_power;
>> + int8_t rssi;
>> + uint16_t interval;
>> + uint8_t direct_addr_type;
>> + uint8_t direct_addr[6];
>> + uint8_t data_len;
>> +} __attribute__ ((packed));
>> +
>> #define BT_HCI_EVT_LE_ADV_SET_TERM 0x12
>> struct bt_hci_evt_le_adv_set_term {
>> uint8_t status;
>> diff --git a/monitor/packet.c b/monitor/packet.c
>> index f43be9adb..6a602d8a8 100644
>> --- a/monitor/packet.c
>> +++ b/monitor/packet.c
>> @@ -2305,7 +2305,7 @@ static void print_num_reports(uint8_t num_reports)
>> print_field("Num reports: %d", num_reports);
>> }
>>
>> -static void print_adv_event_type(uint8_t type)
>> +static void print_adv_event_type(const char *label, uint8_t type)
>> {
>> const char *str;
>>
>> @@ -2330,7 +2330,7 @@ static void print_adv_event_type(uint8_t type)
>> break;
>> }
>>
>> - print_field("Event type: %s (0x%2.2x)", str, type);
>> + print_field("%s: %s (0x%2.2x)", label, str, type);
>> }
>>
>> static void print_adv_channel_map(const char *label, uint8_t value)
>> @@ -6506,12 +6506,11 @@ static void le_set_adv_enable_cmd(const void *da=
ta, uint8_t size)
>> print_field("Advertising: %s (0x%2.2x)", str, cmd->enable);
>> }
>>
>> -static void le_set_scan_parameters_cmd(const void *data, uint8_t size)
>> +static void print_scan_type(const char *label, uint8_t type)
>> {
>> - const struct bt_hci_cmd_le_set_scan_parameters *cmd =3D data;
>> const char *str;
>>
>> - switch (cmd->type) {
>> + switch (type) {
>> case 0x00:
>> str =3D "Passive";
>> break;
>> @@ -6523,13 +6522,14 @@ static void le_set_scan_parameters_cmd(const voi=
d *data, uint8_t size)
>> break;
>> }
>>
>> - print_field("Type: %s (0x%2.2x)", str, cmd->type);
>> + print_field("%s: %s (0x%2.2x)", label, str, type);
>> +}
>>
>> - print_interval(cmd->interval);
>> - print_window(cmd->window);
>> - print_own_addr_type(cmd->own_addr_type);
>> +static void print_scan_filter_policy(uint8_t policy)
>> +{
>> + const char *str;
>>
>> - switch (cmd->filter_policy) {
>> + switch (policy) {
>> case 0x00:
>> str =3D "Accept all advertisement";
>> break;
>> @@ -6547,7 +6547,18 @@ static void le_set_scan_parameters_cmd(const void=
*data, uint8_t size)
>> break;
>> }
>>
>> - print_field("Filter policy: %s (0x%2.2x)", str, cmd->filter_policy=
);
>> + print_field("Filter policy: %s (0x%2.2x)", str, policy);
>> +}
>> +
>> +static void le_set_scan_parameters_cmd(const void *data, uint8_t size)
>> +{
>> + const struct bt_hci_cmd_le_set_scan_parameters *cmd =3D data;
>> +
>> + print_scan_type("Type", cmd->type);
>> + print_interval(cmd->interval);
>> + print_window(cmd->window);
>> + print_own_addr_type(cmd->own_addr_type);
>> + print_scan_filter_policy(cmd->filter_policy);
>> }
>>
>> static void le_set_scan_enable_cmd(const void *data, uint8_t size)
>> @@ -7552,6 +7563,183 @@ static void le_set_periodic_adv_enable_cmd(const=
void *data, uint8_t size)
>> print_handle(cmd->handle);
>> }
>>
>> +static const struct {
>> + uint8_t bit;
>> + const char *str;
>> +} ext_scan_phys_table[] =3D {
>> + { 0, "LE 1M" },
>> + { 2, "LE Coded" },
>> + { }
>> +};
>> +
>> +static void print_ext_scan_phys(const void *data, uint8_t flags)
>> +{
>> + const struct bt_hci_le_scan_phy *scan_phy;
>> + uint8_t mask =3D flags;
>> + int bits_set =3D 0;
>> + int i;
>> +
>> + print_field("PHYs: 0x%2.2x", flags);
>> +
>> + for (i =3D 0; ext_scan_phys_table[i].str; i++) {
>> + if (flags & (1 << ext_scan_phys_table[i].bit)) {
>> + scan_phy =3D data + bits_set * sizeof(*scan_phy);
>> + mask &=3D ~(1 << ext_scan_phys_table[i].bit);
>> +
>> + print_field("Entry %d: %s", bits_set,
>> + ext_scan_phys_table[i].str=
);
>> + print_scan_type(" Type", scan_phy->type);
>> + print_slot_625(" Interval", scan_phy->interval);
>> + print_slot_625(" Window", scan_phy->window);
>> +
>> + ++bits_set;
>> + }
>> + }
>> +
>> + if (mask)
>> + print_text(COLOR_UNKNOWN_ADV_FLAG, " Unknown scanning PHY=
s"
>> + " (0x%2.2x)", mask=
);
>> +}
>> +
>> +static void le_set_ext_scan_params_cmd(const void *data, uint8_t size)
>> +{
>> + const struct bt_hci_cmd_le_set_ext_scan_params *cmd =3D data;
>> +
>> + print_own_addr_type(cmd->own_addr_type);
>> + print_scan_filter_policy(cmd->filter_policy);
>> + print_ext_scan_phys(cmd->data, cmd->num_phys);
>> +}
>> +
>> +static void print_enable(const char *label, uint8_t enable)
>> +{
>> + const char *str;
>> +
>> + switch (enable) {
>> + case 0x00:
>> + str =3D "Disable";
>> + break;
>
> =E2=80=9CDisabled=E2=80=9D.
>
> And didn=E2=80=99t you do this a global new generic one already in an ear=
lier patch?
>
> Regards
>
> Marcel
>
Hi Michal,
> This patch adds decoding for following commands:
>
> LE Set Extended Scan Parameters
> LE Set Extended Scan Enable
> LE Extended Create Connection
> LE Extended Advertising Report Event
>
> < HCI Command: LE Set Extended Scan Parameters (0x08|0x0041) plen 13
> Own address type: Public (0x00)
> Filter policy: Accept all advertisement (0x00)
> PHYs: 0x05
> Entry 0: LE 1M
> Type: Active (0x01)
> Interval: 30.000 msec (0x0030)
> Window: 30.000 msec (0x0030)
> Entry 1: LE Coded
> Type: Active (0x01)
> Interval: 30.000 msec (0x0030)
> Window: 30.000 msec (0x0030)
>
> < HCI Command: LE Set Extended Scan Enable (0x08|0x0042) plen 6
> Extended scan: Enabled (0x01)
> Filter duplicates: Disabled (0x00)
> Duration: 0 msec (0x0000)
> Period: 0.00 sec (0x0000)
>
> < HCI Command: LE Extended Create Connection (0x08|0x0043) plen 29
> Filter policy: White list is not used (0x00)
> Own address type: Public (0x00)
> Peer address type: Public (0x00)
> Peer address: 11:22:33:C0:DE:C0 (OUI 11-22-33)
> Initiating PHYs: 0x04
> Entry 0: LE Coded
> Scan interval: 10.000 msec (0x0010)
> Scan window: 10.000 msec (0x0010)
> Min connection interval: 30.00 msec (0x0018)
> Max connection interval: 50.00 msec (0x0028)
> Connection latency: 0 (0x0000)
> Supervision timeout: 2560 msec (0x0100)
> Min connection length: 10.000 msec (0x0010)
> Max connection length: 480.000 msec (0x0300)
> ---
> monitor/bt.h | 60 ++++++++
> monitor/packet.c | 406 ++++++++++++++++++++++++++++++++++++++++++++++++++++---
> 2 files changed, 449 insertions(+), 17 deletions(-)
>
> diff --git a/monitor/bt.h b/monitor/bt.h
> index 0160dcc7f..74439b9e5 100644
> --- a/monitor/bt.h
> +++ b/monitor/bt.h
> @@ -2275,6 +2275,47 @@ struct bt_hci_cmd_le_set_periodic_adv_enable {
> uint8_t handle;
> } __attribute__ ((packed));
>
> +#define BT_HCI_CMD_LE_SET_EXT_SCAN_PARAMS 0x2041
> +struct bt_hci_cmd_le_set_ext_scan_params {
> + uint8_t own_addr_type;
> + uint8_t filter_policy;
> + uint8_t num_phys;
> + uint8_t data[0];
> +} __attribute__ ((packed));
> +struct bt_hci_le_scan_phy {
> + uint8_t type;
> + uint16_t interval;
> + uint16_t window;
> +} __attribute__ ((packed));
> +
> +#define BT_HCI_CMD_LE_SET_EXT_SCAN_ENABLE 0x2042
> +struct bt_hci_cmd_le_set_ext_scan_enable {
> + uint8_t enable;
> + uint8_t filter_dup;
> + uint16_t duration;
> + uint16_t period;
> +} __attribute__ ((packed));
> +
> +#define BT_HCI_CMD_LE_EXT_CREATE_CONN 0x2043
> +struct bt_hci_cmd_le_ext_create_conn {
> + uint8_t filter_policy;
> + uint8_t own_addr_type;
> + uint8_t peer_addr_type;
> + uint8_t peer_addr[6];
> + uint8_t phys;
> + uint8_t data[0];
> +} __attribute__ ((packed));
> +struct bt_hci_le_ext_create_conn {
> + uint16_t scan_interval;
> + uint16_t scan_window;
> + uint16_t min_interval;
> + uint16_t max_interval;
> + uint16_t latency;
> + uint16_t supv_timeout;
> + uint16_t min_length;
> + uint16_t max_length;
> +} __attribute__ ((packed));
> +
> #define BT_HCI_EVT_INQUIRY_COMPLETE 0x01
> struct bt_hci_evt_inquiry_complete {
> uint8_t status;
> @@ -2885,6 +2926,25 @@ struct bt_hci_evt_le_phy_update_complete {
> uint8_t rx_phy;
> } __attribute__ ((packed));
>
> +#define BT_HCI_EVT_LE_EXT_ADV_REPORT 0x0d
> +struct bt_hci_evt_le_ext_adv_report {
> + uint8_t num_reports;
> +} __attribute__ ((packed));
> +struct bt_hci_le_ext_adv_report {
> + uint16_t event_type;
> + uint8_t addr_type;
> + uint8_t addr[6];
> + uint8_t primary_phy;
> + uint8_t secondary_phy;
> + uint8_t sid;
> + uint8_t tx_power;
> + int8_t rssi;
> + uint16_t interval;
> + uint8_t direct_addr_type;
> + uint8_t direct_addr[6];
> + uint8_t data_len;
> +} __attribute__ ((packed));
> +
> #define BT_HCI_EVT_LE_ADV_SET_TERM 0x12
> struct bt_hci_evt_le_adv_set_term {
> uint8_t status;
> diff --git a/monitor/packet.c b/monitor/packet.c
> index f43be9adb..6a602d8a8 100644
> --- a/monitor/packet.c
> +++ b/monitor/packet.c
> @@ -2305,7 +2305,7 @@ static void print_num_reports(uint8_t num_reports)
> print_field("Num reports: %d", num_reports);
> }
>
> -static void print_adv_event_type(uint8_t type)
> +static void print_adv_event_type(const char *label, uint8_t type)
> {
> const char *str;
>
> @@ -2330,7 +2330,7 @@ static void print_adv_event_type(uint8_t type)
> break;
> }
>
> - print_field("Event type: %s (0x%2.2x)", str, type);
> + print_field("%s: %s (0x%2.2x)", label, str, type);
> }
>
> static void print_adv_channel_map(const char *label, uint8_t value)
> @@ -6506,12 +6506,11 @@ static void le_set_adv_enable_cmd(const void *data, uint8_t size)
> print_field("Advertising: %s (0x%2.2x)", str, cmd->enable);
> }
>
> -static void le_set_scan_parameters_cmd(const void *data, uint8_t size)
> +static void print_scan_type(const char *label, uint8_t type)
> {
> - const struct bt_hci_cmd_le_set_scan_parameters *cmd = data;
> const char *str;
>
> - switch (cmd->type) {
> + switch (type) {
> case 0x00:
> str = "Passive";
> break;
> @@ -6523,13 +6522,14 @@ static void le_set_scan_parameters_cmd(const void *data, uint8_t size)
> break;
> }
>
> - print_field("Type: %s (0x%2.2x)", str, cmd->type);
> + print_field("%s: %s (0x%2.2x)", label, str, type);
> +}
>
> - print_interval(cmd->interval);
> - print_window(cmd->window);
> - print_own_addr_type(cmd->own_addr_type);
> +static void print_scan_filter_policy(uint8_t policy)
> +{
> + const char *str;
>
> - switch (cmd->filter_policy) {
> + switch (policy) {
> case 0x00:
> str = "Accept all advertisement";
> break;
> @@ -6547,7 +6547,18 @@ static void le_set_scan_parameters_cmd(const void *data, uint8_t size)
> break;
> }
>
> - print_field("Filter policy: %s (0x%2.2x)", str, cmd->filter_policy);
> + print_field("Filter policy: %s (0x%2.2x)", str, policy);
> +}
> +
> +static void le_set_scan_parameters_cmd(const void *data, uint8_t size)
> +{
> + const struct bt_hci_cmd_le_set_scan_parameters *cmd = data;
> +
> + print_scan_type("Type", cmd->type);
> + print_interval(cmd->interval);
> + print_window(cmd->window);
> + print_own_addr_type(cmd->own_addr_type);
> + print_scan_filter_policy(cmd->filter_policy);
> }
>
> static void le_set_scan_enable_cmd(const void *data, uint8_t size)
> @@ -7552,6 +7563,183 @@ static void le_set_periodic_adv_enable_cmd(const void *data, uint8_t size)
> print_handle(cmd->handle);
> }
>
> +static const struct {
> + uint8_t bit;
> + const char *str;
> +} ext_scan_phys_table[] = {
> + { 0, "LE 1M" },
> + { 2, "LE Coded" },
> + { }
> +};
> +
> +static void print_ext_scan_phys(const void *data, uint8_t flags)
> +{
> + const struct bt_hci_le_scan_phy *scan_phy;
> + uint8_t mask = flags;
> + int bits_set = 0;
> + int i;
> +
> + print_field("PHYs: 0x%2.2x", flags);
> +
> + for (i = 0; ext_scan_phys_table[i].str; i++) {
> + if (flags & (1 << ext_scan_phys_table[i].bit)) {
> + scan_phy = data + bits_set * sizeof(*scan_phy);
> + mask &= ~(1 << ext_scan_phys_table[i].bit);
> +
> + print_field("Entry %d: %s", bits_set,
> + ext_scan_phys_table[i].str);
> + print_scan_type(" Type", scan_phy->type);
> + print_slot_625(" Interval", scan_phy->interval);
> + print_slot_625(" Window", scan_phy->window);
> +
> + ++bits_set;
> + }
> + }
> +
> + if (mask)
> + print_text(COLOR_UNKNOWN_ADV_FLAG, " Unknown scanning PHYs"
> + " (0x%2.2x)", mask);
> +}
> +
> +static void le_set_ext_scan_params_cmd(const void *data, uint8_t size)
> +{
> + const struct bt_hci_cmd_le_set_ext_scan_params *cmd = data;
> +
> + print_own_addr_type(cmd->own_addr_type);
> + print_scan_filter_policy(cmd->filter_policy);
> + print_ext_scan_phys(cmd->data, cmd->num_phys);
> +}
> +
> +static void print_enable(const char *label, uint8_t enable)
> +{
> + const char *str;
> +
> + switch (enable) {
> + case 0x00:
> + str = "Disable";
> + break;
“Disabled”.
And didn’t you do this a global new generic one already in an earlier patch?
Regards
Marcel
Hi Michal,
> ---
> monitor/packet.c | 321 +++++++------------------------------------------------
> 1 file changed, 37 insertions(+), 284 deletions(-)
>
> diff --git a/monitor/packet.c b/monitor/packet.c
> index e1f69b145..c697890cf 100644
> --- a/monitor/packet.c
> +++ b/monitor/packet.c
> @@ -557,6 +557,25 @@ void packet_print_error(const char *label, uint8_t error)
> print_error(label, error);
> }
>
> +static void print_enable(const char *label, uint8_t enable)
> +{
> + const char *str;
> +
> + switch (enable) {
> + case 0x00:
> + str = "Disable”;
“Disabled”.
> + break;
> + case 0x01:
> + str = "Enabled";
> + break;
> + default:
> + str = "Reserved";
> + break;
> + }
> +
> + print_field("%s: %s (0x%2.2x)", label, str, enable);
> +}
> +
> static void print_addr_type(const char *label, uint8_t addr_type)
> {
> const char *str;
> @@ -1198,21 +1217,7 @@ static void print_power_level(int8_t level, const char *type)
>
> static void print_sync_flow_control(uint8_t enable)
> {
> - const char *str;
> -
> - switch (enable) {
> - case 0x00:
> - str = "Disabled";
> - break;
> - case 0x01:
> - str = "Enabled";
> - break;
> - default:
> - str = "Reserved";
> - break;
> - }
> -
> - print_field("Flow control: %s (0x%2.2x)", str, enable);
> + print_enable("Flow control", enable);
> }
Don’t do this. Use print_enable right where used to have print_sync_flow_control (and so on). Too many indirections are a bad thing.
Regards
Marcel