1 /*
2 * Copyright (c) 2024 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <stdlib.h>
8 #include <zephyr/shell/shell.h>
9 #include <zephyr/bluetooth/mesh.h>
10 #include <zephyr/bluetooth/mesh/shell.h>
11
12 #include "mesh/foundation.h"
13 #include "utils.h"
14
cmd_subnet_bridge_get(const struct shell * sh,size_t argc,char * argv[])15 static int cmd_subnet_bridge_get(const struct shell *sh, size_t argc, char *argv[])
16 {
17 enum bt_mesh_brg_cfg_state rsp;
18 int err;
19
20 err = bt_mesh_brg_cfg_cli_get(bt_mesh_shell_target_ctx.net_idx,
21 bt_mesh_shell_target_ctx.dst, &rsp);
22 if (err) {
23 shell_error(sh, "Failed to send Subnet Bridge Get (err %d)", err);
24 return -ENOEXEC;
25 }
26
27 shell_print(sh, "Subnet Bridge State: %s",
28 (rsp == BT_MESH_BRG_CFG_ENABLED) ? "Enabled" : "Disabled");
29 return 0;
30 }
31
cmd_subnet_bridge_set(const struct shell * sh,size_t argc,char * argv[])32 static int cmd_subnet_bridge_set(const struct shell *sh, size_t argc, char *argv[])
33 {
34 enum bt_mesh_brg_cfg_state set, rsp;
35 int err = 0;
36
37 set = shell_strtobool(argv[1], 0, &err) ? BT_MESH_BRG_CFG_ENABLED
38 : BT_MESH_BRG_CFG_DISABLED;
39
40 if (err) {
41 shell_warn(sh, "Unable to parse input string argument");
42 return err;
43 }
44
45 err = bt_mesh_brg_cfg_cli_set(bt_mesh_shell_target_ctx.net_idx,
46 bt_mesh_shell_target_ctx.dst, set, &rsp);
47 if (err) {
48 shell_error(sh, "Failed to send Subnet Bridge Set (err %d)", err);
49 return -ENOEXEC;
50 }
51
52 shell_print(sh, "Subnet Bridge State: %s",
53 (rsp == BT_MESH_BRG_CFG_ENABLED) ? "Enabled" : "Disabled");
54 return 0;
55 }
56
cmd_bridging_table_size_get(const struct shell * sh,size_t argc,char * argv[])57 static int cmd_bridging_table_size_get(const struct shell *sh, size_t argc, char *argv[])
58 {
59 uint16_t rsp;
60 int err;
61
62 err = bt_mesh_brg_cfg_cli_table_size_get(bt_mesh_shell_target_ctx.net_idx,
63 bt_mesh_shell_target_ctx.dst, &rsp);
64 if (err) {
65 shell_error(sh, "Failed to send Bridging Table Size Get (err %d)", err);
66 return -ENOEXEC;
67 }
68
69 shell_print(sh, "Bridging Table Size: %u", rsp);
70 return 0;
71 }
72
cmd_bridging_table_add(const struct shell * sh,size_t argc,char * argv[])73 static int cmd_bridging_table_add(const struct shell *sh, size_t argc, char *argv[])
74 {
75 struct bt_mesh_brg_cfg_table_entry entry;
76 struct bt_mesh_brg_cfg_table_status rsp;
77 int err = 0;
78
79 entry.directions = shell_strtoul(argv[1], 0, &err);
80 entry.net_idx1 = shell_strtoul(argv[2], 0, &err);
81 entry.net_idx2 = shell_strtoul(argv[3], 0, &err);
82 entry.addr1 = shell_strtoul(argv[4], 0, &err);
83 entry.addr2 = shell_strtoul(argv[5], 0, &err);
84 if (err) {
85 shell_warn(sh, "Unable to parse input string argument");
86 return err;
87 }
88
89 err = bt_mesh_brg_cfg_cli_table_add(bt_mesh_shell_target_ctx.net_idx,
90 bt_mesh_shell_target_ctx.dst, &entry, &rsp);
91 if (err) {
92 shell_error(sh, "Failed to send Bridging Table Add (err %d)", err);
93 return -ENOEXEC;
94 }
95
96 if (rsp.status) {
97 shell_print(sh, "Bridging Table Add failed with status 0x%02x", rsp.status);
98 } else {
99 shell_print(sh, "Bridging Table Add was successful.");
100 }
101 return 0;
102 }
103
cmd_bridging_table_remove(const struct shell * sh,size_t argc,char * argv[])104 static int cmd_bridging_table_remove(const struct shell *sh, size_t argc, char *argv[])
105 {
106 uint16_t net_idx1, net_idx2, addr1, addr2;
107 struct bt_mesh_brg_cfg_table_status rsp;
108 int err = 0;
109
110 net_idx1 = shell_strtoul(argv[1], 0, &err);
111 net_idx2 = shell_strtoul(argv[2], 0, &err);
112 addr1 = shell_strtoul(argv[3], 0, &err);
113 addr2 = shell_strtoul(argv[4], 0, &err);
114 if (err) {
115 shell_warn(sh, "Unable to parse input string argument");
116 return err;
117 }
118
119 err = bt_mesh_brg_cfg_cli_table_remove(bt_mesh_shell_target_ctx.net_idx,
120 bt_mesh_shell_target_ctx.dst, net_idx1, net_idx2,
121 addr1, addr2, &rsp);
122 if (err) {
123 shell_error(sh, "Failed to send Bridging Table Remove (err %d)", err);
124 return -ENOEXEC;
125 }
126
127 if (rsp.status) {
128 shell_print(sh, "Bridging Table Remove failed with status 0x%02x", rsp.status);
129 } else {
130 shell_print(sh, "Bridging Table Remove was successful.");
131 }
132 return 0;
133 }
134
cmd_bridged_subnets_get(const struct shell * sh,size_t argc,char * argv[])135 static int cmd_bridged_subnets_get(const struct shell *sh, size_t argc, char *argv[])
136 {
137 struct bt_mesh_brg_cfg_filter_netkey filter_net_idx;
138 uint8_t start_idx;
139 struct bt_mesh_brg_cfg_subnets_list rsp = {
140 .list = NET_BUF_SIMPLE(CONFIG_BT_MESH_BRG_TABLE_ITEMS_MAX * 3),
141 };
142 int err = 0;
143
144 net_buf_simple_init(rsp.list, 0);
145
146 filter_net_idx.filter = shell_strtoul(argv[1], 0, &err);
147 filter_net_idx.net_idx = shell_strtoul(argv[2], 0, &err);
148 start_idx = shell_strtoul(argv[3], 0, &err);
149 if (err) {
150 shell_warn(sh, "Unable to parse input string argument");
151 return err;
152 }
153
154 err = bt_mesh_brg_cfg_cli_subnets_get(bt_mesh_shell_target_ctx.net_idx,
155 bt_mesh_shell_target_ctx.dst, filter_net_idx,
156 start_idx, &rsp);
157 if (err) {
158 shell_error(sh, "Failed to send Bridged Subnets Get (err %d)", err);
159 return -ENOEXEC;
160 }
161
162 shell_print(sh, "Bridged Subnets List:");
163 shell_print(sh, "\tfilter: %02x", rsp.net_idx_filter.filter);
164 shell_print(sh, "\tnet_idx: %04x", rsp.net_idx_filter.net_idx);
165 shell_print(sh, "\tstart_idx: %u", rsp.start_idx);
166 if (rsp.list) {
167 uint16_t net_idx1, net_idx2;
168 int i = 0;
169
170 while (rsp.list->len) {
171 key_idx_unpack_pair(rsp.list, &net_idx1, &net_idx2);
172 shell_print(sh, "\tEntry %d:", i++);
173 shell_print(sh, "\t\tnet_idx1: 0x%04x, net_idx2: 0x%04x", net_idx1,
174 net_idx2);
175 }
176 }
177 return 0;
178 }
179
cmd_bridging_table_get(const struct shell * sh,size_t argc,char * argv[])180 static int cmd_bridging_table_get(const struct shell *sh, size_t argc, char *argv[])
181 {
182 uint16_t net_idx1, net_idx2, start_idx;
183 struct bt_mesh_brg_cfg_table_list rsp = {
184 .list = NET_BUF_SIMPLE(CONFIG_BT_MESH_BRG_TABLE_ITEMS_MAX * 5),
185 };
186 int err = 0;
187
188 net_buf_simple_init(rsp.list, 0);
189
190 net_idx1 = shell_strtoul(argv[1], 0, &err);
191 net_idx2 = shell_strtoul(argv[2], 0, &err);
192 start_idx = shell_strtoul(argv[3], 0, &err);
193 if (err) {
194 shell_warn(sh, "Unable to parse input string argument");
195 return err;
196 }
197
198 err = bt_mesh_brg_cfg_cli_table_get(bt_mesh_shell_target_ctx.net_idx,
199 bt_mesh_shell_target_ctx.dst, net_idx1, net_idx2,
200 start_idx, &rsp);
201 if (err) {
202 shell_error(sh, "Failed to send Bridging Table Get (err %d)", err);
203 return -ENOEXEC;
204 }
205
206 if (rsp.status) {
207 shell_print(sh, "Bridging Table Get failed with status 0x%02x", rsp.status);
208 } else {
209 shell_print(sh, "Bridging Table List:");
210 shell_print(sh, "\tstatus: %02x", rsp.status);
211 shell_print(sh, "\tnet_idx1: %04x", rsp.net_idx1);
212 shell_print(sh, "\tnet_idx2: %04x", rsp.net_idx2);
213 shell_print(sh, "\tstart_idx: %u", rsp.start_idx);
214 if (rsp.list) {
215 uint16_t addr1, addr2;
216 uint8_t directions;
217 int i = 0;
218
219 while (rsp.list->len) {
220 addr1 = net_buf_simple_pull_le16(rsp.list);
221 addr2 = net_buf_simple_pull_le16(rsp.list);
222 directions = net_buf_simple_pull_u8(rsp.list);
223 shell_print(sh, "\tEntry %d:", i++);
224 shell_print(sh,
225 "\t\taddr1: 0x%04x, addr2: 0x%04x, directions: 0x%02x",
226 addr1, addr2, directions);
227 }
228 }
229 }
230 return 0;
231 }
232
233 SHELL_STATIC_SUBCMD_SET_CREATE(
234 brg_cfg_cmds, SHELL_CMD_ARG(get, NULL, NULL, cmd_subnet_bridge_get, 1, 0),
235 SHELL_CMD_ARG(set, NULL, "<State(disable, enable)>", cmd_subnet_bridge_set, 2, 0),
236 SHELL_CMD_ARG(table-size-get, NULL, NULL, cmd_bridging_table_size_get, 1, 0),
237 SHELL_CMD_ARG(table-add, NULL, "<Directions> <NetIdx1> <NetIdx2> <Addr1> <Addr2>",
238 cmd_bridging_table_add, 6, 0),
239 SHELL_CMD_ARG(table-remove, NULL, "<NetIdx1> <NetIdx2> <Addr1> <Addr2>",
240 cmd_bridging_table_remove, 5, 0),
241 SHELL_CMD_ARG(subnets-get, NULL, "<Filter> <NetIdx> <StartIdx>", cmd_bridged_subnets_get,
242 4, 0),
243 SHELL_CMD_ARG(table-get, NULL, "<NetIdx1> <NetIdx2> <StartIdx>", cmd_bridging_table_get,
244 4, 0),
245 SHELL_SUBCMD_SET_END);
246
247 SHELL_SUBCMD_ADD((mesh, models), brg, &brg_cfg_cmds, "Bridge Configuration Cli commands",
248 bt_mesh_shell_mdl_cmds_help, 1, 1);
249