فهرست منبع

Merge branch 'feature/add_bt_set_page_timeout_api' into 'master'

Feat(bt/bluedroid): Add new apis for bluetooth to set and get page timeout

Closes BT-3392

See merge request espressif/esp-idf!25351
Wang Meng Yang 2 سال پیش
والد
کامیت
0f852ec0da

+ 36 - 1
components/bt/host/bluedroid/api/esp_gap_bt_api.c

@@ -1,5 +1,5 @@
 /*
- * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
+ * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
  *
  * SPDX-License-Identifier: Apache-2.0
  */
@@ -420,4 +420,39 @@ esp_err_t esp_bt_gap_set_qos(esp_bd_addr_t remote_bda, uint32_t t_poll)
     arg.set_qos.t_poll = t_poll;
     return (btc_transfer_context(&msg, &arg, sizeof(btc_gap_bt_args_t), NULL, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
 }
+
+esp_err_t esp_bt_gap_set_page_timeout(uint16_t page_to)
+{
+    btc_msg_t msg;
+    btc_gap_bt_args_t arg;
+
+    if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
+        return  ESP_ERR_INVALID_STATE;
+    }
+    if (page_to < HCI_MIN_PAGE_TOUT) {
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    msg.sig = BTC_SIG_API_CALL;
+    msg.pid = BTC_PID_GAP_BT;
+    msg.act = BTC_GAP_BT_ACT_SET_PAGE_TIMEOUT;
+
+    arg.set_page_to.page_to = page_to;
+    return (btc_transfer_context(&msg, &arg, sizeof(btc_gap_bt_args_t), NULL, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
+}
+
+esp_err_t esp_bt_gap_get_page_timeout(void)
+{
+    btc_msg_t msg;
+
+    if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
+        return  ESP_ERR_INVALID_STATE;
+    }
+
+    msg.sig = BTC_SIG_API_CALL;
+    msg.pid = BTC_PID_GAP_BT;
+    msg.act = BTC_GAP_BT_ACT_GET_PAGE_TIMEOUT;
+
+    return (btc_transfer_context(&msg, NULL, 0, NULL, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
+}
 #endif /* #if BTC_GAP_BT_INCLUDED == TRUE */

+ 47 - 1
components/bt/host/bluedroid/api/include/api/esp_gap_bt_api.h

@@ -1,5 +1,5 @@
 /*
- * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
+ * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
  *
  * SPDX-License-Identifier: Apache-2.0
  */
@@ -218,6 +218,8 @@ typedef enum {
     ESP_BT_GAP_QOS_CMPL_EVT,                        /*!< QOS complete event */
     ESP_BT_GAP_ACL_CONN_CMPL_STAT_EVT,              /*!< ACL connection complete status event */
     ESP_BT_GAP_ACL_DISCONN_CMPL_STAT_EVT,           /*!< ACL disconnection complete status event */
+    ESP_BT_GAP_SET_PAGE_TO_EVT,                     /*!< Set page timeout event */
+    ESP_BT_GAP_GET_PAGE_TO_EVT,                     /*!< Get page timeout event */
     ESP_BT_GAP_EVT_MAX,
 } esp_bt_gap_cb_event_t;
 
@@ -372,6 +374,21 @@ typedef union {
                                                     logical transport. unit is 0.625ms. */
     } qos_cmpl;                                /*!< QoS complete parameter struct */
 
+    /**
+     * @brief ESP_BT_GAP_SET_PAGE_TO_EVT
+     */
+    struct page_to_set_param {
+        esp_bt_status_t stat;                   /*!< set page timeout status*/
+    } set_page_timeout;                         /*!< set page timeout parameter struct */
+
+    /**
+     * @brief ESP_BT_GAP_GET_PAGE_TO_EVT
+     */
+    struct page_to_get_param {
+        esp_bt_status_t stat;                   /*!< get page timeout status*/
+        uint16_t page_to;                       /*!< page_timeout value to be set, unit is 0.625ms. */
+    } get_page_timeout;                         /*!< get page timeout parameter struct */
+
     /**
      * @brief ESP_BT_GAP_ACL_CONN_CMPL_STAT_EVT
      */
@@ -786,6 +803,35 @@ esp_err_t esp_bt_gap_read_remote_name(esp_bd_addr_t remote_bda);
 */
 esp_err_t esp_bt_gap_set_qos(esp_bd_addr_t remote_bda, uint32_t t_poll);
 
+/**
+ * @brief           Set the page timeout
+ *                  esp_bt_gap_cb_t will be called with ESP_BT_GAP_SET_PAGE_TO_EVT
+ *                  after set page timeout ends. The value to be set will not be effective util the
+ *                  next page procedure, it's suggested to set the page timeout before initiating
+ *                  a connection.
+ *
+ * @param[in]       page_to: Page timeout, the maximum time the master will wait for a
+                             Base-band page response from the remote device at a locally
+                             initiated connection attempt. The valid range is 0x0016 ~ 0xffff,
+                             the default value is 0x2000, unit is 0.625ms.
+ *
+ * @return          - ESP_OK: success
+ *                  - ESP_ERR_INVALID_STATE: if bluetooth stack is not yet enabled
+ *                  - other: failed
+ */
+esp_err_t esp_bt_gap_set_page_timeout(uint16_t page_to);
+
+/**
+ * @brief           Get the page timeout
+ *                  esp_bt_gap_cb_t will be called with ESP_BT_GAP_GET_PAGE_TO_EVT
+ *                  after get page timeout ends
+ *
+ * @return          - ESP_OK: success
+ *                  - ESP_ERR_INVALID_STATE: if bluetooth stack is not yet enabled
+ *                  - other: failed
+ */
+esp_err_t esp_bt_gap_get_page_timeout(void);
+
 #ifdef __cplusplus
 }
 #endif

+ 31 - 1
components/bt/host/bluedroid/bta/dm/bta_dm_act.c

@@ -507,7 +507,7 @@ static void bta_dm_sys_hw_cback( tBTA_SYS_HW_EVT status )
 #endif  ///SMP_INCLUDED == TRUE
         BTM_SetDefaultLinkSuperTout(p_bta_dm_cfg->link_timeout);
 #if CLASSIC_BT_INCLUDED
-        BTM_WritePageTimeout(p_bta_dm_cfg->page_timeout);
+        BTM_WritePageTimeout(p_bta_dm_cfg->page_timeout, NULL);
         bta_dm_cb.cur_policy = p_bta_dm_cfg->policy_settings;
         BTM_SetDefaultLinkPolicy(bta_dm_cb.cur_policy);
 #endif
@@ -825,6 +825,36 @@ void bta_dm_config_eir (tBTA_DM_MSG *p_data)
 
     bta_dm_set_eir(NULL);
 }
+
+/*******************************************************************************
+**
+** Function         bta_dm_set_page_timeout
+**
+** Description      Sets page timeout
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_set_page_timeout (tBTA_DM_MSG *p_data)
+{
+    BTM_WritePageTimeout(p_data->set_page_timeout.page_to, p_data->set_page_timeout.set_page_to_cb);
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_get_page_timeout
+**
+** Description      Gets page timeout
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_get_page_timeout (tBTA_DM_MSG *p_data)
+{
+    BTM_ReadPageTimeout(p_data->get_page_timeout.get_page_to_cb);
+}
 #endif
 /*******************************************************************************
 **

+ 45 - 0
components/bt/host/bluedroid/bta/dm/bta_dm_api.c

@@ -271,6 +271,51 @@ void BTA_DmSetAfhChannels(const uint8_t *channels, tBTA_CMPL_CB  *set_afh_cb)
         bta_sys_sendmsg(p_msg);
     }
 }
+
+/*******************************************************************************
+**
+** Function         BTA_DmSetPageTimeout
+**
+** Description      This function sets the Bluetooth page timeout.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_DmSetPageTimeout(UINT16 page_to, tBTM_CMPL_CB *p_cb)
+{
+    tBTA_DM_API_PAGE_TO_SET *p_msg;
+
+    if ((p_msg = (tBTA_DM_API_PAGE_TO_SET *) osi_malloc(sizeof(tBTA_DM_API_PAGE_TO_SET))) != NULL) {
+        p_msg->hdr.event = BTA_DM_API_PAGE_TO_SET_EVT;
+        p_msg->page_to = page_to;
+        p_msg->set_page_to_cb = p_cb;
+
+        bta_sys_sendmsg(p_msg);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         BTA_DmGetPageTimeout
+**
+** Description      This function gets the Bluetooth page timeout.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_DmGetPageTimeout(tBTM_CMPL_CB *p_cb)
+{
+    tBTA_DM_API_PAGE_TO_GET *p_msg;
+
+    if ((p_msg = (tBTA_DM_API_PAGE_TO_GET *) osi_malloc(sizeof(tBTA_DM_API_PAGE_TO_GET))) != NULL) {
+        p_msg->hdr.event = BTA_DM_API_PAGE_TO_GET_EVT;
+        p_msg->get_page_to_cb = p_cb;
+
+        bta_sys_sendmsg(p_msg);
+    }
+}
 #endif /// CLASSIC_BT_INCLUDED == TRUE
 
 #if (SDP_INCLUDED == TRUE)

+ 2 - 0
components/bt/host/bluedroid/bta/dm/bta_dm_main.c

@@ -61,6 +61,8 @@ const tBTA_DM_ACTION bta_dm_action[BTA_DM_MAX_EVT] = {
     bta_dm_get_dev_name,                    /* BTA_DM_API_GET_NAME_EVT */
 #if (CLASSIC_BT_INCLUDED == TRUE)
     bta_dm_config_eir,                      /* BTA_DM_API_CONFIG_EIR_EVT */
+    bta_dm_set_page_timeout,                /* BTA_DM_API_PAGE_TO_SET_EVT */
+    bta_dm_get_page_timeout,                /* BTA_DM_API_PAGE_TO_GET_EVT */
 #endif
     bta_dm_set_afh_channels,                /* BTA_DM_API_SET_AFH_CHANNELS_EVT */
 #if (SDP_INCLUDED == TRUE)

+ 19 - 0
components/bt/host/bluedroid/bta/dm/include/bta_dm_int.h

@@ -56,6 +56,8 @@ enum {
     BTA_DM_API_GET_NAME_EVT,
 #if (CLASSIC_BT_INCLUDED == TRUE)
     BTA_DM_API_CONFIG_EIR_EVT,
+    BTA_DM_API_PAGE_TO_SET_EVT,
+    BTA_DM_API_PAGE_TO_GET_EVT,
 #endif
     BTA_DM_API_SET_AFH_CHANNELS_EVT,
 #if (SDP_INCLUDED == TRUE)
@@ -264,6 +266,19 @@ typedef struct {
     tBTA_CMPL_CB        *set_afh_cb;
 }tBTA_DM_API_SET_AFH_CHANNELS;
 
+/* data type for BTA_DM_API_PAGE_TO_SET_EVT */
+typedef struct {
+    BT_HDR              hdr;
+    UINT16              page_to;
+    tBTM_CMPL_CB        *set_page_to_cb;
+} tBTA_DM_API_PAGE_TO_SET;
+
+/* data type for BTA_DM_API_PAGE_TO_GET_EVT */
+typedef struct {
+    BT_HDR              hdr;
+    tBTM_CMPL_CB        *get_page_to_cb;
+} tBTA_DM_API_PAGE_TO_GET;
+
 /* data type for BTA_DM_API_GET_REMOTE_NAME_EVT */
 typedef struct {
     BT_HDR         hdr;
@@ -1077,6 +1092,8 @@ typedef union {
     tBTA_DM_API_CONFIG_EIR config_eir;
 
     tBTA_DM_API_SET_AFH_CHANNELS set_afh_channels;
+    tBTA_DM_API_PAGE_TO_SET set_page_timeout;
+    tBTA_DM_API_PAGE_TO_GET get_page_timeout;
 #if (SDP_INCLUDED == TRUE)
     tBTA_DM_API_GET_REMOTE_NAME  get_rmt_name;
 #endif
@@ -1577,6 +1594,8 @@ extern void bta_dm_set_dev_name (tBTA_DM_MSG *p_data);
 extern void bta_dm_get_dev_name (tBTA_DM_MSG *p_data);
 #if (CLASSIC_BT_INCLUDED == TRUE)
 extern void bta_dm_config_eir (tBTA_DM_MSG *p_data);
+extern void bta_dm_set_page_timeout (tBTA_DM_MSG *p_data);
+extern void bta_dm_get_page_timeout (tBTA_DM_MSG *p_data);
 #endif
 extern void bta_dm_set_afh_channels (tBTA_DM_MSG *p_data);
 extern void bta_dm_read_rmt_name(tBTA_DM_MSG *p_data);

+ 26 - 0
components/bt/host/bluedroid/bta/include/bta/bta_api.h

@@ -438,6 +438,9 @@ typedef tBTM_RSSI_RESULTS tBTA_RSSI_RESULTS;
 typedef tBTM_SET_AFH_CHANNELS_RESULTS tBTA_SET_AFH_CHANNELS_RESULTS;
 typedef tBTM_BLE_SET_CHANNELS_RESULTS tBTA_BLE_SET_CHANNELS_RESULTS;
 
+typedef tBTM_SET_PAGE_TIMEOUT_RESULTS tBTA_SET_PAGE_TIMEOUT_RESULTS;
+typedef tBTM_GET_PAGE_TIMEOUT_RESULTS tBTA_GET_PAGE_TIMEOUT_RESULTS;
+
 typedef tBTM_REMOTE_DEV_NAME tBTA_REMOTE_DEV_NAME;
 
 /* advertising channel map */
@@ -1760,6 +1763,29 @@ void BTA_DmSetAfhChannels(const uint8_t *channels, tBTA_CMPL_CB  *set_afh_cb);
 void BTA_DmSetQos(BD_ADDR bd_addr, UINT32 t_poll, tBTM_CMPL_CB *p_cb);
 #endif /// (BTA_DM_QOS_INCLUDED == TRUE)
 
+/*******************************************************************************
+**
+** Function         BTA_DmSetPageTimeout
+**
+** Description      This function sets the Bluetooth page timeout.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_DmSetPageTimeout(UINT16 page_to, tBTM_CMPL_CB *p_cb);
+/*******************************************************************************
+**
+** Function         BTA_DmGetPageTimeout
+**
+** Description      This function gets the Bluetooth page timeout.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_DmGetPageTimeout(tBTM_CMPL_CB *p_cb);
+
 #if (BLE_INCLUDED == TRUE)
 /*******************************************************************************
 **

+ 70 - 1
components/bt/host/bluedroid/btc/profile/std/gap/btc_gap_bt.c

@@ -1,5 +1,5 @@
 /*
- * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
+ * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
  *
  * SPDX-License-Identifier: Apache-2.0
  */
@@ -726,6 +726,53 @@ static void btc_gap_bt_set_afh_channels(btc_gap_bt_args_t *arg)
     BTA_DmSetAfhChannels(arg->set_afh_channels.channels, btc_gap_bt_set_afh_channels_cmpl_callback);
 }
 
+static void btc_gap_bt_set_page_timeout_cmpl_callback(void *p_data)
+{
+    tBTA_SET_PAGE_TIMEOUT_RESULTS *result = (tBTA_SET_PAGE_TIMEOUT_RESULTS *)p_data;
+    esp_bt_gap_cb_param_t param;
+    bt_status_t ret;
+    btc_msg_t msg;
+    msg.sig = BTC_SIG_API_CB;
+    msg.pid = BTC_PID_GAP_BT;
+    msg.act = BTC_GAP_BT_SET_PAGE_TO_EVT;
+
+    param.set_page_timeout.stat = btc_btm_status_to_esp_status(result->status);
+
+    ret = btc_transfer_context(&msg, &param, sizeof(esp_bt_gap_cb_param_t), NULL, NULL);
+    if (ret != BT_STATUS_SUCCESS) {
+        BTC_TRACE_ERROR("%s btc_transfer_context failed\n", __func__);
+    }
+}
+
+static void btc_gap_set_page_timeout(btc_gap_bt_args_t *arg)
+{
+    BTA_DmSetPageTimeout(arg->set_page_to.page_to, btc_gap_bt_set_page_timeout_cmpl_callback);
+}
+
+static void btc_gap_bt_get_page_timeout_cmpl_callback(void *p_data)
+{
+    tBTA_GET_PAGE_TIMEOUT_RESULTS *result = (tBTA_GET_PAGE_TIMEOUT_RESULTS *)p_data;
+    esp_bt_gap_cb_param_t param;
+    bt_status_t ret;
+    btc_msg_t msg;
+    msg.sig = BTC_SIG_API_CB;
+    msg.pid = BTC_PID_GAP_BT;
+    msg.act = BTC_GAP_BT_GET_PAGE_TO_EVT;
+
+    param.get_page_timeout.stat = btc_btm_status_to_esp_status(result->status);
+    param.get_page_timeout.page_to = result->page_to;
+
+    ret = btc_transfer_context(&msg, &param, sizeof(esp_bt_gap_cb_param_t), NULL, NULL);
+    if (ret != BT_STATUS_SUCCESS) {
+        BTC_TRACE_ERROR("%s btc_transfer_context failed\n", __func__);
+    }
+}
+
+static void btc_gap_get_page_timeout(void)
+{
+    BTA_DmGetPageTimeout(btc_gap_bt_get_page_timeout_cmpl_callback);
+}
+
 static void btc_gap_bt_read_remote_name_cmpl_callback(void *p_data)
 {
     tBTA_REMOTE_DEV_NAME *result = (tBTA_REMOTE_DEV_NAME *)p_data;
@@ -798,6 +845,8 @@ void btc_gap_bt_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src)
     case BTC_GAP_BT_ACT_SET_AFH_CHANNELS:
     case BTC_GAP_BT_ACT_READ_REMOTE_NAME:
     case BTC_GAP_BT_ACT_SET_QOS:
+    case BTC_GAP_BT_ACT_SET_PAGE_TIMEOUT:
+    case BTC_GAP_BT_ACT_GET_PAGE_TIMEOUT:
         break;
 #if (BT_SSP_INCLUDED == TRUE)
     case BTC_GAP_BT_ACT_PASSKEY_REPLY:
@@ -864,6 +913,8 @@ void btc_gap_bt_arg_deep_free(btc_msg_t *msg)
     case BTC_GAP_BT_ACT_SET_AFH_CHANNELS:
     case BTC_GAP_BT_ACT_READ_REMOTE_NAME:
     case BTC_GAP_BT_ACT_SET_QOS:
+    case BTC_GAP_BT_ACT_SET_PAGE_TIMEOUT:
+    case BTC_GAP_BT_ACT_GET_PAGE_TIMEOUT:
         break;
 #if (BT_SSP_INCLUDED == TRUE)
     case BTC_GAP_BT_ACT_PASSKEY_REPLY:
@@ -966,6 +1017,14 @@ void btc_gap_bt_call_handler(btc_msg_t *msg)
         btc_gap_bt_set_qos(arg);
         break;
     }
+    case BTC_GAP_BT_ACT_SET_PAGE_TIMEOUT: {
+        btc_gap_set_page_timeout(arg);
+        break;
+    }
+    case BTC_GAP_BT_ACT_GET_PAGE_TIMEOUT: {
+        btc_gap_get_page_timeout();
+        break;
+    }
     default:
         break;
     }
@@ -1008,6 +1067,8 @@ void btc_gap_bt_cb_deep_free(btc_msg_t *msg)
     case BTC_GAP_BT_READ_REMOTE_NAME_EVT:
     case BTC_GAP_BT_REMOVE_BOND_DEV_COMPLETE_EVT:
     case BTC_GAP_BT_QOS_EVT:
+    case BTC_GAP_BT_SET_PAGE_TO_EVT:
+    case BTC_GAP_BT_GET_PAGE_TO_EVT:
 #if (BT_SSP_INCLUDED == TRUE)
     case BTC_GAP_BT_CFM_REQ_EVT:
     case BTC_GAP_BT_KEY_NOTIF_EVT:
@@ -1093,6 +1154,14 @@ void btc_gap_bt_cb_handler(btc_msg_t *msg)
         btc_gap_bt_cb_to_app(ESP_BT_GAP_QOS_CMPL_EVT, (esp_bt_gap_cb_param_t *)msg->arg);
         break;
     }
+    case BTC_GAP_BT_SET_PAGE_TO_EVT: {
+        btc_gap_bt_cb_to_app(ESP_BT_GAP_SET_PAGE_TO_EVT, (esp_bt_gap_cb_param_t *)msg->arg);
+        break;
+    }
+    case BTC_GAP_BT_GET_PAGE_TO_EVT: {
+        btc_gap_bt_cb_to_app(ESP_BT_GAP_GET_PAGE_TO_EVT, (esp_bt_gap_cb_param_t *)msg->arg);
+        break;
+    }
     default:
         BTC_TRACE_ERROR("%s: Unhandled event (%d)!\n", __FUNCTION__, msg->act);
         break;

+ 10 - 1
components/bt/host/bluedroid/btc/profile/std/include/btc_gap_bt.h

@@ -1,5 +1,5 @@
 /*
- * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
+ * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
  *
  * SPDX-License-Identifier: Apache-2.0
  */
@@ -31,6 +31,8 @@ typedef enum {
     BTC_GAP_BT_MODE_CHG_EVT,
     BTC_GAP_BT_REMOVE_BOND_DEV_COMPLETE_EVT,
     BTC_GAP_BT_QOS_EVT,
+    BTC_GAP_BT_SET_PAGE_TO_EVT,
+    BTC_GAP_BT_GET_PAGE_TO_EVT,
 }btc_gap_bt_evt_t;
 
 typedef enum {
@@ -51,6 +53,8 @@ typedef enum {
     BTC_GAP_BT_ACT_SET_AFH_CHANNELS,
     BTC_GAP_BT_ACT_READ_REMOTE_NAME,
     BTC_GAP_BT_ACT_SET_QOS,
+    BTC_GAP_BT_ACT_SET_PAGE_TIMEOUT,
+    BTC_GAP_BT_ACT_GET_PAGE_TIMEOUT,
 } btc_gap_bt_act_t;
 
 /* btc_bt_gap_args_t */
@@ -147,6 +151,11 @@ typedef union {
         uint32_t t_poll;
     } set_qos;
 
+    // BTC_GAP_BT_ACT_SET_PAGE_TIMEOUT
+    struct set_page_to_args {
+        uint16_t page_to;
+    } set_page_to;
+
 } btc_gap_bt_args_t;
 
 void btc_gap_bt_call_handler(btc_msg_t *msg);

+ 110 - 3
components/bt/host/bluedroid/stack/btm/btm_devctl.c

@@ -162,6 +162,7 @@ static void reset_complete(void)
     btm_cb.btm_inq_vars.page_scan_window  = HCI_DEF_PAGESCAN_WINDOW;
     btm_cb.btm_inq_vars.page_scan_period  = HCI_DEF_PAGESCAN_INTERVAL;
     btm_cb.btm_inq_vars.page_scan_type    = HCI_DEF_SCAN_TYPE;
+    btm_cb.btm_inq_vars.page_timeout      = HCI_DEFAULT_PAGE_TOUT;
 
 #if (BLE_INCLUDED == TRUE)
     btm_cb.ble_ctr_cb.conn_state = BLE_CONN_IDLE;
@@ -197,6 +198,9 @@ static void reset_complete(void)
 #if (SMP_INCLUDED == TRUE && CLASSIC_BT_INCLUDED == TRUE)
     BTM_SetPinType (btm_cb.cfg.pin_type, btm_cb.cfg.pin_code, btm_cb.cfg.pin_code_len);
 #endif  ///SMP_INCLUDED == TRUE && CLASSIC_BT_INCLUDED == TRUE
+#if (CLASSIC_BT_INCLUDED == TRUE)
+    BTM_WritePageTimeout(btm_cb.btm_inq_vars.page_timeout, NULL);
+#endif  ///CLASSIC_BT_INCLUDED == TRUE
     for (int i = 0; i <= controller->get_last_features_classic_index(); i++) {
         btm_decode_ext_features_page(i, controller->get_features_classic(i)->as_array);
     }
@@ -817,7 +821,7 @@ void btm_vendor_specific_evt (UINT8 *p, UINT8 evt_len)
     BTM_TRACE_DEBUG ("BTM Event: Vendor Specific event from controller");
 }
 
