Hi Michael, On Mon, Jun 15, 2020 at 5:03 PM Michael Sun <michaelfsun@xxxxxxxxxx> wrote: > > This patch introduces a new btmgmt command ‘advmon-features’ to help > user query for supported advertisement features. The command will work > with the new MGMT opcode MGMT_OP_READ_ADV_MONITOR_FEATURES. > > Reviewed-by: Alain Michaud <alainm@xxxxxxxxxxxx> > Reviewed-by: Miao-chen Chou <mcchou@xxxxxxxxxxxx> > Signed-off-by: Michael Sun <michaelfsun@xxxxxxxxxx> > --- > > tools/btmgmt.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 81 insertions(+) > > diff --git a/tools/btmgmt.c b/tools/btmgmt.c > index 46e7465b3..1aae7098c 100644 > --- a/tools/btmgmt.c > +++ b/tools/btmgmt.c > @@ -4567,6 +4567,84 @@ static void cmd_wbs(int argc, char **argv) > cmd_setting(MGMT_OP_SET_WIDEBAND_SPEECH, argc, argv); > } > > +static const char *advmon_features_str[] = { > + "Pattern monitor with logic OR.", > +}; > + > +static const char *advmon_features2str(uint32_t features) > +{ > + static char str[512]; > + int off, i; > + > + off = 0; > + snprintf(str, sizeof(str), "\n\tNone"); > + > + for (i = 0; i < NELEM(advmon_features_str); i++) { > + if ((features & (1 << i)) != 0 && off < sizeof(str)) > + off += snprintf(str + off, sizeof(str) - off, "\n\t%s", > + advmon_features_str[i]); > + } > + > + return str; > +} > + > +static void advmon_features_rsp(uint8_t status, uint16_t len, const void *param, > + void *user_data) > +{ > + const struct mgmt_rp_read_adv_monitor_features *rp = param; > + uint32_t supported_features, enabled_features; > + uint16_t num_handles; > + int i; > + > + if (status != MGMT_STATUS_SUCCESS) { > + error("Reading adv monitor features failed with status 0x%02x " > + "(%s)", status, mgmt_errstr(status)); > + return bt_shell_noninteractive_quit(EXIT_FAILURE); > + } > + > + if (len < sizeof(*rp)) { > + error("Too small adv monitor features reply (%u bytes)", len); > + return bt_shell_noninteractive_quit(EXIT_FAILURE); > + } > + > + if (len < sizeof(*rp) + rp->num_handles * sizeof(uint16_t)) { > + error("Handles count (%u) doesn't match reply length (%u)", > + rp->num_handles, len); > + return bt_shell_noninteractive_quit(EXIT_FAILURE); > + } > + > + supported_features = le32_to_cpu(rp->supported_features); > + enabled_features = le32_to_cpu(rp->enabled_features); > + num_handles = le16_to_cpu(rp->num_handles); > + > + print("Supported features:%s", advmon_features2str(supported_features)); > + print("Enabled features:%s", advmon_features2str(enabled_features)); > + print("Max number of handles: %u", le16_to_cpu(rp->max_num_handles)); > + print("Max number of patterns: %u", rp->max_num_patterns); > + print("Handles list with %u item%s", num_handles, > + num_handles == 0 ? "" : num_handles == 1 ? ":" : "s:"); > + for (i = 0; i < num_handles; i++) { > + print("\t0x%04x ", le16_to_cpu(rp->handles[i])); > + } > + > + return bt_shell_noninteractive_quit(EXIT_SUCCESS); > +} > + > +static void cmd_advmon_features(int argc, char **argv) > +{ > + uint16_t index; > + > + index = mgmt_index; > + if (index == MGMT_INDEX_NONE) > + index = 0; > + > + if (!mgmt_send(mgmt, MGMT_OP_READ_ADV_MONITOR_FEATURES, index, 0, NULL, > + advmon_features_rsp, NULL, NULL)) { > + error("Unable to send advertising monitor features command"); > + return bt_shell_noninteractive_quit(EXIT_FAILURE); > + } > +} > + > static void register_mgmt_callbacks(struct mgmt *mgmt, uint16_t index) > { > mgmt_register(mgmt, MGMT_EV_CONTROLLER_ERROR, index, controller_error, > @@ -4776,6 +4854,9 @@ static const struct bt_shell_menu main_menu = { > cmd_expinfo, "Show experimental features" }, > { "exp-debug", "<on/off>", > cmd_exp_debug, "Set debug feature" }, > + { "advmon-features", NULL, > + cmd_advmon_features, "Show advertisement monitor " > + "features" }, > {} }, > }; It might be a good idea to organize this as a submenu e.g. > menu monitor > features That way we can expand the number of commands for adding/removing monitors without making the list of commands way too big to show in one screen (although it already is).