BT 5.0: Implement CAPIs for read/set phy 06/298106/1
authorAyush Garg <ayush.garg@samsung.com>
Tue, 29 Aug 2023 10:05:36 +0000 (15:35 +0530)
committerAyush Garg <ayush.garg@samsung.com>
Thu, 31 Aug 2023 15:29:55 +0000 (20:59 +0530)
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 <ayush.garg@samsung.com>
include/bluetooth_internal.h
include/bluetooth_private.h
include/bluetooth_type_internal.h
src/bluetooth-common.c
src/bluetooth-gatt.c

index d28faf44ebb112255d3fc1f3410397d64aeebe14..bf3c94ec200524949dfec600e43b1f5d808a2556 100644 (file)
@@ -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.
index 2bf9a9ae0e20e7341f59f5a900bb3320535be2e6..9c6fb529272c49bcff38d4b741eaf48449e53bdd 100644 (file)
@@ -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 {
index 1c3d7a4cae83dde449ce9e3b34613845dc998c57..765770fcf3cc59bd82d073794ff29310912ac0d7 100644 (file)
@@ -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.
index 2c1455bac4c303b1800bafb0dc0ef7e3cbc883a3..de2fcb620c1886f431e186ae1643cd2c9462640c 100644 (file)
@@ -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);
index adcf1cfa872f90c9dcca16b5f935127a6d764709..ce0acd111a1187d8e885621f5641fa2bba83c852 100644 (file)
@@ -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;
+}