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