1 /*
2  * Copyright (c) 2020 - 2022 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/types.h>
8 #include <stddef.h>
9 #include <string.h>
10 #include <errno.h>
11 #include <zephyr/sys/printk.h>
12 #include <zephyr/sys/byteorder.h>
13 #include <zephyr/kernel.h>
14 #include <zephyr/init.h>
15 
16 #include <zephyr/net_buf.h>
17 
18 #include "ots_l2cap_internal.h"
19 
20 #include <zephyr/logging/log.h>
21 
22 /* This l2cap is the only OTS-file in use for OTC.
23  * If only OTC is used, the OTS log module must be registered here.
24  */
25 #if defined(CONFIG_BT_OTS)
26 LOG_MODULE_DECLARE(bt_ots, CONFIG_BT_OTS_LOG_LEVEL);
27 #elif defined(CONFIG_BT_OTS_CLIENT)
28 LOG_MODULE_REGISTER(bt_ots, CONFIG_BT_OTS_CLIENT_LOG_LEVEL);
29 #endif
30 
31 /* According to BLE specification Assigned Numbers that are used in the
32  * Logical Link Control for protocol/service multiplexers.
33  */
34 #define BT_GATT_OTS_L2CAP_PSM	0x0025
35 
36 NET_BUF_POOL_FIXED_DEFINE(ot_chan_tx_pool, 1,
37 			  BT_L2CAP_SDU_BUF_SIZE(CONFIG_BT_OTS_L2CAP_CHAN_TX_MTU),
38 			  CONFIG_BT_CONN_TX_USER_DATA_SIZE, NULL);
39 
40 #if (CONFIG_BT_OTS_L2CAP_CHAN_RX_MTU > BT_L2CAP_SDU_RX_MTU)
41 NET_BUF_POOL_FIXED_DEFINE(ot_chan_rx_pool, 1, CONFIG_BT_OTS_L2CAP_CHAN_RX_MTU, 8,
42 			  NULL);
43 #endif
44 
45 /* List of Object Transfer Channels. */
46 static sys_slist_t channels;
47 
ots_l2cap_send(struct bt_gatt_ots_l2cap * l2cap_ctx)48 static int ots_l2cap_send(struct bt_gatt_ots_l2cap *l2cap_ctx)
49 {
50 	int ret;
51 	struct net_buf *buf;
52 	uint32_t len;
53 
54 	/* Calculate maximum length of data chunk. */
55 	len = MIN(l2cap_ctx->ot_chan.tx.mtu, CONFIG_BT_OTS_L2CAP_CHAN_TX_MTU);
56 	len = MIN(len, l2cap_ctx->tx.len - l2cap_ctx->tx.len_sent);
57 
58 	/* Prepare buffer for sending. */
59 	buf = net_buf_alloc(&ot_chan_tx_pool, K_FOREVER);
60 	net_buf_reserve(buf, BT_L2CAP_SDU_CHAN_SEND_RESERVE);
61 	net_buf_add_mem(buf, &l2cap_ctx->tx.data[l2cap_ctx->tx.len_sent], len);
62 
63 	ret = bt_l2cap_chan_send(&l2cap_ctx->ot_chan.chan, buf);
64 	if (ret < 0) {
65 		LOG_ERR("Unable to send data over CoC: %d", ret);
66 		net_buf_unref(buf);
67 
68 		return -ENOEXEC;
69 	}
70 
71 	/* Mark that L2CAP TX was accepted. */
72 	l2cap_ctx->tx.len_sent += len;
73 
74 	LOG_DBG("Sending TX chunk with %d bytes on L2CAP CoC", len);
75 
76 	return 0;
77 }
78 
79 #if (CONFIG_BT_OTS_L2CAP_CHAN_RX_MTU > BT_L2CAP_SDU_RX_MTU)
l2cap_alloc_buf(struct bt_l2cap_chan * chan)80 static struct net_buf *l2cap_alloc_buf(struct bt_l2cap_chan *chan)
81 {
82 	LOG_DBG("Channel %p allocating buffer", chan);
83 
84 	return net_buf_alloc(&ot_chan_rx_pool, K_FOREVER);
85 }
86 #endif
87 
88 
l2cap_sent(struct bt_l2cap_chan * chan)89 static void l2cap_sent(struct bt_l2cap_chan *chan)
90 {
91 	struct bt_l2cap_le_chan *l2chan = CONTAINER_OF(chan, struct bt_l2cap_le_chan, chan);
92 	struct bt_gatt_ots_l2cap *l2cap_ctx;
93 
94 	LOG_DBG("Outgoing data channel %p transmitted", chan);
95 
96 	l2cap_ctx = CONTAINER_OF(l2chan, struct bt_gatt_ots_l2cap, ot_chan);
97 
98 	/* Ongoing TX - sending next chunk. */
99 	if (l2cap_ctx->tx.len != l2cap_ctx->tx.len_sent) {
100 		ots_l2cap_send(l2cap_ctx);
101 
102 		return;
103 	}
104 
105 	/* TX completed - notify upper layers and clean up. */
106 	memset(&l2cap_ctx->tx, 0, sizeof(l2cap_ctx->tx));
107 
108 	LOG_DBG("Scheduled TX on L2CAP CoC is complete");
109 
110 	if (l2cap_ctx->tx_done) {
111 		l2cap_ctx->tx_done(l2cap_ctx, chan->conn);
112 	}
113 }
114 
l2cap_recv(struct bt_l2cap_chan * chan,struct net_buf * buf)115 static int l2cap_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
116 {
117 	struct bt_l2cap_le_chan *l2chan = CONTAINER_OF(chan, struct bt_l2cap_le_chan, chan);
118 	struct bt_gatt_ots_l2cap *l2cap_ctx;
119 
120 	LOG_DBG("Incoming data channel %p received", chan);
121 
122 	l2cap_ctx = CONTAINER_OF(l2chan, struct bt_gatt_ots_l2cap, ot_chan);
123 
124 	if (!l2cap_ctx->rx_done) {
125 		return -ENODEV;
126 	}
127 
128 	return l2cap_ctx->rx_done(l2cap_ctx, chan->conn, buf);
129 }
130 
l2cap_status(struct bt_l2cap_chan * chan,atomic_t * status)131 static void l2cap_status(struct bt_l2cap_chan *chan, atomic_t *status)
132 {
133 	LOG_DBG("Channel %p status %lu", chan, atomic_get(status));
134 }
135 
l2cap_connected(struct bt_l2cap_chan * chan)136 static void l2cap_connected(struct bt_l2cap_chan *chan)
137 {
138 	LOG_DBG("Channel %p connected", chan);
139 }
140 
l2cap_disconnected(struct bt_l2cap_chan * chan)141 static void l2cap_disconnected(struct bt_l2cap_chan *chan)
142 {
143 	struct bt_l2cap_le_chan *l2chan = CONTAINER_OF(chan, struct bt_l2cap_le_chan, chan);
144 	struct bt_gatt_ots_l2cap *l2cap_ctx;
145 
146 	LOG_DBG("Channel %p disconnected", chan);
147 
148 	l2cap_ctx = CONTAINER_OF(l2chan, struct bt_gatt_ots_l2cap, ot_chan);
149 
150 	if (l2cap_ctx->closed) {
151 		l2cap_ctx->closed(l2cap_ctx, chan->conn);
152 	}
153 }
154 
155 static const struct bt_l2cap_chan_ops l2cap_ops = {
156 #if (CONFIG_BT_OTS_L2CAP_CHAN_RX_MTU > BT_L2CAP_SDU_RX_MTU)
157 	.alloc_buf	= l2cap_alloc_buf,
158 #endif
159 	.sent		= l2cap_sent,
160 	.recv		= l2cap_recv,
161 	.status		= l2cap_status,
162 	.connected	= l2cap_connected,
163 	.disconnected	= l2cap_disconnected,
164 };
165 
l2cap_chan_init(struct bt_l2cap_le_chan * chan)166 static inline void l2cap_chan_init(struct bt_l2cap_le_chan *chan)
167 {
168 	chan->rx.mtu = CONFIG_BT_OTS_L2CAP_CHAN_RX_MTU;
169 	chan->chan.ops = &l2cap_ops;
170 
171 	LOG_DBG("RX MTU set to %u", chan->rx.mtu);
172 }
173 
find_free_l2cap_ctx(void)174 static struct bt_gatt_ots_l2cap *find_free_l2cap_ctx(void)
175 {
176 	struct bt_gatt_ots_l2cap *l2cap_ctx;
177 
178 	SYS_SLIST_FOR_EACH_CONTAINER(&channels, l2cap_ctx, node) {
179 		if (l2cap_ctx->ot_chan.chan.conn) {
180 			continue;
181 		}
182 
183 		return l2cap_ctx;
184 	}
185 
186 	return NULL;
187 }
188 
l2cap_accept(struct bt_conn * conn,struct bt_l2cap_server * server,struct bt_l2cap_chan ** chan)189 static int l2cap_accept(struct bt_conn *conn, struct bt_l2cap_server *server,
190 			struct bt_l2cap_chan **chan)
191 {
192 	struct bt_gatt_ots_l2cap *l2cap_ctx;
193 
194 	LOG_DBG("Incoming conn %p", (void *)conn);
195 
196 	l2cap_ctx = find_free_l2cap_ctx();
197 	if (l2cap_ctx) {
198 		l2cap_chan_init(&l2cap_ctx->ot_chan);
199 		memset(&l2cap_ctx->tx, 0, sizeof(l2cap_ctx->tx));
200 
201 		*chan = &l2cap_ctx->ot_chan.chan;
202 
203 		return 0;
204 	}
205 
206 	return -ENOMEM;
207 }
208 
209 static struct bt_l2cap_server l2cap_server = {
210 	.psm = BT_GATT_OTS_L2CAP_PSM,
211 	.accept	= l2cap_accept,
212 };
213 
bt_gatt_ots_l2cap_init(void)214 static int bt_gatt_ots_l2cap_init(void)
215 {
216 	int err;
217 
218 	sys_slist_init(&channels);
219 
220 	err = bt_l2cap_server_register(&l2cap_server);
221 	if (err) {
222 		LOG_ERR("Unable to register OTS PSM");
223 		return err;
224 	}
225 
226 	LOG_DBG("Initialized OTS L2CAP");
227 
228 	return 0;
229 }
230 
bt_gatt_ots_l2cap_is_open(struct bt_gatt_ots_l2cap * l2cap_ctx,struct bt_conn * conn)231 bool bt_gatt_ots_l2cap_is_open(struct bt_gatt_ots_l2cap *l2cap_ctx,
232 				   struct bt_conn *conn)
233 {
234 	return (l2cap_ctx->ot_chan.chan.conn == conn);
235 }
236 
bt_gatt_ots_l2cap_send(struct bt_gatt_ots_l2cap * l2cap_ctx,uint8_t * data,uint32_t len)237 int bt_gatt_ots_l2cap_send(struct bt_gatt_ots_l2cap *l2cap_ctx,
238 			       uint8_t *data, uint32_t len)
239 {
240 	int err;
241 
242 	if (l2cap_ctx->tx.len != 0) {
243 		LOG_ERR("L2CAP TX in progress");
244 
245 		return -EAGAIN;
246 	}
247 
248 	l2cap_ctx->tx.data = data;
249 	l2cap_ctx->tx.len = len;
250 
251 	LOG_DBG("Starting TX on L2CAP CoC with %d byte packet", len);
252 
253 	err = ots_l2cap_send(l2cap_ctx);
254 	if (err) {
255 		LOG_ERR("Unable to send data over CoC: %d", err);
256 
257 		return err;
258 	}
259 
260 	return 0;
261 }
262 
bt_gatt_ots_l2cap_register(struct bt_gatt_ots_l2cap * l2cap_ctx)263 int bt_gatt_ots_l2cap_register(struct bt_gatt_ots_l2cap *l2cap_ctx)
264 {
265 	sys_slist_append(&channels, &l2cap_ctx->node);
266 
267 	return 0;
268 }
269 
bt_gatt_ots_l2cap_unregister(struct bt_gatt_ots_l2cap * l2cap_ctx)270 int bt_gatt_ots_l2cap_unregister(struct bt_gatt_ots_l2cap *l2cap_ctx)
271 {
272 	sys_slist_find_and_remove(&channels, &l2cap_ctx->node);
273 
274 	return 0;
275 }
276 
277 /* Similar to l2cap_accept(), but for the client side */
bt_gatt_ots_l2cap_connect(struct bt_conn * conn,struct bt_gatt_ots_l2cap ** l2cap_ctx)278 int bt_gatt_ots_l2cap_connect(struct bt_conn *conn,
279 			      struct bt_gatt_ots_l2cap **l2cap_ctx)
280 {
281 	int err;
282 	struct bt_gatt_ots_l2cap *ctx;
283 
284 	if (!conn) {
285 		LOG_WRN("Invalid Connection");
286 		return -ENOTCONN;
287 	}
288 
289 	if (!l2cap_ctx) {
290 		LOG_WRN("Invalid context");
291 		return -EINVAL;
292 	}
293 
294 	*l2cap_ctx = NULL;
295 
296 	ctx = find_free_l2cap_ctx();
297 	if (!ctx) {
298 		return -ENOMEM;
299 	}
300 
301 	l2cap_chan_init(&ctx->ot_chan);
302 	(void)memset(&ctx->tx, 0, sizeof(ctx->tx));
303 
304 	LOG_DBG("Connecting L2CAP CoC");
305 	err = bt_l2cap_chan_connect(conn, &ctx->ot_chan.chan, BT_GATT_OTS_L2CAP_PSM);
306 	if (err) {
307 		LOG_WRN("Unable to connect to psm %u (err %d)", BT_GATT_OTS_L2CAP_PSM, err);
308 	} else {
309 		LOG_DBG("L2CAP connection pending");
310 		*l2cap_ctx = ctx;
311 	}
312 
313 	return err;
314 }
315 
bt_gatt_ots_l2cap_disconnect(struct bt_gatt_ots_l2cap * l2cap_ctx)316 int bt_gatt_ots_l2cap_disconnect(struct bt_gatt_ots_l2cap *l2cap_ctx)
317 {
318 	return bt_l2cap_chan_disconnect(&l2cap_ctx->ot_chan.chan);
319 }
320 
321 SYS_INIT(bt_gatt_ots_l2cap_init, APPLICATION,
322 	 CONFIG_APPLICATION_INIT_PRIORITY);
323