diff --git a/include/zephyr/bluetooth/classic/classic.h b/include/zephyr/bluetooth/classic/classic.h index b8f01d3471c..cdf2045e5b8 100644 --- a/include/zephyr/bluetooth/classic/classic.h +++ b/include/zephyr/bluetooth/classic/classic.h @@ -273,6 +273,30 @@ int bt_br_set_class_of_device(uint32_t local_cod); */ int bt_br_write_local_name(const char *name); +/** + * @brief Read the Extended Inquiry Response configuration parameter of the + * local BR/EDR Controller. + * + * @param status Status of the command. + * @param fec_required FEC required for EIR. + * @param eir Extended Inquiry Response data. + * + * @return Zero on success or error code otherwise, positive in case + * of protocol error or negative (POSIX) in case of stack internal error. + */ +int bt_br_read_ext_inq_response(uint8_t *status, uint8_t *fec_required, uint8_t *eir); + +/** + * @brief Write the Extended Inquiry Response configuration parameter of the + * local BR/EDR Controller. + * + * @param fec_required FEC required for EIR. + * + * @return Zero on success or error code otherwise, positive in case + * of protocol error or negative (POSIX) in case of stack internal error. + */ +int bt_br_write_ext_inq_response(uint8_t fec_required); + /** Information about a br/edr bond with a remote device. */ struct bt_bond_info_br { bt_addr_t addr; diff --git a/include/zephyr/bluetooth/hci_types.h b/include/zephyr/bluetooth/hci_types.h index 34dd3c36ffc..dcb5a75d38a 100644 --- a/include/zephyr/bluetooth/hci_types.h +++ b/include/zephyr/bluetooth/hci_types.h @@ -156,6 +156,7 @@ struct bt_hci_cmd_hdr { #define BT_FEAT_2EV3_PKT(feat) BT_FEAT_TEST(feat, 0, 5, 5) #define BT_FEAT_3EV3_PKT(feat) BT_FEAT_TEST(feat, 0, 5, 6) #define BT_FEAT_3SLOT_PKT(feat) BT_FEAT_TEST(feat, 0, 5, 7) +#define BT_FEAT_EIR(feat) BT_FEAT_TEST(feat, 0, 6, 0) #define BT_FEAT_SSP(feat) BT_FEAT_TEST(feat, 0, 6, 3) /* LE features */ @@ -722,6 +723,19 @@ struct bt_hci_rp_read_tx_power_level { int8_t tx_power_level; } __packed; +#define BT_HCI_OP_READ_EXTENDED_INQUIRY_RESPONSE BT_OP(BT_OGF_BASEBAND, 0x0051) /* 0x0c51 */ +struct bt_hci_rp_read_extended_inquiry_response { + uint8_t status; + uint8_t fec_required; + uint8_t extended_inquiry_response[240]; +} __packed; + +#define BT_HCI_OP_WRITE_EXTENDED_INQUIRY_RESPONSE BT_OP(BT_OGF_BASEBAND, 0x0052) /* 0x0c52 */ +struct bt_hci_cp_write_extended_inquiry_response { + uint8_t fec; + uint8_t extended_inquiry_response[240]; +} __packed; + #define BT_HCI_LE_TX_POWER_PHY_1M 0x01 #define BT_HCI_LE_TX_POWER_PHY_2M 0x02 #define BT_HCI_LE_TX_POWER_PHY_CODED_S8 0x03 diff --git a/subsys/bluetooth/host/classic/br.c b/subsys/bluetooth/host/classic/br.c index a5c80660893..c0d366f2bdc 100644 --- a/subsys/bluetooth/host/classic/br.c +++ b/subsys/bluetooth/host/classic/br.c @@ -1270,6 +1270,79 @@ int bt_br_write_local_name(const char *name) return bt_hci_cmd_send_sync(BT_HCI_OP_WRITE_LOCAL_NAME, buf, NULL); } +int bt_br_read_ext_inq_response(uint8_t *status, uint8_t *fec_required, uint8_t *eir) +{ + struct bt_hci_rp_read_extended_inquiry_response *rp; + struct net_buf *rsp; + int err; + + if (!BT_FEAT_EIR(bt_dev.features)) { + return -ENOTSUP; + } + + err = bt_hci_cmd_send_sync(BT_HCI_OP_READ_EXTENDED_INQUIRY_RESPONSE, NULL, &rsp); + if (err) { + return err; + } + + rp = (void *)rsp->data; + *status = rp->status; + *fec_required = rp->fec_required; + + if (eir) { + memcpy(eir, rp->extended_inquiry_response, sizeof(rp->extended_inquiry_response)); + } + + net_buf_unref(rsp); + + return 0; +} + +int bt_br_write_ext_inq_response(uint8_t fec_required) +{ + struct net_buf *buf; + struct bt_hci_cp_write_extended_inquiry_response *cp; + size_t name_len, eir_len = 240; + uint8_t type; + + if (!BT_FEAT_EIR(bt_dev.features)) { + return -ENOTSUP; + } + + buf = bt_hci_cmd_create(BT_HCI_OP_WRITE_EXTENDED_INQUIRY_RESPONSE, sizeof(*cp)); + if (!buf) { + return -ENOBUFS; + } + + net_buf_add_u8(buf, fec_required); + + /* Fill in EIR data (Name) */ + eir_len -= 2; + name_len = strlen(bt_dev.name); + if (name_len > eir_len) { + name_len = eir_len; + type = EIR_SHORT_NAME; + eir_len = 0; + } else { + type = EIR_COMPLETE_NAME; + eir_len -= name_len; + } + + net_buf_add_u8(buf, name_len + 1); + net_buf_add_u8(buf, type); + net_buf_add_mem(buf, bt_dev.name, name_len); + + /* TODO: Fill in EIR data (COD) */ + /* TODO: Fill in EIR data (UUID) */ + /* TODO: Fill in EIR data (Flags) */ + /* TODO: Fill in EIR data (Manufacturer Specific Data) */ + /* TODO: Fill in EIR data (TX Power) */ + + net_buf_add(buf, eir_len); + + return bt_hci_cmd_send_sync(BT_HCI_OP_WRITE_EXTENDED_INQUIRY_RESPONSE, buf, NULL); +} + int bt_br_remote_name_request(const bt_addr_t *bdaddr, bt_br_remote_name_req_cb_t cb) { struct bt_br_discovery_result *result; diff --git a/subsys/bluetooth/host/hci_core.c b/subsys/bluetooth/host/hci_core.c index a7fecafc321..0a53f201282 100644 --- a/subsys/bluetooth/host/hci_core.c +++ b/subsys/bluetooth/host/hci_core.c @@ -4558,7 +4558,13 @@ int bt_set_name(const char *name) } if (IS_ENABLED(CONFIG_BT_CLASSIC)) { - return bt_br_write_local_name(name); + err = bt_br_write_local_name(name); + if (err) { + LOG_WRN("Unable to set BR/EDR name"); + return err; + } + + return bt_br_write_ext_inq_response(true); } return 0; diff --git a/subsys/bluetooth/host/settings.c b/subsys/bluetooth/host/settings.c index 06b3526c852..12750aeb06b 100644 --- a/subsys/bluetooth/host/settings.c +++ b/subsys/bluetooth/host/settings.c @@ -250,6 +250,7 @@ static int commit_settings(void) } else { if (IS_ENABLED(CONFIG_BT_CLASSIC)) { bt_br_write_local_name(bt_dev.name); + bt_br_write_ext_inq_response(true); } } #endif