Bluetooth: Host: Add more tests for GATT client becoming change-aware
For clients with both a single and multiple ATT channels: - Read a characteristic before reading the DB hash and then retrying - Read the DB hash and then do the reads - Retry the reads without reading the DB hash Signed-off-by: Herman Berget <herman.berget@nordicsemi.no>
This commit is contained in:
parent
2a5d9d10d1
commit
23d4788afa
11 changed files with 308 additions and 46 deletions
|
@ -10,6 +10,7 @@ CONFIG_BT_L2CAP_DYNAMIC_CHANNEL=y
|
|||
CONFIG_BT_L2CAP_ECRED=y
|
||||
CONFIG_BT_EATT=y
|
||||
CONFIG_BT_EATT_MAX=1
|
||||
CONFIG_BT_EATT_AUTO_CONNECT=n
|
||||
|
||||
CONFIG_ASSERT=y
|
||||
CONFIG_BT_TESTING=y
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
|
||||
extern enum bst_result_t bst_result;
|
||||
|
||||
#define WAIT_TIME (30 * 1e6) /*seconds*/
|
||||
#define WAIT_TIME (60 * 1e6) /*seconds*/
|
||||
|
||||
#define CREATE_FLAG(flag) static atomic_t flag = (atomic_t)false
|
||||
#define SET_FLAG(flag) (void)atomic_set(&flag, (atomic_t)true)
|
||||
|
|
|
@ -176,12 +176,7 @@ static void gatt_discover(const struct bt_uuid *uuid, uint8_t type)
|
|||
WAIT_FOR_FLAG(flag_discover_complete);
|
||||
printk("Discover complete\n");
|
||||
}
|
||||
|
||||
static uint8_t gatt_read_cb(struct bt_conn *conn, uint8_t err, struct bt_gatt_read_params *params,
|
||||
const void *data, uint16_t length);
|
||||
|
||||
static struct bt_gatt_read_params chan_1_read = {
|
||||
.func = gatt_read_cb,
|
||||
.handle_count = 1,
|
||||
.single = {
|
||||
.handle = 0, /* Will be set later */
|
||||
|
@ -189,7 +184,6 @@ static struct bt_gatt_read_params chan_1_read = {
|
|||
},
|
||||
};
|
||||
static struct bt_gatt_read_params chan_2_read = {
|
||||
.func = gatt_read_cb,
|
||||
.handle_count = 1,
|
||||
.single = {
|
||||
.handle = 0, /* Will be set later */
|
||||
|
@ -197,7 +191,6 @@ static struct bt_gatt_read_params chan_2_read = {
|
|||
},
|
||||
};
|
||||
static struct bt_gatt_read_params db_hash_read = {
|
||||
.func = gatt_read_cb,
|
||||
.handle_count = 0,
|
||||
.by_uuid = {
|
||||
.start_handle = BT_ATT_FIRST_ATTRIBUTE_HANDLE,
|
||||
|
@ -213,29 +206,54 @@ void expect_status(uint8_t err, uint8_t status)
|
|||
}
|
||||
}
|
||||
|
||||
static uint8_t gatt_read_cb(struct bt_conn *conn, uint8_t err, struct bt_gatt_read_params *params,
|
||||
const void *data, uint16_t length)
|
||||
static uint8_t gatt_read_expect_success_cb(struct bt_conn *conn, uint8_t err,
|
||||
struct bt_gatt_read_params *params, const void *data,
|
||||
uint16_t length)
|
||||
{
|
||||
printk("GATT read cb: err 0x%02X\n", err);
|
||||
expect_status(err, BT_ATT_ERR_SUCCESS);
|
||||
|
||||
if (params == &db_hash_read) {
|
||||
expect_status(err, BT_ATT_ERR_SUCCESS);
|
||||
SET_FLAG(flag_db_hash_read);
|
||||
} else if (params == &chan_1_read) {
|
||||
if (flag_db_hash_read) {
|
||||
expect_status(err, BT_ATT_ERR_SUCCESS);
|
||||
} else {
|
||||
expect_status(err, BT_ATT_ERR_DB_OUT_OF_SYNC);
|
||||
}
|
||||
|
||||
SET_FLAG(flag_chan_1_read);
|
||||
} else if (params == &chan_2_read) {
|
||||
if (flag_db_hash_read) {
|
||||
expect_status(err, BT_ATT_ERR_SUCCESS);
|
||||
} else {
|
||||
expect_status(err, BT_ATT_ERR_DB_OUT_OF_SYNC);
|
||||
}
|
||||
SET_FLAG(flag_chan_2_read);
|
||||
} else {
|
||||
FAIL("Unexpected params\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint8_t gatt_read_expect_err_unlikely_cb(struct bt_conn *conn, uint8_t err,
|
||||
struct bt_gatt_read_params *params,
|
||||
const void *data, uint16_t length)
|
||||
{
|
||||
printk("GATT read cb: err 0x%02X\n", err);
|
||||
expect_status(err, BT_ATT_ERR_UNLIKELY);
|
||||
|
||||
if (params == &chan_1_read) {
|
||||
SET_FLAG(flag_chan_1_read);
|
||||
} else if (params == &chan_2_read) {
|
||||
SET_FLAG(flag_chan_2_read);
|
||||
} else {
|
||||
FAIL("Unexpected params\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint8_t gatt_read_expect_err_out_of_sync_cb(struct bt_conn *conn, uint8_t err,
|
||||
struct bt_gatt_read_params *params,
|
||||
const void *data, uint16_t length)
|
||||
{
|
||||
printk("GATT read cb: err 0x%02X\n", err);
|
||||
expect_status(err, BT_ATT_ERR_DB_OUT_OF_SYNC);
|
||||
|
||||
if (params == &chan_1_read) {
|
||||
SET_FLAG(flag_chan_1_read);
|
||||
} else if (params == &chan_2_read) {
|
||||
SET_FLAG(flag_chan_2_read);
|
||||
} else {
|
||||
FAIL("Unexpected params\n");
|
||||
|
@ -294,7 +312,7 @@ static void enable_robust_caching(void)
|
|||
printk("Success\n");
|
||||
}
|
||||
|
||||
static void test_main(void)
|
||||
static void test_main_common(bool connect_eatt)
|
||||
{
|
||||
int err;
|
||||
|
||||
|
@ -326,9 +344,11 @@ static void test_main(void)
|
|||
|
||||
enable_robust_caching();
|
||||
|
||||
while (bt_eatt_count(g_conn) < 1) {
|
||||
/* Wait for EATT channel to connect, in case it hasn't already */
|
||||
k_sleep(K_MSEC(10));
|
||||
if (connect_eatt) {
|
||||
while (bt_eatt_count(g_conn) < 1) {
|
||||
/* Wait for EATT channel to connect, in case it hasn't already */
|
||||
k_sleep(K_MSEC(10));
|
||||
}
|
||||
}
|
||||
|
||||
/* Tell the server to register additional service */
|
||||
|
@ -339,7 +359,39 @@ static void test_main(void)
|
|||
|
||||
chan_1_read.single.handle = chrc_handle;
|
||||
chan_2_read.single.handle = chrc_handle;
|
||||
}
|
||||
|
||||
static void test_main_db_hash_read_eatt(void)
|
||||
{
|
||||
test_main_common(true);
|
||||
|
||||
/* Read the DB hash to become change-aware */
|
||||
db_hash_read.func = gatt_read_expect_success_cb;
|
||||
gatt_read(&db_hash_read);
|
||||
WAIT_FOR_FLAG(flag_db_hash_read);
|
||||
|
||||
/* These shall now succeed */
|
||||
chan_1_read.func = gatt_read_expect_success_cb;
|
||||
chan_2_read.func = gatt_read_expect_success_cb;
|
||||
UNSET_FLAG(flag_chan_1_read);
|
||||
UNSET_FLAG(flag_chan_2_read);
|
||||
gatt_read(&chan_1_read);
|
||||
gatt_read(&chan_2_read);
|
||||
WAIT_FOR_FLAG(flag_chan_1_read);
|
||||
WAIT_FOR_FLAG(flag_chan_2_read);
|
||||
|
||||
/* Signal to server that reads are done */
|
||||
backchannel_sync_send();
|
||||
|
||||
PASS("GATT client Passed\n");
|
||||
}
|
||||
|
||||
static void test_main_out_of_sync_eatt(void)
|
||||
{
|
||||
test_main_common(true);
|
||||
|
||||
chan_1_read.func = gatt_read_expect_err_out_of_sync_cb;
|
||||
chan_2_read.func = gatt_read_expect_err_out_of_sync_cb;
|
||||
gatt_read(&chan_1_read);
|
||||
gatt_read(&chan_2_read);
|
||||
|
||||
|
@ -350,9 +402,14 @@ static void test_main(void)
|
|||
WAIT_FOR_FLAG(flag_chan_1_read);
|
||||
WAIT_FOR_FLAG(flag_chan_2_read);
|
||||
|
||||
/* Read the DB hash to become change-aware */
|
||||
db_hash_read.func = gatt_read_expect_success_cb;
|
||||
gatt_read(&db_hash_read);
|
||||
WAIT_FOR_FLAG(flag_db_hash_read);
|
||||
|
||||
/* These shall now succeed */
|
||||
chan_1_read.func = gatt_read_expect_success_cb;
|
||||
chan_2_read.func = gatt_read_expect_success_cb;
|
||||
UNSET_FLAG(flag_chan_1_read);
|
||||
UNSET_FLAG(flag_chan_2_read);
|
||||
gatt_read(&chan_1_read);
|
||||
|
@ -360,15 +417,146 @@ static void test_main(void)
|
|||
WAIT_FOR_FLAG(flag_chan_1_read);
|
||||
WAIT_FOR_FLAG(flag_chan_2_read);
|
||||
|
||||
/* Signal to server that reads are done */
|
||||
backchannel_sync_send();
|
||||
|
||||
PASS("GATT client Passed\n");
|
||||
}
|
||||
|
||||
static void test_main_retry_reads_eatt(void)
|
||||
{
|
||||
test_main_common(true);
|
||||
|
||||
chan_1_read.func = gatt_read_expect_err_out_of_sync_cb;
|
||||
chan_2_read.func = gatt_read_expect_err_out_of_sync_cb;
|
||||
gatt_read(&chan_1_read);
|
||||
gatt_read(&chan_2_read);
|
||||
|
||||
/* Wait until received response on both reads. When robust caching is implemented
|
||||
* on the client side, the waiting shall be done automatically by the host when
|
||||
* reading the DB hash.
|
||||
*/
|
||||
WAIT_FOR_FLAG(flag_chan_1_read);
|
||||
WAIT_FOR_FLAG(flag_chan_2_read);
|
||||
|
||||
/* Retry the reads, these shall time out */
|
||||
chan_1_read.func = gatt_read_expect_err_unlikely_cb;
|
||||
chan_2_read.func = gatt_read_expect_err_unlikely_cb;
|
||||
UNSET_FLAG(flag_chan_1_read);
|
||||
UNSET_FLAG(flag_chan_2_read);
|
||||
gatt_read(&chan_1_read);
|
||||
gatt_read(&chan_2_read);
|
||||
WAIT_FOR_FLAG(flag_chan_1_read);
|
||||
WAIT_FOR_FLAG(flag_chan_2_read);
|
||||
|
||||
/* Signal to server that reads are done */
|
||||
backchannel_sync_send();
|
||||
|
||||
PASS("GATT client Passed\n");
|
||||
}
|
||||
|
||||
static void test_main_db_hash_read_no_eatt(void)
|
||||
{
|
||||
test_main_common(false);
|
||||
|
||||
/* Read the DB hash to become change-aware */
|
||||
db_hash_read.func = gatt_read_expect_success_cb;
|
||||
gatt_read(&db_hash_read);
|
||||
WAIT_FOR_FLAG(flag_db_hash_read);
|
||||
|
||||
/* Read shall now succeed */
|
||||
chan_1_read.func = gatt_read_expect_success_cb;
|
||||
UNSET_FLAG(flag_chan_1_read);
|
||||
gatt_read(&chan_1_read);
|
||||
WAIT_FOR_FLAG(flag_chan_1_read);
|
||||
|
||||
/* Signal to server that reads are done */
|
||||
backchannel_sync_send();
|
||||
|
||||
PASS("GATT client Passed\n");
|
||||
}
|
||||
|
||||
static void test_main_out_of_sync_no_eatt(void)
|
||||
{
|
||||
test_main_common(false);
|
||||
|
||||
chan_1_read.func = gatt_read_expect_err_out_of_sync_cb;
|
||||
gatt_read(&chan_1_read);
|
||||
WAIT_FOR_FLAG(flag_chan_1_read);
|
||||
|
||||
/* Read the DB hash to become change-aware */
|
||||
db_hash_read.func = gatt_read_expect_success_cb;
|
||||
gatt_read(&db_hash_read);
|
||||
WAIT_FOR_FLAG(flag_db_hash_read);
|
||||
|
||||
/* Read shall now succeed */
|
||||
chan_1_read.func = gatt_read_expect_success_cb;
|
||||
UNSET_FLAG(flag_chan_1_read);
|
||||
gatt_read(&chan_1_read);
|
||||
WAIT_FOR_FLAG(flag_chan_1_read);
|
||||
|
||||
/* Signal to server that reads are done */
|
||||
backchannel_sync_send();
|
||||
|
||||
PASS("GATT client Passed\n");
|
||||
}
|
||||
|
||||
static void test_main_retry_reads_no_eatt(void)
|
||||
{
|
||||
test_main_common(false);
|
||||
|
||||
chan_1_read.func = gatt_read_expect_err_out_of_sync_cb;
|
||||
gatt_read(&chan_1_read);
|
||||
WAIT_FOR_FLAG(flag_chan_1_read);
|
||||
|
||||
/* Read again to become change-aware */
|
||||
chan_1_read.func = gatt_read_expect_success_cb;
|
||||
UNSET_FLAG(flag_chan_1_read);
|
||||
gatt_read(&chan_1_read);
|
||||
WAIT_FOR_FLAG(flag_chan_1_read);
|
||||
|
||||
/* Signal to server that reads are done */
|
||||
backchannel_sync_send();
|
||||
|
||||
PASS("GATT client Passed\n");
|
||||
}
|
||||
|
||||
static const struct bst_test_instance test_vcs[] = {
|
||||
{
|
||||
.test_id = "gatt_client",
|
||||
.test_id = "gatt_client_db_hash_read_eatt",
|
||||
.test_post_init_f = test_init,
|
||||
.test_tick_f = test_tick,
|
||||
.test_main_f = test_main,
|
||||
.test_main_f = test_main_db_hash_read_eatt,
|
||||
},
|
||||
{
|
||||
.test_id = "gatt_client_out_of_sync_eatt",
|
||||
.test_post_init_f = test_init,
|
||||
.test_tick_f = test_tick,
|
||||
.test_main_f = test_main_out_of_sync_eatt,
|
||||
},
|
||||
{
|
||||
.test_id = "gatt_client_retry_reads_eatt",
|
||||
.test_post_init_f = test_init,
|
||||
.test_tick_f = test_tick,
|
||||
.test_main_f = test_main_retry_reads_eatt,
|
||||
},
|
||||
{
|
||||
.test_id = "gatt_client_db_hash_read_no_eatt",
|
||||
.test_post_init_f = test_init,
|
||||
.test_tick_f = test_tick,
|
||||
.test_main_f = test_main_db_hash_read_no_eatt,
|
||||
},
|
||||
{
|
||||
.test_id = "gatt_client_out_of_sync_no_eatt",
|
||||
.test_post_init_f = test_init,
|
||||
.test_tick_f = test_tick,
|
||||
.test_main_f = test_main_out_of_sync_no_eatt,
|
||||
},
|
||||
{
|
||||
.test_id = "gatt_client_retry_reads_no_eatt",
|
||||
.test_post_init_f = test_init,
|
||||
.test_tick_f = test_tick,
|
||||
.test_main_f = test_main_retry_reads_no_eatt,
|
||||
},
|
||||
BSTEST_END_MARKER,
|
||||
};
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
extern enum bst_result_t bst_result;
|
||||
|
||||
CREATE_FLAG(flag_is_connected);
|
||||
CREATE_FLAG(flag_read_done);
|
||||
|
||||
static struct bt_conn *g_conn;
|
||||
|
||||
|
@ -61,7 +60,6 @@ static ssize_t read_test_chrc(struct bt_conn *conn, const struct bt_gatt_attr *a
|
|||
uint16_t len, uint16_t offset)
|
||||
{
|
||||
printk("Characteristic read\n");
|
||||
SET_FLAG(flag_read_done);
|
||||
|
||||
return bt_gatt_attr_read(conn, attr, buf, len, offset, (const void *)chrc_data, CHRC_SIZE);
|
||||
}
|
||||
|
@ -76,7 +74,7 @@ static struct bt_gatt_attr additional_attributes[] = {
|
|||
|
||||
static struct bt_gatt_service additional_gatt_service = BT_GATT_SERVICE(additional_attributes);
|
||||
|
||||
static void test_main(void)
|
||||
static void test_main_common(bool connect_eatt)
|
||||
{
|
||||
int err;
|
||||
const struct bt_data ad[] = { BT_DATA_BYTES(BT_DATA_FLAGS,
|
||||
|
@ -104,6 +102,15 @@ static void test_main(void)
|
|||
|
||||
WAIT_FOR_FLAG(flag_is_connected);
|
||||
|
||||
if (connect_eatt) {
|
||||
err = bt_eatt_connect(g_conn, CONFIG_BT_EATT_MAX);
|
||||
if (err) {
|
||||
FAIL("Failed to connect EATT channels (err %d)\n", err);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Wait for client to do discovery and configuration */
|
||||
backchannel_sync_wait();
|
||||
|
||||
|
@ -116,17 +123,34 @@ static void test_main(void)
|
|||
/* Signal to client that additional service is registered */
|
||||
backchannel_sync_send();
|
||||
|
||||
WAIT_FOR_FLAG(flag_read_done);
|
||||
/* Wait for client to be done reading */
|
||||
backchannel_sync_wait();
|
||||
|
||||
PASS("GATT server passed\n");
|
||||
}
|
||||
|
||||
static void test_main_eatt(void)
|
||||
{
|
||||
test_main_common(true);
|
||||
}
|
||||
|
||||
static void test_main_no_eatt(void)
|
||||
{
|
||||
test_main_common(false);
|
||||
}
|
||||
|
||||
static const struct bst_test_instance test_gatt_server[] = {
|
||||
{
|
||||
.test_id = "gatt_server",
|
||||
.test_id = "gatt_server_eatt",
|
||||
.test_post_init_f = test_init,
|
||||
.test_tick_f = test_tick,
|
||||
.test_main_f = test_main,
|
||||
.test_main_f = test_main_eatt,
|
||||
},
|
||||
{
|
||||
.test_id = "gatt_server_no_eatt",
|
||||
.test_post_init_f = test_init,
|
||||
.test_tick_f = test_tick,
|
||||
.test_main_f = test_main_no_eatt,
|
||||
},
|
||||
BSTEST_END_MARKER,
|
||||
};
|
||||
|
|
|
@ -2,17 +2,18 @@
|
|||
# Copyright 2022 Nordic Semiconductor ASA
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
simulation_id="gatt_change_aware"
|
||||
verbosity_level=2
|
||||
process_ids=""; exit_code=0
|
||||
process_ids=""
|
||||
exit_code=0
|
||||
|
||||
function Execute(){
|
||||
if [ ! -f $1 ]; then
|
||||
echo -e " \e[91m`pwd`/`basename $1` cannot be found (did you forget to\
|
||||
function Execute() {
|
||||
if [ ! -f $1 ]; then
|
||||
echo -e " \e[91m$(pwd)/$(basename $1) cannot be found (did you forget to\
|
||||
compile it?)\e[39m"
|
||||
exit 1
|
||||
fi
|
||||
timeout 120 $@ & process_ids="$process_ids $!"
|
||||
exit 1
|
||||
fi
|
||||
timeout 120 $@ &
|
||||
process_ids="$process_ids $!"
|
||||
}
|
||||
|
||||
: "${BSIM_OUT_PATH:?BSIM_OUT_PATH must be defined}"
|
||||
|
@ -23,15 +24,15 @@ BOARD="${BOARD:-nrf52_bsim}"
|
|||
cd ${BSIM_OUT_PATH}/bin
|
||||
|
||||
Execute ./bs_${BOARD}_tests_bluetooth_bsim_bt_bsim_test_gatt_caching_prj_conf \
|
||||
-v=${verbosity_level} -s=${simulation_id} -d=0 -testid=gatt_client
|
||||
-v=${verbosity_level} -s=${simulation_id} -d=0 -testid=${client_id}
|
||||
|
||||
Execute ./bs_${BOARD}_tests_bluetooth_bsim_bt_bsim_test_gatt_caching_prj_conf \
|
||||
-v=${verbosity_level} -s=${simulation_id} -d=1 -testid=gatt_server
|
||||
-v=${verbosity_level} -s=${simulation_id} -d=1 -testid=${server_id}
|
||||
|
||||
Execute ./bs_2G4_phy_v1 -v=${verbosity_level} -s=${simulation_id} \
|
||||
-D=2 -sim_length=60e6 $@
|
||||
-D=2 -sim_length=60e6 $@
|
||||
|
||||
for process_id in $process_ids; do
|
||||
wait $process_id || let "exit_code=$?"
|
||||
wait $process_id || let "exit_code=$?"
|
||||
done
|
||||
exit $exit_code #the last exit code != 0
|
|
@ -0,0 +1,8 @@
|
|||
#!/usr/bin/env bash
|
||||
# Copyright 2022 Nordic Semiconductor ASA
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
simulation_id="gatt_caching_db_hash_read_eatt" \
|
||||
client_id="gatt_client_db_hash_read_eatt" \
|
||||
server_id="gatt_server_eatt" \
|
||||
$(dirname "${BASH_SOURCE[0]}")/_run_test.sh
|
|
@ -0,0 +1,8 @@
|
|||
#!/usr/bin/env bash
|
||||
# Copyright 2022 Nordic Semiconductor ASA
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
simulation_id="gatt_caching_db_hash_read_no_eatt" \
|
||||
client_id="gatt_client_db_hash_read_no_eatt" \
|
||||
server_id="gatt_server_no_eatt" \
|
||||
$(dirname "${BASH_SOURCE[0]}")/_run_test.sh
|
|
@ -0,0 +1,8 @@
|
|||
#!/usr/bin/env bash
|
||||
# Copyright 2022 Nordic Semiconductor ASA
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
simulation_id="gatt_caching_out_of_sync_eatt" \
|
||||
client_id="gatt_client_out_of_sync_eatt" \
|
||||
server_id="gatt_server_eatt" \
|
||||
$(dirname "${BASH_SOURCE[0]}")/_run_test.sh
|
|
@ -0,0 +1,8 @@
|
|||
#!/usr/bin/env bash
|
||||
# Copyright 2022 Nordic Semiconductor ASA
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
simulation_id="gatt_caching_out_of_sync_no_eatt" \
|
||||
client_id="gatt_client_out_of_sync_no_eatt" \
|
||||
server_id="gatt_server_no_eatt" \
|
||||
$(dirname "${BASH_SOURCE[0]}")/_run_test.sh
|
|
@ -0,0 +1,8 @@
|
|||
#!/usr/bin/env bash
|
||||
# Copyright 2022 Nordic Semiconductor ASA
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
simulation_id="gatt_caching_retry_reads_eatt" \
|
||||
client_id="gatt_client_retry_reads_eatt" \
|
||||
server_id="gatt_server_eatt" \
|
||||
$(dirname "${BASH_SOURCE[0]}")/_run_test.sh
|
|
@ -0,0 +1,8 @@
|
|||
#!/usr/bin/env bash
|
||||
# Copyright 2022 Nordic Semiconductor ASA
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
simulation_id="gatt_caching_retry_reads_no_eatt" \
|
||||
client_id="gatt_client_retry_reads_no_eatt" \
|
||||
server_id="gatt_server_no_eatt" \
|
||||
$(dirname "${BASH_SOURCE[0]}")/_run_test.sh
|
Loading…
Add table
Add a link
Reference in a new issue