1 /*
2  * Copyright (c) 2020 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 <sys/printk.h>
12 #include <sys/byteorder.h>
13 #include <zephyr.h>
14 #include <init.h>
15 
16 #include <net/buf.h>
17 
18 #include "ots_l2cap_internal.h"
19 
20 #include <logging/log.h>
21 
22 LOG_MODULE_DECLARE(bt_ots, CONFIG_BT_OTS_LOG_LEVEL);
23 
24 /* According to BLE specification Assigned Numbers that are used in the
25  * Logical Link Control for protocol/service multiplexers.
26  */
27 #define BT_GATT_OTS_L2CAP_PSM	0x0025
28 
29 
30 NET_BUF_POOL_FIXED_DEFINE(ot_chan_tx_pool, 1,
31 			  BT_L2CAP_SDU_BUF_SIZE(CONFIG_BT_OTS_L2CAP_CHAN_TX_MTU),
32 			  NULL);
33 
34 #if (CONFIG_BT_OTS_L2CAP_CHAN_RX_MTU > BT_L2CAP_SDU_RX_MTU)
35 NET_BUF_POOL_FIXED_DEFINE(ot_chan_rx_pool, 1, CONFIG_BT_OTS_L2CAP_CHAN_RX_MTU,
36 			  NULL);
37 #endif
38 
39 /* List of Object Transfer Channels. */
40 static sys_slist_t channels;
41 
ots_l2cap_send(struct bt_gatt_ots_l2cap * l2cap_ctx)42 static int ots_l2cap_send(struct bt_gatt_ots_l2cap *l2cap_ctx)
43 {
44 	int ret;
45 	struct net_buf *buf;
46 	uint32_t len;
47 
48 	/* Calculate maximum length of data chunk. */
49 	len = MIN(l2cap_ctx->ot_chan.tx.mtu, CONFIG_BT_OTS_L2CAP_CHAN_TX_MTU);
50 	len = MIN(len, l2cap_ctx->tx.len - l2cap_ctx->tx.len_sent);
51 
52 	/* Prepare buffer for sending. */
53 	buf = net_buf_alloc(&ot_chan_tx_pool, K_FOREVER);
54 	net_buf_reserve(buf, BT_L2CAP_SDU_CHAN_SEND_RESERVE);
55 	net_buf_add_mem(buf, &l2cap_ctx->tx.data[l2cap_ctx->tx.len_sent], len);
56 
57 	ret = bt_l2cap_chan_send(&l2cap_ctx->ot_chan.chan, buf);
58 	if (ret < 0) {
59 		LOG_ERR("Unable to send data over CoC: %d", ret);
60 		net_buf_unref(buf);
61 
62 		return -ENOEXEC;
63 	}
64 
65 	/* Mark that L2CAP TX was accepted. */
66 	l2cap_ctx->tx.len_sent += len;
67 
68 	LOG_DBG("Sending TX chunk with %d bytes on L2CAP CoC", len);
69 
70 	return 0;
71 }
72 
73 #if (CONFIG_BT_OTS_L2CAP_CHAN_RX_MTU > BT_L2CAP_SDU_RX_MTU)
l2cap_alloc_buf(struct bt_l2cap_chan * chan)74 static struct net_buf *l2cap_alloc_buf(struct bt_l2cap_chan *chan)
75 {
76 	LOG_DBG("Channel %p allocating buffer", chan);
77 
78 	return net_buf_alloc(&ot_chan_rx_pool, K_FOREVER);
79 }
80 #endif
81 
82 
l2cap_sent(struct bt_l2cap_chan * chan)83 static void l2cap_sent(struct bt_l2cap_chan *chan)
84 {
85 	struct bt_gatt_ots_l2cap *l2cap_ctx;
86 
87 	LOG_DBG("Outgoing data channel %p transmitted", chan);
88 
89 	l2cap_ctx = CONTAINER_OF(chan, struct bt_gatt_ots_l2cap, ot_chan);
90 
91 	/* Ongoing TX - sending next chunk. */
92 	if (l2cap_ctx->tx.len != l2cap_ctx->tx.len_sent) {
93 		ots_l2cap_send(l2cap_ctx);
94 
95 		return;
96 	}
97 
98 	/* TX completed - notify upper layers and clean up. */
99 	memset(&l2cap_ctx->tx, 0, sizeof(l2cap_ctx->tx));
100 
101 	LOG_DBG("Scheduled TX on L2CAP CoC is complete");
102 
103 	if (l2cap_ctx->tx_done) {
104 		l2cap_ctx->tx_done(l2cap_ctx, chan->conn);
105 	}
106 }
107 
l2cap_recv(struct bt_l2cap_chan * chan,struct net_buf * buf)108 static int l2cap_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
109 {
110 	struct bt_gatt_ots_l2cap *l2cap_ctx;
111 
112 	LOG_DBG("Incoming data channel %p received", chan);
113 
114 	l2cap_ctx = CONTAINER_OF(chan, struct bt_gatt_ots_l2cap, ot_chan);
115 
116 	if (!l2cap_ctx->rx_done) {
117 		return -ENODEV;
118 	}
119 
120 	return l2cap_ctx->rx_done(l2cap_ctx, chan->conn, buf);
121 }
122 
l2cap_status(struct bt_l2cap_chan * chan,atomic_t * status)123 static void l2cap_status(struct bt_l2cap_chan *chan, atomic_t *status)
124 {
125 	LOG_DBG("Channel %p status %u", chan, *status);
126 }
127 
l2cap_connected(struct bt_l2cap_chan * chan)128 static void l2cap_connected(struct bt_l2cap_chan *chan)
129 {
130 	LOG_DBG("Channel %p connected", chan);
131 }
132 
l2cap_disconnected(struct bt_l2cap_chan * chan)133 static void l2cap_disconnected(struct bt_l2cap_chan *chan)
134 {
135 	struct bt_gatt_ots_l2cap *l2cap_ctx;
136 
137 	LOG_DBG("Channel %p disconnected", chan);
138 
139 	l2cap_ctx = CONTAINER_OF(chan, struct bt_gatt_ots_l2cap, ot_chan);
140 
141 	if (l2cap_ctx->closed) {
142 		l2cap_ctx->closed(l2cap_ctx, chan->conn);
143 	}
144 }
145 
146 static const struct bt_l2cap_chan_ops l2cap_ops = {
147 #if (CONFIG_BT_OTS_L2CAP_CHAN_RX_MTU > BT_L2CAP_SDU_RX_MTU)
148 	.alloc_buf	= l2cap_alloc_buf,
149 #endif
150 	.sent		= l2cap_sent,
151 	.recv		= l2cap_recv,
152 	.status		= l2cap_status,
153 	.connected	= l2cap_connected,
154 	.disconnected	= l2cap_disconnected,
155 };
156 
l2cap_chan_init(struct bt_l2cap_le_chan * chan)157 static inline void l2cap_chan_init(struct bt_l2cap_le_chan *chan)
158 {
159 	chan->rx.mtu = CONFIG_BT_OTS_L2CAP_CHAN_RX_MTU;
160 	chan->chan.ops = &l2cap_ops;
161 
162 	LOG_DBG("RX MTU set to %u", chan->rx.mtu);
163 }
164 
l2cap_accept(struct bt_conn * conn,struct bt_l2cap_chan ** chan)165 static int l2cap_accept(struct bt_conn *conn, struct bt_l2cap_chan **chan)
166 {
167 	struct bt_gatt_ots_l2cap *l2cap_ctx;
168 
169 	LOG_DBG("Incoming conn %p", (void *)conn);
170 
171 	SYS_SLIST_FOR_EACH_CONTAINER(&channels, l2cap_ctx, node) {
172 		if (l2cap_ctx->ot_chan.chan.conn) {
173 			continue;
174 		}
175 
176 		l2cap_chan_init(&l2cap_ctx->ot_chan);
177 		memset(&l2cap_ctx->tx, 0, sizeof(l2cap_ctx->tx));
178 
179 		*chan = &l2cap_ctx->ot_chan.chan;
180 
181 		return 0;
182 	}
183 
184 	return -ENOMEM;
185 }
186 
187 static struct bt_l2cap_server l2cap_server = {
188 	.psm = BT_GATT_OTS_L2CAP_PSM,
189 	.accept	= l2cap_accept,
190 };
191 
bt_gatt_ots_l2cap_init(const struct device * arg)192 static int bt_gatt_ots_l2cap_init(const struct device *arg)
193 {
194 	int err;
195 
196 	sys_slist_init(&channels);
197 
198 	err = bt_l2cap_server_register(&l2cap_server);
199 	if (err) {
200 		LOG_ERR("Unable to register OTS PSM");
201 		return err;
202 	}
203 
204 	LOG_DBG("Initialized OTS L2CAP");
205 
206 	return 0;
207 }
208 
bt_gatt_ots_l2cap_is_open(struct bt_gatt_ots_l2cap * l2cap_ctx,struct bt_conn * conn)209 bool bt_gatt_ots_l2cap_is_open(struct bt_gatt_ots_l2cap *l2cap_ctx,
210 				   struct bt_conn *conn)
211 {
212 	return (l2cap_ctx->ot_chan.chan.conn == conn);
213 }
214 
bt_gatt_ots_l2cap_send(struct bt_gatt_ots_l2cap * l2cap_ctx,uint8_t * data,uint32_t len)215 int bt_gatt_ots_l2cap_send(struct bt_gatt_ots_l2cap *l2cap_ctx,
216 			       uint8_t *data, uint32_t len)
217 {
218 	int err;
219 
220 	if (l2cap_ctx->tx.len != 0) {
221 		LOG_ERR("L2CAP TX in progress");
222 
223 		return -EAGAIN;
224 	}
225 
226 	l2cap_ctx->tx.data = data;
227 	l2cap_ctx->tx.len = len;
228 
229 	LOG_DBG("Starting TX on L2CAP CoC with %d byte packet", len);
230 
231 	err = ots_l2cap_send(l2cap_ctx);
232 	if (err) {
233 		LOG_ERR("Unable to send data over CoC: %d", err);
234 
235 		return err;
236 	}
237 
238 	return 0;
239 }
240 
bt_gatt_ots_l2cap_register(struct bt_gatt_ots_l2cap * l2cap_ctx)241 int bt_gatt_ots_l2cap_register(struct bt_gatt_ots_l2cap *l2cap_ctx)
242 {
243 	sys_slist_append(&channels, &l2cap_ctx->node);
244 
245 	return 0;
246 }
247 
bt_gatt_ots_l2cap_unregister(struct bt_gatt_ots_l2cap * l2cap_ctx)248 int bt_gatt_ots_l2cap_unregister(struct bt_gatt_ots_l2cap *l2cap_ctx)
249 {
250 	sys_slist_find_and_remove(&channels, &l2cap_ctx->node);
251 
252 	return 0;
253 }
254 
bt_gatt_ots_l2cap_disconnect(struct bt_gatt_ots_l2cap * l2cap_ctx)255 int bt_gatt_ots_l2cap_disconnect(struct bt_gatt_ots_l2cap *l2cap_ctx)
256 {
257 	return bt_l2cap_chan_disconnect(&l2cap_ctx->ot_chan.chan);
258 }
259 
260 SYS_INIT(bt_gatt_ots_l2cap_init, APPLICATION,
261 	 CONFIG_APPLICATION_INIT_PRIORITY);
262