From 6356a25ef1719432c2e0274ced4877ab1338c436 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 81c7ba723b6c..fa0a4ff4a879 100644 --- a/tests/bluetooth/tester/src/btp/btp_gap.h +++ b/tests/bluetooth/tester/src/btp/btp_gap.h @@ -578,6 +578,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 f3535d4acca7..463dba9a042e 100644 --- a/tests/bluetooth/tester/src/btp_gap.c +++ b/tests/bluetooth/tester/src/btp_gap.c @@ -65,35 +65,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; } @@ -164,6 +193,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; @@ -971,26 +1001,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) {