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