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(&register_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