diff --git a/doc/releases/release-notes-4.1.rst b/doc/releases/release-notes-4.1.rst index b1f810d3a43..7a8fd4b2728 100644 --- a/doc/releases/release-notes-4.1.rst +++ b/doc/releases/release-notes-4.1.rst @@ -133,6 +133,10 @@ New APIs and options * Bluetooth + * Host + + * :c:func:`bt_conn_is_type` + * Mesh * :c:member:`bt_mesh_health_cli::update` callback can be used to periodically update the message diff --git a/include/zephyr/bluetooth/conn.h b/include/zephyr/bluetooth/conn.h index 73a14b09ab9..070fd1ef25b 100644 --- a/include/zephyr/bluetooth/conn.h +++ b/include/zephyr/bluetooth/conn.h @@ -4,6 +4,7 @@ /* * Copyright (c) 2015-2016 Intel Corporation + * Copyright (c) 2025 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ @@ -722,7 +723,7 @@ struct bt_conn *bt_conn_lookup_addr_le(uint8_t id, const bt_addr_le_t *peer); * * @param conn Connection object. * - * @return Destination address. + * @return Destination address if @p conn is a valid @ref BT_CONN_TYPE_LE connection */ const bt_addr_le_t *bt_conn_get_dst(const struct bt_conn *conn); @@ -1041,9 +1042,20 @@ enum bt_conn_auth_keypress { */ int bt_conn_get_info(const struct bt_conn *conn, struct bt_conn_info *info); +/** @brief Function to determine the type of a connection + * + * @param conn The connection object + * @param type The types to check against. It is possible to supply multiple types, + * e.g. BT_CONN_TYPE_LE | BT_CONN_TYPE_SCO. + * + * @retval true @p conn is of type @p type + * @retval false @p conn is either NULL or not of type @p type + */ +bool bt_conn_is_type(const struct bt_conn *conn, enum bt_conn_type type); + /** @brief Get connection info for the remote device. * - * @param conn Connection object. + * @param conn @ref BT_CONN_TYPE_LE or @ref BT_CONN_TYPE_BR connection object. * @param remote_info Connection remote info object. * * @note In order to retrieve the remote version (version, manufacturer @@ -1055,51 +1067,56 @@ int bt_conn_get_info(const struct bt_conn *conn, struct bt_conn_info *info); * * @return Zero on success or (negative) error code on failure. * @return -EBUSY The remote information is not yet available. + * @return -EINVAL @p conn is not a valid @ref BT_CONN_TYPE_LE or @ref BT_CONN_TYPE_BR connection. */ int bt_conn_get_remote_info(struct bt_conn *conn, struct bt_conn_remote_info *remote_info); /** @brief Get connection transmit power level. * - * @param conn Connection object. + * @param conn @ref BT_CONN_TYPE_LE connection object. * @param tx_power_level Transmit power level descriptor. * * @return Zero on success or (negative) error code on failure. * @return -ENOBUFS HCI command buffer is not available. + * @return -EINVAL @p conn is not a valid @ref BT_CONN_TYPE_LE connection. */ int bt_conn_le_get_tx_power_level(struct bt_conn *conn, struct bt_conn_le_tx_power *tx_power_level); /** @brief Get local enhanced connection transmit power level. * - * @param conn Connection object. + * @param conn @ref BT_CONN_TYPE_LE connection object. * @param tx_power Transmit power level descriptor. * * @return Zero on success or (negative) error code on failure. * @retval -ENOBUFS HCI command buffer is not available. + * @return -EINVAL @p conn is not a valid @ref BT_CONN_TYPE_LE connection. */ int bt_conn_le_enhanced_get_tx_power_level(struct bt_conn *conn, struct bt_conn_le_tx_power *tx_power); /** @brief Get remote (peer) transmit power level. * - * @param conn Connection object. + * @param conn @ref BT_CONN_TYPE_LE connection object. * @param phy PHY information. * * @return Zero on success or (negative) error code on failure. * @retval -ENOBUFS HCI command buffer is not available. + * @return -EINVAL @p conn is not a valid @ref BT_CONN_TYPE_LE connection. */ int bt_conn_le_get_remote_tx_power_level(struct bt_conn *conn, enum bt_conn_le_tx_power_phy phy); /** @brief Enable transmit power reporting. * - * @param conn Connection object. + * @param conn @ref BT_CONN_TYPE_LE connection object. * @param local_enable Enable/disable reporting for local. * @param remote_enable Enable/disable reporting for remote. * * @return Zero on success or (negative) error code on failure. * @retval -ENOBUFS HCI command buffer is not available. + * @return -EINVAL @p conn is not a valid @ref BT_CONN_TYPE_LE connection. */ int bt_conn_le_set_tx_power_report_enable(struct bt_conn *conn, bool local_enable, @@ -1111,10 +1128,11 @@ int bt_conn_le_set_tx_power_report_enable(struct bt_conn *conn, * * @note To use this API @kconfig{CONFIG_BT_PATH_LOSS_MONITORING} must be set. * - * @param conn Connection object. + * @param conn @ref BT_CONN_TYPE_LE connection object. * @param param Path Loss Monitoring parameters * * @return Zero on success or (negative) error code on failure. + * @return -EINVAL @p conn is not a valid @ref BT_CONN_TYPE_LE connection. */ int bt_conn_le_set_path_loss_mon_param(struct bt_conn *conn, const struct bt_conn_le_path_loss_reporting_param *param); @@ -1126,10 +1144,11 @@ int bt_conn_le_set_path_loss_mon_param(struct bt_conn *conn, * * @note To use this API @kconfig{CONFIG_BT_PATH_LOSS_MONITORING} must be set. * - * @param conn Connection Object. + * @param conn @ref BT_CONN_TYPE_LE connection object. * @param enable Enable/disable path loss reporting. * * @return Zero on success or (negative) error code on failure. + * @return -EINVAL @p conn is not a valid @ref BT_CONN_TYPE_LE connection. */ int bt_conn_le_set_path_loss_mon_enable(struct bt_conn *conn, bool enable); @@ -1155,10 +1174,11 @@ int bt_conn_le_subrate_set_defaults(const struct bt_conn_le_subrate_param *param * * @note To use this API @kconfig{CONFIG_BT_SUBRATING} must be set. * - * @param conn Connection object. + * @param conn @ref BT_CONN_TYPE_LE connection object. * @param params Subrating parameters. * * @return Zero on success or (negative) error code on failure. + * @return -EINVAL @p conn is not a valid @ref BT_CONN_TYPE_LE connection. */ int bt_conn_le_subrate_request(struct bt_conn *conn, const struct bt_conn_le_subrate_param *params); @@ -1169,20 +1189,22 @@ int bt_conn_le_subrate_request(struct bt_conn *conn, * parameters will be delayed. This delay can be configured by through the * @kconfig{CONFIG_BT_CONN_PARAM_UPDATE_TIMEOUT} option. * - * @param conn Connection object. + * @param conn @ref BT_CONN_TYPE_LE connection object. * @param param Updated connection parameters. * * @return Zero on success or (negative) error code on failure. + * @return -EINVAL @p conn is not a valid @ref BT_CONN_TYPE_LE connection. */ int bt_conn_le_param_update(struct bt_conn *conn, const struct bt_le_conn_param *param); /** @brief Update the connection transmit data length parameters. * - * @param conn Connection object. + * @param conn @ref BT_CONN_TYPE_LE connection object. * @param param Updated data length parameters. * * @return Zero on success or (negative) error code on failure. + * @return -EINVAL @p conn is not a valid @ref BT_CONN_TYPE_LE connection. */ int bt_conn_le_data_len_update(struct bt_conn *conn, const struct bt_conn_le_data_len_param *param); @@ -1192,10 +1214,11 @@ int bt_conn_le_data_len_update(struct bt_conn *conn, * Update the preferred transmit and receive PHYs of the connection. * Use @ref BT_GAP_LE_PHY_NONE to indicate no preference. * - * @param conn Connection object. + * @param conn @ref BT_CONN_TYPE_LE connection object. * @param param Updated connection parameters. * * @return Zero on success or (negative) error code on failure. + * @return -EINVAL @p conn is not a valid @ref BT_CONN_TYPE_LE connection. */ int bt_conn_le_phy_update(struct bt_conn *conn, const struct bt_conn_le_phy_param *param); @@ -1469,16 +1492,22 @@ __deprecated int bt_le_set_auto_conn(const bt_addr_le_t *addr, * @note When @ref BT_SECURITY_FORCE_PAIR within @p sec is enabled then the pairing * procedure will always be initiated. * - * @param conn Connection object. + * @param conn @ref BT_CONN_TYPE_LE or @ref BT_CONN_TYPE_BR connection object. * @param sec Requested minimum security level. * * @return 0 on success or negative error + * @return -EINVAL @p conn is not a valid @ref BT_CONN_TYPE_LE or @ref BT_CONN_TYPE_BR connection. */ int bt_conn_set_security(struct bt_conn *conn, bt_security_t sec); /** @brief Get security level for a connection. * - * @return Connection security level + * @param conn @ref BT_CONN_TYPE_LE or @ref BT_CONN_TYPE_BR connection object. + * + * @return Connection security level if @kconfig{CONFIG_BT_SMP} or @kconfig{CONFIG_BT_CLASSIC} is + * enabled, else @ref BT_SECURITY_L1 + * @return @ref BT_SECURITY_L0 @p conn is not a valid @ref BT_CONN_TYPE_LE or @ref BT_CONN_TYPE_BR + * connection. */ bt_security_t bt_conn_get_security(const struct bt_conn *conn); @@ -1487,9 +1516,10 @@ bt_security_t bt_conn_get_security(const struct bt_conn *conn); * This function gets encryption key size. * If there is no security (encryption) enabled 0 will be returned. * - * @param conn Existing connection object. + * @param conn @ref BT_CONN_TYPE_LE or @ref BT_CONN_TYPE_BR connection object. * * @return Encryption key size. + * @return 0 @p conn is not a valid @ref BT_CONN_TYPE_LE or @ref BT_CONN_TYPE_BR connection. */ uint8_t bt_conn_enc_key_size(const struct bt_conn *conn); @@ -2013,8 +2043,13 @@ bool bt_get_bondable(void); * The default value of the global configuration is defined using * CONFIG_BT_BONDABLE Kconfig option. * - * @param conn Connection object. + * @param conn @ref BT_CONN_TYPE_LE or @ref BT_CONN_TYPE_BR connection object. * @param enable Value allowing/disallowing to be bondable. + * + * @retval 0 Success + * @retval -EALREADY Already in the requested state + * @return -EINVAL @p conn is not a valid @ref BT_CONN_TYPE_LE or @ref BT_CONN_TYPE_BR connection + * @return -EINVAL @p conn is a valid @ref BT_CONN_TYPE_LE but could not get SMP context */ int bt_conn_set_bondable(struct bt_conn *conn, bool enable); @@ -2040,10 +2075,12 @@ void bt_le_oob_set_legacy_flag(bool enable); * The function should only be called in response to the oob_data_request() * callback provided that the legacy method is user pairing. * - * @param conn Connection object + * @param conn @ref BT_CONN_TYPE_LE connection object. * @param tk Pointer to 16 byte long TK array * - * @return Zero on success or -EINVAL if NULL + * @retval 0 Success + * @return -EINVAL @p conn is not a valid @ref BT_CONN_TYPE_LE connection. + * @return -EINVAL @p tk is NULL. */ int bt_le_oob_set_legacy_tk(struct bt_conn *conn, const uint8_t *tk); @@ -2058,12 +2095,13 @@ int bt_le_oob_set_legacy_tk(struct bt_conn *conn, const uint8_t *tk); * data present, with only remote OOB data present or with both local and * remote OOB data present. * - * @param conn Connection object + * @param conn @ref BT_CONN_TYPE_LE connection object. * @param oobd_local Local OOB data or NULL if not present * @param oobd_remote Remote OOB data or NULL if not present * * @return Zero on success or error code otherwise, positive in case of * protocol error or negative (POSIX) in case of stack internal error. + * @return -EINVAL @p conn is not a valid @ref BT_CONN_TYPE_LE connection. */ int bt_le_oob_set_sc_data(struct bt_conn *conn, const struct bt_le_oob_sc_data *oobd_local, @@ -2077,12 +2115,13 @@ int bt_le_oob_set_sc_data(struct bt_conn *conn, * @note The OOB data will only be available as long as the connection object * associated with it is valid. * - * @param conn Connection object + * @param conn @ref BT_CONN_TYPE_LE connection object. * @param oobd_local Local OOB data or NULL if not set * @param oobd_remote Remote OOB data or NULL if not set * * @return Zero on success or error code otherwise, positive in case of * protocol error or negative (POSIX) in case of stack internal error. + * @return -EINVAL @p conn is not a valid @ref BT_CONN_TYPE_LE connection. */ int bt_le_oob_get_sc_data(struct bt_conn *conn, const struct bt_le_oob_sc_data **oobd_local, @@ -2428,10 +2467,11 @@ int bt_conn_auth_cb_register(const struct bt_conn_auth_cb *cb); * security procedures in the SMP module have already started. This function * can be called only once per connection. * - * @param conn Connection object. + * @param conn @ref BT_CONN_TYPE_LE or @ref BT_CONN_TYPE_BR connection object. * @param cb Callback struct. * * @return Zero on success or negative error code otherwise + * @return -EINVAL @p conn is not a valid @ref BT_CONN_TYPE_LE or @ref BT_CONN_TYPE_BR connection */ int bt_conn_auth_cb_overlay(struct bt_conn *conn, const struct bt_conn_auth_cb *cb); @@ -2461,10 +2501,11 @@ int bt_conn_auth_info_cb_unregister(struct bt_conn_auth_info_cb *cb); * This function should be called only after passkey_entry callback from * bt_conn_auth_cb structure was called. * - * @param conn Connection object. + * @param conn @ref BT_CONN_TYPE_LE or @ref BT_CONN_TYPE_BR connection object. * @param passkey Entered passkey. * * @return Zero on success or negative error code otherwise + * @return -EINVAL @p conn is not a valid @ref BT_CONN_TYPE_LE or @ref BT_CONN_TYPE_BR connection */ int bt_conn_auth_passkey_entry(struct bt_conn *conn, unsigned int passkey); @@ -2475,13 +2516,14 @@ int bt_conn_auth_passkey_entry(struct bt_conn *conn, unsigned int passkey); * * Requires @kconfig{CONFIG_BT_PASSKEY_KEYPRESS}. * - * @param conn Destination for the notification. + * @param conn @ref BT_CONN_TYPE_LE destination connection for the notification. * @param type What keypress event type to send. @see bt_conn_auth_keypress. * * @retval 0 Success * @retval -EINVAL Improper use of the API. * @retval -ENOMEM Failed to allocate. * @retval -ENOBUFS Failed to allocate. + * @return -EINVAL @p conn is not a valid @ref BT_CONN_TYPE_LE connection */ int bt_conn_auth_keypress_notify(struct bt_conn *conn, enum bt_conn_auth_keypress type); @@ -2489,9 +2531,10 @@ int bt_conn_auth_keypress_notify(struct bt_conn *conn, enum bt_conn_auth_keypres * * This function allows to cancel ongoing authenticated pairing. * - * @param conn Connection object. + * @param conn @ref BT_CONN_TYPE_LE or @ref BT_CONN_TYPE_BR connection object. * * @return Zero on success or negative error code otherwise + * @return -EINVAL @p conn is not a valid @ref BT_CONN_TYPE_LE or @ref BT_CONN_TYPE_BR connection */ int bt_conn_auth_cancel(struct bt_conn *conn); @@ -2500,9 +2543,10 @@ int bt_conn_auth_cancel(struct bt_conn *conn); * This function should be called only after passkey_confirm callback from * bt_conn_auth_cb structure was called. * - * @param conn Connection object. + * @param conn @ref BT_CONN_TYPE_LE or @ref BT_CONN_TYPE_BR connection object. * * @return Zero on success or negative error code otherwise + * @return -EINVAL @p conn is not a valid @ref BT_CONN_TYPE_LE or @ref BT_CONN_TYPE_BR connection */ int bt_conn_auth_passkey_confirm(struct bt_conn *conn); @@ -2511,9 +2555,10 @@ int bt_conn_auth_passkey_confirm(struct bt_conn *conn); * This function should be called only after pairing_confirm callback from * bt_conn_auth_cb structure was called if user confirmed incoming pairing. * - * @param conn Connection object. + * @param conn @ref BT_CONN_TYPE_LE or @ref BT_CONN_TYPE_BR connection object. * * @return Zero on success or negative error code otherwise + * @return -EINVAL @p conn is not a valid @ref BT_CONN_TYPE_LE or @ref BT_CONN_TYPE_BR connection */ int bt_conn_auth_pairing_confirm(struct bt_conn *conn); @@ -2522,10 +2567,11 @@ int bt_conn_auth_pairing_confirm(struct bt_conn *conn); * This function should be called only after PIN code callback from * bt_conn_auth_cb structure was called. It's for legacy 2.0 devices. * - * @param conn Connection object. + * @param conn @ref BT_CONN_TYPE_BR connection object. * @param pin Entered PIN code. * * @return Zero on success or negative error code otherwise + * @return -EINVAL @p conn is not a valid @ref BT_CONN_TYPE_BR connection */ int bt_conn_auth_pincode_entry(struct bt_conn *conn, const char *pin); diff --git a/subsys/bluetooth/host/classic/ssp.c b/subsys/bluetooth/host/classic/ssp.c index 9ccf22d3632..6884b731027 100644 --- a/subsys/bluetooth/host/classic/ssp.c +++ b/subsys/bluetooth/host/classic/ssp.c @@ -1,12 +1,14 @@ /* - * Copyright (c) 2017 Nordic Semiconductor ASA + * Copyright (c) 2017-2025 Nordic Semiconductor ASA * Copyright (c) 2015 Intel Corporation * * SPDX-License-Identifier: Apache-2.0 */ +#include #include +#include #include #include @@ -87,7 +89,8 @@ int bt_conn_auth_pincode_entry(struct bt_conn *conn, const char *pin) return -EINVAL; } - if (conn->type != BT_CONN_TYPE_BR) { + if (!bt_conn_is_type(conn, BT_CONN_TYPE_BR)) { + LOG_DBG("Invalid connection type: %u for %p", conn->type, conn); return -EINVAL; } diff --git a/subsys/bluetooth/host/conn.c b/subsys/bluetooth/host/conn.c index 7642aa74728..a781c7efa6c 100644 --- a/subsys/bluetooth/host/conn.c +++ b/subsys/bluetooth/host/conn.c @@ -2,6 +2,7 @@ /* * Copyright (c) 2015-2016 Intel Corporation + * Copyright (c) 2025 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ @@ -2570,6 +2571,11 @@ int bt_conn_le_start_encryption(struct bt_conn *conn, uint8_t rand[8], #if defined(CONFIG_BT_SMP) || defined(CONFIG_BT_CLASSIC) uint8_t bt_conn_enc_key_size(const struct bt_conn *conn) { + if (!bt_conn_is_type(conn, BT_CONN_TYPE_LE | BT_CONN_TYPE_BR)) { + LOG_DBG("Invalid connection type: %u for %p", conn->type, conn); + return 0; + } + if (!conn->encrypt) { return 0; } @@ -2685,6 +2691,11 @@ int bt_conn_set_security(struct bt_conn *conn, bt_security_t sec) bool force_pair; int err; + if (!bt_conn_is_type(conn, BT_CONN_TYPE_LE | BT_CONN_TYPE_BR)) { + LOG_DBG("Invalid connection type: %u for %p", conn->type, conn); + return -EINVAL; + } + if (conn->state != BT_CONN_CONNECTED) { return -ENOTCONN; } @@ -2720,6 +2731,11 @@ int bt_conn_set_security(struct bt_conn *conn, bt_security_t sec) bt_security_t bt_conn_get_security(const struct bt_conn *conn) { + if (!bt_conn_is_type(conn, BT_CONN_TYPE_LE | BT_CONN_TYPE_BR)) { + LOG_DBG("Invalid connection type: %u for %p", conn->type, conn); + return BT_SECURITY_L0; + } + return conn->sec_level; } #else @@ -2880,6 +2896,11 @@ struct bt_conn *bt_conn_lookup_state_le(uint8_t id, const bt_addr_le_t *peer, const bt_addr_le_t *bt_conn_get_dst(const struct bt_conn *conn) { + if (!bt_conn_is_type(conn, BT_CONN_TYPE_LE)) { + LOG_DBG("Invalid connection type: %u for %p", conn->type, conn); + return NULL; + } + return &conn->le.dst; } @@ -2973,9 +2994,23 @@ int bt_conn_get_info(const struct bt_conn *conn, struct bt_conn_info *info) return -EINVAL; } +bool bt_conn_is_type(const struct bt_conn *conn, enum bt_conn_type type) +{ + if (conn == NULL) { + return false; + } + + return (conn->type & type) != 0; +} + int bt_conn_get_remote_info(struct bt_conn *conn, struct bt_conn_remote_info *remote_info) { + if (!bt_conn_is_type(conn, BT_CONN_TYPE_LE | BT_CONN_TYPE_BR)) { + LOG_DBG("Invalid connection type: %u for %p", conn->type, conn); + return -EINVAL; + } + if (!atomic_test_bit(conn->flags, BT_CONN_LE_FEATURES_EXCHANGED) || (IS_ENABLED(CONFIG_BT_REMOTE_VERSION) && !atomic_test_bit(conn->flags, BT_CONN_AUTO_VERSION_INFO))) { @@ -3069,6 +3104,11 @@ int bt_conn_le_enhanced_get_tx_power_level(struct bt_conn *conn, struct bt_hci_cp_le_read_tx_power_level *cp; struct net_buf *buf; + if (!bt_conn_is_type(conn, BT_CONN_TYPE_LE)) { + LOG_DBG("Invalid connection type: %u for %p", conn->type, conn); + return -EINVAL; + } + if (!tx_power->phy) { return -EINVAL; } @@ -3102,6 +3142,11 @@ int bt_conn_le_get_remote_tx_power_level(struct bt_conn *conn, struct bt_hci_cp_le_read_tx_power_level *cp; struct net_buf *buf; + if (!bt_conn_is_type(conn, BT_CONN_TYPE_LE)) { + LOG_DBG("Invalid connection type: %u for %p", conn->type, conn); + return -EINVAL; + } + if (!phy) { return -EINVAL; } @@ -3125,6 +3170,11 @@ int bt_conn_le_set_tx_power_report_enable(struct bt_conn *conn, struct bt_hci_cp_le_set_tx_power_report_enable *cp; struct net_buf *buf; + if (!bt_conn_is_type(conn, BT_CONN_TYPE_LE)) { + LOG_DBG("Invalid connection type: %u for %p", conn->type, conn); + return -EINVAL; + } + buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_TX_POWER_REPORT_ENABLE, sizeof(*cp)); if (!buf) { return -ENOBUFS; @@ -3146,6 +3196,11 @@ int bt_conn_le_get_tx_power_level(struct bt_conn *conn, { int err; + if (!bt_conn_is_type(conn, BT_CONN_TYPE_LE)) { + LOG_DBG("Invalid connection type: %u for %p", conn->type, conn); + return -EINVAL; + } + if (tx_power_level->phy != 0) { if (IS_ENABLED(CONFIG_BT_TRANSMIT_POWER_CONTROL)) { return bt_conn_le_enhanced_get_tx_power_level(conn, tx_power_level); @@ -3191,6 +3246,11 @@ int bt_conn_le_set_path_loss_mon_param(struct bt_conn *conn, struct bt_hci_cp_le_set_path_loss_reporting_parameters *cp; struct net_buf *buf; + if (!bt_conn_is_type(conn, BT_CONN_TYPE_LE)) { + LOG_DBG("Invalid connection type: %u for %p", conn->type, conn); + return -EINVAL; + } + buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_PATH_LOSS_REPORTING_PARAMETERS, sizeof(*cp)); if (!buf) { return -ENOBUFS; @@ -3212,6 +3272,11 @@ int bt_conn_le_set_path_loss_mon_enable(struct bt_conn *conn, bool reporting_ena struct bt_hci_cp_le_set_path_loss_reporting_enable *cp; struct net_buf *buf; + if (!bt_conn_is_type(conn, BT_CONN_TYPE_LE)) { + LOG_DBG("Invalid connection type: %u for %p", conn->type, conn); + return -EINVAL; + } + buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_PATH_LOSS_REPORTING_ENABLE, sizeof(*cp)); if (!buf) { return -ENOBUFS; @@ -3308,6 +3373,11 @@ int bt_conn_le_subrate_request(struct bt_conn *conn, struct bt_hci_cp_le_subrate_request *cp; struct net_buf *buf; + if (!bt_conn_is_type(conn, BT_CONN_TYPE_LE)) { + LOG_DBG("Invalid connection type: %u for %p", conn->type, conn); + return -EINVAL; + } + if (!le_subrate_common_params_valid(params)) { return -EINVAL; } @@ -3454,6 +3524,11 @@ void notify_cs_subevent_result(struct bt_conn *conn, struct bt_conn_le_cs_subeve int bt_conn_le_param_update(struct bt_conn *conn, const struct bt_le_conn_param *param) { + if (!bt_conn_is_type(conn, BT_CONN_TYPE_LE)) { + LOG_DBG("Invalid connection type: %u for %p", conn->type, conn); + return -EINVAL; + } + LOG_DBG("conn %p features 0x%02x params (%d-%d %d %d)", conn, conn->le.features[0], param->interval_min, param->interval_max, param->latency, param->timeout); @@ -3483,6 +3558,11 @@ int bt_conn_le_param_update(struct bt_conn *conn, int bt_conn_le_data_len_update(struct bt_conn *conn, const struct bt_conn_le_data_len_param *param) { + if (!bt_conn_is_type(conn, BT_CONN_TYPE_LE)) { + LOG_DBG("Invalid connection type: %u for %p", conn->type, conn); + return -EINVAL; + } + if (conn->le.data_len.tx_max_len == param->tx_max_len && conn->le.data_len.tx_max_time == param->tx_max_time) { return -EALREADY; @@ -3498,6 +3578,11 @@ int bt_conn_le_phy_update(struct bt_conn *conn, { uint8_t phy_opts, all_phys; + if (!bt_conn_is_type(conn, BT_CONN_TYPE_LE)) { + LOG_DBG("Invalid connection type: %u for %p", conn->type, conn); + return -EINVAL; + } + if ((param->options & BT_CONN_LE_PHY_OPT_CODED_S2) && (param->options & BT_CONN_LE_PHY_OPT_CODED_S8)) { phy_opts = BT_HCI_LE_PHY_CODED_ANY; @@ -3972,7 +4057,8 @@ int bt_conn_auth_cb_register(const struct bt_conn_auth_cb *cb) #if defined(CONFIG_BT_SMP) int bt_conn_auth_cb_overlay(struct bt_conn *conn, const struct bt_conn_auth_cb *cb) { - CHECKIF(conn == NULL) { + if (!bt_conn_is_type(conn, BT_CONN_TYPE_LE | BT_CONN_TYPE_BR)) { + LOG_DBG("Invalid connection type: %u for %p", conn->type, conn); return -EINVAL; } @@ -4023,6 +4109,11 @@ int bt_conn_auth_info_cb_unregister(struct bt_conn_auth_info_cb *cb) int bt_conn_auth_passkey_entry(struct bt_conn *conn, unsigned int passkey) { + if (!bt_conn_is_type(conn, BT_CONN_TYPE_LE | BT_CONN_TYPE_BR)) { + LOG_DBG("Invalid connection type: %u for %p", conn->type, conn); + return -EINVAL; + } + if (IS_ENABLED(CONFIG_BT_SMP) && conn->type == BT_CONN_TYPE_LE) { return bt_smp_auth_passkey_entry(conn, passkey); } @@ -4042,7 +4133,12 @@ int bt_conn_auth_passkey_entry(struct bt_conn *conn, unsigned int passkey) int bt_conn_auth_keypress_notify(struct bt_conn *conn, enum bt_conn_auth_keypress type) { - if (IS_ENABLED(CONFIG_BT_SMP) && conn->type == BT_CONN_TYPE_LE) { + if (!bt_conn_is_type(conn, BT_CONN_TYPE_LE)) { + LOG_DBG("Invalid connection type: %u for %p", conn->type, conn); + return -EINVAL; + } + + if (IS_ENABLED(CONFIG_BT_SMP)) { return bt_smp_auth_keypress_notify(conn, type); } @@ -4053,6 +4149,11 @@ int bt_conn_auth_keypress_notify(struct bt_conn *conn, int bt_conn_auth_passkey_confirm(struct bt_conn *conn) { + if (!bt_conn_is_type(conn, BT_CONN_TYPE_LE | BT_CONN_TYPE_BR)) { + LOG_DBG("Invalid connection type: %u for %p", conn->type, conn); + return -EINVAL; + } + if (IS_ENABLED(CONFIG_BT_SMP) && conn->type == BT_CONN_TYPE_LE) { return bt_smp_auth_passkey_confirm(conn); } @@ -4070,6 +4171,11 @@ int bt_conn_auth_passkey_confirm(struct bt_conn *conn) int bt_conn_auth_cancel(struct bt_conn *conn) { + if (!bt_conn_is_type(conn, BT_CONN_TYPE_LE | BT_CONN_TYPE_BR)) { + LOG_DBG("Invalid connection type: %u for %p", conn->type, conn); + return -EINVAL; + } + if (IS_ENABLED(CONFIG_BT_SMP) && conn->type == BT_CONN_TYPE_LE) { return bt_smp_auth_cancel(conn); } @@ -4087,6 +4193,11 @@ int bt_conn_auth_cancel(struct bt_conn *conn) int bt_conn_auth_pairing_confirm(struct bt_conn *conn) { + if (!bt_conn_is_type(conn, BT_CONN_TYPE_LE | BT_CONN_TYPE_BR)) { + LOG_DBG("Invalid connection type: %u for %p", conn->type, conn); + return -EINVAL; + } + if (IS_ENABLED(CONFIG_BT_SMP) && conn->type == BT_CONN_TYPE_LE) { return bt_smp_auth_pairing_confirm(conn); } diff --git a/subsys/bluetooth/host/id.c b/subsys/bluetooth/host/id.c index 67f691dfa79..31b49bbc1b9 100644 --- a/subsys/bluetooth/host/id.c +++ b/subsys/bluetooth/host/id.c @@ -1,13 +1,15 @@ /* - * Copyright (c) 2017-2024 Nordic Semiconductor ASA + * Copyright (c) 2017-2025 Nordic Semiconductor ASA * Copyright (c) 2015-2016 Intel Corporation * * SPDX-License-Identifier: Apache-2.0 */ +#include #include #include +#include #include #include #include @@ -2133,7 +2135,12 @@ int bt_le_ext_adv_oob_get_local(struct bt_le_ext_adv *adv, #if !defined(CONFIG_BT_SMP_SC_PAIR_ONLY) int bt_le_oob_set_legacy_tk(struct bt_conn *conn, const uint8_t *tk) { - CHECKIF(conn == NULL || tk == NULL) { + if (!bt_conn_is_type(conn, BT_CONN_TYPE_LE)) { + LOG_DBG("Invalid connection type: %u for %p", conn->type, conn); + return -EINVAL; + } + + CHECKIF(tk == NULL) { return -EINVAL; } @@ -2146,7 +2153,8 @@ int bt_le_oob_set_sc_data(struct bt_conn *conn, const struct bt_le_oob_sc_data *oobd_local, const struct bt_le_oob_sc_data *oobd_remote) { - CHECKIF(conn == NULL) { + if (!bt_conn_is_type(conn, BT_CONN_TYPE_LE)) { + LOG_DBG("Invalid connection type: %u for %p", conn->type, conn); return -EINVAL; } @@ -2161,7 +2169,9 @@ int bt_le_oob_get_sc_data(struct bt_conn *conn, const struct bt_le_oob_sc_data **oobd_local, const struct bt_le_oob_sc_data **oobd_remote) { - CHECKIF(conn == NULL) { + if (!bt_conn_is_type(conn, BT_CONN_TYPE_LE)) { + LOG_ERR("Invalid connection: %p", conn); + LOG_ERR("Invalid connection type: %u for %p", conn->handle, conn); return -EINVAL; } diff --git a/subsys/bluetooth/host/smp.c b/subsys/bluetooth/host/smp.c index db936b28fdf..133ca08851e 100644 --- a/subsys/bluetooth/host/smp.c +++ b/subsys/bluetooth/host/smp.c @@ -4,7 +4,7 @@ */ /* - * Copyright (c) 2017 Nordic Semiconductor ASA + * Copyright (c) 2017-2025 Nordic Semiconductor ASA * Copyright (c) 2015-2016 Intel Corporation * * SPDX-License-Identifier: Apache-2.0 @@ -5441,6 +5441,11 @@ int bt_conn_set_bondable(struct bt_conn *conn, bool enable) { struct bt_smp *smp; + if (!bt_conn_is_type(conn, BT_CONN_TYPE_LE | BT_CONN_TYPE_BR)) { + LOG_DBG("Invalid connection type: %u for %p", conn->type, conn); + return -EINVAL; + } + if (IS_ENABLED(CONFIG_BT_CLASSIC) && (conn->type == BT_CONN_TYPE_BR)) { if (enable && atomic_test_and_set_bit(conn->flags, BT_CONN_BR_BONDABLE)) { return -EALREADY; diff --git a/tests/bluetooth/host/conn/CMakeLists.txt b/tests/bluetooth/host/conn/CMakeLists.txt index 23cf77fbd2f..2d3c317dec0 100644 --- a/tests/bluetooth/host/conn/CMakeLists.txt +++ b/tests/bluetooth/host/conn/CMakeLists.txt @@ -16,6 +16,10 @@ add_subdirectory(${ZEPHYR_BASE}/tests/bluetooth/host/conn/mocks mocks) target_link_libraries(testbinary PRIVATE mocks host_mocks) +target_include_directories(mocks PUBLIC + ${ZEPHYR_BASE}/subsys/bluetooth/host +) + target_sources(testbinary PRIVATE src/main.c diff --git a/tests/bluetooth/host/conn/src/main.c b/tests/bluetooth/host/conn/src/main.c index 95220dc3873..d4c800bd521 100644 --- a/tests/bluetooth/host/conn/src/main.c +++ b/tests/bluetooth/host/conn/src/main.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Nordic Semiconductor ASA + * Copyright (c) 2024-2025 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ @@ -9,6 +9,8 @@ #include #include +#include + #include "mocks/addr_internal.h" #include "mocks/att_internal.h" #include "mocks/bt_str.h" @@ -132,3 +134,29 @@ ZTEST(conn, test_bt_conn_le_create_synced_check_null_conn) err = bt_conn_le_create_synced(adv, &synced_param, &conn_param, &conn); zassert_not_equal(err, -EINVAL, "Failed starting initiator (err %d)", err); } + +ZTEST(conn, test_bt_conn_is_type) +{ + struct bt_conn conn = {0}; + + conn.type = BT_CONN_TYPE_LE; + zassert_true(bt_conn_is_type(&conn, BT_CONN_TYPE_LE)); + zassert_false(bt_conn_is_type(&conn, 0)); + zassert_false(bt_conn_is_type(&conn, BT_CONN_TYPE_BR)); + zassert_false(bt_conn_is_type(&conn, BT_CONN_TYPE_SCO)); + zassert_false(bt_conn_is_type(&conn, BT_CONN_TYPE_ISO)); + + zassert_true(bt_conn_is_type(&conn, BT_CONN_TYPE_LE | BT_CONN_TYPE_BR)); + zassert_true(bt_conn_is_type(&conn, BT_CONN_TYPE_LE | BT_CONN_TYPE_SCO)); + zassert_true(bt_conn_is_type(&conn, BT_CONN_TYPE_LE | BT_CONN_TYPE_ISO)); + zassert_true(bt_conn_is_type(&conn, BT_CONN_TYPE_ALL)); + + conn.type = BT_CONN_TYPE_BR; + zassert_true(bt_conn_is_type(&conn, BT_CONN_TYPE_BR)); + + conn.type = BT_CONN_TYPE_SCO; + zassert_true(bt_conn_is_type(&conn, BT_CONN_TYPE_SCO)); + + conn.type = BT_CONN_TYPE_ISO; + zassert_true(bt_conn_is_type(&conn, BT_CONN_TYPE_ISO)); +} diff --git a/tests/bluetooth/host/id/mocks/conn.c b/tests/bluetooth/host/id/mocks/conn.c index 14b18da99c4..99796076e01 100644 --- a/tests/bluetooth/host/id/mocks/conn.c +++ b/tests/bluetooth/host/id/mocks/conn.c @@ -1,14 +1,20 @@ /* - * Copyright (c) 2022 Nordic Semiconductor ASA + * Copyright (c) 2022-2025 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ -#include "mocks/conn.h" - +#include #include +#include "mocks/conn.h" + DEFINE_FAKE_VOID_FUNC(bt_conn_unref, struct bt_conn *); DEFINE_FAKE_VALUE_FUNC(int, bt_le_create_conn_cancel); DEFINE_FAKE_VALUE_FUNC(struct bt_conn *, bt_conn_lookup_state_le, uint8_t, const bt_addr_le_t *, const bt_conn_state_t); + +bool bt_conn_is_type(const struct bt_conn *conn, enum bt_conn_type type) +{ + return true; +} diff --git a/tests/bluetooth/host/id/mocks/conn.h b/tests/bluetooth/host/id/mocks/conn.h index 4cfbe8d4e33..1d2da0a4106 100644 --- a/tests/bluetooth/host/id/mocks/conn.h +++ b/tests/bluetooth/host/id/mocks/conn.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Nordic Semiconductor ASA + * Copyright (c) 2022-2025 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ @@ -20,3 +20,4 @@ DECLARE_FAKE_VOID_FUNC(bt_conn_unref, struct bt_conn *); DECLARE_FAKE_VALUE_FUNC(int, bt_le_create_conn_cancel); DECLARE_FAKE_VALUE_FUNC(struct bt_conn *, bt_conn_lookup_state_le, uint8_t, const bt_addr_le_t *, const bt_conn_state_t); +DECLARE_FAKE_VALUE_FUNC(bool, bt_conn_is_type, const struct bt_conn *, enum bt_conn_type);