From fd12b6b4e692d5ae528e42aa7332cadebce76e01 Mon Sep 17 00:00:00 2001 From: Szymon Czapracki Date: Thu, 16 Apr 2026 12:58:51 +0200 Subject: [PATCH] nimble/bttester: Add BTP supported events handling Populate and return per-service event bitmaps so autopts can query supported events after registration, just like supported commands. --- apps/bttester/src/btp/btp.h | 4 +++ apps/bttester/src/btp/btp_bap.h | 6 ++++ apps/bttester/src/btp/btp_gap.h | 5 +++ apps/bttester/src/btp/btp_gatt.h | 5 +++ apps/bttester/src/btp/btp_gattc.h | 5 +++ apps/bttester/src/btp/btp_l2cap.h | 5 +++ apps/bttester/src/btp/btp_mesh.h | 5 +++ apps/bttester/src/btp/bttester.h | 4 +++ apps/bttester/src/btp_bap.c | 46 ++++++++++++++++++++++++ apps/bttester/src/btp_gap.c | 58 +++++++++++++++++++++++++++++++ apps/bttester/src/btp_gatt.c | 37 ++++++++++++++++++++ apps/bttester/src/btp_gatt_cl.c | 50 ++++++++++++++++++++++++++ apps/bttester/src/btp_l2cap.c | 40 +++++++++++++++++++++ apps/bttester/src/btp_mesh.c | 46 ++++++++++++++++++++++++ apps/bttester/src/bttester.c | 28 +++++++++++++++ 15 files changed, 344 insertions(+) diff --git a/apps/bttester/src/btp/btp.h b/apps/bttester/src/btp/btp.h index 17fe388767..614b58c080 100644 --- a/apps/bttester/src/btp/btp.h +++ b/apps/bttester/src/btp/btp.h @@ -58,6 +58,10 @@ #define BTP_STATUS_UNKNOWN_CMD 0x02 #define BTP_STATUS_NOT_READY 0x03 +#define BTP_EVENT_OPCODE_BASE 0x80 +#define BTP_EVENT_BIT(ev) ((uint8_t)(ev) - BTP_EVENT_OPCODE_BASE) +#define BTP_EVENT_BITMAP_LEN(last_ev) (BTP_EVENT_BIT(last_ev) / 8 + 1) + /* TODO indicate delay response, should be removed when all commands are * converted to cmd+status+ev pattern */ diff --git a/apps/bttester/src/btp/btp_bap.h b/apps/bttester/src/btp/btp_bap.h index ea117ac4a5..c4e6d8c104 100644 --- a/apps/bttester/src/btp/btp_bap.h +++ b/apps/bttester/src/btp/btp_bap.h @@ -200,6 +200,12 @@ struct btp_bap_broadcast_source_setup_v2_rp { uint32_t gap_settings; } __packed; +#define BTP_BAP_READ_SUPPORTED_EVENTS 0x1b +struct btp_bap_read_supported_events_rp { + uint8_t data[0]; +} __packed; + +/* events */ #define BTP_BAP_EV_DISCOVERY_COMPLETED 0x80 struct btp_bap_discovery_completed_ev { ble_addr_t address; diff --git a/apps/bttester/src/btp/btp_gap.h b/apps/bttester/src/btp/btp_gap.h index c95a0d219f..3f9ae12ed8 100644 --- a/apps/bttester/src/btp/btp_gap.h +++ b/apps/bttester/src/btp/btp_gap.h @@ -339,6 +339,11 @@ struct gap_subrate_request_cmd { uint16_t supervision_timeout; } __packed; +#define BTP_GAP_READ_SUPPORTED_EVENTS 0x35 +struct btp_gap_read_supported_events_rp { + uint8_t data[0]; +} __packed; + /* events */ #define BTP_GAP_EV_NEW_SETTINGS 0x80 struct btp_gap_new_settings_ev { diff --git a/apps/bttester/src/btp/btp_gatt.h b/apps/bttester/src/btp/btp_gatt.h index 6c57ade092..0650ee409c 100644 --- a/apps/bttester/src/btp/btp_gatt.h +++ b/apps/bttester/src/btp/btp_gatt.h @@ -321,6 +321,11 @@ struct btp_gatt_notify_mult_val_cmd { uint16_t handles[0]; } __packed; +#define BTP_GATT_READ_SUPPORTED_EVENTS 0x24 +struct btp_gatt_read_supported_events_rp { + uint8_t data[0]; +} __packed; + /* GATT events */ #define BTP_GATT_EV_NOTIFICATION 0x80 struct btp_gatt_notification_ev { diff --git a/apps/bttester/src/btp/btp_gattc.h b/apps/bttester/src/btp/btp_gattc.h index df90ef0d96..5e74911522 100644 --- a/apps/bttester/src/btp/btp_gattc.h +++ b/apps/bttester/src/btp/btp_gattc.h @@ -173,6 +173,11 @@ struct btp_gattc_read_multiple_var_cmd { uint16_t handles[0]; } __packed; +#define BTP_GATTC_READ_SUPPORTED_EVENTS 0x15 +struct btp_gattc_read_supported_events_rp { + uint8_t data[0]; +} __packed; + /* events */ #define BTP_GATTC_EV_MTU_EXCHANGED 0x80 struct btp_gattc_exchange_mtu_ev { diff --git a/apps/bttester/src/btp/btp_l2cap.h b/apps/bttester/src/btp/btp_l2cap.h index 7d2adcaea6..6e56a90c3b 100644 --- a/apps/bttester/src/btp/btp_l2cap.h +++ b/apps/bttester/src/btp/btp_l2cap.h @@ -92,6 +92,11 @@ struct btp_l2cap_credits_cmd { uint8_t chan_id; } __packed; +#define BTP_L2CAP_READ_SUPPORTED_EVENTS 0x0e +struct btp_l2cap_read_supported_events_rp { + uint8_t data[0]; +} __packed; + /* events */ #define BTP_L2CAP_EV_CONNECTION_REQ 0x80 struct btp_l2cap_connection_req_ev { diff --git a/apps/bttester/src/btp/btp_mesh.h b/apps/bttester/src/btp/btp_mesh.h index 096c398060..35393507e0 100644 --- a/apps/bttester/src/btp/btp_mesh.h +++ b/apps/bttester/src/btp/btp_mesh.h @@ -140,6 +140,11 @@ struct btp_mesh_lpn_unsubscribe_cmd { #define BTP_MESH_PROXY_IDENTITY 0x13 #define BTP_MESH_START 0x78 +#define BTP_MESH_READ_SUPPORTED_EVENTS 0x79 +struct btp_mesh_read_supported_events_rp { + uint8_t data[0]; +} __packed; + /* events */ #define BTP_MESH_EV_OUT_NUMBER_ACTION 0x80 struct btp_mesh_out_number_action_ev { diff --git a/apps/bttester/src/btp/bttester.h b/apps/bttester/src/btp/bttester.h index ac56d8846d..14c83a0cd7 100644 --- a/apps/bttester/src/btp/bttester.h +++ b/apps/bttester/src/btp/bttester.h @@ -94,7 +94,11 @@ void tester_register_command_handlers(uint8_t service, const struct btp_handler *handlers, size_t num); +void tester_register_supported_events(uint8_t service, const uint8_t *events, + uint8_t len); + uint16_t tester_supported_commands(uint8_t service, uint8_t *cmds); +uint16_t tester_supported_events(uint8_t service, uint8_t *events); void tester_send_buf(uint8_t service, uint8_t opcode, uint8_t index, diff --git a/apps/bttester/src/btp_bap.c b/apps/bttester/src/btp_bap.c index 7ff489bb92..b10c77fcf8 100644 --- a/apps/bttester/src/btp_bap.c +++ b/apps/bttester/src/btp_bap.c @@ -58,6 +58,31 @@ static uint32_t sdu_interval; static struct ble_audio_base tester_base; +/* Important: Remember to update this if new events are introduced */ +#define BTP_BAP_EV_MAX BTP_BAP_EV_PA_SYNC_REQ + +#define BAP_SUPPORTED_EVENTS_LEN BTP_EVENT_BITMAP_LEN(BTP_BAP_EV_MAX) + +static uint8_t bap_supported_events[BAP_SUPPORTED_EVENTS_LEN]; + +static void +bap_init_supported_events(void) +{ + memset(bap_supported_events, 0, sizeof(bap_supported_events)); + + tester_set_bit(bap_supported_events, BTP_EVENT_BIT(BTP_BAP_EV_DISCOVERY_COMPLETED)); + tester_set_bit(bap_supported_events, BTP_EVENT_BIT(BTP_BAP_EV_CODEC_CAP_FOUND)); + tester_set_bit(bap_supported_events, BTP_EVENT_BIT(BTP_BAP_EV_ASE_FOUND)); + tester_set_bit(bap_supported_events, BTP_EVENT_BIT(BTP_BAP_EV_STREAM_RECEIVED)); + tester_set_bit(bap_supported_events, BTP_EVENT_BIT(BTP_BAP_EV_BAA_FOUND)); + tester_set_bit(bap_supported_events, BTP_EVENT_BIT(BTP_BAP_EV_BIS_FOUND)); + tester_set_bit(bap_supported_events, BTP_EVENT_BIT(BTP_BAP_EV_BIS_SYNCED)); + tester_set_bit(bap_supported_events, BTP_EVENT_BIT(BTP_BAP_EV_BIS_STREAM_RECEIVED)); + tester_set_bit(bap_supported_events, BTP_EVENT_BIT(BTP_BAP_EV_SCAN_DELEGATOR_FOUND)); + tester_set_bit(bap_supported_events, BTP_EVENT_BIT(BTP_BAP_EV_BROADCAST_RECEIVE_STATE)); + tester_set_bit(bap_supported_events, BTP_EVENT_BIT(BTP_BAP_EV_PA_SYNC_REQ)); +} + static os_membuf_t bis_mem[ OS_MEMPOOL_SIZE(MYNEWT_VAL(BLE_ISO_MAX_BISES), sizeof(struct ble_audio_bis)) @@ -145,6 +170,17 @@ supported_commands(const void *cmd, uint16_t cmd_len, return BTP_STATUS_SUCCESS; } +static uint8_t +supported_events(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len) +{ + struct btp_bap_read_supported_events_rp *rp = rsp; + + *rsp_len = tester_supported_events(BTP_SERVICE_ID_BAP, rp->data); + *rsp_len += sizeof(*rp); + + return BTP_STATUS_SUCCESS; +} + static int base_create(const struct bap_broadcast_source_setup_cmd *cmd) { @@ -402,6 +438,12 @@ static const struct btp_handler handlers[] = { .expect_len = 0, .func = supported_commands, }, + { + .opcode = BTP_BAP_READ_SUPPORTED_EVENTS, + .index = BTP_INDEX_NONE, + .expect_len = 0, + .func = supported_events, + }, { .opcode = BTP_BAP_BROADCAST_SOURCE_SETUP, .index = BTP_INDEX, @@ -653,8 +695,12 @@ tester_init_bap(void) scan_delegator_audio_event_handler, NULL); assert(rc == 0); + bap_init_supported_events(); + tester_register_command_handlers(BTP_SERVICE_ID_BAP, handlers, ARRAY_SIZE(handlers)); + tester_register_supported_events(BTP_SERVICE_ID_BAP, bap_supported_events, + sizeof(bap_supported_events)); return BTP_STATUS_SUCCESS; } diff --git a/apps/bttester/src/btp_gap.c b/apps/bttester/src/btp_gap.c index 29fb50a103..624da9232f 100644 --- a/apps/bttester/src/btp_gap.c +++ b/apps/bttester/src/btp_gap.c @@ -34,6 +34,7 @@ #include "../../../nimble/host/src/ble_sm_priv.h" #include "btp/btp.h" +#include "btp/bttester.h" #include @@ -89,6 +90,43 @@ static const struct ble_gap_conn_params dflt_conn_params = { .max_ce_len = 0x0300, }; +/* Important: Remember to update this if new events are introduced */ +#define BTP_GAP_EV_MAX GAP_EV_SUBRATE_CHANGE + +#define GAP_SUPPORTED_EVENTS_LEN BTP_EVENT_BITMAP_LEN(BTP_GAP_EV_MAX) + +static uint8_t gap_supported_events[GAP_SUPPORTED_EVENTS_LEN]; + +static void +gap_init_supported_events(void) +{ + memset(gap_supported_events, 0, sizeof(gap_supported_events)); + + tester_set_bit(gap_supported_events, BTP_EVENT_BIT(BTP_GAP_EV_NEW_SETTINGS)); + tester_set_bit(gap_supported_events, BTP_EVENT_BIT(BTP_GAP_EV_DEVICE_FOUND)); + tester_set_bit(gap_supported_events, BTP_EVENT_BIT(BTP_GAP_EV_DEVICE_CONNECTED)); + tester_set_bit(gap_supported_events, BTP_EVENT_BIT(BTP_GAP_EV_DEVICE_DISCONNECTED)); + tester_set_bit(gap_supported_events, BTP_EVENT_BIT(BTP_GAP_EV_PASSKEY_DISPLAY)); + tester_set_bit(gap_supported_events, BTP_EVENT_BIT(BTP_GAP_EV_PASSKEY_ENTRY_REQ)); + tester_set_bit(gap_supported_events, BTP_EVENT_BIT(BTP_GAP_EV_PASSKEY_CONFIRM_REQ)); + tester_set_bit(gap_supported_events, BTP_EVENT_BIT(BTP_GAP_EV_IDENTITY_RESOLVED)); + tester_set_bit(gap_supported_events, BTP_EVENT_BIT(BTP_GAP_EV_CONN_PARAM_UPDATE)); + tester_set_bit(gap_supported_events, BTP_EVENT_BIT(BTP_GAP_EV_SEC_LEVEL_CHANGED)); + tester_set_bit(gap_supported_events, BTP_EVENT_BIT(BTP_GAP_EV_BOND_LOST)); + tester_set_bit(gap_supported_events, BTP_EVENT_BIT(BTP_GAP_EV_SEC_PAIRING_FAILED)); +#if MYNEWT_VAL(BLE_PERIODIC_ADV) + tester_set_bit(gap_supported_events, BTP_EVENT_BIT(GAP_EV_PERIODIC_SYNC_ESTABLISHED)); + tester_set_bit(gap_supported_events, BTP_EVENT_BIT(GAP_EV_PERIODIC_SYNC_LOST)); + tester_set_bit(gap_supported_events, BTP_EVENT_BIT(GAP_EV_PERIODIC_REPORT)); +#endif +#if MYNEWT_VAL(BLE_PERIODIC_ADV_SYNC_TRANSFER) + tester_set_bit(gap_supported_events, BTP_EVENT_BIT(GAP_EV_PERIODIC_TRANSFER_RECEIVED)); +#endif +#if MYNEWT_VAL(BLE_CONN_SUBRATING) + tester_set_bit(gap_supported_events, BTP_EVENT_BIT(GAP_EV_SUBRATE_CHANGE)); +#endif +} + static int gap_conn_find_by_addr(const ble_addr_t *dev_addr, struct ble_gap_conn_desc *out_desc) @@ -134,6 +172,17 @@ supported_commands(const void *cmd, uint16_t cmd_len, return BTP_STATUS_SUCCESS; } +static uint8_t +supported_events(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len) +{ + struct btp_gap_read_supported_events_rp *rp = rsp; + + *rsp_len = tester_supported_events(BTP_SERVICE_ID_GAP, rp->data); + *rsp_len += sizeof(*rp); + + return BTP_STATUS_SUCCESS; +} + static uint8_t controller_index_list(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len) @@ -2277,6 +2326,12 @@ static const struct btp_handler handlers[] = { .expect_len = 0, .func = supported_commands, }, + { + .opcode = BTP_GAP_READ_SUPPORTED_EVENTS, + .index = BTP_INDEX_NONE, + .expect_len = 0, + .func = supported_events, + }, { .opcode = BTP_GAP_READ_CONTROLLER_INDEX_LIST, .index = BTP_INDEX_NONE, @@ -2483,9 +2538,12 @@ tester_init_gap(void) assert(adv_buf); tester_init_gap_cb(); + gap_init_supported_events(); tester_register_command_handlers(BTP_SERVICE_ID_GAP, handlers, ARRAY_SIZE(handlers)); + tester_register_supported_events(BTP_SERVICE_ID_GAP, gap_supported_events, + sizeof(gap_supported_events)); return BTP_STATUS_SUCCESS; } diff --git a/apps/bttester/src/btp_gatt.c b/apps/bttester/src/btp_gatt.c index 17c083bf3a..38559dd418 100644 --- a/apps/bttester/src/btp_gatt.c +++ b/apps/bttester/src/btp_gatt.c @@ -75,6 +75,22 @@ #define PTS_INC_SVC 0x001e #define PTS_CHR_READ_WRITE_ALT 0x001f +/* Important: Remember to update this if new events are introduced */ +#define BTP_GATT_EV_MAX BTP_GATT_EV_ATTR_VALUE_CHANGED + +#define GATT_SUPPORTED_EVENTS_LEN BTP_EVENT_BITMAP_LEN(BTP_GATT_EV_MAX) + +static uint8_t gatt_supported_events[GATT_SUPPORTED_EVENTS_LEN]; + +static void +gatt_init_supported_events(void) +{ + memset(gatt_supported_events, 0, sizeof(gatt_supported_events)); + + tester_set_bit(gatt_supported_events, BTP_EVENT_BIT(BTP_GATT_EV_NOTIFICATION)); + tester_set_bit(gatt_supported_events, BTP_EVENT_BIT(BTP_GATT_EV_ATTR_VALUE_CHANGED)); +} + static uint8_t gatt_svr_pts_static_long_val[300]; static uint8_t gatt_svr_pts_static_val[30]; static uint8_t gatt_svr_pts_static_short_val; @@ -1958,6 +1974,17 @@ supported_commands(const void *cmd, uint16_t cmd_len, return BTP_STATUS_SUCCESS; } +static uint8_t +supported_events(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len) +{ + struct btp_gatt_read_supported_events_rp *rp = rsp; + + *rsp_len = tester_supported_events(BTP_SERVICE_ID_GATT, rp->data); + *rsp_len += sizeof(*rp); + + return BTP_STATUS_SUCCESS; +} + enum attr_type { BLE_GATT_ATTR_SVC = 0, BLE_GATT_ATTR_CHR, @@ -1971,6 +1998,12 @@ static const struct btp_handler handlers[] = { .expect_len = 0, .func = supported_commands, }, + { + .opcode = BTP_GATT_READ_SUPPORTED_EVENTS, + .index = BTP_INDEX_NONE, + .expect_len = 0, + .func = supported_events, + }, { .opcode = BTP_GATT_START_SERVER, .expect_len = 0, @@ -2294,8 +2327,12 @@ tester_init_gatt(void) os_callout_init(¬ify_tx_timer, os_eventq_dflt_get(), notify_test, NULL); + gatt_init_supported_events(); + tester_register_command_handlers(BTP_SERVICE_ID_GATT, handlers, ARRAY_SIZE(handlers)); + tester_register_supported_events(BTP_SERVICE_ID_GATT, gatt_supported_events, + sizeof(gatt_supported_events)); return BTP_STATUS_SUCCESS; } diff --git a/apps/bttester/src/btp_gatt_cl.c b/apps/bttester/src/btp_gatt_cl.c index 37fae1c5bb..501c6706ac 100644 --- a/apps/bttester/src/btp_gatt_cl.c +++ b/apps/bttester/src/btp_gatt_cl.c @@ -33,6 +33,37 @@ #define CONTROLLER_INDEX 0 #define MAX_BUFFER_SIZE 2048 +/* Important: Remember to update this if new events are introduced */ +#define BTP_GATTC_EV_MAX BTP_GATTC_READ_MULTIPLE_VAR_RP + +#define GATTC_SUPPORTED_EVENTS_LEN BTP_EVENT_BITMAP_LEN(BTP_GATTC_EV_MAX) + +static uint8_t gattc_supported_events[GATTC_SUPPORTED_EVENTS_LEN]; + +static void +gattc_init_supported_events(void) +{ + memset(gattc_supported_events, 0, sizeof(gattc_supported_events)); + + tester_set_bit(gattc_supported_events, BTP_EVENT_BIT(BTP_GATTC_EV_MTU_EXCHANGED)); + tester_set_bit(gattc_supported_events, BTP_EVENT_BIT(BTP_GATTC_DISC_ALL_PRIM_RP)); + tester_set_bit(gattc_supported_events, BTP_EVENT_BIT(BTP_GATTC_DISC_PRIM_UUID_RP)); + tester_set_bit(gattc_supported_events, BTP_EVENT_BIT(BTP_GATTC_FIND_INCLUDED_RP)); + tester_set_bit(gattc_supported_events, BTP_EVENT_BIT(BTP_GATTC_DISC_ALL_CHRC_RP)); + tester_set_bit(gattc_supported_events, BTP_EVENT_BIT(BTP_GATTC_DISC_CHRC_UUID_RP)); + tester_set_bit(gattc_supported_events, BTP_EVENT_BIT(BTP_GATTC_DISC_ALL_DESC_RP)); + tester_set_bit(gattc_supported_events, BTP_EVENT_BIT(BTP_GATTC_READ_RP)); + tester_set_bit(gattc_supported_events, BTP_EVENT_BIT(BTP_GATTC_READ_UUID_RP)); + tester_set_bit(gattc_supported_events, BTP_EVENT_BIT(BTP_GATTC_READ_LONG_RP)); + tester_set_bit(gattc_supported_events, BTP_EVENT_BIT(BTP_GATTC_READ_MULTIPLE_RP)); + tester_set_bit(gattc_supported_events, BTP_EVENT_BIT(BTP_GATTC_WRITE_LONG_RP)); + tester_set_bit(gattc_supported_events, BTP_EVENT_BIT(BTP_GATTC_RELIABLE_WRITE_RP)); + tester_set_bit(gattc_supported_events, BTP_EVENT_BIT(BTP_GATTC_CFG_NOTIFY_RP)); + tester_set_bit(gattc_supported_events, BTP_EVENT_BIT(BTP_GATTC_CFG_INDICATE_RP)); + tester_set_bit(gattc_supported_events, BTP_EVENT_BIT(BTP_GATTC_EV_NOTIFICATION_RXED)); + tester_set_bit(gattc_supported_events, BTP_EVENT_BIT(BTP_GATTC_READ_MULTIPLE_VAR_RP)); +} + /* Convert UUID from BTP command to bt_uuid */ static uint8_t btp2bt_uuid(const uint8_t *uuid, uint8_t len, @@ -1497,6 +1528,16 @@ supported_commands(const void *cmd, uint16_t cmd_len, return BTP_STATUS_SUCCESS; } +static uint8_t +supported_events(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len) +{ + struct btp_gattc_read_supported_events_rp *rp = rsp; + + *rsp_len = tester_supported_events(BTP_SERVICE_ID_GATTC, rp->data); + *rsp_len += sizeof(*rp); + + return BTP_STATUS_SUCCESS; +} static const struct btp_handler handlers[] = { { @@ -1505,6 +1546,12 @@ static const struct btp_handler handlers[] = { .expect_len = 0, .func = supported_commands, }, + { + .opcode = BTP_GATTC_READ_SUPPORTED_EVENTS, + .index = BTP_INDEX_NONE, + .expect_len = 0, + .func = supported_events, + }, { .opcode = BTP_GATTC_EXCHANGE_MTU, .expect_len = sizeof(struct btp_gattc_exchange_mtu_cmd), @@ -1607,8 +1654,11 @@ static const struct btp_handler handlers[] = { uint8_t tester_init_gatt_cl(void) { + gattc_init_supported_events(); tester_register_command_handlers(BTP_SERVICE_ID_GATTC, handlers, ARRAY_SIZE(handlers)); + tester_register_supported_events(BTP_SERVICE_ID_GATTC, gattc_supported_events, + sizeof(gattc_supported_events)); return BTP_STATUS_SUCCESS; } diff --git a/apps/bttester/src/btp_l2cap.c b/apps/bttester/src/btp_l2cap.c index e11c54de3c..bae7c2da82 100644 --- a/apps/bttester/src/btp_l2cap.c +++ b/apps/bttester/src/btp_l2cap.c @@ -42,6 +42,36 @@ #define TESTER_COC_MTU MYNEWT_VAL(BTTESTER_L2CAP_COC_MTU) #define TESTER_COC_BUF_COUNT (3 * MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM)) +/* Important: Remember to update this if new events are introduced */ +#define BTP_L2CAP_EV_MAX BTP_L2CAP_EV_RECONFIGURED + +#define L2CAP_SUPPORTED_EVENTS_LEN BTP_EVENT_BITMAP_LEN(BTP_L2CAP_EV_MAX) + +static uint8_t l2cap_supported_events[L2CAP_SUPPORTED_EVENTS_LEN]; + +static void +l2cap_init_supported_events(void) +{ + memset(l2cap_supported_events, 0, sizeof(l2cap_supported_events)); + + tester_set_bit(l2cap_supported_events, BTP_EVENT_BIT(BTP_L2CAP_EV_CONNECTION_REQ)); + tester_set_bit(l2cap_supported_events, BTP_EVENT_BIT(BTP_L2CAP_EV_CONNECTED)); + tester_set_bit(l2cap_supported_events, BTP_EVENT_BIT(BTP_L2CAP_EV_DISCONNECTED)); + tester_set_bit(l2cap_supported_events, BTP_EVENT_BIT(BTP_L2CAP_EV_DATA_RECEIVED)); + tester_set_bit(l2cap_supported_events, BTP_EVENT_BIT(BTP_L2CAP_EV_RECONFIGURED)); +} + +static uint8_t +supported_events(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len) +{ + struct btp_l2cap_read_supported_events_rp *rp = rsp; + + *rsp_len = tester_supported_events(BTP_SERVICE_ID_L2CAP, rp->data); + *rsp_len += sizeof(*rp); + + return BTP_STATUS_SUCCESS; +} + static os_membuf_t tester_sdu_coc_mem[ OS_MEMPOOL_SIZE(TESTER_COC_BUF_COUNT, TESTER_COC_MTU) ]; @@ -724,6 +754,12 @@ static const struct btp_handler handlers[] = { .expect_len = 0, .func = supported_commands, }, + { + .opcode = BTP_L2CAP_READ_SUPPORTED_EVENTS, + .index = BTP_INDEX_NONE, + .expect_len = 0, + .func = supported_events, + }, { .opcode = BTP_L2CAP_CONNECT, .expect_len = sizeof(struct btp_l2cap_connect_cmd), @@ -771,8 +807,12 @@ tester_init_l2cap(void) TESTER_COC_MTU, TESTER_COC_BUF_COUNT); assert(rc == 0); + l2cap_init_supported_events(); + tester_register_command_handlers(BTP_SERVICE_ID_L2CAP, handlers, ARRAY_SIZE(handlers)); + tester_register_supported_events(BTP_SERVICE_ID_L2CAP, l2cap_supported_events, + sizeof(l2cap_supported_events)); return BTP_STATUS_SUCCESS; } diff --git a/apps/bttester/src/btp_mesh.c b/apps/bttester/src/btp_mesh.c index 4815dbe5b8..64a86ea894 100644 --- a/apps/bttester/src/btp_mesh.c +++ b/apps/bttester/src/btp_mesh.c @@ -88,6 +88,32 @@ static struct { .dst = BT_MESH_ADDR_UNASSIGNED, }; +/* Important: Remember to update this if new events are introduced */ +#define BTP_MESH_EV_MAX BTP_MESH_EV_LPN_POLLED + +#define MESH_SUPPORTED_EVENTS_LEN BTP_EVENT_BITMAP_LEN(BTP_MESH_EV_MAX) + +static uint8_t mesh_supported_events[MESH_SUPPORTED_EVENTS_LEN]; + +static void +mesh_init_supported_events(void) +{ + memset(mesh_supported_events, 0, sizeof(mesh_supported_events)); + + tester_set_bit(mesh_supported_events, BTP_EVENT_BIT(BTP_MESH_EV_OUT_NUMBER_ACTION)); + tester_set_bit(mesh_supported_events, BTP_EVENT_BIT(BTP_MESH_EV_OUT_STRING_ACTION)); + tester_set_bit(mesh_supported_events, BTP_EVENT_BIT(BTP_MESH_EV_IN_ACTION)); + tester_set_bit(mesh_supported_events, BTP_EVENT_BIT(BTP_MESH_EV_PROVISIONED)); + tester_set_bit(mesh_supported_events, BTP_EVENT_BIT(BTP_MESH_EV_PROV_LINK_OPEN)); + tester_set_bit(mesh_supported_events, BTP_EVENT_BIT(BTP_MESH_EV_PROV_LINK_CLOSED)); + tester_set_bit(mesh_supported_events, BTP_EVENT_BIT(BTP_MESH_EV_NET_RECV)); + tester_set_bit(mesh_supported_events, BTP_EVENT_BIT(BTP_MESH_EV_INVALID_BEARER)); + tester_set_bit(mesh_supported_events, BTP_EVENT_BIT(BTP_MESH_EV_INCOMP_TIMER_EXP)); + tester_set_bit(mesh_supported_events, BTP_EVENT_BIT(BTP_MESH_EV_LPN_ESTABLISHED)); + tester_set_bit(mesh_supported_events, BTP_EVENT_BIT(BTP_MESH_EV_LPN_TERMINATED)); + tester_set_bit(mesh_supported_events, BTP_EVENT_BIT(BTP_MESH_EV_LPN_POLLED)); +} + static uint8_t supported_commands(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len) @@ -100,6 +126,17 @@ supported_commands(const void *cmd, uint16_t cmd_len, return BTP_STATUS_SUCCESS; } +static uint8_t +supported_events(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len) +{ + struct btp_mesh_read_supported_events_rp *rp = rsp; + + *rsp_len = tester_supported_events(BTP_SERVICE_ID_MESH, rp->data); + *rsp_len += sizeof(*rp); + + return BTP_STATUS_SUCCESS; +} + static void get_faults(uint8_t *faults, uint8_t faults_size, uint8_t *dst, uint8_t *count) { @@ -831,6 +868,12 @@ static const struct btp_handler handlers[] = { .expect_len = 0, .func = supported_commands, }, + { + .opcode = BTP_MESH_READ_SUPPORTED_EVENTS, + .index = BTP_INDEX_NONE, + .expect_len = 0, + .func = supported_events, + }, { .opcode = BTP_MESH_CONFIG_PROVISIONING, .expect_len = BTP_HANDLER_LENGTH_VARIABLE, @@ -1083,9 +1126,12 @@ tester_init_mesh(void) bt_mesh_lpn_set_cb(lpn_cb); bt_test_cb_register(&bt_test_cb); } + mesh_init_supported_events(); tester_register_command_handlers(BTP_SERVICE_ID_MESH, handlers, ARRAY_SIZE(handlers)); + tester_register_supported_events(BTP_SERVICE_ID_MESH, mesh_supported_events, + sizeof(mesh_supported_events)); return BTP_STATUS_SUCCESS; } diff --git a/apps/bttester/src/bttester.c b/apps/bttester/src/bttester.c index ad8a827d30..9a15d53d3a 100644 --- a/apps/bttester/src/bttester.c +++ b/apps/bttester/src/bttester.c @@ -62,6 +62,10 @@ static struct { uint8_t num; } service_handler[BTP_SERVICE_ID_MAX + 1]; +static struct { + const uint8_t *events; + uint8_t len; +} service_events[BTP_SERVICE_ID_MAX + 1]; void tester_mbuf_reset(struct os_mbuf *buf) @@ -89,6 +93,16 @@ tester_register_command_handlers(uint8_t service, service_handler[service].num = num; } +void +tester_register_supported_events(uint8_t service, const uint8_t *events, uint8_t len) +{ + assert(service <= BTP_SERVICE_ID_MAX); + assert(service_events[service].events == NULL); + + service_events[service].events = events; + service_events[service].len = len; +} + const char * string_from_bytes(const void *buf, size_t len) { @@ -394,3 +408,17 @@ tester_supported_commands(uint8_t service, uint8_t *cmds) return (opcode_max / 8) + 1; } + +uint16_t +tester_supported_events(uint8_t service, uint8_t *events) +{ + assert(service <= BTP_SERVICE_ID_MAX); + + if (!service_events[service].events || !service_events[service].len) { + return 0; + } + + memcpy(events, service_events[service].events, service_events[service].len); + + return service_events[service].len; +}