1 /* btp_csis.c - Bluetooth CSIS Tester */
2
3 /*
4 * Copyright (c) 2023 Oticon
5 *
6 * SPDX-License-Identifier: Apache-2.0
7 */
8 #include <zephyr/bluetooth/audio/csip.h>
9
10 #include "btp/btp.h"
11 #include <zephyr/sys/byteorder.h>
12
13 #include <zephyr/logging/log.h>
14 #define LOG_MODULE_NAME bttester_csis
15 LOG_MODULE_REGISTER(LOG_MODULE_NAME, CONFIG_BTTESTER_LOG_LEVEL);
16
17 #define BTP_STATUS_VAL(err) (err) ? BTP_STATUS_FAILED : BTP_STATUS_SUCCESS
18
19 static struct bt_csip_set_member_svc_inst *csis_svc_inst;
20 static bool enc_sirk;
21
csis_supported_commands(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)22 static uint8_t csis_supported_commands(const void *cmd, uint16_t cmd_len,
23 void *rsp, uint16_t *rsp_len)
24 {
25 struct btp_csis_read_supported_commands_rp *rp = rsp;
26
27 /* octet 0 */
28 tester_set_bit(rp->data, BTP_CSIS_READ_SUPPORTED_COMMANDS);
29 tester_set_bit(rp->data, BTP_CSIS_SET_MEMBER_LOCK);
30 tester_set_bit(rp->data, BTP_CSIS_GET_MEMBER_RSI);
31 tester_set_bit(rp->data, BTP_CSIS_ENC_SIRK_TYPE);
32
33 *rsp_len = sizeof(*rp) + 1;
34
35 return BTP_STATUS_SUCCESS;
36 }
37
csis_set_member_lock(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)38 static uint8_t csis_set_member_lock(const void *cmd, uint16_t cmd_len,
39 void *rsp, uint16_t *rsp_len)
40 {
41 const struct btp_csis_set_member_lock_cmd *cp = cmd;
42 int err = -1;
43
44 if (csis_svc_inst) {
45 err = bt_csip_set_member_lock(csis_svc_inst, cp->lock, cp->force);
46 }
47
48 return BTP_STATUS_VAL(err);
49 }
50
csis_get_member_rsi(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)51 static uint8_t csis_get_member_rsi(const void *cmd, uint16_t cmd_len,
52 void *rsp, uint16_t *rsp_len)
53 {
54 struct btp_csis_get_member_rsi_rp *rp = rsp;
55 int err = -1;
56
57 if (csis_svc_inst) {
58 err = bt_csip_set_member_generate_rsi(csis_svc_inst, rp->rsi);
59 }
60
61 *rsp_len = sizeof(*rp);
62
63 return BTP_STATUS_VAL(err);
64 }
65
csis_sirk_type(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)66 static uint8_t csis_sirk_type(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len)
67 {
68 const struct btp_csis_sirk_type_cmd *cp = cmd;
69
70 enc_sirk = cp->encrypted != 0U;
71
72 LOG_DBG("SIRK type: %s", enc_sirk ? "encrypted" : "plain text");
73
74 return BTP_STATUS_SUCCESS;
75 }
76
77 static const struct btp_handler csis_handlers[] = {
78 {
79 .opcode = BTP_CSIS_READ_SUPPORTED_COMMANDS,
80 .index = BTP_INDEX_NONE,
81 .expect_len = 0,
82 .func = csis_supported_commands,
83 },
84 {
85 .opcode = BTP_CSIS_SET_MEMBER_LOCK,
86 .expect_len = sizeof(struct btp_csis_set_member_lock_cmd),
87 .func = csis_set_member_lock,
88 },
89 {
90 .opcode = BTP_CSIS_GET_MEMBER_RSI,
91 .expect_len = sizeof(struct btp_csis_get_member_rsi_cmd),
92 .func = csis_get_member_rsi,
93 },
94 {
95 .opcode = BTP_CSIS_ENC_SIRK_TYPE,
96 .expect_len = sizeof(struct btp_csis_sirk_type_cmd),
97 .func = csis_sirk_type,
98 },
99 };
100
lock_changed_cb(struct bt_conn * conn,struct bt_csip_set_member_svc_inst * svc_inst,bool locked)101 static void lock_changed_cb(struct bt_conn *conn, struct bt_csip_set_member_svc_inst *svc_inst,
102 bool locked)
103 {
104 LOG_DBG("%s", locked ? "locked" : "unlocked");
105 }
106
sirk_read_cb(struct bt_conn * conn,struct bt_csip_set_member_svc_inst * svc_inst)107 static uint8_t sirk_read_cb(struct bt_conn *conn, struct bt_csip_set_member_svc_inst *svc_inst)
108 {
109 if (enc_sirk) {
110 return BT_CSIP_READ_SIRK_REQ_RSP_ACCEPT_ENC;
111 } else {
112 return BT_CSIP_READ_SIRK_REQ_RSP_ACCEPT;
113 }
114 }
115
116 static struct bt_csip_set_member_cb csis_cb = {
117 .lock_changed = lock_changed_cb,
118 .sirk_read_req = sirk_read_cb,
119 };
120
tester_init_csis(void)121 uint8_t tester_init_csis(void)
122 {
123 const struct bt_csip_set_member_register_param register_params = {
124 .set_size = 1,
125 .sirk = { 0xB8, 0x03, 0xEA, 0xC6, 0xAF, 0xBB, 0x65, 0xA2,
126 0x5A, 0x41, 0xF1, 0x53, 0x05, 0x68, 0x8E, 0x83 },
127 .lockable = true,
128 .rank = 1,
129 .cb = &csis_cb,
130 };
131 int err = bt_csip_set_member_register(®ister_params, &csis_svc_inst);
132
133 tester_register_command_handlers(BTP_SERVICE_ID_CSIS, csis_handlers,
134 ARRAY_SIZE(csis_handlers));
135
136 return BTP_STATUS_VAL(err);
137 }
138
tester_unregister_csis(void)139 uint8_t tester_unregister_csis(void)
140 {
141 return BTP_STATUS_SUCCESS;
142 }
143