diff --git a/include/zephyr/bluetooth/classic/classic.h b/include/zephyr/bluetooth/classic/classic.h index 0aeec12d3b2e2..8ac85eada4208 100644 --- a/include/zephyr/bluetooth/classic/classic.h +++ b/include/zephyr/bluetooth/classic/classic.h @@ -204,6 +204,304 @@ int bt_br_set_discoverable(bool enable, bool limited); */ int bt_br_set_connectable(bool enable); +/** + * @name Defined BR/EDR Page Scan timers + * @{ + */ +#define BT_BR_PAGE_SCAN_INTERVAL_R0 0x0800 /* 0x0800, 1.280s, U:0.625 */ +#define BT_BR_PAGE_SCAN_WINDOW_R0 0x0800 /* 0x0800, 1.280s, U:0.625 */ + +#define BT_BR_PAGE_SCAN_FAST_INTERVAL_R1 0x00a0 /* 0x00a0, 100.0ms, U:0.625 */ +#define BT_BR_PAGE_SCAN_FAST_WINDOW_R1 0x0011 /* 0x0011, 10.625ms, U:0.625 */ + +#define BT_BR_PAGE_SCAN_MEDIUM_INTERVAL_R1 0x0800 /* 0x0800, 1.280s, U:0.625 */ +#define BT_BR_PAGE_SCAN_MEDIUM_WINDOW_R1 0x0011 /* 0x0011, 10.625ms, U:0.625 */ + +#define BT_BR_PAGE_SCAN_SLOW_INTERVAL_R1 0x0800 /* 0x0800, 1.280s, U:0.625 */ +#define BT_BR_PAGE_SCAN_SLOW_WINDOW_R1 0x0011 /* 0x0011, 10.625ms, U:0.625 */ + +#define BT_BR_PAGE_SCAN_FAST_INTERVAL_R2 0x1000 /* 0x1000, 2.560s, U:0.625 */ +#define BT_BR_PAGE_SCAN_FAST_WINDOW_R2 0x0011 /* 0x0011, 10.625ms, U:0.625 */ + +#define BT_BR_PAGE_SCAN_SLOW_INTERVAL_R2 0x1000 /* 0x1000, 2.560s, U:0.625 */ +#define BT_BR_PAGE_SCAN_SLOW_WINDOW_R2 0x0011 /* 0x0011, 10.625ms, U:0.625 */ +/** + * @} + */ + +/** Page scan type. */ +enum bt_br_scan_type { + /** Standard scan (default) */ + BT_BR_SCAN_TYPE_STANDARD = 0, + + /** Interlaced scan (1.2 devices only) */ + BT_BR_SCAN_TYPE_INTERLACED = 1, +}; + +struct bt_br_page_scan_param { + /** Page scan interval in 0.625 ms units + * Range: 0x0012 to 0x1000; only even values are valid. + */ + uint16_t interval; + + /** Page scan window in 0.625 ms units + * Range: 0x0011 to 0x1000. + */ + uint16_t window; + + /** Page scan type. */ + enum bt_br_scan_type type; +}; + +/** + * @brief Initialize BR Scan parameters + * + * @param _interval Scan interval + * @param _window Scan window + * @param _type Scan type + */ + +#define BT_BR_SCAN_INIT(_interval, _window, _type) \ +{ \ + .interval = (_interval), \ + .window = (_window), \ + .type = (_type) \ +} + +/** + * Helper to declare BR/EDR page scan parameters inline + * + * @param _interval page scan interval, N * 0.625 milliseconds + * @param _window page scan window, N * 0.625 milliseconds + * @param _type BT_BR_SCAN_TYPE_STANDARD or BT_BR_SCAN_TYPE_INTERLACED + */ + +#define BT_BR_PAGE_SCAN_PARAM(_interval, _window, _type) \ + ((const struct bt_br_page_scan_param[]) { \ + BT_BR_SCAN_INIT(_interval, _window, _type) \ + }) + +/** + * @brief Default page scan parameters for R0 + * + * Page scan interval and window are set to 1.280 seconds (0x0800 in 0.625 ms units). + * The scan type is set to standard. + */ +#define BT_BR_PAGE_SCAN_PARAM_R0 BT_BR_PAGE_SCAN_PARAM(BT_BR_PAGE_SCAN_INTERVAL_R0, \ + BT_BR_PAGE_SCAN_WINDOW_R0, \ + BT_BR_SCAN_TYPE_STANDARD) + +/** + * @brief Fast page scan parameters for R1 + * + * Page scan interval is set to 100 ms (0x00A0 in 0.625 ms units), and the + * page scan window is set to 10.240 seconds (0x27FF in 1 ms units). + * The scan type is set to interlaced. + */ +#define BT_BR_PAGE_SCAN_PARAM_FAST_R1 \ + BT_BR_PAGE_SCAN_PARAM(BT_BR_PAGE_SCAN_FAST_INTERVAL_R1, \ + BT_BR_PAGE_SCAN_FAST_WINDOW_R1, \ + BT_BR_SCAN_TYPE_INTERLACED) + +/** + * @brief Medium page scan parameters for R1 + * + * Page scan interval and window are set to 1.280 seconds (0x0800 in 0.625 ms units). + * The scan type is set to standard. + */ +#define BT_BR_PAGE_SCAN_PARAM_MEDIUM_R1 \ + BT_BR_PAGE_SCAN_PARAM( \ + BT_BR_PAGE_SCAN_MEDIUM_INTERVAL_R1, \ + BT_BR_PAGE_SCAN_MEDIUM_WINDOW_R1, \ + BT_BR_SCAN_TYPE_INTERLACED) + +/** + * @brief Slow page scan parameters for R1 + * + * Page scan interval and window are set to 1.280 seconds (0x0800 in 0.625 ms units). + * The scan type is set to standard. + */ +#define BT_BR_PAGE_SCAN_PARAM_SLOW_R1 \ + BT_BR_PAGE_SCAN_PARAM( \ + BT_BR_PAGE_SCAN_SLOW_INTERVAL_R1, \ + BT_BR_PAGE_SCAN_SLOW_WINDOW_R1, \ + BT_BR_SCAN_TYPE_STANDARD) + +/** + * @brief Fast page scan parameters for R2 + * + * Page scan interval is set to 2.560 seconds (0x1000 in 0.625 ms units), and the + * page scan window is set to 10.240 seconds (0x27FF in 1 ms units). + * The scan type is set to standard. + */ +#define BT_BR_PAGE_SCAN_PARAM_FAST_R2 \ + BT_BR_PAGE_SCAN_PARAM( \ + BT_BR_PAGE_SCAN_FAST_INTERVAL_R2, \ + BT_BR_PAGE_SCAN_FAST_WINDOW_R2, \ + BT_BR_SCAN_TYPE_INTERLACED) + +/** + * @brief Slow page scan parameters for R2 + * + * Page scan interval and window are set to 2.560 seconds (0x1000 in 0.625 ms units). + * The scan type is set to standard. + */ +#define BT_BR_PAGE_SCAN_PARAM_SLOW_R2 \ + BT_BR_PAGE_SCAN_PARAM( \ + BT_BR_PAGE_SCAN_SLOW_INTERVAL_R2, \ + BT_BR_PAGE_SCAN_SLOW_WINDOW_R2, \ + BT_BR_SCAN_TYPE_STANDARD) + +/** + * @brief Update BR/EDR page scan parameters. + * + * This function updates the page scan parameters of the local BR/EDR controller. + * Page scan parameters determine how the controller listens for incoming + * connection requests from remote devices. + * + * The function validates the provided parameters, including the interval, + * window, and scan type, and sends the appropriate HCI commands to update + * the controller's page scan activity and scan type. + * + * The user can set custom page scan parameters using the helper macro + * `BT_BR_PAGE_SCAN_PARAM(interval, window, type)` to define their own values. + * Alternatively, the user can use predefined standard parameters as defined + * in the Bluetooth specification: + * - `BT_BR_PAGE_SCAN_PARAM_R0`: Default page scan parameters. + * - `BT_BR_PAGE_SCAN_PARAM_FAST_R1`: Fast page scan parameters for R1. + * - `BT_BR_PAGE_SCAN_PARAM_MEDIUM_R1`: Medium page scan parameters for R1. + * - `BT_BR_PAGE_SCAN_PARAM_SLOW_R1`: Slow page scan parameters for R1. + * - `BT_BR_PAGE_SCAN_PARAM_FAST_R2`: Fast page scan parameters for R2. + * - `BT_BR_PAGE_SCAN_PARAM_SLOW_R2`: Slow page scan parameters for R2. + * + * These predefined parameters are designed to meet common use cases and + * ensure compliance with the Bluetooth specification. + * + * @param param Page scan parameters, including: + * - interval: Time between consecutive page scans (in 0.625 ms units). + * Must be in the range [0x0012, 0x1000]. + * - window: Duration of a single page scan (in 0.625 ms units). + * Must be in the range [0x0011, 0x1000]. + * - type: Page scan type (e.g., standard or interlaced). + * + * @return 0 on success. + * @return -EINVAL if the provided parameters are invalid. + * @return -EAGAIN if the device is not ready. + * @return -ENOBUFS if memory allocation for HCI commands fails. + * @return Other negative error codes for internal failures. + */ +int bt_br_page_scan_update_param(const struct bt_br_page_scan_param *param); + +/** + * @brief BR/EDR inquiry scan parameters + * @note These parameters are used to configure the inquiry scan behavior of the + * local BR/EDR controller. + */ +struct bt_br_inquiry_scan_param { + /** Inquiry scan interval in 0.625 ms units + * Range: 0x0012 to 0x1000; only even values are valid. + */ + uint16_t interval; + + /** Inquiry scan window in 0.625 ms units + * Range: 0x0011 to 0x1000. + */ + uint16_t window; + + /** Inquiry scan type. */ + enum bt_br_scan_type type; +}; + +/** + * @name Defined BR Page Scan timers + * @{ + */ +#define BT_BR_INQUIRY_SCAN_INTERVAL_DEFAULT 0x1000 /* 0x1000, 2.560s, U:0.625 */ +#define BT_BR_INQUIRY_SCAN_WINDOW_DEFAULT 0x0012 /* 0x0012, 11.25mss, U:0.625 */ +/** + * @} + */ + +/** + * Helper to declare BR/EDR inquiry scan parameters inline + * + * @param _interval Inquiry scan interval, N * 0.625 milliseconds + * @param _window Inquiry scan window, N * 0.625 milliseconds + * @param _type BT_BR_SCAN_TYPE_STANDARD or BT_BR_SCAN_TYPE_INTERLACED + */ +#define BT_BR_INQUIRY_SCAN_PARAM(_interval, _window, _type) \ + ((const struct bt_br_inquiry_scan_param[]) { \ + BT_BR_SCAN_INIT(_interval, _window, _type) \ + }) + +/** + * @brief Default inquiry scan parameters + * + * Inquiry scan interval is set to 2.560 seconds (0x1000 in 0.625 ms units), and the + * inquiry scan window is set to 11.25 milliseconds (0x0012 in 0.625 ms units). + * The scan type is set to standard. + */ +#define BT_BR_INQUIRY_SCAN_PARAM_DEFAULT \ + BT_BR_INQUIRY_SCAN_PARAM( \ + BT_BR_INQUIRY_SCAN_INTERVAL_DEFAULT, \ + BT_BR_INQUIRY_SCAN_WINDOW_DEFAULT, \ + BT_BR_SCAN_TYPE_STANDARD) + +/** + * @brief Update BR/EDR inquiry scan parameters. + * + * This function updates the inquiry scan parameters of the local BR/EDR controller. + * Inquiry scan parameters determine how the controller handle inquiry requests. + * + * The function validates the provided parameters, including the interval, + * window, and scan type, and sends the appropriate HCI commands to update + * the controller's inquiry scan activity and scan type. + * + * The user can set custom inquiry scan parameters using the helper macro + * `BT_BR_INQUIRY_SCAN_PARAM(interval, window, type)` to define their own values. + * Alternatively, the user can use predefined standard parameters as defined + * in the Bluetooth specification: + * - `BT_BR_INQUIRY_SCAN_PARAM_DEFAULT`: Default inquiry scan parameters. + * These predefined parameters are designed to meet common use cases and + * ensure compliance with the Bluetooth specification. + * + * @param param Inquiry scan parameters, including: + * - interval: Time between consecutive inquiry scans (in 0.625 ms units). + * Must be in the range [0x0012, 0x1000]. + * - window: Duration of a single inquiry scan (in 0.625 ms units). + * Must be in the range [0x0011, 0x1000]. + * - type: Inquiry scan type (e.g., standard or interlaced). + * + * @return 0 on success. + * @return -EINVAL if the provided parameters are invalid. + * @return -EAGAIN if the device is not ready. + * @return -ENOBUFS if memory allocation for HCI commands fails. + * @return Other negative error codes for internal failures. + */ +int bt_br_inquiry_scan_update_param(const struct bt_br_inquiry_scan_param *param); + +/** + * @brief Set the Class of Device configuration parameter of the local + * BR/EDR Controller. + * + * @param cod Class of Device value. + * + * @return Negative if fail set to requested state or requested state has been + * already set. Zero if done successfully. + */ +int bt_br_set_class_of_device(uint32_t cod); + +/** + * @brief Get the Class of Device configuration parameter of the local + * BR/EDR Controller. + * + * @param cod Class of Device value. + * + * @return Negative if fail set to requested state or requested state has been + * already set. Zero if done successfully. + */ +int bt_br_get_class_of_device(uint32_t *cod); + /** @brief Check if a Bluetooth classic device address is bonded. * * @param addr Bluetooth classic device address. diff --git a/include/zephyr/bluetooth/hci_types.h b/include/zephyr/bluetooth/hci_types.h index 92f51b69a4551..8c98807c0c03c 100644 --- a/include/zephyr/bluetooth/hci_types.h +++ b/include/zephyr/bluetooth/hci_types.h @@ -636,6 +636,13 @@ struct bt_hci_rp_write_conn_accept_timeout { #define BT_BREDR_SCAN_INQUIRY 0x01 #define BT_BREDR_SCAN_PAGE 0x02 +#define BT_HCI_OP_WRITE_PAGE_SCAN_ACTIVITY BT_OP(BT_OGF_BASEBAND, 0x001c) /* 0x0c1c */ +#define BT_HCI_OP_WRITE_INQUIRY_SCAN_ACTIVITY BT_OP(BT_OGF_BASEBAND, 0x001e) /* 0x0c1e */ +struct bt_hci_cp_write_scan_activity { + uint16_t interval; + uint16_t window; +} __packed; + #define BT_HCI_OP_READ_CLASS_OF_DEVICE BT_OP(BT_OGF_BASEBAND, 0x0023) /* 0x0c23 */ struct bt_hci_rp_read_class_of_device { uint8_t status; @@ -837,11 +844,18 @@ struct bt_hci_cp_write_current_iac_lap { struct bt_hci_iac_lap lap[0]; } __packed; +#define BT_HCI_OP_WRITE_INQUIRY_SCAN_TYPE BT_OP(BT_OGF_BASEBAND, 0x0043) /* 0x0c43 */ + #define BT_HCI_OP_WRITE_INQUIRY_MODE BT_OP(BT_OGF_BASEBAND, 0x0045) /* 0x0c45 */ struct bt_hci_cp_write_inquiry_mode { uint8_t mode; } __packed; +#define BT_HCI_OP_WRITE_PAGE_SCAN_TYPE BT_OP(BT_OGF_BASEBAND, 0x0047) /* 0x0c47 */ +struct bt_hci_cp_write_scan_type { + uint8_t type; +} __packed; + #define BT_HCI_OP_WRITE_SSP_MODE BT_OP(BT_OGF_BASEBAND, 0x0056) /* 0x0c56 */ struct bt_hci_cp_write_ssp_mode { uint8_t mode; diff --git a/subsys/bluetooth/host/classic/br.c b/subsys/bluetooth/host/classic/br.c index 4e9902747381a..e5325658d6312 100644 --- a/subsys/bluetooth/host/classic/br.c +++ b/subsys/bluetooth/host/classic/br.c @@ -1296,6 +1296,151 @@ int bt_br_set_discoverable(bool enable, bool limited) return 0; } +static int bt_br_write_scan_activity(uint16_t opcode, uint16_t interval, uint16_t window) +{ + struct bt_hci_cp_write_scan_activity *cp; + struct net_buf *buf; + + if (!atomic_test_bit(bt_dev.flags, BT_DEV_READY)) { + return -EAGAIN; + } + + buf = bt_hci_cmd_alloc(K_FOREVER); + if (!buf) { + return -ENOBUFS; + } + + cp = net_buf_add(buf, sizeof(*cp)); + cp->interval = sys_cpu_to_le16(interval); + cp->window = sys_cpu_to_le16(window); + + return bt_hci_cmd_send_sync(opcode, buf, NULL); +} + +static int bt_br_write_scan_type(uint16_t opcode, uint8_t type) +{ + struct bt_hci_cp_write_scan_type *cp; + struct net_buf *buf; + int err; + + if (!atomic_test_bit(bt_dev.flags, BT_DEV_READY)) { + return -EAGAIN; + } + + buf = bt_hci_cmd_alloc(K_FOREVER); + if (!buf) { + return -ENOBUFS; + } + + cp = net_buf_add(buf, sizeof(*cp)); + cp->type = type; + + err = bt_hci_cmd_send_sync(opcode, buf, NULL); + if (err) { + return err; + } + + return 0; +} + +int bt_br_page_scan_update_param(const struct bt_br_page_scan_param *param) +{ + int err; + + if (param->interval < 0x0012 || param->interval > 0x1000) { + return -EINVAL; + } + + if (param->window < 0x0011 || param->window > 0x1000) { + return -EINVAL; + } + + if (param->interval < param->window) { + return -EINVAL; + } + + err = bt_br_write_scan_activity(BT_HCI_OP_WRITE_PAGE_SCAN_ACTIVITY, + param->interval, param->window); + if (err) { + LOG_ERR("write page scan activity failed (err %d)", err); + return err; + } + + err = bt_br_write_scan_type(BT_HCI_OP_WRITE_PAGE_SCAN_TYPE, param->type); + if (err) { + LOG_ERR("write page scan type failed (err %d)", err); + return err; + } + + return 0; +} + +int bt_br_inquiry_scan_update_param(const struct bt_br_inquiry_scan_param *param) +{ + int err; + + if (param->interval < 0x0012 || param->interval > 0x1000) { + return -EINVAL; + } + + if (param->window < 0x0011 || param->window > 0x1000) { + return -EINVAL; + } + + if (param->interval < param->window) { + return -EINVAL; + } + + err = bt_br_write_scan_activity(BT_HCI_OP_WRITE_INQUIRY_SCAN_ACTIVITY, + param->interval, param->window); + if (err) { + LOG_ERR("write inquiry scan activity failed (err %d)", err); + return err; + } + + err = bt_br_write_scan_type(BT_HCI_OP_WRITE_INQUIRY_SCAN_TYPE, param->type); + if (err) { + LOG_ERR("write inquiry scan type failed (err %d)", err); + return err; + } + + return 0; +} + +int bt_br_set_class_of_device(uint32_t cod) +{ + int err; + + if (!atomic_test_bit(bt_dev.flags, BT_DEV_READY)) { + return -EAGAIN; + } + + err = bt_br_write_cod(cod); + if (err) { + LOG_ERR("write cod:0x%08x failed (err %d)", cod, err); + return err; + } + + return 0; +} + +int bt_br_get_class_of_device(uint32_t *cod) +{ + int err; + + if (!atomic_test_bit(bt_dev.flags, BT_DEV_READY)) { + return -EAGAIN; + } + + err = bt_br_read_cod(cod); + if (err) { + LOG_ERR("read cod failed (err %d)", err); + return err; + } + + return 0; +} + bool bt_br_bond_exists(const bt_addr_t *addr) { struct bt_keys_link_key *key = bt_keys_find_link_key(addr); diff --git a/subsys/bluetooth/host/classic/shell/bredr.c b/subsys/bluetooth/host/classic/shell/bredr.c index e21f64f2de381..f6e1bb227a19e 100644 --- a/subsys/bluetooth/host/classic/shell/bredr.c +++ b/subsys/bluetooth/host/classic/shell/bredr.c @@ -792,6 +792,45 @@ static int cmd_discoverable(const struct shell *sh, size_t argc, char *argv[]) return 0; } +static int cmd_iscan_param(const struct shell *sh, size_t argc, char *argv[]) +{ + int err = 0; + + if (argc == 1) { + err = bt_br_inquiry_scan_update_param(BT_BR_INQUIRY_SCAN_PARAM_DEFAULT); + if (err) { + shell_print(sh, "BR/EDR update inquiry scan param failed (err %d)", err); + return -ENOEXEC; + } + } else if (argc == 4) { + uint16_t interval; + uint16_t window; + enum bt_br_scan_type type; + struct bt_br_inquiry_scan_param param = {0}; + + interval = strtoul(argv[1], NULL, 16); + window = strtoul(argv[2], NULL, 16); + type = strtoul(argv[3], NULL, 16); + + param.interval = interval; + param.window = window; + param.type = type; + + err = bt_br_inquiry_scan_update_param(¶m); + if (err) { + shell_print(sh, "BR/EDR update inquiry scan param failed (err %d)", err); + return -ENOEXEC; + } + } else { + shell_help(sh); + return SHELL_CMD_HELP_PRINTED; + } + + shell_print(sh, "BR/EDR update inquiry scan param done"); + + return 0; +} + static int cmd_connectable(const struct shell *sh, size_t argc, char *argv[]) { int err; @@ -818,6 +857,83 @@ static int cmd_connectable(const struct shell *sh, size_t argc, char *argv[]) return 0; } +static int cmd_pscan_param(const struct shell *sh, size_t argc, char *argv[]) +{ + int err = 0; + + if (argc == 2) { + if (!strcmp(argv[1], "r0")) { + err = bt_br_page_scan_update_param(BT_BR_PAGE_SCAN_PARAM_R0); + if (err) { + shell_print(sh, "BR/EDR update page scan param failed (err %d)", + err); + return -ENOEXEC; + } + } else if (!strcmp(argv[1], "fr1")) { + err = bt_br_page_scan_update_param(BT_BR_PAGE_SCAN_PARAM_FAST_R1); + if (err) { + shell_print(sh, "BR/EDR update page scan param failed (err %d)", + err); + return -ENOEXEC; + } + } else if (!strcmp(argv[1], "mr1")) { + err = bt_br_page_scan_update_param(BT_BR_PAGE_SCAN_PARAM_MEDIUM_R1); + if (err) { + shell_print(sh, "BR/EDR update page scan param failed (err %d)", + err); + return -ENOEXEC; + } + } else if (!strcmp(argv[1], "sr1")) { + err = bt_br_page_scan_update_param(BT_BR_PAGE_SCAN_PARAM_SLOW_R1); + if (err) { + shell_print(sh, "BR/EDR update page scan param failed (err %d)", + err); + return -ENOEXEC; + } + } else if (!strcmp(argv[1], "fr2")) { + err = bt_br_page_scan_update_param(BT_BR_PAGE_SCAN_PARAM_FAST_R2); + if (err) { + shell_print(sh, "BR/EDR update page scan param failed (err %d)", + err); + return -ENOEXEC; + } + } else if (!strcmp(argv[1], "sr2")) { + err = bt_br_page_scan_update_param(BT_BR_PAGE_SCAN_PARAM_SLOW_R2); + if (err) { + shell_print(sh, "BR/EDR update page scan param failed (err %d)", + err); + return -ENOEXEC; + } + } + } else if (argc == 4) { + uint16_t interval; + uint16_t window; + enum bt_br_scan_type type; + struct bt_br_page_scan_param param = {0}; + + interval = strtoul(argv[1], NULL, 16); + window = strtoul(argv[2], NULL, 16); + type = strtoul(argv[3], NULL, 16); + + param.interval = interval; + param.window = window; + param.type = type; + + err = bt_br_page_scan_update_param(¶m); + if (err) { + shell_print(sh, "BR/EDR update page scan param failed (err %d)", err); + return -ENOEXEC; + } + } else { + shell_help(sh); + return SHELL_CMD_HELP_PRINTED; + } + + shell_print(sh, "BR/EDR update page scan param done"); + + return 0; +} + static int cmd_oob(const struct shell *sh, size_t argc, char *argv[]) { char addr[BT_ADDR_STR_LEN]; @@ -1469,6 +1585,38 @@ static int cmd_set_role_switchable(const struct shell *sh, size_t argc, char *ar return 0; } +static int cmd_class_of_device(const struct shell *sh, size_t argc, char *argv[]) +{ + int err; + const char *action; + uint32_t cod; + + action = argv[1]; + + if (!strcmp(action, "get")) { + err = bt_br_get_class_of_device(&cod); + if (err) { + shell_error(sh, "fail to set cod (err %d)", err); + } else { + shell_print(sh, "get cod:0x%04x success", cod); + } + } else if (!strcmp(action, "set")) { + cod = strtoul(argv[2], NULL, 16); + + err = bt_br_set_class_of_device(cod); + if (err) { + shell_error(sh, "fail to set cod (err %d)", err); + } else { + shell_print(sh, "set cod:0x%04x success", cod); + } + } else { + shell_help(sh); + return SHELL_CMD_HELP_PRINTED; + } + + return 0; +} + #if defined(CONFIG_BT_L2CAP_CONNLESS) static void connless_recv(struct bt_conn *conn, uint16_t psm, struct net_buf *buf) { @@ -1582,6 +1730,18 @@ static int cmd_default_handler(const struct shell *sh, size_t argc, char **argv) " [hold_credit] " \ "[mode_optional] [extended_control]" +#define HELP_PSCAN_PARAM \ + "[mode: r0, fr1, mr1, sr1, fr2, sr2]\n" \ + "[\n" \ + " \n" \ + " ]" + +#define HELP_ISCAN_PARAM \ + "[default parameter if not specified]\n" \ + "[\n" \ + " \n" \ + " ]" + SHELL_STATIC_SUBCMD_SET_CREATE(echo_cmds, SHELL_CMD_ARG(register, NULL, HELP_NONE, cmd_l2cap_echo_reg, 1, 0), SHELL_CMD_ARG(unregister, NULL, HELP_NONE, cmd_l2cap_echo_unreg, 1, 0), @@ -1631,14 +1791,17 @@ SHELL_STATIC_SUBCMD_SET_CREATE(br_cmds, cmd_discovery, 2, 2), SHELL_CMD_ARG(iscan, NULL, " [mode: limited]", cmd_discoverable, 2, 1), + SHELL_CMD_ARG(iscan-param, NULL, HELP_ISCAN_PARAM, cmd_iscan_param, 0, 3), SHELL_CMD(l2cap, &l2cap_cmds, HELP_NONE, cmd_default_handler), SHELL_CMD_ARG(oob, NULL, NULL, cmd_oob, 1, 0), SHELL_CMD_ARG(pscan, NULL, "", cmd_connectable, 2, 0), + SHELL_CMD_ARG(pscan-param, NULL, HELP_PSCAN_PARAM, cmd_pscan_param, 2, 3), SHELL_CMD_ARG(sdp-find, NULL, "", cmd_sdp_find_record, 2, 0), SHELL_CMD_ARG(switch-role, NULL, "", cmd_switch_role, 2, 0), SHELL_CMD_ARG(set-role-switchable, NULL, "", cmd_set_role_switchable, 2, 0), + SHELL_CMD_ARG(cod, NULL, " []", cmd_class_of_device, 2, 1), SHELL_SUBCMD_SET_END );