From: Ayush Garg Date: Tue, 29 Aug 2023 10:05:36 +0000 (+0530) Subject: BT 5.0: Implement CAPIs for read/set phy X-Git-Tag: accepted/tizen/unified/20230911.091135~2^2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=2569d7f0b8351071ffe2d0deaa4a4ed4b8a25696;p=platform%2Fcore%2Fapi%2Fbluetooth.git BT 5.0: Implement CAPIs for read/set phy This patch adds following APIs: 1. bt_gatt_client_read_phy() 2. bt_gatt_client_set_phy() 3. bt_gatt_client_set_phy_update_cb() 4. bt_gatt_client_unset_phy_update_cb() 5. bt_gatt_server_read_phy() 6. bt_gatt_server_set_phy() 7. bt_gatt_server_set_phy_update_cb() 8. bt_gatt_server_unset_phy_update_cb() Change-Id: Ica0b1850b7c3e84086bed2e7b9a35866271626d6 Signed-off-by: Ayush Garg --- diff --git a/include/bluetooth_internal.h b/include/bluetooth_internal.h index d28faf4..bf3c94e 100644 --- a/include/bluetooth_internal.h +++ b/include/bluetooth_internal.h @@ -2519,6 +2519,183 @@ int bt_gatt_server_set_characteristic_notif_state_change_cb(bt_gatt_h gatt_handl */ int bt_gatt_destroy(bt_gatt_h gatt_handle); +/** + * @ingroup CAPI_NETWORK_BLUETOOTH_GATT_SERVER_MODULE + * @brief Gets the PHY values set for a connection. + * @since_tizen 8.0 + * + * @param[in] server The created GATT server's handle + * @param[in] remote_address The address of the remote Bluetooth device. + * @param[in] callback The callback function to get the PHY values in + * @param[in] user_data The user data to be passed to the callback function + * + * @return 0 on success, otherwise a negative error value. + * @retval #BT_ERROR_NONE Successful + * @retval #BT_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #BT_ERROR_NOT_INITIALIZED Not initialized + * @retval #BT_ERROR_NOT_ENABLED Not enabled + * @retval #BT_ERROR_OPERATION_FAILED Operation failed + * @retval #BT_ERROR_NOT_SUPPORTED Not supported + * @retval #BT_ERROR_REMOTE_DEVICE_NOT_CONNECTED Remote device is not connected + * @see bt_gatt_server_phy_read_cb() + */ +int bt_gatt_server_read_phy(bt_gatt_server_h server, const char *remote_address, + bt_gatt_server_phy_read_cb callback, void *user_data); + +/** + * @ingroup CAPI_NETWORK_BLUETOOTH_GATT_SERVER_MODULE + * @brief request a change of the PHY values. + * @since_tizen 8.0 + * @privlevel public + * @privilege %http://tizen.org/privilege/bluetooth + * + * @param[in] server The created GATT server's handle + * @param[in] remote_address The address of the remote Bluetooth device. + * @param[in] tx_phy The preferred sender PHY + * @param[in] rx_phy The preferred receiver PHY + * @param[in] phy_options The preferred coding to use when transmitting on LE CODED PHY + * + * @return 0 on success, otherwise a negative error value. + * @retval #BT_ERROR_NONE Successful + * @retval #BT_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #BT_ERROR_NOT_INITIALIZED Not initialized + * @retval #BT_ERROR_NOT_ENABLED Not enabled + * @retval #BT_ERROR_OPERATION_FAILED Operation failed + * @retval #BT_ERROR_PERMISSION_DENIED Permission denied + * @retval #BT_ERROR_NOT_SUPPORTED Not supported + * @retval #BT_ERROR_REMOTE_DEVICE_NOT_CONNECTED Remote device is not connected + * @see bt_gatt_server_set_phy_update_cb() + */ +int bt_gatt_server_set_phy(bt_gatt_server_h server, const char *remote_address, + int tx_phy, int rx_phy, int phy_options); + +/** + * @ingroup CAPI_NETWORK_BLUETOOTH_GATT_SERVER_MODULE + * @brief Registers a callback function to be invoked when the PHY is changed. + * @since_tizen 8.0 + * @param[in] server The created GATT server's handle + * @param[in] callback The callback function to register + * @param[in] user_data The user data to be passed to the callback function + * @return 0 on success, otherwise a negative error value. + * @retval #BT_ERROR_NONE Successful + * @retval #BT_ERROR_NOT_INITIALIZED Not initialized + * @retval #BT_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #BT_ERROR_NOT_SUPPORTED Not supported + * + * @pre The Bluetooth service must be initialized with bt_initialize(). + * @post bt_device_connection_state_changed_cb() will be invoked. + * @see bt_initialize() + * @see bt_gatt_server_initialize() + * @see bt_gatt_server_create() + * @see bt_gatt_server_unset_phy_update_cb() + */ +int bt_gatt_server_set_phy_update_cb(bt_gatt_server_h server, + bt_gatt_server_phy_update_cb callback, void *user_data); + +/** + * @ingroup CAPI_NETWORK_BLUETOOTH_GATT_SERVER_MODULE + * @brief Unregisters the callback function to be invoked when the PHY is changed. + * @since_tizen 8.0 + * @param[in] server The created GATT server's handle + * @return 0 on success, otherwise a negative error value. + * @retval #BT_ERROR_NONE Successful + * @retval #BT_ERROR_NOT_INITIALIZED Not initialized + * @retval #BT_ERROR_NOT_SUPPORTED Not supported + * + * @pre The Bluetooth service must be initialized with bt_initialize(). + * @see bt_initialize() + * @see bt_gatt_server_set_phy_update_cb() + */ +int bt_gatt_server_unset_phy_update_cb(bt_gatt_server_h server); + +/** + * @ingroup CAPI_NETWORK_BLUETOOTH_GATT_CLIENT_MODULE + * @brief Gets the PHY values set for a connection. + * @since_tizen 8.0 + * + * @param[in] client The created GATT client's handle + * @param[in] callback The callback function to get the PHY values in + * @param[in] user_data The user data to be passed to the callback function + * + * @return 0 on success, otherwise a negative error value. + * @retval #BT_ERROR_NONE Successful + * @retval #BT_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #BT_ERROR_NOT_INITIALIZED Not initialized + * @retval #BT_ERROR_NOT_ENABLED Not enabled + * @retval #BT_ERROR_OPERATION_FAILED Operation failed + * @retval #BT_ERROR_NOT_SUPPORTED Not supported + * @retval #BT_ERROR_REMOTE_DEVICE_NOT_CONNECTED Remote device is not connected + * @see bt_gatt_client_phy_read_cb() + */ +int bt_gatt_client_read_phy(bt_gatt_client_h client, + bt_gatt_client_phy_read_cb callback, void *user_data); + +/** + * @ingroup CAPI_NETWORK_BLUETOOTH_GATT_CLIENT_MODULE + * @brief request a change of the PHY values. + * @since_tizen 8.0 + * @privlevel public + * @privilege %http://tizen.org/privilege/bluetooth + * + * @param[in] client The created GATT client's handle + * @param[in] tx_phy The preferred sender PHY + * @param[in] rx_phy The preferred receiver PHY + * @param[in] phy_options The preferred coding to use when transmitting on LE CODED PHY + * + * @return 0 on success, otherwise a negative error value. + * @retval #BT_ERROR_NONE Successful + * @retval #BT_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #BT_ERROR_NOT_INITIALIZED Not initialized + * @retval #BT_ERROR_NOT_ENABLED Not enabled + * @retval #BT_ERROR_OPERATION_FAILED Operation failed + * @retval #BT_ERROR_PERMISSION_DENIED Permission denied + * @retval #BT_ERROR_NOT_SUPPORTED Not supported + * @retval #BT_ERROR_REMOTE_DEVICE_NOT_CONNECTED Remote device is not connected + * @see bt_gatt_client_set_phy_update_cb() + */ +int bt_gatt_client_set_phy(bt_gatt_client_h client, int tx_phy, int rx_phy, + int phy_options); + +/** + * @ingroup CAPI_NETWORK_BLUETOOTH_GATT_CLIENT_MODULE + * @brief Registers a callback function to be invoked when the PHY is changed. + * @since_tizen 8.0 + * @param[in] client The created GATT client's handle + * @param[in] callback The callback function to register + * @param[in] user_data The user data to be passed to the callback function + * @return 0 on success, otherwise a negative error value. + * @retval #BT_ERROR_NONE Successful + * @retval #BT_ERROR_NOT_INITIALIZED Not initialized + * @retval #BT_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #BT_ERROR_NOT_SUPPORTED Not supported + * + * @pre The Bluetooth service must be initialized with bt_initialize(). + * @post bt_device_connection_state_changed_cb() will be invoked. + * @see bt_initialize() + * @see bt_gatt_client_set_phy() + * @see bt_gatt_client_unset_phy_update_cb() + */ +int bt_gatt_client_set_phy_update_cb(bt_gatt_client_h client, + bt_gatt_client_phy_update_cb callback, void *user_data); + +/** + * @ingroup CAPI_NETWORK_BLUETOOTH_GATT_CLIENT_MODULE + * @brief Unregisters the callback function to be invoked when the PHY is changed. + * @since_tizen 8.0 + * @param[in] client The created GATT client's handle + * @return 0 on success, otherwise a negative error value. + * @retval #BT_ERROR_NONE Successful + * @retval #BT_ERROR_NOT_INITIALIZED Not initialized + * @retval #BT_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #BT_ERROR_NOT_SUPPORTED Not supported + * + * @pre The Bluetooth service must be initialized with bt_initialize(). + * @see bt_initialize() + * @see bt_gatt_client_set_phy() + * @see bt_gatt_client_set_phy_update_cb() + */ +int bt_gatt_client_unset_phy_update_cb(bt_gatt_client_h client); + /** * @ingroup CAPI_NETWORK_BLUETOOTH_GATT_SERVER_MODULE * @brief Registers a callback function to be invoked when the ATT MTU is changed. diff --git a/include/bluetooth_private.h b/include/bluetooth_private.h index 2bf9a9a..9c6fb52 100644 --- a/include/bluetooth_private.h +++ b/include/bluetooth_private.h @@ -365,6 +365,10 @@ typedef struct { bt_gatt_server_connection_state_changed_cb server_connection_change_cb; void *connection_change_user_data; void *att_mtu_changed_user_data; + bt_gatt_server_phy_update_cb phy_update_cb; + void *phy_update_user_data; + bt_gatt_server_phy_read_cb phy_read_cb; + void *phy_read_user_data; } bt_gatt_server_s; typedef struct { @@ -383,6 +387,10 @@ typedef struct { #ifdef TIZEN_GATT_CLIENT int client_id; #endif + bt_gatt_client_phy_update_cb phy_update_cb; + void *phy_update_user_data; + bt_gatt_client_phy_read_cb phy_read_cb; + void *phy_read_user_data; } bt_gatt_client_s; typedef struct { diff --git a/include/bluetooth_type_internal.h b/include/bluetooth_type_internal.h index 1c3d7a4..765770f 100644 --- a/include/bluetooth_type_internal.h +++ b/include/bluetooth_type_internal.h @@ -406,6 +406,28 @@ typedef enum { BT_LE_CODED_PHY = 0x03 } bt_adapter_le_phy_e; +/** +* @ingroup CAPI_NETWORK_BLUETOOTH_ADAPTER_LE_MODULE +* @since_tizen 8.0 +* @brief Enumerations of the Bluetooth LE phy mask. +*/ +typedef enum { + BT_LE_1M_PHY_MASK = 0x01, + BT_LE_2M_PHY_MASK = 0x02, + BT_LE_CODED_PHY_MASK = 0x04 +} bt_adapter_le_phy_mask_e; + +/** +* @ingroup CAPI_NETWORK_BLUETOOTH_ADAPTER_LE_MODULE +* @since_tizen 8.0 +* @brief Enumerations of the preferred coding when transmitting on LE CODED PHY. +*/ +typedef enum { + PHY_OPTION_NO_PREFERRED = 0x00, + PHY_OPTION_S2 = 0x01, + PHY_OPTION_S8 = 0x02 +} bt_adapter_le_phy_option_e; + /** * @ingroup CAPI_NETWORK_BLUETOOTH_ADAPTER_MODULE * @brief Called when the manufacturer dat changes. @@ -727,6 +749,87 @@ typedef void (*bt_gatt_server_att_mtu_changed_cb)(bt_gatt_server_h server, const bt_gatt_server_att_mtu_info_s *mtu_info, void *user_data); +/** + * @ingroup CAPI_NETWORK_BLUETOOTH_DEVICE_MODULE + * @brief PHY change information structure. + * @since_tizen 8.0 + * + * @see bt_gatt_server_phy_update_cb() + * @see bt_gatt_server_phy_read_cb() + * @see bt_gatt_client_phy_update_cb() + * @see bt_gatt_client_phy_read_cb() + */ +typedef struct { + char *remote_address; /**< The address of remote device */ + int tx_phy; /**< The transmitter PHY in use */ + int rx_phy; /**< The receiver PHY in use */ + int status; /**< Status of the PHY operation */ +} bt_gatt_phy_info_s; + +/** + * @ingroup CAPI_NETWORK_BLUETOOTH_GATT_SERVER_MODULE + * @brief This callback will be invoked as a result of bt_gatt_server_set_phy(), or as a result of remote device changing the PHY. + * @since_tizen 8.0 + * + * @remarks The @a phy_info must not be freed by application. + * @a phy_info can be used only inside the callback. + * If it's needed outside, make a copy. + * + * @param[in] server The handle of a GATT server + * @param[in] phy_info The PHY information + * @param[in] user_data The user data passed from the callback registration function + */ +typedef void (*bt_gatt_server_phy_update_cb) (bt_gatt_server_h server, + const bt_gatt_phy_info_s *phy_info, void *user_data); + +/** + * @ingroup CAPI_NETWORK_BLUETOOTH_GATT_SERVER_MODULE + * @brief This callback will be invoked as a result of bt_gatt_server_read_phy(). + * @since_tizen 8.0 + * + * @remarks The @a phy_info must not be freed by application. + * @a phy_info can be used only inside the callback. + * If it's needed outside, make a copy. + * + * @param[in] server The handle of a GATT server + * @param[in] phy_info The PHY information + * @param[in] user_data The user data passed from the callback registration function + */ +typedef void (*bt_gatt_server_phy_read_cb) (bt_gatt_server_h server, + const bt_gatt_phy_info_s *phy_info, void *user_data); + +/** + * @ingroup CAPI_NETWORK_BLUETOOTH_GATT_CLIENT_MODULE + * @brief This callback will be invoked as a result of bt_gatt_client_set_phy(), or as a result of remote device changing the PHY. + * @since_tizen 8.0 + * + * @remarks The @a phy_info must not be freed by application. + * @a phy_info can be used only inside the callback. + * If it's needed outside, make a copy. + * + * @param[in] client The created GATT client's handle + * @param[in] phy_info The PHY information + * @param[in] user_data The user data passed from the callback registration function + */ +typedef void (*bt_gatt_client_phy_update_cb) (bt_gatt_client_h client, + const bt_gatt_phy_info_s *phy_info, void *user_data); + +/** + * @ingroup CAPI_NETWORK_BLUETOOTH_GATT_CLIENT_MODULE + * @brief This callback will be invoked as a result of bt_gatt_client_read_phy(). + * @since_tizen 8.0 + * + * @remarks The @a phy_info must not be freed by application. + * @a phy_info can be used only inside the callback. + * If it's needed outside, make a copy. + * + * @param[in] client The created GATT client's handle + * @param[in] phy_info The PHY information + * @param[in] user_data The user data passed from the callback registration function + */ +typedef void (*bt_gatt_client_phy_read_cb) (bt_gatt_client_h client, + const bt_gatt_phy_info_s *phy_info, void *user_data); + /** * @ingroup CAPI_NETWORK_BLUETOOTH_GATT_MODULE * @brief Called when the connection state is changed. diff --git a/src/bluetooth-common.c b/src/bluetooth-common.c index 2c1455b..de2fcb6 100644 --- a/src/bluetooth-common.c +++ b/src/bluetooth-common.c @@ -922,6 +922,26 @@ static int __bt_get_bt_gatt_server_att_mtu_info_s(bt_gatt_server_att_mtu_info_s return BT_ERROR_NONE; } +static int __bt_get_bt_gatt_phy_info_s(bt_gatt_phy_info_s **dest, bluetooth_le_phy_info_t *source) +{ + BT_CHECK_INPUT_PARAMETER(source); + + *dest = (bt_gatt_phy_info_s *)g_malloc0(sizeof(bt_gatt_phy_info_s)); + + if (_bt_convert_address_to_string(&((*dest)->remote_address), &(source->device_address)) != BT_ERROR_NONE) { + g_free(*dest); + *dest = NULL; + return BT_ERROR_OUT_OF_MEMORY; + } + + (*dest)->tx_phy = source->tx_phy; + (*dest)->rx_phy = source->rx_phy; + (*dest)->status = source->status; + + return BT_ERROR_NONE; +} + + static int __bt_get_bt_device_connection_info_s(bt_device_connection_info_s **dest, bt_connection_info_t *source) { *dest = (bt_device_connection_info_s *)g_malloc0(sizeof(bt_device_connection_info_s)); @@ -1516,6 +1536,10 @@ static bool __bt_need_to_handle(int event) case BLUETOOTH_EVENT_GATT_WRITE_CHAR: case BLUETOOTH_EVENT_GATT_READ_DESC: case BLUETOOTH_EVENT_GATT_WRITE_DESC: + case BLUETOOTH_EVENT_GATT_SERVER_PHY_READ: + case BLUETOOTH_EVENT_GATT_SERVER_PHY_UPDATED: + case BLUETOOTH_EVENT_GATT_CLIENT_PHY_READ: + case BLUETOOTH_EVENT_GATT_CLIENT_PHY_UPDATED: /* Mesh Events */ case BLUETOOTH_EVENT_MESH_SCAN_STARTED: case BLUETOOTH_EVENT_MESH_SCAN_FINISHED: @@ -3366,6 +3390,118 @@ static void __bt_event_proxy(int event, bluetooth_event_param_t *param, void *us g_free(mtu_info); break; } + case BLUETOOTH_EVENT_GATT_SERVER_PHY_READ: { + const GSList *gatt_server_list = NULL; + const GSList *l1; + bt_gatt_phy_info_s *phy_info = NULL; + + BT_INFO("BLUETOOTH_EVENT_GATT_SERVER_PHY_READ"); + + if (__bt_get_bt_gatt_phy_info_s(&phy_info, + (bluetooth_le_phy_info_t *)(param->param_data)) != BT_ERROR_NONE) { + BT_ERR("Fail to read PHY info"); + break; + } + + if (phy_info == NULL) + break; + + gatt_server_list = _bt_gatt_get_server_list(); + + for (l1 = gatt_server_list; l1 != NULL; l1 = l1->next) { + bt_gatt_server_s *serv = l1->data; + + if (!serv || !(serv->phy_read_cb)) + continue; + + BT_INFO("PHY read callback"); + serv->phy_read_cb(serv, (const bt_gatt_phy_info_s *)phy_info, + serv->phy_read_user_data); + } + + g_free(phy_info); + break; + } + case BLUETOOTH_EVENT_GATT_SERVER_PHY_UPDATED: { + const GSList *gatt_server_list = NULL; + const GSList *l1; + bt_gatt_phy_info_s *phy_info = NULL; + + BT_INFO("BLUETOOTH_EVENT_GATT_SERVER_PHY_UPDATED"); + + if (__bt_get_bt_gatt_phy_info_s(&phy_info, + (bluetooth_le_phy_info_t *)(param->param_data)) != BT_ERROR_NONE) { + BT_ERR("Fail to get PHY info"); + break; + } + + if (phy_info == NULL) + break; + + gatt_server_list = _bt_gatt_get_server_list(); + + for (l1 = gatt_server_list; l1 != NULL; l1 = l1->next) { + bt_gatt_server_s *serv = l1->data; + + if (!serv || !(serv->phy_update_cb)) + continue; + + BT_INFO("PHY update callback"); + serv->phy_update_cb(serv, (const bt_gatt_phy_info_s *)phy_info, + serv->phy_update_user_data); + } + + g_free(phy_info); + break; + } + case BLUETOOTH_EVENT_GATT_CLIENT_PHY_READ: { + bt_gatt_phy_info_s *phy_info = NULL; + bt_gatt_client_s *client = NULL; + + BT_INFO("BLUETOOTH_EVENT_GATT_CLIENT_PHY_READ"); + + if (__bt_get_bt_gatt_phy_info_s(&phy_info, + (bluetooth_le_phy_info_t *)(param->param_data)) != BT_ERROR_NONE) { + BT_ERR("Fail to get PHY info"); + break; + } + + if (phy_info == NULL) + break; + + client = _bt_gatt_get_client(phy_info->remote_address); + + if (client && client->connected && client->phy_read_cb) + client->phy_read_cb(client, (const bt_gatt_phy_info_s *)phy_info, + client->phy_read_user_data); + + g_free(phy_info); + break; + } + case BLUETOOTH_EVENT_GATT_CLIENT_PHY_UPDATED: { + bt_gatt_phy_info_s *phy_info = NULL; + bt_gatt_client_s *client = NULL; + + BT_INFO("BLUETOOTH_EVENT_GATT_CLIENT_PHY_UPDATED"); + + if (__bt_get_bt_gatt_phy_info_s(&phy_info, + (bluetooth_le_phy_info_t *)(param->param_data)) != BT_ERROR_NONE) { + BT_ERR("Fail to get PHY info"); + break; + } + + if (phy_info == NULL) + break; + + client = _bt_gatt_get_client(phy_info->remote_address); + + if (client && client->connected && client->phy_update_cb) + client->phy_update_cb(client, (const bt_gatt_phy_info_s *)phy_info, + client->phy_update_user_data); + + g_free(phy_info); + break; + } case BLUETOOTH_EVENT_LE_DATA_LENGTH_CHANGED: BT_INFO("__bt_le_set_data_length_changed_cb() will be called"); data_length_info = (bt_le_data_length_params_t *)(param->param_data); diff --git a/src/bluetooth-gatt.c b/src/bluetooth-gatt.c index adcf1cf..ce0acd1 100644 --- a/src/bluetooth-gatt.c +++ b/src/bluetooth-gatt.c @@ -78,6 +78,18 @@ struct notify_char_changed_cb_s { BT_CHECK_SUPPORTED_FEATURE(BT_FEATURE_GATT_CLIENT); \ } +#define BT_CHECK_GATT_SERVER_PHY_SUPPORT() \ +{ \ + BT_CHECK_GATT_SERVER_SUPPORT(); \ + BT_CHECK_SUPPORTED_FEATURE(BT_FEATURE_LE_5_0); \ +} + +#define BT_CHECK_GATT_CLIENT_PHY_SUPPORT() \ +{ \ + BT_CHECK_GATT_CLIENT_SUPPORT(); \ + BT_CHECK_SUPPORTED_FEATURE(BT_FEATURE_LE_5_0); \ +} + #define BT_CHECK_GATT_SERVER_INIT_STATUS() { \ if (__bt_check_gatt_server_init_status() == BT_ERROR_NOT_INITIALIZED) { \ LOGE("[%s] NOT_INITIALIZED(0x%08x)", __FUNCTION__, \ @@ -86,6 +98,22 @@ struct notify_char_changed_cb_s { } \ } +#define BT_CHECK_PHY_PARAMS(phy) { \ + if (!__bt_gatt_is_phy_valid(phy)) { \ + LOGE("[%s] INVALID_PARAMETER(0x%08x)", __FUNCTION__, \ + BT_ERROR_INVALID_PARAMETER); \ + return BT_ERROR_INVALID_PARAMETER; \ + } \ +} + +#define BT_CHECK_PHY_OPTIONS(phy_option) { \ + if (!__bt_gatt_is_phy_options_valid(phy_option)) { \ + LOGE("[%s] INVALID_PARAMETER(0x%08x)", __FUNCTION__, \ + BT_ERROR_INVALID_PARAMETER); \ + return BT_ERROR_INVALID_PARAMETER; \ + } \ +} + #define BT_VALIDATE_GATT_HANDLE(h1) \ { \ GSList *l; \ @@ -3613,6 +3641,124 @@ int bt_gatt_server_get_device_mtu(const char *remote_address, unsigned int *mtu) return ret; } /* LCOV_EXCL_STOP */ +static bool __bt_gatt_is_phy_options_valid(int phy_options) +{ + if (phy_options < PHY_OPTION_NO_PREFERRED || + phy_options > PHY_OPTION_S8) + return false; + + return true; +} + +static bool __bt_gatt_is_phy_valid(int phy) +{ + if (phy | BT_LE_2M_PHY_MASK) { + bool is_2m_phy_supported = false; + int ret = bt_adapter_le_is_2m_phy_supported(&is_2m_phy_supported); + if (!ret || !is_2m_phy_supported) + return false; + } + + if (phy | BT_LE_CODED_PHY_MASK) { + bool is_coded_phy_supported = false; + int ret = bt_adapter_le_is_coded_phy_supported(&is_coded_phy_supported); + if (!ret || !is_coded_phy_supported) + return false; + } + + return true; +} + +int bt_gatt_server_read_phy(bt_gatt_server_h server, const char *remote_address, + bt_gatt_server_phy_read_cb callback, void *user_data) +{ + int ret; + bluetooth_device_address_t addr_hex = { {0,} }; + bt_gatt_server_s *server_s = (bt_gatt_server_s *)server; + + BT_CHECK_GATT_SERVER_PHY_SUPPORT(); + BT_CHECK_INIT_STATUS(); + + BT_CHECK_INPUT_PARAMETER(server); + BT_CHECK_INPUT_PARAMETER(callback); + BT_CHECK_INPUT_PARAMETER(remote_address); + + _bt_convert_address_to_hex(&addr_hex, remote_address); + + ret = _bt_get_error_code(bluetooth_gatt_server_read_phy(&addr_hex)); + + if (ret != BT_ERROR_NONE) { + BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(ret), ret); + return ret; + } + + server_s->phy_read_cb = callback; + server_s->phy_read_user_data = user_data; + + return ret; +} + +int bt_gatt_server_set_phy(bt_gatt_server_h server, const char *remote_address, + int tx_phy, int rx_phy, int phy_options) +{ + int ret; + bluetooth_device_address_t addr_hex = { {0,} }; + + BT_CHECK_GATT_SERVER_PHY_SUPPORT(); + BT_CHECK_INIT_STATUS(); + + BT_CHECK_INPUT_PARAMETER(server); + BT_CHECK_INPUT_PARAMETER(remote_address); + + BT_CHECK_PHY_PARAMS(tx_phy); + BT_CHECK_PHY_PARAMS(rx_phy); + BT_CHECK_PHY_OPTIONS(phy_options); + + _bt_convert_address_to_hex(&addr_hex, remote_address); + + ret = _bt_get_error_code(bluetooth_gatt_server_set_phy(&addr_hex, tx_phy, rx_phy, phy_options)); + if (BT_ERROR_NONE != ret) + BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(ret), ret); + + return ret; +} + +int bt_gatt_server_set_phy_update_cb(bt_gatt_server_h server, + bt_gatt_server_phy_update_cb callback, void *user_data) +{ + bt_gatt_server_s *server_s = (bt_gatt_server_s *)server; + + BT_CHECK_GATT_SERVER_PHY_SUPPORT(); + BT_CHECK_INIT_STATUS(); + BT_CHECK_INPUT_PARAMETER(callback); + BT_CHECK_INPUT_PARAMETER(server); + + if (server_s->phy_update_cb) + BT_INFO("Gatt Server PHY Update already registered"); + else + BT_INFO("Gatt Server PHY Update callback registered"); + + server_s->phy_update_cb = callback; + server_s->phy_update_user_data = user_data; + + return BT_ERROR_NONE; +} + +int bt_gatt_server_unset_phy_update_cb(bt_gatt_server_h server) +{ + bt_gatt_server_s *server_s = (bt_gatt_server_s *)server; + + BT_CHECK_GATT_SERVER_PHY_SUPPORT(); + BT_CHECK_INIT_STATUS(); + BT_CHECK_INPUT_PARAMETER(server); + + BT_INFO("Gatt Server PHY Update callback unregistered"); + server_s->phy_update_cb = NULL; + server_s->phy_update_user_data = NULL; + + return BT_ERROR_NONE; +} + int bt_gatt_server_foreach_services(bt_gatt_server_h server, bt_gatt_foreach_cb callback, void *user_data) { @@ -5427,3 +5573,92 @@ int bt_gatt_get_uuid_specification_name(const char *uuid, char **name) return BT_ERROR_NONE; } /* LCOV_EXCL_STOP */ + +int bt_gatt_client_read_phy(bt_gatt_client_h client, + bt_gatt_client_phy_read_cb callback, void *user_data) +{ + int ret; + bluetooth_device_address_t addr_hex = { {0,} }; + bt_gatt_client_s *client_s = (bt_gatt_client_s *)client; + + BT_CHECK_GATT_CLIENT_PHY_SUPPORT(); + BT_CHECK_INIT_STATUS(); + + BT_CHECK_INPUT_PARAMETER(client); + BT_CHECK_INPUT_PARAMETER(callback); + + _bt_convert_address_to_hex(&addr_hex, client_s->remote_address); + + ret = _bt_get_error_code(bluetooth_gatt_client_read_phy(&addr_hex)); + + if (ret != BT_ERROR_NONE) { + BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(ret), ret); + return ret; + } + + client_s->phy_read_cb = callback; + client_s->phy_read_user_data = user_data; + + return ret; +} + +int bt_gatt_client_set_phy(bt_gatt_client_h client, int tx_phy, int rx_phy, + int phy_options) +{ + int ret; + bluetooth_device_address_t addr_hex = { {0,} }; + bt_gatt_client_s *client_s = (bt_gatt_client_s *)client; + + BT_CHECK_GATT_CLIENT_PHY_SUPPORT(); + BT_CHECK_INIT_STATUS(); + BT_CHECK_INPUT_PARAMETER(client); + + BT_CHECK_PHY_PARAMS(tx_phy); + BT_CHECK_PHY_PARAMS(rx_phy); + BT_CHECK_PHY_OPTIONS(phy_options); + + _bt_convert_address_to_hex(&addr_hex, client_s->remote_address); + + ret = _bt_get_error_code(bluetooth_gatt_client_set_phy(&addr_hex, + tx_phy, rx_phy, phy_options)); + if (BT_ERROR_NONE != ret) + BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(ret), ret); + + return ret; +} + +int bt_gatt_client_set_phy_update_cb(bt_gatt_client_h client, + bt_gatt_client_phy_update_cb callback, void *user_data) +{ + bt_gatt_client_s *client_s = (bt_gatt_client_s *)client; + + BT_CHECK_GATT_CLIENT_PHY_SUPPORT(); + BT_CHECK_INIT_STATUS(); + BT_CHECK_INPUT_PARAMETER(callback); + BT_CHECK_INPUT_PARAMETER(client); + + if (client_s->phy_update_cb) + BT_INFO("Gatt Client PHY Update already registered"); + else + BT_INFO("Gatt Client PHY Update callback registered"); + + client_s->phy_update_cb = callback; + client_s->phy_update_user_data = user_data; + + return BT_ERROR_NONE; +} + +int bt_gatt_client_unset_phy_update_cb(bt_gatt_client_h client) +{ + bt_gatt_client_s *client_s = (bt_gatt_client_s *)client; + + BT_CHECK_GATT_CLIENT_PHY_SUPPORT(); + BT_CHECK_INIT_STATUS(); + BT_CHECK_INPUT_PARAMETER(client); + + BT_INFO("Gatt Client PHY Update callback unregistered"); + client_s->phy_update_cb = NULL; + client_s->phy_update_user_data = NULL; + + return BT_ERROR_NONE; +}