1 /* btp_tmap.c - Bluetooth TMAP Tester */
2 
3 /*
4  * Copyright (c) 2024 Codecoup
5  *
6  * SPDX-License-Identifier: Apache-2.0
7  */
8 #include <zephyr/bluetooth/audio/tmap.h>
9 #include "btp/btp.h"
10 
11 #include <zephyr/logging/log.h>
12 LOG_MODULE_REGISTER(bttester_tmap, CONFIG_BTTESTER_LOG_LEVEL);
13 
read_supported_commands(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)14 static uint8_t read_supported_commands(const void *cmd, uint16_t cmd_len, void *rsp,
15 				       uint16_t *rsp_len)
16 {
17 	struct btp_tmap_read_supported_commands_rp *rp = rsp;
18 
19 	tester_set_bit(rp->data, BTP_TMAP_READ_SUPPORTED_COMMANDS);
20 	tester_set_bit(rp->data, BTP_TMAP_DISCOVER);
21 
22 	*rsp_len = sizeof(*rp) + 1;
23 
24 	return BTP_STATUS_SUCCESS;
25 }
26 
tmap_discover_cb(enum bt_tmap_role role,struct bt_conn * conn,int err)27 static void tmap_discover_cb(enum bt_tmap_role role, struct bt_conn *conn, int err)
28 {
29 	struct btp_tmap_discovery_complete_ev ev;
30 
31 	if (err) {
32 		LOG_ERR("Discovery failed (%d)", err);
33 	}
34 
35 	bt_addr_le_copy(&ev.address, bt_conn_get_dst(conn));
36 	ev.status = err;
37 	ev.role = role;
38 
39 	tester_event(BTP_SERVICE_ID_TMAP, BT_TMAP_EV_DISCOVERY_COMPLETE, &ev, sizeof(ev));
40 }
41 
42 static const struct bt_tmap_cb tmap_cb = {
43 	.discovery_complete = tmap_discover_cb,
44 };
45 
tmap_discover(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)46 static uint8_t tmap_discover(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len)
47 {
48 	const struct btp_tmap_discover_cmd *cp = cmd;
49 	struct bt_conn *conn;
50 	int err;
51 
52 	conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address);
53 	if (!conn) {
54 		LOG_ERR("Unknown connection");
55 		return BTP_STATUS_FAILED;
56 	}
57 
58 	err = bt_tmap_discover(conn, &tmap_cb);
59 	if (err != 0) {
60 		LOG_ERR("Failed to discover remote TMAP: %d", err);
61 	}
62 
63 	bt_conn_unref(conn);
64 
65 	return BTP_STATUS_VAL(err);
66 }
67 
68 static const struct btp_handler tmap_handlers[] = {
69 	{
70 		.opcode = BTP_TMAP_READ_SUPPORTED_COMMANDS,
71 		.index = BTP_INDEX_NONE,
72 		.expect_len = 0,
73 		.func = read_supported_commands,
74 	},
75 	{
76 		.opcode = BTP_TMAP_DISCOVER,
77 		.expect_len = sizeof(struct btp_tmap_discover_cmd),
78 		.func = tmap_discover,
79 	},
80 };
81 
tester_init_tmap(void)82 uint8_t tester_init_tmap(void)
83 {
84 	const enum bt_tmap_role role = (BT_TMAP_CG_SUPPORTED ? BT_TMAP_ROLE_CG : 0U) |
85 				       (BT_TMAP_CT_SUPPORTED ? BT_TMAP_ROLE_CT : 0U) |
86 				       (BT_TMAP_UMS_SUPPORTED ? BT_TMAP_ROLE_UMS : 0U) |
87 				       (BT_TMAP_UMR_SUPPORTED ? BT_TMAP_ROLE_UMR : 0U) |
88 				       (BT_TMAP_BMS_SUPPORTED ? BT_TMAP_ROLE_BMS : 0U) |
89 				       (BT_TMAP_BMR_SUPPORTED ? BT_TMAP_ROLE_BMR : 0U);
90 	int err;
91 
92 	err = bt_tmap_register(role);
93 
94 	if (err != 0) {
95 		LOG_ERR("Failed to register TMAP (err %d)", err);
96 		return BTP_STATUS_FAILED;
97 	}
98 
99 	tester_register_command_handlers(BTP_SERVICE_ID_TMAP, tmap_handlers,
100 					 ARRAY_SIZE(tmap_handlers));
101 
102 	return BTP_STATUS_SUCCESS;
103 }
104 
tester_unregister_tmap(void)105 uint8_t tester_unregister_tmap(void)
106 {
107 	return BTP_STATUS_SUCCESS;
108 }
109