1 /*
2 * Copyright (c) 2024 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/kernel.h>
8 #include <zephyr/bluetooth/bluetooth.h>
9 #include <zephyr/bluetooth/conn.h>
10 #include <zephyr/bluetooth/l2cap.h>
11 #include <zephyr/logging/log.h>
12
13 #include "testlib/conn.h"
14 #include "testlib/scan.h"
15
16 #include "babblekit/flags.h"
17 #include "babblekit/testcase.h"
18
19 LOG_MODULE_REGISTER(dut, CONFIG_APP_LOG_LEVEL);
20
21 static atomic_t disconnected_channels;
22
23 static struct bt_l2cap_le_chan chans[4];
24
sent_cb(struct bt_l2cap_chan * chan)25 void sent_cb(struct bt_l2cap_chan *chan)
26 {
27 LOG_DBG("%p", chan);
28 }
29
recv_cb(struct bt_l2cap_chan * chan,struct net_buf * buf)30 int recv_cb(struct bt_l2cap_chan *chan, struct net_buf *buf)
31 {
32 LOG_DBG("%p", chan);
33
34 return 0;
35 }
36
l2cap_chan_connected_cb(struct bt_l2cap_chan * l2cap_chan)37 void l2cap_chan_connected_cb(struct bt_l2cap_chan *l2cap_chan)
38 {
39 TEST_ASSERT("This shouldn't happen");
40 }
41
l2cap_chan_disconnected_cb(struct bt_l2cap_chan * chan)42 void l2cap_chan_disconnected_cb(struct bt_l2cap_chan *chan)
43 {
44 atomic_inc(&disconnected_channels);
45 }
46
47 static struct bt_l2cap_chan_ops ops = {
48 .connected = l2cap_chan_connected_cb,
49 .disconnected = l2cap_chan_disconnected_cb,
50 .recv = recv_cb,
51 .sent = sent_cb,
52 };
53
entrypoint_dut(void)54 void entrypoint_dut(void)
55 {
56 /* Test purpose:
57 *
58 * Verify that a peer that doesn't support ECRED channels doesn't result
59 * in us keeping half-open channels.
60 *
61 * Two devices:
62 * - `dut`: tries to establish 4 ecred chans
63 * - `peer`: rejects the request
64 *
65 * Initial conditions:
66 * - Both devices are connected
67 *
68 * Procedure:
69 * - [dut] request to establish 4 ecred channels
70 * - [peer] reject command as unknown
71 * - [dut] get `disconnected` called on all 4 channels
72 *
73 * [verdict]
74 * - each channel gets the `disconnected` callback called
75 */
76 int err;
77 bt_addr_le_t peer = {};
78 struct bt_conn *conn = NULL;
79
80 TEST_START("dut");
81
82 /* Initialize Bluetooth */
83 err = bt_enable(NULL);
84 TEST_ASSERT(err == 0, "Can't enable Bluetooth (err %d)", err);
85 LOG_DBG("Bluetooth initialized");
86
87 err = bt_testlib_scan_find_name(&peer, "ecred_peer");
88 TEST_ASSERT(!err, "Failed to start scan (err %d)", err);
89
90 /* Create a connection using that address */
91 err = bt_testlib_connect(&peer, &conn);
92 TEST_ASSERT(!err, "Failed to initiate connection (err %d)", err);
93
94 LOG_DBG("Connected");
95
96 LOG_INF("Send ECRED connection request");
97 struct bt_l2cap_chan *chan_list[5] = {0};
98
99 for (int i = 0; i < 4; i++) {
100 /* Register the callbacks */
101 chans[i].chan.ops = &ops;
102
103 /* Add the channel to the connection request list */
104 chan_list[i] = &chans[i].chan;
105 }
106
107 /* The PSM doesn't matter, as the peer doesn't support the command */
108 err = bt_l2cap_ecred_chan_connect(conn, chan_list, 0x0080);
109 TEST_ASSERT(!err, "Error connecting l2cap channels (err %d)\n", err);
110
111 LOG_INF("Wait until peer rejects the channel establishment request");
112 while (atomic_get(&disconnected_channels) < 4) {
113 k_sleep(K_MSEC(10));
114 }
115
116 TEST_PASS_AND_EXIT("dut");
117 }
118