From 89a62703722962741ff028ebac590af11ff463b5 Mon Sep 17 00:00:00 2001 From: alperen sener Date: Wed, 20 Aug 2025 15:39:52 +0200 Subject: [PATCH] tests: Bluetooth: tester: Fix Central Address Resolution chr. read CAR characteristic read process was incomplete, CAR status was not actually stored. Added a new BTP_GAP_EV_PEER_CAR_RECEIVED to tester. This is to prevent disconnect events before IUT successfully reads CAR from central. Updated start_directed_advertising() so that if the central has no CAR support we must not send directed advertisements. IUT might enter another connectable mode according to specification, thus IUT starts sending connectable undirected advertisements with resovable address. Signed-off-by: alperen sener --- tests/bluetooth/tester/src/btp/btp_gap.h | 6 ++ tests/bluetooth/tester/src/btp_gap.c | 76 ++++++++++++++++++------ 2 files changed, 63 insertions(+), 19 deletions(-) diff --git a/tests/bluetooth/tester/src/btp/btp_gap.h b/tests/bluetooth/tester/src/btp/btp_gap.h index 1530d774e1c94..6d27aae31ea6f 100644 --- a/tests/bluetooth/tester/src/btp/btp_gap.h +++ b/tests/bluetooth/tester/src/btp/btp_gap.h @@ -619,6 +619,12 @@ struct btp_gap_periodic_biginfo_ev { uint8_t encryption; } __packed; +#define BTP_GAP_EV_PEER_CAR_RECEIVED 0x98 +struct btp_gap_peer_car_status_ev { + bt_addr_le_t address; + uint8_t car; +} __packed; + struct bt_le_per_adv_param; struct bt_le_per_adv_sync_param; struct bt_le_adv_param; diff --git a/tests/bluetooth/tester/src/btp_gap.c b/tests/bluetooth/tester/src/btp_gap.c index 4d0867b5a33f8..7295b0f2fe1f4 100644 --- a/tests/bluetooth/tester/src/btp_gap.c +++ b/tests/bluetooth/tester/src/btp_gap.c @@ -66,35 +66,64 @@ static struct bt_le_oob oob_sc_remote = { 0 }; #define REJECT_LATENCY 0x0000 #define REJECT_SUPERVISION_TIMEOUT 0x0C80 +/* Used to store CAR support status of peer devices. */ static struct { bt_addr_le_t addr; + bool paired; bool supported; -} cars[CONFIG_BT_MAX_PAIRED]; +} peers_with_car[CONFIG_BT_MAX_PAIRED]; + + +static void add_to_peers_with_car(const bt_addr_le_t *addr, bool supported) +{ + + for (int i = 0; i < CONFIG_BT_MAX_PAIRED; i++) { + if (!peers_with_car[i].paired) { + peers_with_car[i].paired = true; + peers_with_car[i].supported = supported; + bt_addr_le_copy(&peers_with_car[i].addr, addr); + return; + } + } +} + +static void remove_from_peers_with_car(const bt_addr_le_t *addr) +{ + + for (int i = 0; i < CONFIG_BT_MAX_PAIRED; i++) { + if (peers_with_car[i].paired && bt_addr_le_cmp(addr, &peers_with_car[i].addr)) { + peers_with_car[i].paired = false; + return; + } + } +} static uint8_t read_car_cb(struct bt_conn *conn, uint8_t err, struct bt_gatt_read_params *params, const void *data, uint16_t length) { + struct btp_gap_peer_car_status_ev ev; struct bt_conn_info info; bool supported = false; + ev.car = 0x00; + if (!err && data && length == 1) { const uint8_t *tmp = data; /* only 0 or 1 are valid values */ if (tmp[0] == 1) { supported = true; + ev.car = 0x01; } } bt_conn_get_info(conn, &info); - for (int i = 0; i < CONFIG_BT_MAX_PAIRED; i++) { - if (bt_addr_le_eq(info.le.dst, &cars[i].addr)) { - cars[i].supported = supported; - break; - } - } + add_to_peers_with_car(info.le.dst, supported); + + bt_addr_le_copy(&ev.address, info.le.dst); + tester_event(BTP_SERVICE_ID_GAP, BTP_GAP_EV_PEER_CAR_RECEIVED, &ev, sizeof(ev)); return BT_GATT_ITER_STOP; } @@ -165,6 +194,7 @@ static void le_disconnected(struct bt_conn *conn, uint8_t reason) addr = bt_conn_get_dst(conn); (void)bt_addr_le_to_str(addr, addr_str, sizeof(addr_str)); bt_addr_le_copy(&ev.address, addr); + remove_from_peers_with_car(addr); } else if (IS_ENABLED(CONFIG_BT_CLASSIC) && bt_conn_is_type(conn, BT_CONN_TYPE_BR)) { const bt_addr_t *br_addr; @@ -972,26 +1002,34 @@ static uint8_t start_directed_advertising(const void *cmd, uint16_t cmd_len, { const struct btp_gap_start_directed_adv_cmd *cp = cmd; struct btp_gap_start_directed_adv_rp *rp = rsp; - struct bt_le_adv_param adv_param; + struct bt_le_adv_param adv_param = + BT_LE_ADV_PARAM_INIT(BT_LE_ADV_OPT_CONN, BT_GAP_ADV_FAST_INT_MIN_2, + BT_GAP_ADV_FAST_INT_MAX_2, NULL); uint16_t options = sys_le16_to_cpu(cp->options); - adv_param = *BT_LE_ADV_CONN_DIR(&cp->address); - - if (!(options & BTP_GAP_START_DIRECTED_ADV_HD)) { - adv_param.options |= BT_LE_ADV_OPT_DIR_MODE_LOW_DUTY; - adv_param.interval_max = BT_GAP_ADV_FAST_INT_MAX_2; - adv_param.interval_min = BT_GAP_ADV_FAST_INT_MIN_2; - } - if (IS_ENABLED(CONFIG_BT_PRIVACY) && (options & BTP_GAP_START_DIRECTED_ADV_PEER_RPA)) { - /* check if peer supports Central Address Resolution */ + /* + * Check if peer supports Central Address Resolution. + * if not supported the advertisement will be started as undirected + */ for (int i = 0; i < CONFIG_BT_MAX_PAIRED; i++) { - if (bt_addr_le_eq(&cp->address, &cars[i].addr)) { - if (cars[i].supported) { + if (bt_addr_le_eq(&cp->address, &peers_with_car[i].addr)) { + if (peers_with_car[i].supported) { adv_param.options |= BT_LE_ADV_OPT_DIR_ADDR_RPA; + adv_param.peer = &cp->address; + + if (!(options & BTP_GAP_START_DIRECTED_ADV_HD)) { + adv_param.options |= BT_LE_ADV_OPT_DIR_MODE_LOW_DUTY; + } + break; } } } + } else { + adv_param.peer = &cp->address; + if (!(options & BTP_GAP_START_DIRECTED_ADV_HD)) { + adv_param.options |= BT_LE_ADV_OPT_DIR_MODE_LOW_DUTY; + } } if (bt_le_adv_start(&adv_param, NULL, 0, NULL, 0) < 0) {