-
+#if (CLASSIC_BT_INCLUDED == TRUE)
 /*******************************************************************************
 **
 ** Function         BTM_WritePageTimeout
@@ -830,12 +834,115 @@ void btm_vendor_specific_evt (UINT8 *p, UINT8 evt_len)
 **
 **
 *******************************************************************************/
-tBTM_STATUS BTM_WritePageTimeout(UINT16 timeout)
+tBTM_STATUS BTM_WritePageTimeout(UINT16 timeout, tBTM_CMPL_CB *p_cb)
 {
     BTM_TRACE_EVENT ("BTM: BTM_WritePageTimeout: Timeout: %d.", timeout);
 
+    if (timeout >= HCI_MIN_PAGE_TOUT) {
+        btm_cb.btm_inq_vars.page_timeout = timeout;
+    }
+    btm_cb.devcb.p_page_to_set_cmpl_cb = p_cb;
+
     /* Send the HCI command */
-    if (btsnd_hcic_write_page_tout (timeout)) {
+    if (!btsnd_hcic_write_page_tout (timeout)) {
+        return (BTM_NO_RESOURCES);
+    }
+
+    if (p_cb) {
+        btu_start_timer(&btm_cb.devcb.page_timeout_set_timer, BTU_TTYPE_BTM_SET_PAGE_TO, BTM_DEV_REPLY_TIMEOUT);
+    }
+
+    return (BTM_CMD_STARTED);
+}
+
+/*******************************************************************************
+**
+** Function         btm_set_page_timeout_complete
+**
+** Description      This function is called when setting page timeout complete.
+**                  message is received from the HCI.
+**
+** Returns          void
+**
+*******************************************************************************/
+void btm_set_page_timeout_complete (const UINT8 *p)
+{
+    tBTM_SET_PAGE_TIMEOUT_RESULTS results;
+
+    tBTM_CMPL_CB *p_cb = btm_cb.devcb.p_page_to_set_cmpl_cb;
+    btm_cb.devcb.p_page_to_set_cmpl_cb = NULL;
+    btu_free_timer (&btm_cb.devcb.page_timeout_set_timer);
+
+    /* If there is a callback address for setting page timeout, call it */
+    if (p_cb) {
+        if (p) {
+            STREAM_TO_UINT8 (results.hci_status, p);
+            switch (results.hci_status) {
+                case HCI_SUCCESS:
+                    results.status = BTM_SUCCESS;
+                    break;
+                case HCI_ERR_UNSUPPORTED_VALUE:
+                case HCI_ERR_ILLEGAL_PARAMETER_FMT:
+                    results.status = BTM_ILLEGAL_VALUE;
+                    break;
+                default:
+                    results.status = BTM_NO_RESOURCES;
+                    break;
+            }
+        } else {
+            results.hci_status = HCI_ERR_HOST_TIMEOUT;
+            results.status = BTM_DEVICE_TIMEOUT;
+        }
+        (*p_cb)(&results);
+    }
+}
+#endif  /// CLASSIC_BT_INCLUDED == TRUE
+
+/*******************************************************************************
+**
+** Function         btm_page_to_setup_timeout
+**
+** Description      This function processes a timeout.
+**                  Currently, we just report an error log
+**
+** Returns          void
+**
+*******************************************************************************/
+void btm_page_to_setup_timeout (void *p_tle)
+{
+    UNUSED(p_tle);
+    BTM_TRACE_DEBUG ("%s\n", __func__);
+
+#if (CLASSIC_BT_INCLUDED == TRUE)
+    btm_set_page_timeout_complete (NULL);
+#endif  /// CLASSIC_BT_INCLUDED == TRUE
+}
+
+/*******************************************************************************
+**
+** Function         BTM_ReadPageTimeout
+**
+** Description      Send HCI Read Page Timeout.
+**
+** Returns
+**      BTM_SUCCESS         Command sent.
+**      BTM_NO_RESOURCES    If out of resources to send the command.
+**
+*******************************************************************************/
+//extern
+tBTM_STATUS BTM_ReadPageTimeout(tBTM_CMPL_CB *p_cb)
+{
+    BTM_TRACE_EVENT ("BTM: BTM_ReadPageTimeout");
+
+    /* Get the page timeout */
+    tBTM_GET_PAGE_TIMEOUT_RESULTS results;
+
+    if (p_cb) {
+        results.hci_status = HCI_SUCCESS;
+        results.status = BTM_SUCCESS;
+        results.page_to = btm_cb.btm_inq_vars.page_timeout;
+
+        (*p_cb)(&results);
         return (BTM_SUCCESS);
     } else {
         return (BTM_NO_RESOURCES);

+ 7 - 0
components/bt/host/bluedroid/stack/btm/include/btm_int.h

@@ -214,6 +214,10 @@ tBTM_CMPL_CB        *p_tx_power_cmpl_cb;/* Callback function to be called
 TIMER_LIST_ENT       afh_channels_timer;
 tBTM_CMPL_CB        *p_afh_channels_cmpl_cb; /* Callback function to be called  When */
 /* set AFH channels is completed   */
+
+TIMER_LIST_ENT       page_timeout_set_timer;
+tBTM_CMPL_CB         *p_page_to_set_cmpl_cb; /* Callback function to be called when */
+/* set page timeout is completed */
 #endif
 
 DEV_CLASS            dev_class;         /* Local device class                   */
@@ -315,6 +319,7 @@ typedef struct {
     UINT16           inq_scan_type;
     UINT16           page_scan_type;        /* current page scan type */
     tBTM_INQ_TYPE    scan_type;
+    UINT16           page_timeout;
 
     BD_ADDR          remname_bda;           /* Name of bd addr for active remote name request */
 #define BTM_RMT_NAME_INACTIVE       0
@@ -1135,6 +1140,8 @@ void btm_delete_stored_link_key_complete (UINT8 *p);
 void btm_report_device_status (tBTM_DEV_STATUS status);
 void btm_set_afh_channels_complete (UINT8 *p);
 void btm_ble_set_channels_complete (UINT8 *p);
+void btm_set_page_timeout_complete (const UINT8 *p);
+void btm_page_to_setup_timeout (void *p_tle);
 
 /* Internal functions provided by btm_dev.c
 **********************************************

+ 3 - 0
components/bt/host/bluedroid/stack/btu/btu_hcif.c

@@ -996,6 +996,9 @@ static void btu_hcif_hdl_command_complete (UINT16 opcode, UINT8 *p, UINT16 evt_l
     case HCI_SET_AFH_CHANNELS:
         btm_set_afh_channels_complete(p);
         break;
+    case HCI_WRITE_PAGE_TOUT:
+        btm_set_page_timeout_complete(p);
+        break;
 #endif
 
 #if (BLE_INCLUDED == TRUE)

+ 3 - 0
components/bt/host/bluedroid/stack/btu/btu_task.c

@@ -401,6 +401,9 @@ static void btu_general_alarm_process(void *param)
     case BTU_TTYPE_BTM_QOS:
         btm_qos_setup_timeout(p_tle);
         break;
+    case BTU_TTYPE_BTM_SET_PAGE_TO:
+        btm_page_to_setup_timeout(p_tle);
+        break;
     default:
         for (int i = 0; i < BTU_MAX_REG_TIMER; i++) {
             if (btu_cb.timer_reg[i].timer_cb == NULL) {

+ 32 - 1
components/bt/host/bluedroid/stack/include/stack/btm_api.h

@@ -810,6 +810,23 @@ typedef struct {
     UINT8       hci_status;
 } tBTM_SET_AFH_CHANNELS_RESULTS;
 
+/* Structure returned with set page timeout event (in tBTM_CMPL_CB callback function)
+** in response to BTM_WritePageTimeout call.
+*/
+typedef struct {
+    tBTM_STATUS status;
+    UINT8       hci_status;
+} tBTM_SET_PAGE_TIMEOUT_RESULTS;
+
+/* Structure returned with get page timeout event (in tBTM_CMPL_CB callback function)
+** in response to BTM_ReadPageTimeout call.
+*/
+typedef struct {
+    tBTM_STATUS status;
+    UINT8       hci_status;
+    UINT16      page_to;
+} tBTM_GET_PAGE_TIMEOUT_RESULTS;
+
 /* Structure returned with set BLE channels event (in tBTM_CMPL_CB callback function)
 ** in response to BTM_BleSetChannels call.
 */
@@ -2192,7 +2209,21 @@ UINT8 BTM_SetTraceLevel (UINT8 new_level);
 **
 *******************************************************************************/
 //extern
-tBTM_STATUS BTM_WritePageTimeout(UINT16 timeout);
+tBTM_STATUS BTM_WritePageTimeout(UINT16 timeout, tBTM_CMPL_CB *p_cb);
+
+/*******************************************************************************
+**
+** Function         BTM_ReadPageTimeout
+**
+** Description      Send HCI Read Page Timeout.
+**
+** Returns
+**      BTM_SUCCESS         Command sent.
+**      BTM_NO_RESOURCES    If out of resources to send the command.
+**
+*******************************************************************************/
+//extern
+tBTM_STATUS BTM_ReadPageTimeout(tBTM_CMPL_CB *p_cb);
 
 /*******************************************************************************
 **

+ 3 - 0
components/bt/host/bluedroid/stack/include/stack/btu.h

@@ -166,6 +166,9 @@ typedef void (*tBTU_EVENT_CALLBACK)(BT_HDR *p_hdr);
 /* BTU internal timer for QOS */
 #define BTU_TTYPE_BTM_QOS                           110
 
+/* BTU internal timer for set page timeout*/
+#define BTU_TTYPE_BTM_SET_PAGE_TO                   111
+
 /* BTU Task Signal */
 typedef enum {
     SIG_BTU_START_UP = 0,

+ 1 - 0
components/bt/host/bluedroid/stack/include/stack/hcidefs.h

@@ -1285,6 +1285,7 @@ typedef UINT8 tHCI_STATUS;
 
 /* Page timeout is used in LC only and LC is counting down slots not using OS */
 #define HCI_DEFAULT_PAGE_TOUT           0x2000  /* 5.12 sec (in slots) */
+#define HCI_MIN_PAGE_TOUT               0x0016  /* 13.75 ms (in slots) */
 
 /* Scan enable flags */
 #define HCI_NO_SCAN_ENABLED             0x00

+ 1 - 1
components/bt/host/bluedroid/stack/include/stack/hcimsgs.h

@@ -586,7 +586,7 @@ BOOLEAN btsnd_hcic_ble_set_channels (BLE_CHANNELS channels);
 BOOLEAN btsnd_hcic_write_pin_type(UINT8 type);                   /* Write PIN Type */
 BOOLEAN btsnd_hcic_write_auto_accept(UINT8 flag);                /* Write Auto Accept */
 BOOLEAN btsnd_hcic_read_name (void);                             /* Read Local Name */
-BOOLEAN btsnd_hcic_write_page_tout(UINT16 timeout);              /* Write Page Timout */
+BOOLEAN btsnd_hcic_write_page_tout(UINT16 timeout);              /* Write Page Timeout */
 BOOLEAN btsnd_hcic_write_scan_enable(UINT8 flag);                /* Write Scan Enable */
 BOOLEAN btsnd_hcic_write_pagescan_cfg(UINT16 interval,
                                       UINT16 window);            /* Write Page Scan Activity */