From 7567b13ef328b74794d00bfec2a3a7f51231be6e Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 8 Dec 2013 08:49:36 -0800 Subject: [PATCH] monitor: Add support for slave broadcast commands and events --- monitor/bt.h | 105 +++++++++++++++++++++ monitor/packet.c | 238 +++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 305 insertions(+), 38 deletions(-) diff --git a/monitor/bt.h b/monitor/bt.h index cfd4005d2..849ed86f4 100644 --- a/monitor/bt.h +++ b/monitor/bt.h @@ -411,6 +411,64 @@ struct bt_hci_cmd_flow_spec_modify { uint8_t rx_flow_spec[16]; } __attribute__ ((packed)); +#define BT_HCI_CMD_TRUNCATED_PAGE 0x043f +struct bt_hci_cmd_truncated_page { + uint8_t bdaddr[6]; + uint8_t pscan_rep_mode; + uint16_t clock_offset; +} __attribute__ ((packed)); + +#define BT_HCI_CMD_TRUNCATED_PAGE_CANCEL 0x0440 +struct bt_hci_cmd_truncated_page_cancel { + uint8_t bdaddr[6]; +} __attribute__ ((packed)); + +#define BT_HCI_CMD_SET_SLAVE_BROADCAST 0x0441 +struct bt_hci_cmd_set_slave_broadcast { + uint8_t enable; + uint8_t lt_addr; + uint8_t lpo_allowed; + uint16_t pkt_type; + uint16_t min_interval; + uint16_t max_interval; + uint16_t timeout; +} __attribute__ ((packed)); +struct bt_hci_rsp_set_slave_broadcast { + uint8_t status; + uint8_t lt_addr; + uint16_t interval; +} __attribute__ ((packed)); + +#define BT_HCI_CMD_SET_SLAVE_BROADCAST_RECEIVE 0x0442 +struct bt_hci_cmd_set_slave_broadcast_receive { + uint8_t enable; + uint8_t bdaddr[6]; + uint8_t lt_addr; + uint16_t interval; + uint32_t offset; + uint32_t instant; + uint16_t timeout; + uint8_t accuracy; + uint8_t skip; + uint16_t pkt_type; + uint8_t map[10]; +} __attribute__ ((packed)); +struct bt_hci_rsp_set_slave_broadcast_receive { + uint8_t status; + uint8_t bdaddr[6]; + uint8_t lt_addr; +} __attribute__ ((packed)); + +#define BT_HCI_CMD_START_SYNC_TRAIN 0x0443 + +#define BT_HCI_CMD_RECEIVE_SYNC_TRAIN 0x0444 +struct bt_hci_cmd_receive_sync_train { + uint8_t bdaddr[6]; + uint16_t timeout; + uint16_t window; + uint16_t interval; +} __attribute__ ((packed)); + #define BT_HCI_CMD_REMOTE_OOB_EXT_DATA_REQUEST_REPLY 0x0445 struct bt_hci_cmd_remote_oob_ext_data_request_reply { uint8_t bdaddr[6]; @@ -1920,6 +1978,53 @@ struct bt_hci_evt_amp_status_change { uint8_t amp_status; } __attribute__ ((packed)); +#define BT_HCI_EVT_SYNC_TRAIN_COMPLETE 0x4f +struct bt_hci_evt_sync_train_complete { + uint8_t status; +} __attribute__ ((packed)); + +#define BT_HCI_EVT_SYNC_TRAIN_RECEIVED 0x50 +struct bt_hci_evt_sync_train_received { + uint8_t status; + uint8_t bdaddr[6]; + uint32_t offset; + uint8_t map[10]; + uint8_t lt_addr; + uint32_t instant; + uint16_t interval; + uint8_t service_data; +} __attribute__ ((packed)); + +#define BT_HCI_EVT_SLAVE_BROADCAST_RECEIVE 0x51 +struct bt_hci_evt_slave_broadcast_receive { + uint8_t bdaddr[6]; + uint8_t lt_addr; + uint32_t clock; + uint32_t offset; + uint8_t status; + uint8_t fragment; + uint8_t length; +} __attribute__ ((packed)); + +#define BT_HCI_EVT_SLAVE_BROADCAST_TIMEOUT 0x52 +struct bt_hci_evt_slave_broadcast_timeout { + uint8_t bdaddr[6]; + uint8_t lt_addr; +} __attribute__ ((packed)); + +#define BT_HCI_EVT_TRUNCATED_PAGE_COMPLETE 0x53 +struct bt_hci_evt_truncated_page_complete { + uint8_t status; + uint8_t bdaddr[6]; +} __attribute__ ((packed)); + +#define BT_HCI_EVT_SLAVE_PAGE_RESPONSE_TIMEOUT 0x54 + +#define BT_HCI_EVT_SLAVE_BROADCAST_CHANNEL_MAP_CHANGE 0x55 +struct bt_hci_evt_slave_broadcast_channel_map_change { + uint8_t map[10]; +} __attribute__ ((packed)); + #define BT_HCI_EVT_AUTH_PAYLOAD_TIMEOUT_EXPIRED 0x57 struct bt_hci_evt_auth_payload_timeout_expired { uint16_t handle; diff --git a/monitor/packet.c b/monitor/packet.c index eb7d791c5..6ec7d9be5 100644 --- a/monitor/packet.c +++ b/monitor/packet.c @@ -1175,6 +1175,31 @@ static void print_clock_accuracy(uint16_t accuracy) btohs(accuracy) * 0.3125, btohs(accuracy)); } +static void print_broadcast_fragment(uint8_t fragment) +{ + const char *str; + + switch (fragment) { + case 0x00: + str = "Continuation fragment"; + break; + case 0x01: + str = "Starting fragment"; + break; + case 0x02: + str = "Ending fragment"; + break; + case 0x03: + str = "No fragmentation"; + break; + default: + str = "Reserved"; + break; + } + + print_field("Fragment: %s (0x%2.2x)", str, fragment); +} + static void print_link_type(uint8_t link_type) { const char *str; @@ -3335,6 +3360,80 @@ static void flow_spec_modify_cmd(const void *data, uint8_t size) print_flow_spec("RX", cmd->rx_flow_spec); } +static void truncated_page_cmd(const void *data, uint8_t size) +{ + const struct bt_hci_cmd_truncated_page *cmd = data; + + print_bdaddr(cmd->bdaddr); + print_pscan_rep_mode(cmd->pscan_rep_mode); + print_clock_offset(cmd->clock_offset); +} + +static void truncated_page_cancel_cmd(const void *data, uint8_t size) +{ + const struct bt_hci_cmd_truncated_page_cancel *cmd = data; + + print_bdaddr(cmd->bdaddr); +} + +static void set_slave_broadcast_cmd(const void *data, uint8_t size) +{ + const struct bt_hci_cmd_set_slave_broadcast *cmd = data; + + print_field("Enable: 0x%2.2x", cmd->enable); + print_lt_addr(cmd->lt_addr); + print_field("LPO allowed: 0x%2.2x", cmd->lpo_allowed); + print_pkt_type(cmd->pkt_type); + print_slot_625("Min interval", cmd->min_interval); + print_slot_625("Max interval", cmd->max_interval); + print_slot_625("Supervision timeout", cmd->timeout); +} + +static void set_slave_broadcast_rsp(const void *data, uint8_t size) +{ + const struct bt_hci_rsp_set_slave_broadcast *rsp = data; + + print_status(rsp->status); + print_lt_addr(rsp->lt_addr); + print_interval(rsp->interval); +} + +static void set_slave_broadcast_receive_cmd(const void *data, uint8_t size) +{ + const struct bt_hci_cmd_set_slave_broadcast_receive *cmd = data; + + print_field("Enable: 0x%2.2x", cmd->enable); + print_bdaddr(cmd->bdaddr); + print_lt_addr(cmd->lt_addr); + print_interval(cmd->interval); + print_field("Offset: 0x%8.8x", btohl(cmd->offset)); + print_field("Next broadcast instant: 0x%4.4x", btohs(cmd->instant)); + print_slot_625("Supervision timeout", cmd->timeout); + print_field("Remote timing accuracy: %d ppm", cmd->accuracy); + print_field("Skip: 0x%2.2x", cmd->skip); + print_pkt_type(cmd->pkt_type); + print_channel_map(cmd->map); +} + +static void set_slave_broadcast_receive_rsp(const void *data, uint8_t size) +{ + const struct bt_hci_rsp_set_slave_broadcast_receive *rsp = data; + + print_status(rsp->status); + print_bdaddr(rsp->bdaddr); + print_lt_addr(rsp->lt_addr); +} + +static void receive_sync_train_cmd(const void *data, uint8_t size) +{ + const struct bt_hci_cmd_receive_sync_train *cmd = data; + + print_bdaddr(cmd->bdaddr); + print_timeout(cmd->timeout); + print_window(cmd->window); + print_interval(cmd->interval); +} + static void remote_oob_ext_data_request_reply_cmd(const void *data, uint8_t size) { const struct bt_hci_cmd_remote_oob_ext_data_request_reply *cmd = data; @@ -4319,29 +4418,9 @@ static void delete_reserved_lt_addr_rsp(const void *data, uint8_t size) static void set_slave_broadcast_data_cmd(const void *data, uint8_t size) { const struct bt_hci_cmd_set_slave_broadcast_data *cmd = data; - const char *str; print_lt_addr(cmd->lt_addr); - - switch (cmd->fragment) { - case 0x00: - str = "Continuation fragment"; - break; - case 0x01: - str = "Starting fragment"; - break; - case 0x02: - str = "Ending fragment"; - break; - case 0x03: - str = "No fragmentation"; - break; - default: - str = "Reserved"; - break; - } - - print_field("Fragment: %s (0x%2.2x)", str, cmd->fragment); + print_broadcast_fragment(cmd->fragment); print_field("Length: %d", cmd->length); if (size - 3 != cmd->length) @@ -5322,12 +5401,21 @@ static const struct opcode_data opcode_table[] = { flow_spec_modify_cmd, 34, true }, { 0x043d, 235, "Enhanced Setup Synchronous Connection" }, { 0x043e, 236, "Enhanced Accept Synchronous Connection Request" }, - { 0x043f, 246, "Truncated Page" }, - { 0x0440, 247, "Truncated Page Cancel" }, - { 0x0441, 248, "Set Connectionless Slave Broadcast" }, - { 0x0442, 249, "Set Connectionless Slave Broadcast Receive" }, - { 0x0443, 250, "Start Synchronization Train" }, - { 0x0444, 251, "Receive Synchronization Train" }, + { 0x043f, 246, "Truncated Page", + truncated_page_cmd, 9, true }, + { 0x0440, 247, "Truncated Page Cancel", + truncated_page_cancel_cmd, 6, true, + status_bdaddr_rsp, 7, true }, + { 0x0441, 248, "Set Connectionless Slave Broadcast", + set_slave_broadcast_cmd, 11, true, + set_slave_broadcast_rsp, 4, true }, + { 0x0442, 249, "Set Connectionless Slave Broadcast Receive", + set_slave_broadcast_receive_cmd, 34, true, + set_slave_broadcast_receive_rsp, 8, true }, + { 0x0443, 250, "Start Synchronization Train", + null_cmd, 0, true }, + { 0x0444, 251, "Receive Synchronization Train", + receive_sync_train_cmd, 12, true }, { 0x0445, 257, "Remote OOB Extended Data Request Reply", remote_oob_ext_data_request_reply_cmd, 70, true, status_bdaddr_rsp, 7, true }, @@ -5824,11 +5912,11 @@ static const char *get_supported_command(int bit) return NULL; } -static void status_evt(const void *data, uint8_t size) +static void inquiry_complete_evt(const void *data, uint8_t size) { - uint8_t status = *((uint8_t *) data); + const struct bt_hci_evt_inquiry_complete *evt = data; - print_status(status); + print_status(evt->status); } static void inquiry_result_evt(const void *data, uint8_t size) @@ -6515,6 +6603,73 @@ static void amp_status_change_evt(const void *data, uint8_t size) print_amp_status(evt->amp_status); } +static void sync_train_complete_evt(const void *data, uint8_t size) +{ + const struct bt_hci_evt_sync_train_complete *evt = data; + + print_status(evt->status); +} + +static void sync_train_received_evt(const void *data, uint8_t size) +{ + const struct bt_hci_evt_sync_train_received *evt = data; + + print_status(evt->status); + print_bdaddr(evt->bdaddr); + print_field("Offset: 0x%8.8x", btohl(evt->offset)); + print_channel_map(evt->map); + print_lt_addr(evt->lt_addr); + print_field("Next broadcast instant: 0x%4.4x", btohs(evt->instant)); + print_interval(evt->interval); + print_field("Service Data: 0x%2.2x", evt->service_data); +} + +static void slave_broadcast_receive_evt(const void *data, uint8_t size) +{ + const struct bt_hci_evt_slave_broadcast_receive *evt = data; + + print_bdaddr(evt->bdaddr); + print_lt_addr(evt->lt_addr); + print_field("Clock: 0x%8.8x", btohl(evt->clock)); + print_field("Offset: 0x%8.8x", btohl(evt->offset)); + print_field("Receive status: 0x%2.2x", evt->status); + print_broadcast_fragment(evt->fragment); + print_field("Length: %d", evt->length); + + if (size - 18 != evt->length) + print_text(COLOR_ERROR, "invalid data size (%d != %d)", + size - 18, evt->length); + + packet_hexdump(data + 18, size - 18); +} + +static void slave_broadcast_timeout_evt(const void *data, uint8_t size) +{ + const struct bt_hci_evt_slave_broadcast_timeout *evt = data; + + print_bdaddr(evt->bdaddr); + print_lt_addr(evt->lt_addr); +} + +static void truncated_page_complete_evt(const void *data, uint8_t size) +{ + const struct bt_hci_evt_truncated_page_complete *evt = data; + + print_status(evt->status); + print_bdaddr(evt->bdaddr); +} + +static void slave_page_response_timeout_evt(const void *data, uint8_t size) +{ +} + +static void slave_broadcast_channel_map_change_evt(const void *data, uint8_t size) +{ + const struct bt_hci_evt_slave_broadcast_channel_map_change *evt = data; + + print_channel_map(evt->map); +} + static void auth_payload_timeout_expired_evt(const void *data, uint8_t size) { const struct bt_hci_evt_auth_payload_timeout_expired *evt = data; @@ -6705,7 +6860,7 @@ struct event_data { static const struct event_data event_table[] = { { 0x01, "Inquiry Complete", - status_evt, 1, true }, + inquiry_complete_evt, 1, true }, { 0x02, "Inquiry Result", inquiry_result_evt, 1, false }, { 0x03, "Connect Complete", @@ -6834,13 +6989,20 @@ static const struct event_data event_table[] = { { 0x4d, "AMP Status Change", amp_status_change_evt, 2, true }, { 0x4e, "Triggered Clock Capture" }, - { 0x4f, "Synchronization Train Complete" }, - { 0x50, "Synchronization Train Received" }, - { 0x51, "Connectionless Slave Broadcast Receive" }, - { 0x52, "Connectionless Slave Broadcast Timeout" }, - { 0x53, "Truncated Page Complete" }, - { 0x54, "Slave Page Response Timeout" }, - { 0x55, "Connectionless Slave Broadcast Channel Map Change" }, + { 0x4f, "Synchronization Train Complete", + sync_train_complete_evt, 1, true }, + { 0x50, "Synchronization Train Received", + sync_train_received_evt, 29, true }, + { 0x51, "Connectionless Slave Broadcast Receive", + slave_broadcast_receive_evt, 18, false }, + { 0x52, "Connectionless Slave Broadcast Timeout", + slave_broadcast_timeout_evt, 7, true }, + { 0x53, "Truncated Page Complete", + truncated_page_complete_evt, 7, true }, + { 0x54, "Slave Page Response Timeout", + slave_page_response_timeout_evt, 0, true }, + { 0x55, "Connectionless Slave Broadcast Channel Map Change", + slave_broadcast_channel_map_change_evt, 10, true }, { 0x56, "Inquiry Response Notification" }, { 0x57, "Authenticated Payload Timeout Expired", auth_payload_timeout_expired_evt, 2, true }, -- 2.47.3