1 /* l2cap.c - Bluetooth L2CAP Tester */
2 
3 /*
4  * Copyright (c) 2016 Intel Corporation
5  *
6  * SPDX-License-Identifier: Apache-2.0
7  */
8 
9 #include <zephyr/bluetooth/bluetooth.h>
10 
11 #include <errno.h>
12 #include <zephyr/bluetooth/l2cap.h>
13 #include <zephyr/bluetooth/att.h>
14 #include <zephyr/sys/byteorder.h>
15 
16 #include <zephyr/logging/log.h>
17 #define LOG_MODULE_NAME bttester_l2cap
18 LOG_MODULE_REGISTER(LOG_MODULE_NAME, CONFIG_BTTESTER_LOG_LEVEL);
19 
20 #include "btp/btp.h"
21 
22 #define L2CAP_MPS        96
23 #define DATA_MTU         (3 * L2CAP_MPS)
24 #define DATA_MTU_INITIAL (2 * L2CAP_MPS)
25 
26 #define CHANNELS 2
27 #define SERVERS 1
28 
29 NET_BUF_POOL_FIXED_DEFINE(data_pool, CHANNELS, BT_L2CAP_SDU_BUF_SIZE(DATA_MTU),
30 			  CONFIG_BT_CONN_TX_USER_DATA_SIZE, NULL);
31 
32 static bool authorize_flag;
33 static uint8_t req_keysize;
34 
35 static struct channel {
36 	uint8_t chan_id; /* Internal number that identifies L2CAP channel. */
37 	struct bt_l2cap_le_chan le;
38 	bool in_use;
39 	bool hold_credit;
40 #if defined(CONFIG_BT_L2CAP_SEG_RECV)
41 	unsigned int pending_credits;
42 	uint8_t recv_cb_buf[DATA_MTU + sizeof(struct btp_l2cap_data_received_ev)];
43 #else
44 	struct net_buf *pending_credit;
45 #endif
46 } channels[CHANNELS];
47 
48 /* TODO Extend to support multiple servers */
49 static struct bt_l2cap_server servers[SERVERS];
50 
51 #if defined(CONFIG_BT_L2CAP_SEG_RECV)
seg_recv_cb(struct bt_l2cap_chan * l2cap_chan,size_t sdu_len,off_t seg_offset,struct net_buf_simple * seg)52 static void seg_recv_cb(struct bt_l2cap_chan *l2cap_chan, size_t sdu_len, off_t seg_offset,
53 			struct net_buf_simple *seg)
54 {
55 	struct btp_l2cap_data_received_ev *ev;
56 	struct bt_l2cap_le_chan *l2cap_le_chan =
57 		CONTAINER_OF(l2cap_chan, struct bt_l2cap_le_chan, chan);
58 	struct channel *chan = CONTAINER_OF(l2cap_le_chan, struct channel, le);
59 
60 	ev = (void *)chan->recv_cb_buf;
61 	memcpy(&ev->data[seg_offset], seg->data, seg->len);
62 
63 	/* complete SDU received */
64 	if (seg_offset + seg->len == sdu_len) {
65 		ev->chan_id = chan->chan_id;
66 		ev->data_length = sys_cpu_to_le16(sdu_len);
67 
68 		tester_event(BTP_SERVICE_ID_L2CAP, BTP_L2CAP_EV_DATA_RECEIVED, chan->recv_cb_buf,
69 			     sizeof(*ev) + sdu_len);
70 	}
71 
72 	if (chan->hold_credit) {
73 		chan->pending_credits++;
74 	} else {
75 		bt_l2cap_chan_give_credits(l2cap_chan, 1);
76 	}
77 }
78 #else
alloc_buf_cb(struct bt_l2cap_chan * chan)79 static struct net_buf *alloc_buf_cb(struct bt_l2cap_chan *chan)
80 {
81 	return net_buf_alloc(&data_pool, K_FOREVER);
82 }
83 
84 static uint8_t recv_cb_buf[DATA_MTU + sizeof(struct btp_l2cap_data_received_ev)];
85 
recv_cb(struct bt_l2cap_chan * l2cap_chan,struct net_buf * buf)86 static int recv_cb(struct bt_l2cap_chan *l2cap_chan, struct net_buf *buf)
87 {
88 	struct btp_l2cap_data_received_ev *ev = (void *) recv_cb_buf;
89 	struct bt_l2cap_le_chan *l2cap_le_chan = CONTAINER_OF(
90 			l2cap_chan, struct bt_l2cap_le_chan, chan);
91 	struct channel *chan = CONTAINER_OF(l2cap_le_chan, struct channel, le);
92 
93 	ev->chan_id = chan->chan_id;
94 	ev->data_length = sys_cpu_to_le16(buf->len);
95 	memcpy(ev->data, buf->data, buf->len);
96 
97 	tester_event(BTP_SERVICE_ID_L2CAP, BTP_L2CAP_EV_DATA_RECEIVED,
98 		     recv_cb_buf, sizeof(*ev) + buf->len);
99 
100 	if (chan->hold_credit && !chan->pending_credit) {
101 		/* no need for extra ref, as when returning EINPROGRESS user
102 		 * becomes owner of the netbuf
103 		 */
104 		chan->pending_credit = buf;
105 		return -EINPROGRESS;
106 	}
107 
108 	return 0;
109 }
110 #endif
111 
connected_cb(struct bt_l2cap_chan * l2cap_chan)112 static void connected_cb(struct bt_l2cap_chan *l2cap_chan)
113 {
114 	struct btp_l2cap_connected_ev ev;
115 	struct bt_l2cap_le_chan *l2cap_le_chan = CONTAINER_OF(
116 			l2cap_chan, struct bt_l2cap_le_chan, chan);
117 	struct channel *chan = CONTAINER_OF(l2cap_le_chan, struct channel, le);
118 	struct bt_conn_info info;
119 
120 	ev.chan_id = chan->chan_id;
121 	/* TODO: ev.psm */
122 	if (!bt_conn_get_info(l2cap_chan->conn, &info)) {
123 		switch (info.type) {
124 		case BT_CONN_TYPE_LE:
125 			ev.mtu_remote = sys_cpu_to_le16(chan->le.tx.mtu);
126 			ev.mps_remote = sys_cpu_to_le16(chan->le.tx.mps);
127 			ev.mtu_local = sys_cpu_to_le16(chan->le.rx.mtu);
128 			ev.mps_local = sys_cpu_to_le16(chan->le.rx.mps);
129 			bt_addr_le_copy(&ev.address, info.le.dst);
130 			break;
131 		case BT_CONN_TYPE_BR:
132 		default:
133 			/* TODO figure out how (if) want to handle BR/EDR */
134 			return;
135 		}
136 	}
137 
138 	tester_event(BTP_SERVICE_ID_L2CAP, BTP_L2CAP_EV_CONNECTED, &ev, sizeof(ev));
139 }
140 
disconnected_cb(struct bt_l2cap_chan * l2cap_chan)141 static void disconnected_cb(struct bt_l2cap_chan *l2cap_chan)
142 {
143 	struct btp_l2cap_disconnected_ev ev;
144 	struct bt_l2cap_le_chan *l2cap_le_chan = CONTAINER_OF(
145 			l2cap_chan, struct bt_l2cap_le_chan, chan);
146 	struct channel *chan = CONTAINER_OF(l2cap_le_chan, struct channel, le);
147 	struct bt_conn_info info;
148 
149 #if !defined(CONFIG_BT_L2CAP_SEG_RECV)
150 	/* release netbuf on premature disconnection */
151 	if (chan->pending_credit) {
152 		net_buf_unref(chan->pending_credit);
153 		chan->pending_credit = NULL;
154 	}
155 #endif
156 
157 	(void)memset(&ev, 0, sizeof(struct btp_l2cap_disconnected_ev));
158 
159 	/* TODO: ev.result */
160 	ev.chan_id = chan->chan_id;
161 	/* TODO: ev.psm */
162 	if (!bt_conn_get_info(l2cap_chan->conn, &info)) {
163 		switch (info.type) {
164 		case BT_CONN_TYPE_LE:
165 			bt_addr_le_copy(&ev.address, info.le.dst);
166 			break;
167 		case BT_CONN_TYPE_BR:
168 		default:
169 			/* TODO figure out how (if) want to handle BR/EDR */
170 			return;
171 		}
172 	}
173 
174 	chan->in_use = false;
175 
176 	tester_event(BTP_SERVICE_ID_L2CAP, BTP_L2CAP_EV_DISCONNECTED, &ev, sizeof(ev));
177 }
178 
179 #if defined(CONFIG_BT_L2CAP_ECRED)
reconfigured_cb(struct bt_l2cap_chan * l2cap_chan)180 static void reconfigured_cb(struct bt_l2cap_chan *l2cap_chan)
181 {
182 	struct btp_l2cap_reconfigured_ev ev;
183 	struct bt_l2cap_le_chan *l2cap_le_chan = CONTAINER_OF(
184 			l2cap_chan, struct bt_l2cap_le_chan, chan);
185 	struct channel *chan = CONTAINER_OF(l2cap_le_chan, struct channel, le);
186 
187 	(void)memset(&ev, 0, sizeof(ev));
188 
189 	ev.chan_id = chan->chan_id;
190 	ev.mtu_remote = sys_cpu_to_le16(chan->le.tx.mtu);
191 	ev.mps_remote = sys_cpu_to_le16(chan->le.tx.mps);
192 	ev.mtu_local = sys_cpu_to_le16(chan->le.rx.mtu);
193 	ev.mps_local = sys_cpu_to_le16(chan->le.rx.mps);
194 
195 	tester_event(BTP_SERVICE_ID_L2CAP, BTP_L2CAP_EV_RECONFIGURED, &ev, sizeof(ev));
196 }
197 #endif
198 
199 static const struct bt_l2cap_chan_ops l2cap_ops = {
200 #if defined(CONFIG_BT_L2CAP_SEG_RECV)
201 	.seg_recv = seg_recv_cb,
202 #else
203 	.alloc_buf = alloc_buf_cb,
204 	.recv = recv_cb,
205 #endif
206 	.connected = connected_cb,
207 	.disconnected = disconnected_cb,
208 #if defined(CONFIG_BT_L2CAP_ECRED)
209 	.reconfigured = reconfigured_cb,
210 #endif
211 };
212 
get_free_channel()213 static struct channel *get_free_channel()
214 {
215 	uint8_t i;
216 	struct channel *chan;
217 
218 	for (i = 0U; i < CHANNELS; i++) {
219 		if (channels[i].in_use) {
220 			continue;
221 		}
222 
223 		chan = &channels[i];
224 
225 		(void)memset(chan, 0, sizeof(*chan));
226 		chan->chan_id = i;
227 
228 		channels[i].in_use = true;
229 
230 		return chan;
231 	}
232 
233 	return NULL;
234 }
235 
connect(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)236 static uint8_t connect(const void *cmd, uint16_t cmd_len,
237 		       void *rsp, uint16_t *rsp_len)
238 {
239 	const struct btp_l2cap_connect_cmd *cp = cmd;
240 	struct btp_l2cap_connect_rp *rp = rsp;
241 	struct bt_conn *conn;
242 	struct channel *chan = NULL;
243 	struct bt_l2cap_chan *allocated_channels[5] = {};
244 	uint16_t mtu = sys_le16_to_cpu(cp->mtu);
245 	uint16_t psm = sys_le16_to_cpu(cp->psm);
246 	uint8_t i = 0;
247 	bool ecfc = cp->options & BTP_L2CAP_CONNECT_OPT_ECFC;
248 	int err;
249 
250 	if (cp->num == 0 || cp->num > CHANNELS || mtu > DATA_MTU_INITIAL) {
251 		return BTP_STATUS_FAILED;
252 	}
253 
254 	conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address);
255 	if (!conn) {
256 		return BTP_STATUS_FAILED;
257 	}
258 
259 	for (i = 0U; i < cp->num; i++) {
260 		chan = get_free_channel();
261 		if (!chan) {
262 			goto fail;
263 		}
264 		chan->le.chan.ops = &l2cap_ops;
265 		chan->le.rx.mtu = mtu;
266 #if defined(CONFIG_BT_L2CAP_SEG_RECV)
267 		chan->le.rx.mps = L2CAP_MPS;
268 #endif
269 		rp->chan_id[i] = chan->chan_id;
270 		allocated_channels[i] = &chan->le.chan;
271 
272 		chan->hold_credit = cp->options & BTP_L2CAP_CONNECT_OPT_HOLD_CREDIT;
273 
274 		bt_l2cap_chan_give_credits(&chan->le.chan, 1);
275 	}
276 
277 	if (cp->num == 1 && !ecfc) {
278 		err = bt_l2cap_chan_connect(conn, &chan->le.chan, psm);
279 		if (err < 0) {
280 			goto fail;
281 		}
282 	} else if (ecfc) {
283 #if defined(CONFIG_BT_L2CAP_ECRED)
284 		err = bt_l2cap_ecred_chan_connect(conn, allocated_channels,
285 							psm);
286 		if (err < 0) {
287 			goto fail;
288 		}
289 #else
290 		goto fail;
291 #endif
292 	} else {
293 		LOG_ERR("Invalid 'num' parameter value");
294 		goto fail;
295 	}
296 
297 	rp->num = cp->num;
298 	*rsp_len = sizeof(*rp) + (rp->num * sizeof(rp->chan_id[0]));
299 
300 	return BTP_STATUS_SUCCESS;
301 
302 fail:
303 	for (i = 0U; i < ARRAY_SIZE(allocated_channels); i++) {
304 		if (allocated_channels[i]) {
305 			channels[BT_L2CAP_LE_CHAN(allocated_channels[i])->ident].in_use = false;
306 		}
307 	}
308 	return BTP_STATUS_FAILED;
309 }
310 
disconnect(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)311 static uint8_t disconnect(const void *cmd, uint16_t cmd_len,
312 			  void *rsp, uint16_t *rsp_len)
313 {
314 	const struct btp_l2cap_disconnect_cmd *cp = cmd;
315 	struct channel *chan;
316 	int err;
317 
318 	if (cp->chan_id >= CHANNELS) {
319 		return BTP_STATUS_FAILED;
320 	}
321 
322 	chan = &channels[cp->chan_id];
323 
324 	err = bt_l2cap_chan_disconnect(&chan->le.chan);
325 	if (err) {
326 		return BTP_STATUS_FAILED;
327 	}
328 
329 	return BTP_STATUS_SUCCESS;
330 }
331 
332 #if defined(CONFIG_BT_L2CAP_ECRED)
reconfigure(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)333 static uint8_t reconfigure(const void *cmd, uint16_t cmd_len,
334 			   void *rsp, uint16_t *rsp_len)
335 {
336 	const struct btp_l2cap_reconfigure_cmd *cp = cmd;
337 	uint16_t mtu;
338 	uint16_t mps;
339 	struct bt_conn *conn;
340 	int err;
341 	struct bt_l2cap_chan *reconf_channels[CHANNELS + 1] = {};
342 
343 	if (cmd_len < sizeof(*cp) ||
344 	    cmd_len != sizeof(*cp) + cp->num) {
345 		return BTP_STATUS_FAILED;
346 	}
347 
348 	if (cp->num > CHANNELS) {
349 		return BTP_STATUS_FAILED;
350 	}
351 
352 	mtu = sys_le16_to_cpu(cp->mtu);
353 	if (mtu > DATA_MTU) {
354 		return BTP_STATUS_FAILED;
355 	}
356 
357 	for (int i = 0; i < cp->num; i++) {
358 		if (cp->chan_id[i] > CHANNELS) {
359 			return BTP_STATUS_FAILED;
360 		}
361 
362 		reconf_channels[i] = &channels[cp->chan_id[i]].le.chan;
363 	}
364 
365 	conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address);
366 	if (!conn) {
367 		LOG_ERR("Unknown connection");
368 		return BTP_STATUS_FAILED;
369 	}
370 
371 	mps = MIN(L2CAP_MPS, BT_L2CAP_RX_MTU);
372 	err = bt_l2cap_ecred_chan_reconfigure_explicit(reconf_channels, cp->num, mtu, mps);
373 	if (err) {
374 		bt_conn_unref(conn);
375 		return BTP_STATUS_FAILED;
376 	}
377 
378 	bt_conn_unref(conn);
379 	return BTP_STATUS_SUCCESS;
380 }
381 #endif
382 
383 #if defined(CONFIG_BT_EATT)
disconnect_eatt_chans(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)384 static uint8_t disconnect_eatt_chans(const void *cmd, uint16_t cmd_len,
385 				     void *rsp, uint16_t *rsp_len)
386 {
387 	const struct btp_l2cap_disconnect_eatt_chans_cmd *cp = cmd;
388 	struct bt_conn *conn;
389 	int err;
390 
391 	conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address);
392 	if (!conn) {
393 		LOG_ERR("Unknown connection");
394 		return BTP_STATUS_FAILED;
395 	}
396 
397 	for (int i = 0; i < cp->count; i++) {
398 		err = bt_eatt_disconnect_one(conn);
399 		if (err) {
400 			bt_conn_unref(conn);
401 			return BTP_STATUS_FAILED;
402 		}
403 	}
404 
405 	bt_conn_unref(conn);
406 	return BTP_STATUS_SUCCESS;
407 }
408 #endif
409 
410 
send_data(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)411 static uint8_t send_data(const void *cmd, uint16_t cmd_len,
412 			 void *rsp, uint16_t *rsp_len)
413 {
414 	const struct btp_l2cap_send_data_cmd *cp = cmd;
415 	struct channel *chan;
416 	struct net_buf *buf;
417 	uint16_t data_len;
418 	int ret;
419 
420 	if (cmd_len < sizeof(*cp) ||
421 	    cmd_len != sizeof(*cp) + sys_le16_to_cpu(cp->data_len)) {
422 		return BTP_STATUS_FAILED;
423 	}
424 
425 	if (cp->chan_id >= CHANNELS) {
426 		return BTP_STATUS_FAILED;
427 	}
428 
429 	chan = &channels[cp->chan_id];
430 	data_len = sys_le16_to_cpu(cp->data_len);
431 
432 
433 	/* FIXME: For now, fail if data length exceeds buffer length */
434 	if (data_len > DATA_MTU) {
435 		return BTP_STATUS_FAILED;
436 	}
437 
438 	/* FIXME: For now, fail if data length exceeds remote's L2CAP SDU */
439 	if (data_len > chan->le.tx.mtu) {
440 		return BTP_STATUS_FAILED;
441 	}
442 
443 	buf = net_buf_alloc(&data_pool, K_FOREVER);
444 	net_buf_reserve(buf, BT_L2CAP_SDU_CHAN_SEND_RESERVE);
445 
446 	net_buf_add_mem(buf, cp->data, data_len);
447 	ret = bt_l2cap_chan_send(&chan->le.chan, buf);
448 	if (ret < 0) {
449 		LOG_ERR("Unable to send data: %d", -ret);
450 		net_buf_unref(buf);
451 		return BTP_STATUS_FAILED;
452 	}
453 
454 	return BTP_STATUS_SUCCESS;
455 }
456 
get_free_server(void)457 static struct bt_l2cap_server *get_free_server(void)
458 {
459 	uint8_t i;
460 
461 	for (i = 0U; i < SERVERS ; i++) {
462 		if (servers[i].psm) {
463 			continue;
464 		}
465 
466 		return &servers[i];
467 	}
468 
469 	return NULL;
470 }
471 
is_free_psm(uint16_t psm)472 static bool is_free_psm(uint16_t psm)
473 {
474 	uint8_t i;
475 
476 	for (i = 0U; i < ARRAY_SIZE(servers); i++) {
477 		if (servers[i].psm == psm) {
478 			return false;
479 		}
480 	}
481 
482 	return true;
483 }
484 
accept(struct bt_conn * conn,struct bt_l2cap_server * server,struct bt_l2cap_chan ** l2cap_chan)485 static int accept(struct bt_conn *conn, struct bt_l2cap_server *server,
486 		  struct bt_l2cap_chan **l2cap_chan)
487 {
488 	struct channel *chan;
489 
490 	if (bt_conn_enc_key_size(conn) < req_keysize) {
491 		return -EPERM;
492 	}
493 
494 	if (authorize_flag) {
495 		return -EACCES;
496 	}
497 
498 	chan = get_free_channel();
499 	if (!chan) {
500 		return -ENOMEM;
501 	}
502 
503 	chan->le.chan.ops = &l2cap_ops;
504 	chan->le.rx.mtu = DATA_MTU_INITIAL;
505 #if defined(CONFIG_BT_L2CAP_SEG_RECV)
506 	chan->le.rx.mps = L2CAP_MPS;
507 #endif
508 
509 	*l2cap_chan = &chan->le.chan;
510 
511 	bt_l2cap_chan_give_credits(&chan->le.chan, 1);
512 
513 	return 0;
514 }
515 
listen(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)516 static uint8_t listen(const void *cmd, uint16_t cmd_len,
517 		      void *rsp, uint16_t *rsp_len)
518 {
519 	const struct btp_l2cap_listen_cmd *cp = cmd;
520 	struct bt_l2cap_server *server;
521 	uint16_t psm = sys_le16_to_cpu(cp->psm);
522 
523 	/* TODO: Handle cmd->transport flag */
524 
525 	if (psm == 0 || !is_free_psm(psm)) {
526 		return BTP_STATUS_FAILED;
527 	}
528 
529 	server = get_free_server();
530 	if (!server) {
531 		return BTP_STATUS_FAILED;
532 	}
533 
534 	server->accept = accept;
535 	server->psm = psm;
536 
537 	switch (cp->response) {
538 	case BTP_L2CAP_CONNECTION_RESPONSE_SUCCESS:
539 		break;
540 	case BTP_L2CAP_CONNECTION_RESPONSE_INSUFF_ENC_KEY:
541 		/* TSPX_psm_encryption_key_size_required */
542 		req_keysize = 16;
543 		break;
544 	case BTP_L2CAP_CONNECTION_RESPONSE_INSUFF_AUTHOR:
545 		authorize_flag = true;
546 		break;
547 	case BTP_L2CAP_CONNECTION_RESPONSE_INSUFF_AUTHEN:
548 		server->sec_level = BT_SECURITY_L3;
549 		break;
550 	case BTP_L2CAP_CONNECTION_RESPONSE_INSUFF_ENCRYPTION:
551 		server->sec_level = BT_SECURITY_L2;
552 		break;
553 	default:
554 		return BTP_STATUS_FAILED;
555 	}
556 
557 	if (bt_l2cap_server_register(server) < 0) {
558 		server->psm = 0U;
559 		return BTP_STATUS_FAILED;
560 	}
561 
562 	return BTP_STATUS_SUCCESS;
563 }
564 
credits(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)565 static uint8_t credits(const void *cmd, uint16_t cmd_len,
566 		      void *rsp, uint16_t *rsp_len)
567 {
568 	const struct btp_l2cap_credits_cmd *cp = cmd;
569 	struct channel *chan;
570 
571 	if (cp->chan_id >= CHANNELS) {
572 		return BTP_STATUS_FAILED;
573 	}
574 
575 	chan = &channels[cp->chan_id];
576 
577 	if (!chan->in_use) {
578 		return BTP_STATUS_FAILED;
579 	}
580 #if defined(CONFIG_BT_L2CAP_SEG_RECV)
581 	if (chan->pending_credits) {
582 		if (bt_l2cap_chan_give_credits(&chan->le.chan, chan->pending_credits) < 0) {
583 			return BTP_STATUS_FAILED;
584 		}
585 
586 		chan->pending_credits = 0;
587 	}
588 #else
589 	if (chan->pending_credit) {
590 		if (bt_l2cap_chan_recv_complete(&chan->le.chan,
591 						chan->pending_credit) < 0) {
592 			return BTP_STATUS_FAILED;
593 		}
594 
595 		chan->pending_credit = NULL;
596 	}
597 #endif
598 
599 	return BTP_STATUS_SUCCESS;
600 }
601 
supported_commands(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)602 static uint8_t supported_commands(const void *cmd, uint16_t cmd_len,
603 				  void *rsp, uint16_t *rsp_len)
604 {
605 	struct btp_l2cap_read_supported_commands_rp *rp = rsp;
606 
607 	/* octet 0 */
608 	tester_set_bit(rp->data, BTP_L2CAP_READ_SUPPORTED_COMMANDS);
609 	tester_set_bit(rp->data, BTP_L2CAP_CONNECT);
610 	tester_set_bit(rp->data, BTP_L2CAP_DISCONNECT);
611 	tester_set_bit(rp->data, BTP_L2CAP_SEND_DATA);
612 	tester_set_bit(rp->data, BTP_L2CAP_LISTEN);
613 #if defined(CONFIG_BT_L2CAP_ECRED)
614 	tester_set_bit(rp->data, BTP_L2CAP_RECONFIGURE);
615 #endif
616 	/* octet 1 */
617 	tester_set_bit(rp->data, BTP_L2CAP_CREDITS);
618 #if defined(CONFIG_BT_EATT)
619 	tester_set_bit(rp->data, BTP_L2CAP_DISCONNECT_EATT_CHANS);
620 #endif
621 
622 	*rsp_len = sizeof(*rp) + 2;
623 
624 	return BTP_STATUS_SUCCESS;
625 }
626 
627 static const struct btp_handler handlers[] = {
628 	{
629 		.opcode = BTP_L2CAP_READ_SUPPORTED_COMMANDS,
630 		.index = BTP_INDEX_NONE,
631 		.expect_len = 0,
632 		.func = supported_commands,
633 	},
634 	{
635 		.opcode = BTP_L2CAP_CONNECT,
636 		.expect_len = sizeof(struct btp_l2cap_connect_cmd),
637 		.func = connect,
638 	},
639 	{
640 		.opcode = BTP_L2CAP_DISCONNECT,
641 		.expect_len = sizeof(struct btp_l2cap_disconnect_cmd),
642 		.func = disconnect,
643 	},
644 	{
645 		.opcode = BTP_L2CAP_SEND_DATA,
646 		.expect_len = BTP_HANDLER_LENGTH_VARIABLE,
647 		.func = send_data,
648 	},
649 	{
650 		.opcode = BTP_L2CAP_LISTEN,
651 		.expect_len = sizeof(struct btp_l2cap_listen_cmd),
652 		.func = listen,
653 	},
654 	{
655 		.opcode = BTP_L2CAP_RECONFIGURE,
656 		.expect_len = BTP_HANDLER_LENGTH_VARIABLE,
657 		.func = reconfigure,
658 	},
659 	{
660 		.opcode = BTP_L2CAP_CREDITS,
661 		.expect_len = sizeof(struct btp_l2cap_credits_cmd),
662 		.func = credits,
663 	},
664 	{
665 		.opcode = BTP_L2CAP_DISCONNECT_EATT_CHANS,
666 		.expect_len = sizeof(struct btp_l2cap_disconnect_eatt_chans_cmd),
667 		.func = disconnect_eatt_chans,
668 	},
669 };
670 
tester_init_l2cap(void)671 uint8_t tester_init_l2cap(void)
672 {
673 	tester_register_command_handlers(BTP_SERVICE_ID_L2CAP, handlers,
674 					 ARRAY_SIZE(handlers));
675 
676 	return BTP_STATUS_SUCCESS;
677 }
678 
tester_unregister_l2cap(void)679 uint8_t tester_unregister_l2cap(void)
680 {
681 	return BTP_STATUS_SUCCESS;
682 }
683