diff --git a/tests/bsim/bluetooth/host/compile.sh b/tests/bsim/bluetooth/host/compile.sh index 33c71bc3ddf..31a4b70162e 100755 --- a/tests/bsim/bluetooth/host/compile.sh +++ b/tests/bsim/bluetooth/host/compile.sh @@ -53,6 +53,8 @@ app=tests/bsim/bluetooth/host/l2cap/credits compile app=tests/bsim/bluetooth/host/l2cap/credits conf_file=prj_ecred.conf compile app=tests/bsim/bluetooth/host/l2cap/credits_seg_recv compile app=tests/bsim/bluetooth/host/l2cap/credits_seg_recv conf_file=prj_ecred.conf compile +app=tests/bsim/bluetooth/host/l2cap/send_on_connect compile +app=tests/bsim/bluetooth/host/l2cap/send_on_connect conf_file=prj_ecred.conf compile app=tests/bsim/bluetooth/host/misc/disable compile diff --git a/tests/bsim/bluetooth/host/l2cap/send_on_connect/CMakeLists.txt b/tests/bsim/bluetooth/host/l2cap/send_on_connect/CMakeLists.txt new file mode 100644 index 00000000000..f6db9d424e2 --- /dev/null +++ b/tests/bsim/bluetooth/host/l2cap/send_on_connect/CMakeLists.txt @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(bsim_test_l2cap_send_on_connect) + +target_sources(app PRIVATE + src/common.c + src/main_l2cap_send_on_connect.c + src/main.c +) + +zephyr_include_directories( + ${BSIM_COMPONENTS_PATH}/libUtilv1/src/ + ${BSIM_COMPONENTS_PATH}/libPhyComv1/src/ + ) diff --git a/tests/bsim/bluetooth/host/l2cap/send_on_connect/prj.conf b/tests/bsim/bluetooth/host/l2cap/send_on_connect/prj.conf new file mode 100644 index 00000000000..8206e01ea66 --- /dev/null +++ b/tests/bsim/bluetooth/host/l2cap/send_on_connect/prj.conf @@ -0,0 +1,10 @@ +CONFIG_BT=y +CONFIG_BT_CENTRAL=y +CONFIG_BT_PERIPHERAL=y +CONFIG_BT_SMP=y +CONFIG_BT_L2CAP_DYNAMIC_CHANNEL=y +CONFIG_BT_L2CAP_ECRED=n + +CONFIG_BT_BUF_ACL_RX_SIZE=75 + +CONFIG_ASSERT=y diff --git a/tests/bsim/bluetooth/host/l2cap/send_on_connect/prj_ecred.conf b/tests/bsim/bluetooth/host/l2cap/send_on_connect/prj_ecred.conf new file mode 100644 index 00000000000..6d418003174 --- /dev/null +++ b/tests/bsim/bluetooth/host/l2cap/send_on_connect/prj_ecred.conf @@ -0,0 +1,10 @@ +CONFIG_BT=y +CONFIG_BT_CENTRAL=y +CONFIG_BT_PERIPHERAL=y +CONFIG_BT_SMP=y +CONFIG_BT_L2CAP_DYNAMIC_CHANNEL=y +CONFIG_BT_L2CAP_ECRED=y + +CONFIG_BT_BUF_ACL_RX_SIZE=75 + +CONFIG_ASSERT=y diff --git a/tests/bsim/bluetooth/host/l2cap/send_on_connect/src/common.c b/tests/bsim/bluetooth/host/l2cap/send_on_connect/src/common.c new file mode 100644 index 00000000000..f725ac6129c --- /dev/null +++ b/tests/bsim/bluetooth/host/l2cap/send_on_connect/src/common.c @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2022 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "common.h" + +extern enum bst_result_t bst_result; + +void test_init(void) +{ + bst_result = In_progress; + bst_ticker_set_next_tick_absolute(WAIT_TIME); +} + +void test_tick(bs_time_t HW_device_time) +{ + if (bst_result != Passed) { + FAIL("test failed (not passed after %i us)\n", WAIT_TIME); + } +} diff --git a/tests/bsim/bluetooth/host/l2cap/send_on_connect/src/common.h b/tests/bsim/bluetooth/host/l2cap/send_on_connect/src/common.h new file mode 100644 index 00000000000..3b0d09c53b6 --- /dev/null +++ b/tests/bsim/bluetooth/host/l2cap/send_on_connect/src/common.h @@ -0,0 +1,44 @@ +/* + * Common functions and helpers for L2CAP tests + * + * Copyright (c) 2022 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include "bs_types.h" +#include "bs_tracing.h" +#include "bstests.h" + +#define CREATE_FLAG(flag) static atomic_t flag = (atomic_t)false +#define SET_FLAG(flag) (void)atomic_set(&flag, (atomic_t)true) +#define UNSET_FLAG(flag) (void)atomic_set(&flag, (atomic_t)false) +#define WAIT_FOR_FLAG_SET(flag) \ + while (!(bool)atomic_get(&flag)) { \ + (void)k_sleep(K_MSEC(1)); \ + } +#define WAIT_FOR_FLAG_UNSET(flag) \ + while ((bool)atomic_get(&flag)) { \ + (void)k_sleep(K_MSEC(1)); \ + } + + +#define WAIT_TIME (30e6) /* 30 seconds*/ + +#define FAIL(...) \ + do { \ + bst_result = Failed; \ + bs_trace_error_time_line(__VA_ARGS__); \ + } while (0) + +#define PASS(...) \ + do { \ + bst_result = Passed; \ + bs_trace_info_time(1, __VA_ARGS__); \ + } while (0) + + +void test_init(void); +void test_tick(bs_time_t HW_device_time); diff --git a/tests/bsim/bluetooth/host/l2cap/send_on_connect/src/main.c b/tests/bsim/bluetooth/host/l2cap/send_on_connect/src/main.c new file mode 100644 index 00000000000..6fcc26c6cad --- /dev/null +++ b/tests/bsim/bluetooth/host/l2cap/send_on_connect/src/main.c @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2022 Nordic Semiconductor + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "bstests.h" + +extern struct bst_test_list *test_main_l2cap_send_on_connect_install(struct bst_test_list *tests); + +bst_test_install_t test_installers[] = { + test_main_l2cap_send_on_connect_install, + NULL +}; + +int main(void) +{ + bst_main(); + return 0; +} diff --git a/tests/bsim/bluetooth/host/l2cap/send_on_connect/src/main_l2cap_send_on_connect.c b/tests/bsim/bluetooth/host/l2cap/send_on_connect/src/main_l2cap_send_on_connect.c new file mode 100644 index 00000000000..b7eab47736d --- /dev/null +++ b/tests/bsim/bluetooth/host/l2cap/send_on_connect/src/main_l2cap_send_on_connect.c @@ -0,0 +1,259 @@ +/* + * Copyright (c) 2022 Nordic Semiconductor + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "common.h" + +#include +#include + +extern enum bst_result_t bst_result; + +static struct bt_conn *default_conn; + +#define PSM 0x80 + +CREATE_FLAG(is_connected); +CREATE_FLAG(chan_connected); +CREATE_FLAG(data_received); + +#define DATA_BYTE_VAL 0xBB + +/* L2CAP channel buffer pool */ +NET_BUF_POOL_DEFINE(buf_pool, 1, BT_L2CAP_SDU_BUF_SIZE(16), 8, NULL); + +static void chan_connected_cb(struct bt_l2cap_chan *l2cap_chan) +{ + struct net_buf *buf; + int err; + + /* Send data immediately on L2CAP connection */ + buf = net_buf_alloc(&buf_pool, K_NO_WAIT); + if (!buf) { + FAIL("Buffer allocation failed\n"); + } + + (void)net_buf_reserve(buf, BT_L2CAP_SDU_CHAN_SEND_RESERVE); + (void)net_buf_add_u8(buf, DATA_BYTE_VAL); + + /* Try to send data */ + err = bt_l2cap_chan_send(l2cap_chan, buf); + if (err) { + FAIL("Could not send data, error %d\n", err); + } + + SET_FLAG(chan_connected); +} + +static void chan_disconnected_cb(struct bt_l2cap_chan *l2cap_chan) +{ + (void)l2cap_chan; + + UNSET_FLAG(chan_connected); +} + +static int chan_recv_cb(struct bt_l2cap_chan *chan, struct net_buf *buf) +{ + (void)chan; + + if ((buf->len != 1) || (buf->data[0] != DATA_BYTE_VAL)) { + FAIL("Unexpected data received"); + } + + SET_FLAG(data_received); + + return 0; +} + +static const struct bt_l2cap_chan_ops l2cap_ops = { + .connected = chan_connected_cb, + .disconnected = chan_disconnected_cb, + .recv = chan_recv_cb, +}; + +static struct bt_l2cap_le_chan channel; + +static int accept(struct bt_conn *conn, struct bt_l2cap_chan **l2cap_chan) +{ + channel.chan.ops = &l2cap_ops; + *l2cap_chan = &channel.chan; + + return 0; +} + +static struct bt_l2cap_server server = { + .accept = accept, + .sec_level = BT_SECURITY_L1, + .psm = PSM, +}; + +static void connect_l2cap_channel(void) +{ + struct bt_l2cap_chan *chans[] = {&channel.chan, NULL}; + int err; + + channel.chan.ops = &l2cap_ops; + + if (IS_ENABLED(CONFIG_BT_L2CAP_ECRED)) { + err = bt_l2cap_ecred_chan_connect(default_conn, chans, server.psm); + if (err) { + FAIL("Failed to send ecred connection request (err %d)\n", err); + } + } else { + err = bt_l2cap_chan_connect(default_conn, &channel.chan, server.psm); + if (err) { + FAIL("Failed to send connection request (err %d)\n", err); + } + } +} + +static void register_l2cap_server(void) +{ + int err; + + err = bt_l2cap_server_register(&server); + if (err < 0) { + FAIL("Failed to get free server (err %d)\n"); + return; + } +} + +static void connected(struct bt_conn *conn, uint8_t err) +{ + if (err) { + FAIL("Failed to connect (err %d)\n", err); + bt_conn_unref(default_conn); + default_conn = NULL; + return; + } + + default_conn = bt_conn_ref(conn); + + SET_FLAG(is_connected); +} + +static void disconnected(struct bt_conn *conn, uint8_t reason) +{ + if (default_conn != conn) { + FAIL("Connection mismatch %p %p)\n", default_conn, conn); + return; + } + + bt_conn_unref(default_conn); + default_conn = NULL; + UNSET_FLAG(is_connected); +} + +BT_CONN_CB_DEFINE(conn_callbacks) = { + .connected = connected, + .disconnected = disconnected, +}; + +static void device_found(const bt_addr_le_t *addr, int8_t rssi, uint8_t type, + struct net_buf_simple *ad) +{ + struct bt_le_conn_param *param; + int err; + + err = bt_le_scan_stop(); + if (err) { + FAIL("Failed to stop scanning (err %d)\n", err); + return; + } + + param = BT_LE_CONN_PARAM_DEFAULT; + err = bt_conn_le_create(addr, BT_CONN_LE_CREATE_CONN, param, &default_conn); + if (err) { + FAIL("Failed to create connection (err %d)\n", err); + return; + } +} + +static void test_peripheral_main(void) +{ + int err; + const struct bt_data ad[] = { + BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)), + }; + + err = bt_enable(NULL); + if (err != 0) { + FAIL("Bluetooth init failed (err %d)\n", err); + return; + } + + register_l2cap_server(); + + err = bt_le_adv_start(BT_LE_ADV_CONN_NAME, ad, ARRAY_SIZE(ad), NULL, 0); + if (err != 0) { + FAIL("Advertising failed to start (err %d)\n", err); + return; + } + + WAIT_FOR_FLAG_SET(is_connected); + + WAIT_FOR_FLAG_SET(chan_connected); + + WAIT_FOR_FLAG_SET(data_received); + + WAIT_FOR_FLAG_UNSET(is_connected); + + PASS("Test passed\n"); +} + +static void test_central_main(void) +{ + int err; + + err = bt_enable(NULL); + if (err != 0) { + FAIL("Bluetooth init failed (err %d)\n", err); + } + + err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, device_found); + if (err != 0) { + FAIL("Scanning failed to start (err %d)\n", err); + } + + WAIT_FOR_FLAG_SET(is_connected); + + connect_l2cap_channel(); + WAIT_FOR_FLAG_SET(chan_connected); + + WAIT_FOR_FLAG_SET(data_received); + + err = bt_conn_disconnect(default_conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN); + if (err) { + FAIL("Failed to disconnect (err %d)\n", err); + return; + } + + WAIT_FOR_FLAG_UNSET(is_connected); + + PASS("Test passed\n"); +} + +static const struct bst_test_instance test_def[] = { + { + .test_id = "peripheral", + .test_descr = "Peripheral", + .test_post_init_f = test_init, + .test_tick_f = test_tick, + .test_main_f = test_peripheral_main, + }, + { + .test_id = "central", + .test_descr = "Central", + .test_post_init_f = test_init, + .test_tick_f = test_tick, + .test_main_f = test_central_main, + }, + BSTEST_END_MARKER, +}; + +struct bst_test_list *test_main_l2cap_send_on_connect_install(struct bst_test_list *tests) +{ + return bst_add_tests(tests, test_def); +} diff --git a/tests/bsim/bluetooth/host/l2cap/send_on_connect/tests_scripts/l2cap.sh b/tests/bsim/bluetooth/host/l2cap/send_on_connect/tests_scripts/l2cap.sh new file mode 100755 index 00000000000..7fa0459c327 --- /dev/null +++ b/tests/bsim/bluetooth/host/l2cap/send_on_connect/tests_scripts/l2cap.sh @@ -0,0 +1,39 @@ +#!/usr/bin/env bash +# Copyright (c) 2022 Nordic Semiconductor +# SPDX-License-Identifier: Apache-2.0 + +source ${ZEPHYR_BASE}/tests/bsim/sh_common.source + +simulation_id="l2cap_send_on_connect" +verbosity_level=2 +EXECUTE_TIMEOUT=120 + +cd ${BSIM_OUT_PATH}/bin + +Execute ./bs_${BOARD}_tests_bsim_bluetooth_host_l2cap_send_on_connect_prj_conf \ + -v=${verbosity_level} -s=${simulation_id} -d=0 -testid=central + +Execute ./bs_${BOARD}_tests_bsim_bluetooth_host_l2cap_send_on_connect_prj_conf \ + -v=${verbosity_level} -s=${simulation_id} -d=1 -testid=peripheral + +Execute ./bs_2G4_phy_v1 -v=${verbosity_level} -s=${simulation_id} \ + -D=2 -sim_length=30e6 $@ + +wait_for_background_jobs + +simulation_id="l2cap_send_on_connect_ecred" +verbosity_level=2 +EXECUTE_TIMEOUT=120 + +cd ${BSIM_OUT_PATH}/bin + +Execute ./bs_${BOARD}_tests_bsim_bluetooth_host_l2cap_send_on_connect_prj_ecred_conf \ + -v=${verbosity_level} -s=${simulation_id} -d=0 -testid=central + +Execute ./bs_${BOARD}_tests_bsim_bluetooth_host_l2cap_send_on_connect_prj_ecred_conf \ + -v=${verbosity_level} -s=${simulation_id} -d=1 -testid=peripheral + +Execute ./bs_2G4_phy_v1 -v=${verbosity_level} -s=${simulation_id} \ + -D=2 -sim_length=30e6 $@ + +wait_for_background_jobs