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