diff --git a/components/bt/host/bluedroid/api/esp_bt_device.c b/components/bt/host/bluedroid/api/esp_bt_device.c index ff5361a2d7..761ae66fd0 100644 --- a/components/bt/host/bluedroid/api/esp_bt_device.c +++ b/components/bt/host/bluedroid/api/esp_bt_device.c @@ -106,3 +106,31 @@ esp_err_t esp_bt_config_file_path_update(const char *file_path) return btc_config_file_path_update(file_path); } + +esp_err_t esp_bt_dev_vendor_command_send(esp_bt_dev_vendor_cmd_params_t *vendor_cmd_param) +{ + btc_msg_t msg = {0}; + btc_dev_args_t arg; + + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + if (!vendor_cmd_param || !vendor_cmd_param->p_param_buf || !vendor_cmd_param->param_len) { + return ESP_ERR_NOT_ALLOWED; + } + // If command is not a VSC, return error + if ((vendor_cmd_param->opcode & VENDOR_HCI_CMD_MASK) != VENDOR_HCI_CMD_MASK) { + return ESP_ERR_NOT_ALLOWED; + } + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_DEV; + msg.act = BTC_DEV_ACT_VENDOR_HCI_CMD_EVT; + arg.vendor_cmd_send.opcode = vendor_cmd_param->opcode; + arg.vendor_cmd_send.param_len = vendor_cmd_param->param_len; + arg.vendor_cmd_send.p_param_buf = vendor_cmd_param->p_param_buf; + + return (btc_transfer_context(&msg, &arg, sizeof(btc_dev_args_t), btc_dev_call_arg_deep_copy, btc_dev_call_arg_deep_free) + == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} diff --git a/components/bt/host/bluedroid/api/include/api/esp_bt_device.h b/components/bt/host/bluedroid/api/include/api/esp_bt_device.h index 25da240374..80ff4141d7 100644 --- a/components/bt/host/bluedroid/api/include/api/esp_bt_device.h +++ b/components/bt/host/bluedroid/api/include/api/esp_bt_device.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -29,6 +29,17 @@ extern "C" { #define ESP_BT_DEV_COEX_OP_SET 0x01 typedef uint8_t esp_bt_dev_coex_op_t; +#define VENDOR_HCI_CMD_MASK (0x3F << 10) /**!< 0xFC00 */ + +/** + * @brief Vendor HCI command parameters + */ +typedef struct { + uint16_t opcode; /*!< vendor hci command opcode */ + uint8_t param_len; /*!< the length of parameter */ + uint8_t *p_param_buf; /*!< the point of parameter buffer */ +} esp_bt_dev_vendor_cmd_params_t; + /** * @brief Bluetooth device coex type */ @@ -40,6 +51,7 @@ typedef enum { /// BT device callback events typedef enum { ESP_BT_DEV_NAME_RES_EVT = 0, /*!< Device name result event */ + ESP_BT_DEV_VENDOR_CMD_COMPLETE_EVT, /*!< When vendor hci command complete, the event comes */ ESP_BT_DEV_EVT_MAX, } esp_bt_dev_cb_event_t; @@ -52,6 +64,14 @@ typedef union { esp_bt_status_t status; /*!< Status of getting device name */ char *name; /*!< Name of Bluetooth device */ } name_res; /*!< discovery result parameter struct */ + /** + * @brief ESP_BT_DEV_VENDOR_CMD_COMPLETE_EVT + */ + struct vendor_cmd_cmpl_evt_param { + uint16_t opcode; /*!< vendor hci command opcode */ + uint16_t param_len; /*!< The lenght of parameter buffer */ + uint8_t *p_param_buf; /*!< The point of parameter buffer */ + } vendor_cmd_cmpl; /*!< Event parameter of ESP_BT_DEV_VENDOR_CMD_COMPLETE_EVT */ } esp_bt_dev_cb_param_t; /** @@ -140,6 +160,19 @@ esp_err_t esp_bt_dev_coex_status_config(esp_bt_dev_coex_type_t type, esp_bt_dev_ */ esp_err_t esp_bt_config_file_path_update(const char *file_path); +/** + * @brief This function is called to send vendor hci comamnd. + * + * + * + * @param[in] vendor_cmd_param: vendor hci command parameters + * + * @return + * - ESP_OK : success + * - other : failed + */ +esp_err_t esp_bt_dev_vendor_command_send(esp_bt_dev_vendor_cmd_params_t *vendor_cmd_param); + #ifdef __cplusplus } #endif diff --git a/components/bt/host/bluedroid/bta/dm/bta_dm_act.c b/components/bt/host/bluedroid/bta/dm/bta_dm_act.c index f1eb9a1246..a4e580728b 100644 --- a/components/bt/host/bluedroid/bta/dm/bta_dm_act.c +++ b/components/bt/host/bluedroid/bta/dm/bta_dm_act.c @@ -724,6 +724,14 @@ void bta_dm_cfg_coex_status (tBTA_DM_MSG *p_data) } #endif +void bta_dm_send_vendor_hci(tBTA_DM_MSG *p_data) +{ + BTM_VendorSpecificCommand(p_data->vendor_hci_cmd.opcode, + p_data->vendor_hci_cmd.param_len, + p_data->vendor_hci_cmd.p_param_buf, + p_data->vendor_hci_cmd.vendor_hci_cb); +} + /******************************************************************************* ** ** Function bta_dm_set_afh_channels diff --git a/components/bt/host/bluedroid/bta/dm/bta_dm_api.c b/components/bt/host/bluedroid/bta/dm/bta_dm_api.c index ecb6b6ee57..ed8b7d1e3f 100644 --- a/components/bt/host/bluedroid/bta/dm/bta_dm_api.c +++ b/components/bt/host/bluedroid/bta/dm/bta_dm_api.c @@ -227,6 +227,21 @@ void BTA_DmCfgCoexStatus(UINT8 op, UINT8 type, UINT8 status) } #endif +void BTA_DmsendVendorHciCmd(UINT16 opcode, UINT8 param_len, UINT8 *p_param_buf, tBTA_SEND_VENDOR_HCI_CMPL_CBACK p_vendor_cmd_complete_cback) +{ + tBTA_DM_API_SEND_VENDOR_HCI_CMD *p_msg; + if ((p_msg = (tBTA_DM_API_SEND_VENDOR_HCI_CMD *)osi_malloc(sizeof(tBTA_DM_API_SEND_VENDOR_HCI_CMD) + param_len)) != NULL) { + p_msg->hdr.event = BTA_DM_API_SEND_VENDOR_HCI_CMD_EVT; + p_msg->opcode = opcode; + p_msg->param_len = param_len; + p_msg->p_param_buf = (UINT8 *)(p_msg + 1); + memcpy(p_msg->p_param_buf, p_param_buf, param_len); + p_msg->vendor_hci_cb = p_vendor_cmd_complete_cback; + + bta_sys_sendmsg(p_msg); + } +} + #if (CLASSIC_BT_INCLUDED == TRUE) void BTA_DmConfigEir(tBTA_DM_EIR_CONF *eir_config) diff --git a/components/bt/host/bluedroid/bta/dm/bta_dm_main.c b/components/bt/host/bluedroid/bta/dm/bta_dm_main.c index 42e67d77b5..d931469fc7 100644 --- a/components/bt/host/bluedroid/bta/dm/bta_dm_main.c +++ b/components/bt/host/bluedroid/bta/dm/bta_dm_main.c @@ -65,6 +65,7 @@ const tBTA_DM_ACTION bta_dm_action[BTA_DM_MAX_EVT] = { #if (ESP_COEX_VSC_INCLUDED == TRUE) bta_dm_cfg_coex_status, /* BTA_DM_API_CFG_COEX_ST_EVT */ #endif + bta_dm_send_vendor_hci, /* BTA_DM_API_SEND_VENDOR_HCI_CMD_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 */ diff --git a/components/bt/host/bluedroid/bta/dm/include/bta_dm_int.h b/components/bt/host/bluedroid/bta/dm/include/bta_dm_int.h index a46651d342..4689460a5a 100644 --- a/components/bt/host/bluedroid/bta/dm/include/bta_dm_int.h +++ b/components/bt/host/bluedroid/bta/dm/include/bta_dm_int.h @@ -57,6 +57,7 @@ enum { #if (ESP_COEX_VSC_INCLUDED == TRUE) BTA_DM_API_CFG_COEX_ST_EVT, #endif + BTA_DM_API_SEND_VENDOR_HCI_CMD_EVT, #if (CLASSIC_BT_INCLUDED == TRUE) BTA_DM_API_CONFIG_EIR_EVT, BTA_DM_API_PAGE_TO_SET_EVT, @@ -265,6 +266,14 @@ typedef struct { } tBTA_DM_API_CFG_COEX_STATUS; #endif +typedef struct { + BT_HDR hdr; + UINT16 opcode; + UINT8 param_len; + UINT8 *p_param_buf; + tBTA_SEND_VENDOR_HCI_CMPL_CBACK *vendor_hci_cb; +}tBTA_DM_API_SEND_VENDOR_HCI_CMD; + /* data type for BTA_DM_API_CONFIG_EIR_EVT */ typedef struct { BT_HDR hdr; @@ -1162,6 +1171,7 @@ typedef union { #if (ESP_COEX_VSC_INCLUDED == TRUE) tBTA_DM_API_CFG_COEX_STATUS cfg_coex_status; #endif + tBTA_DM_API_SEND_VENDOR_HCI_CMD vendor_hci_cmd; tBTA_DM_API_CONFIG_EIR config_eir; tBTA_DM_API_SET_AFH_CHANNELS set_afh_channels; @@ -1676,6 +1686,7 @@ extern void bta_dm_get_dev_name (tBTA_DM_MSG *p_data); #if (ESP_COEX_VSC_INCLUDED == TRUE) extern void bta_dm_cfg_coex_status(tBTA_DM_MSG *p_data); #endif +extern void bta_dm_send_vendor_hci(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); diff --git a/components/bt/host/bluedroid/bta/include/bta/bta_api.h b/components/bt/host/bluedroid/bta/include/bta/bta_api.h index 8ba75884f5..54922ade8a 100644 --- a/components/bt/host/bluedroid/bta/include/bta/bta_api.h +++ b/components/bt/host/bluedroid/bta/include/bta/bta_api.h @@ -417,6 +417,8 @@ typedef void (tBTA_UPDATE_DUPLICATE_EXCEPTIONAL_LIST_CMPL_CBACK) (tBTA_STATUS st typedef void (tBTA_SET_ADV_DATA_CMPL_CBACK) (tBTA_STATUS status); +typedef tBTM_VSC_CMPL_CB tBTA_SEND_VENDOR_HCI_CMPL_CBACK; + typedef tBTM_START_ADV_CMPL_CBACK tBTA_START_ADV_CMPL_CBACK; typedef tBTM_START_STOP_ADV_CMPL_CBACK tBTA_START_STOP_ADV_CMPL_CBACK; @@ -433,6 +435,8 @@ typedef tBTM_SET_LOCAL_PRIVACY_CBACK tBTA_SET_LOCAL_PRIVACY_CBACK; typedef tBTM_CMPL_CB tBTA_CMPL_CB; +typedef tBTM_VSC_CMPL tBTA_VSC_CMPL; + typedef tBTM_TX_POWER_RESULTS tBTA_TX_POWER_RESULTS; typedef tBTM_RSSI_RESULTS tBTA_RSSI_RESULTS; @@ -1744,6 +1748,8 @@ extern void BTA_DmGetDeviceName(tBTA_GET_DEV_NAME_CBACK *p_cback); extern void BTA_DmCfgCoexStatus(UINT8 op, UINT8 type, UINT8 status); #endif +extern void BTA_DmsendVendorHciCmd(UINT16 opcode, UINT8 param_len, UINT8 *p_param_buf, tBTA_SEND_VENDOR_HCI_CMPL_CBACK p_vendor_cmd_complete_cback); + /******************************************************************************* ** ** Function BTA_DmGetRemoteName diff --git a/components/bt/host/bluedroid/btc/core/btc_dev.c b/components/bt/host/bluedroid/btc/core/btc_dev.c index a096700da2..115599cb68 100644 --- a/components/bt/host/bluedroid/btc/core/btc_dev.c +++ b/components/bt/host/bluedroid/btc/core/btc_dev.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -48,6 +48,43 @@ static void btc_dev_get_dev_name_callback(UINT8 status, char *name) } } +static void btc_dev_vendor_hci_cmd_complete_callback(tBTA_VSC_CMPL *p_param) +{ + bool param_invalid = false; + if ((!p_param) || (!p_param->param_len) || (!p_param->p_param_buf)) { + BTC_TRACE_ERROR("%s param error\n", __func__); + param_invalid = true; + } + + esp_bt_dev_cb_param_t param = {0}; + bt_status_t ret; + btc_msg_t msg = {0}; + + msg.sig = BTC_SIG_API_CB; + msg.pid = BTC_PID_DEV; + msg.act = ESP_BT_DEV_VENDOR_CMD_COMPLETE_EVT; + if (!param_invalid) { + param.vendor_cmd_cmpl.opcode = p_param->opcode; + param.vendor_cmd_cmpl.param_len = p_param->param_len; + param.vendor_cmd_cmpl.p_param_buf = p_param->p_param_buf; + } else { + if (p_param) { + param.vendor_cmd_cmpl.opcode = p_param->opcode; + } else { + param.vendor_cmd_cmpl.opcode = 0; + } + param.vendor_cmd_cmpl.param_len = 0; + param.vendor_cmd_cmpl.p_param_buf = NULL; + } + + ret = btc_transfer_context(&msg, ¶m, sizeof(esp_bt_dev_cb_param_t), btc_dev_cb_arg_deep_copy, btc_dev_cb_arg_deep_free); + + if (ret != BT_STATUS_SUCCESS) { + BTC_TRACE_ERROR("%s btc_transfer_context failed\n", __func__); + } + +} + void btc_dev_call_arg_deep_free(btc_msg_t *msg) { BTC_TRACE_DEBUG("%s \n", __func__); @@ -65,12 +102,65 @@ void btc_dev_call_arg_deep_free(btc_msg_t *msg) case BTC_DEV_ACT_CFG_COEX_STATUS: #endif break; + case BTC_DEV_ACT_VENDOR_HCI_CMD_EVT: { + uint8_t *p_param_buf = ((btc_dev_args_t *)msg->arg)->vendor_cmd_send.p_param_buf; + if (p_param_buf) { + osi_free(p_param_buf); + } + break; + } default: BTC_TRACE_DEBUG("Unhandled deep free %d\n", msg->act); break; } } +void btc_dev_call_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src) +{ + switch (msg->act) { + case BTC_DEV_ACT_VENDOR_HCI_CMD_EVT: { + btc_dev_args_t *src = (btc_dev_args_t *)p_src; + btc_dev_args_t *dst = (btc_dev_args_t *)p_dest; + if (src->vendor_cmd_send.param_len) { + dst->vendor_cmd_send.p_param_buf = osi_malloc(src->vendor_cmd_send.param_len); + if (dst->vendor_cmd_send.p_param_buf) { + memcpy(dst->vendor_cmd_send.p_param_buf, src->vendor_cmd_send.p_param_buf, src->vendor_cmd_send.param_len); + } else { + BTC_TRACE_ERROR("%s %d no mem\n",__func__, msg->act); + } + } + break; + } + default: + BTC_TRACE_ERROR("Unhandled deep copy %d\n", msg->act); + break; + } +} + +void btc_dev_cb_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src) +{ + switch (msg->act) { + case ESP_BT_DEV_VENDOR_CMD_COMPLETE_EVT: { + esp_bt_dev_cb_param_t *src = (esp_bt_dev_cb_param_t *)p_src; + esp_bt_dev_cb_param_t *dst = (esp_bt_dev_cb_param_t *) p_dest; + + if (src->vendor_cmd_cmpl.param_len) { + dst->vendor_cmd_cmpl.p_param_buf = osi_malloc(src->vendor_cmd_cmpl.param_len); + if (dst->vendor_cmd_cmpl.p_param_buf) { + memcpy(dst->vendor_cmd_cmpl.p_param_buf, src->vendor_cmd_cmpl.p_param_buf, + src->vendor_cmd_cmpl.param_len); + } else { + BTC_TRACE_ERROR("%s, malloc failed\n", __func__); + } + } + break; + } + default: + BTC_TRACE_ERROR("%s, Unhandled deep copy %d\n", __func__, msg->act); + break; + } +} + void btc_dev_cb_arg_deep_free(btc_msg_t *msg) { BTC_TRACE_DEBUG("%s \n", __func__); @@ -83,6 +173,13 @@ void btc_dev_cb_arg_deep_free(btc_msg_t *msg) } break; } + case ESP_BT_DEV_VENDOR_CMD_COMPLETE_EVT: { + uint8_t *value = ((esp_bt_dev_cb_param_t *)msg->arg)->vendor_cmd_cmpl.p_param_buf; + if (value) { + osi_free(value); + } + break; + } default: BTC_TRACE_DEBUG("Unhandled deep free %d\n", msg->act); break; @@ -109,6 +206,12 @@ void btc_dev_call_handler(btc_msg_t *msg) arg->cfg_coex_status.status); break; #endif + case BTC_DEV_ACT_VENDOR_HCI_CMD_EVT: + BTA_DmsendVendorHciCmd(arg->vendor_cmd_send.opcode, + arg->vendor_cmd_send.param_len, + arg->vendor_cmd_send.p_param_buf, + btc_dev_vendor_hci_cmd_complete_callback); + break; default: break; } diff --git a/components/bt/host/bluedroid/btc/include/btc/btc_dev.h b/components/bt/host/bluedroid/btc/include/btc/btc_dev.h index 4f2978aeec..d560c0792e 100644 --- a/components/bt/host/bluedroid/btc/include/btc/btc_dev.h +++ b/components/bt/host/bluedroid/btc/include/btc/btc_dev.h @@ -17,6 +17,7 @@ typedef enum { #if (ESP_COEX_VSC_INCLUDED == TRUE) BTC_DEV_ACT_CFG_COEX_STATUS, #endif + BTC_DEV_ACT_VENDOR_HCI_CMD_EVT, } btc_dev_act_t; /* btc_dev_args_t */ @@ -34,9 +35,21 @@ typedef union { uint8_t status; } cfg_coex_status; #endif + + //BTC_DEV_VENDOR_HCI_CMD_EVT + struct vendor_cmd_send_args { + uint16_t opcode; + uint8_t param_len; + uint8_t *p_param_buf; + } vendor_cmd_send; } btc_dev_args_t; void btc_dev_call_handler(btc_msg_t *msg); void btc_dev_cb_handler(btc_msg_t *msg); +void btc_dev_call_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src); +void btc_dev_call_arg_deep_free(btc_msg_t *msg); + +void btc_dev_cb_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src); +void btc_dev_cb_arg_deep_free(btc_msg_t *msg); #endif /* __BTC_DEV_H__ */ diff --git a/components/bt/host/bluedroid/stack/btm/btm_devctl.c b/components/bt/host/bluedroid/stack/btm/btm_devctl.c index bffb5bbee0..21534d5a76 100644 --- a/components/bt/host/bluedroid/stack/btm/btm_devctl.c +++ b/components/bt/host/bluedroid/stack/btm/btm_devctl.c @@ -740,8 +740,9 @@ void btm_vsc_complete (UINT8 *p, UINT16 opcode, UINT16 evt_len, break; } default: - break; + break; } +#endif // (BLE_INCLUDED == TRUE) tBTM_VSC_CMPL vcs_cplt_params; /* If there was a callback address for vcs complete, call it */ @@ -752,7 +753,7 @@ void btm_vsc_complete (UINT8 *p, UINT16 opcode, UINT16 evt_len, vcs_cplt_params.p_param_buf = p; (*p_vsc_cplt_cback)(&vcs_cplt_params); /* Call the VSC complete callback function */ } -#endif + } /*******************************************************************************