From 1d9fd4707abd0a5caa4ab7b191bc183ed020b93b Mon Sep 17 00:00:00 2001 From: xiongweichao Date: Thu, 21 Apr 2022 14:26:29 +0800 Subject: [PATCH] add sdp api --- components/bt/CMakeLists.txt | 2 + components/bt/common/btc/core/btc_task.c | 6 + .../bt/common/btc/include/btc/btc_task.h | 1 + .../bt/host/bluedroid/api/esp_sdp_api.c | 129 +++ .../bluedroid/api/include/api/esp_sdp_api.h | 271 +++++ .../bluedroid/bta/include/bta/bta_sdp_api.h | 14 +- .../bt/host/bluedroid/bta/sdp/bta_sdp_act.c | 14 +- .../bt/host/bluedroid/bta/sdp/bta_sdp_api.c | 2 + .../btc/profile/std/include/bt_sdp.h | 5 +- .../btc/profile/std/include/btc_sdp.h | 53 + .../bluedroid/btc/profile/std/sdp/btc_sdp.c | 1023 +++++++++++++++++ .../common/include/common/bt_target.h | 3 +- 12 files changed, 1510 insertions(+), 13 deletions(-) create mode 100644 components/bt/host/bluedroid/api/esp_sdp_api.c create mode 100644 components/bt/host/bluedroid/api/include/api/esp_sdp_api.h create mode 100644 components/bt/host/bluedroid/btc/profile/std/include/btc_sdp.h create mode 100644 components/bt/host/bluedroid/btc/profile/std/sdp/btc_sdp.c diff --git a/components/bt/CMakeLists.txt b/components/bt/CMakeLists.txt index 34ea3ce564..7eb63851e9 100644 --- a/components/bt/CMakeLists.txt +++ b/components/bt/CMakeLists.txt @@ -113,6 +113,7 @@ if(CONFIG_BT_ENABLED) "host/bluedroid/api/esp_hf_ag_api.c" "host/bluedroid/api/esp_hf_client_api.c" "host/bluedroid/api/esp_spp_api.c" + "host/bluedroid/api/esp_sdp_api.c" "host/bluedroid/api/esp_l2cap_bt_api.c" "host/bluedroid/bta/ar/bta_ar.c" "host/bluedroid/bta/av/bta_av_aact.c" @@ -215,6 +216,7 @@ if(CONFIG_BT_ENABLED) "host/bluedroid/btc/profile/std/gatt/btc_gattc.c" "host/bluedroid/btc/profile/std/gatt/btc_gatts.c" "host/bluedroid/btc/profile/std/spp/btc_spp.c" + "host/bluedroid/btc/profile/std/sdp/btc_sdp.c" "host/bluedroid/btc/profile/std/l2cap/btc_l2cap.c" "host/bluedroid/device/bdaddr.c" "host/bluedroid/device/controller.c" diff --git a/components/bt/common/btc/core/btc_task.c b/components/bt/common/btc/core/btc_task.c index 73063922a8..1348fcbd2d 100644 --- a/components/bt/common/btc/core/btc_task.c +++ b/components/bt/common/btc/core/btc_task.c @@ -42,6 +42,9 @@ #if (BTC_L2CAP_INCLUDED == TRUE) #include "btc_l2cap.h" #endif /* #if (BTC_L2CAP_INCLUDED == TRUE) */ +#if (BTC_SDP_INCLUDED == TRUE) +#include "btc_sdp.h" +#endif /* #if (BTC_SDP_INCLUDED == TRUE) */ #if BTC_HF_INCLUDED #include "btc_hf_ag.h" #endif/* #if BTC_HF_INCLUDED */ @@ -118,6 +121,9 @@ static const btc_func_t profile_tab[BTC_PID_NUM] = { #if (BTC_L2CAP_INCLUDED == TRUE) [BTC_PID_L2CAP] = {btc_l2cap_call_handler, btc_l2cap_cb_handler }, #endif /* #if (BTC_L2CAP_INCLUDED == TRUE) */ +#if (BTC_SDP_INCLUDED == TRUE) + [BTC_PID_SDP] = {btc_sdp_call_handler, btc_sdp_cb_handler }, +#endif /* #if (BTC_SDP_INCLUDED == TRUE) */ #if BTC_HF_INCLUDED [BTC_PID_HF] = {btc_hf_call_handler, btc_hf_cb_handler}, #endif /* #if BTC_HF_INCLUDED */ diff --git a/components/bt/common/btc/include/btc/btc_task.h b/components/bt/common/btc/include/btc/btc_task.h index 130208a81e..13f51cfe50 100644 --- a/components/bt/common/btc/include/btc/btc_task.h +++ b/components/bt/common/btc/include/btc/btc_task.h @@ -60,6 +60,7 @@ typedef enum { BTC_PID_HD, BTC_PID_HH, BTC_PID_L2CAP, + BTC_PID_SDP, #if (BTC_HF_INCLUDED == TRUE) BTC_PID_HF, #endif /* BTC_HF_INCLUDED */ diff --git a/components/bt/host/bluedroid/api/esp_sdp_api.c b/components/bt/host/bluedroid/api/esp_sdp_api.c new file mode 100644 index 0000000000..7831b218ad --- /dev/null +++ b/components/bt/host/bluedroid/api/esp_sdp_api.c @@ -0,0 +1,129 @@ +/* + * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include "esp_bt_main.h" +#include "btc/btc_manage.h" + +#include "btc_sdp.h" +#include "esp_sdp_api.h" +#include "common/bt_target.h" + +#if (defined BTC_SDP_INCLUDED && BTC_SDP_INCLUDED == TRUE) + +esp_err_t esp_sdp_register_callback(esp_sdp_cb_t callback) +{ + ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); + + if (callback == NULL) { + return ESP_FAIL; + } + + btc_profile_cb_set(BTC_PID_SDP, callback); + return ESP_OK; +} + +esp_err_t esp_sdp_init(void) +{ + ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); + + btc_msg_t msg; + bt_status_t stat; + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_SDP; + msg.act = BTC_SDP_ACT_INIT; + + /* Switch to BTC context */ + stat = btc_transfer_context(&msg, NULL, 0, NULL); + return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; +} + +esp_err_t esp_sdp_deinit(void) +{ + ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); + + btc_msg_t msg; + bt_status_t stat; + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_SDP; + msg.act = BTC_SDP_ACT_DEINIT; + + /* Switch to BTC context */ + stat = btc_transfer_context(&msg, NULL, 0, NULL); + return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; +} + +esp_err_t esp_sdp_search_record(esp_bd_addr_t bd_addr, esp_bt_uuid_t uuid) +{ + ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); + + btc_msg_t msg; + bt_status_t stat; + btc_sdp_args_t arg; + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_SDP; + msg.act = BTC_SDP_ACT_SEARCH; + + memset(&arg, 0, sizeof(btc_sdp_args_t)); + memcpy(arg.search.bd_addr, bd_addr, ESP_BD_ADDR_LEN); + arg.search.sdp_uuid.len = uuid.len; + memcpy(&arg.search.sdp_uuid.uu, &uuid.uuid, sizeof(uuid.uuid)); + + /* Switch to BTC context */ + stat = btc_transfer_context(&msg, &arg, sizeof(btc_sdp_args_t), NULL); + return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; +} + +esp_err_t esp_sdp_create_record(esp_bluetooth_sdp_record_t *record) +{ + ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); + + if (record == NULL || record->hdr.service_name_length > ESP_SDP_SERVER_NAME_MAX + || strlen(record->hdr.service_name)+1 != record->hdr.service_name_length) { + LOG_ERROR("Invalid server name!\n"); + return ESP_ERR_INVALID_ARG; + } + + btc_msg_t msg; + bt_status_t stat; + btc_sdp_args_t arg; + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_SDP; + msg.act = BTC_SDP_ACT_CREATE_RECORD; + + memset(&arg, 0, sizeof(btc_sdp_args_t)); + arg.creat_record.record = (bluetooth_sdp_record *)record; + + /* Switch to BTC context */ + stat = btc_transfer_context(&msg, &arg, sizeof(btc_sdp_args_t), btc_sdp_arg_deep_copy); + return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; +} + +esp_err_t esp_sdp_remove_record(int record_handle) +{ + ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); + + btc_msg_t msg; + bt_status_t stat; + btc_sdp_args_t arg; + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_SDP; + msg.act = BTC_SDP_ACT_REMOVE_RECORD; + + arg.remove_record.record_handle = record_handle; + + /* Switch to BTC context */ + stat = btc_transfer_context(&msg, &arg, sizeof(btc_sdp_args_t), NULL); + return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; +} + +#endif ///defined BTC_SDP_INCLUDED && BTC_SDP_INCLUDED == TRUE diff --git a/components/bt/host/bluedroid/api/include/api/esp_sdp_api.h b/components/bt/host/bluedroid/api/include/api/esp_sdp_api.h new file mode 100644 index 0000000000..cb944a5ced --- /dev/null +++ b/components/bt/host/bluedroid/api/include/api/esp_sdp_api.h @@ -0,0 +1,271 @@ +/* + * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __ESP_SDP_API_H__ +#define __ESP_SDP_API_H__ + +#include "esp_err.h" +#include "esp_bt_defs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ESP_SDP_SERVER_NAME_MAX 32 /*!< Service name max length */ +#define SDP_OPP_SUPPORTED_FORMATS_MAX_LENGTH 15 /*!< OPP supported format list maximum length */ + +typedef enum { + ESP_SDP_SUCCESS = 0, /*!< Successful operation. */ + ESP_SDP_FAILURE, /*!< Generic failure. */ + ESP_SDP_NO_RESOURCE, /*!< No more resource */ + ESP_SDP_NEED_INIT, /*!< SDP module shall init first */ + ESP_SDP_NEED_DEINIT, /*!< SDP module shall deinit first */ + ESP_SDP_NO_CREATE_RECORD, /*!< No record created */ +} esp_sdp_status_t; + +/** + * @brief SDP callback function events + */ +typedef enum { + ESP_SDP_INIT_EVT = 0, /*!< When SDP is inited, the event comes */ + ESP_SDP_DEINIT_EVT = 1, /*!< When SDP is deinited, the event comes */ + ESP_SDP_SEARCH_COMP_EVT = 2, /*!< When SDP search complete, the event comes */ + ESP_SDP_CREATE_RECORD_COMP_EVT = 3, /*!< When create SDP records complete, the event comes */ + ESP_SDP_REMOVE_RECORD_COMP_EVT = 4, /*!< When remove a SDP record complete, the event comes */ +} esp_sdp_cb_event_t; + +/** + * @brief SDP record type + */ +typedef enum { + ESP_SDP_TYPE_RAW, /*!< Used to carry raw SDP search data for unknown UUIDs */ + ESP_SDP_TYPE_MAP_MAS, /*!< Message Access Profile - Server */ + ESP_SDP_TYPE_MAP_MNS, /*!< Message Access Profile - Client (Notification Server) */ + ESP_SDP_TYPE_PBAP_PSE, /*!< Phone Book Profile - Server */ + ESP_SDP_TYPE_PBAP_PCE, /*!< Phone Book Profile - Client */ + ESP_SDP_TYPE_OPP_SERVER, /*!< Object Push Profile */ + ESP_SDP_TYPE_SAP_SERVER /*!< SIM Access Profile */ +} esp_bluetooth_sdp_types_t; + +/** + * @brief Some signals need additional pointers, hence we introduce a + * generic way to handle these pointers. + */ +typedef struct bluetooth_sdp_hdr_overlay { + esp_bluetooth_sdp_types_t type; /*!< SDP type */ + esp_bt_uuid_t uuid; /*!< UUID type, include uuid and uuid length */ + uint32_t service_name_length; /*!< Service name length */ + char *service_name; /*!< service name */ + int32_t rfcomm_channel_number; /*!< rfcomm channel number, if not used set to -1*/ + int32_t l2cap_psm; /*!< l2cap psm, if not used set to -1 */ + int32_t profile_version; /*!< profile version */ + + // User pointers, only used for some signals - see esp_bluetooth_sdp_ops_record_t + int user1_ptr_len; /*!< see esp_bluetooth_sdp_ops_record_t */ + uint8_t *user1_ptr; /*!< see esp_bluetooth_sdp_ops_record_t */ + int user2_ptr_len; /*!< see esp_bluetooth_sdp_ops_record_t */ + uint8_t *user2_ptr; /*!< see esp_bluetooth_sdp_ops_record_t */ +} esp_bluetooth_sdp_hdr_overlay_t; + +/** + * @brief Message Access Profile - Server parameters + */ +typedef struct bluetooth_sdp_mas_record { + esp_bluetooth_sdp_hdr_overlay_t hdr; /*!< General info */ + uint32_t mas_instance_id; /*!< MAS Instance ID */ + uint32_t supported_features; /*!< Map supported features */ + uint32_t supported_message_types; /*!< Supported message types */ +} esp_bluetooth_sdp_mas_record_t; + +/** + * @brief Message Access Profile - Client (Notification Server) parameters + */ +typedef struct bluetooth_sdp_mns_record { + esp_bluetooth_sdp_hdr_overlay_t hdr; /*!< General info */ + uint32_t supported_features; /*!< Supported features */ +} esp_bluetooth_sdp_mns_record_t; + +/** + * @brief Phone Book Profile - Server parameters + */ +typedef struct bluetooth_sdp_pse_record { + esp_bluetooth_sdp_hdr_overlay_t hdr; /*!< General info */ + uint32_t supported_features; /*!< Pbap Supported Features */ + uint32_t supported_repositories; /*!< Supported Repositories */ +} esp_bluetooth_sdp_pse_record_t; + +/** + * @brief Phone Book Profile - Client parameters + */ +typedef struct bluetooth_sdp_pce_record { + esp_bluetooth_sdp_hdr_overlay_t hdr; /*!< General info */ +} esp_bluetooth_sdp_pce_record_t; + +/** + * @brief Object Push Profile parameters + */ +typedef struct bluetooth_sdp_ops_record { + esp_bluetooth_sdp_hdr_overlay_t hdr; /*!< General info */ + int supported_formats_list_len; /*!< Supported formats list length */ + uint8_t supported_formats_list[SDP_OPP_SUPPORTED_FORMATS_MAX_LENGTH]; /*!< Supported formats list */ +} esp_bluetooth_sdp_ops_record_t; + +/** + * @brief SIM Access Profile parameters + */ +typedef struct bluetooth_sdp_sap_record { + esp_bluetooth_sdp_hdr_overlay_t hdr; /*!< General info */ +} esp_bluetooth_sdp_sap_record_t; + +/** + * @brief SDP record parameters union + */ +typedef union { + esp_bluetooth_sdp_hdr_overlay_t hdr; /*!< General info */ + esp_bluetooth_sdp_mas_record_t mas; /*!< Message Access Profile - Server */ + esp_bluetooth_sdp_mns_record_t mns; /*!< Message Access Profile - Client (Notification Server) */ + esp_bluetooth_sdp_pse_record_t pse; /*!< Phone Book Profile - Server */ + esp_bluetooth_sdp_pce_record_t pce; /*!< Phone Book Profile - Client */ + esp_bluetooth_sdp_ops_record_t ops; /*!< Object Push Profile */ + esp_bluetooth_sdp_sap_record_t sap; /*!< SIM Access Profile */ +} esp_bluetooth_sdp_record_t; + +/** + * @brief SDP callback parameters union + */ +typedef union { + /** + * @brief ESP_SDP_INIT_EVT + */ + struct sdp_init_evt_param { + esp_sdp_status_t status; /*!< status */ + } init; /*!< SDP callback param of ESP_SDP_INIT_EVT */ + + /** + * @brief ESP_SDP_DEINIT_EVT + */ + struct sdp_deinit_evt_param { + esp_sdp_status_t status; /*!< status */ + } deinit; /*!< SDP callback param of ESP_SDP_DEINIT_EVT */ + + /** + * @brief ESP_SDP_SEARCH_COMP_EVT + */ + struct sdp_search_evt_param { + esp_sdp_status_t status; /*!< status */ + esp_bd_addr_t remote_addr; /*!< remote device address */ + esp_bt_uuid_t sdp_uuid; /*!< service uuid */ + int record_count; /*!< Number of SDP records */ + esp_bluetooth_sdp_record_t *records;/*!< SDP records */ + } search; /*!< SDP callback param of ESP_SDP_SEARCH_COMP_EVT */ + + /** + * @brief ESP_SDP_CREATE_RECORD_COMP_EVT + */ + struct sdp_crate_record_evt_param { + esp_sdp_status_t status; /*!< status */ + int record_handle; /*!< SDP record handle */ + } create_record; /*!< SDP callback param of ESP_SDP_CREATE_RECORD_COMP_EVT */ + + /** + * @brief ESP_SDP_REMOVE_RECORD_COMP_EVT + */ + struct sdp_remove_record_evt_param { + esp_sdp_status_t status; /*!< status */ + } remove_record; /*!< SDP callback param of ESP_SDP_REMOVE_RECORD_COMP_EVT */ + +} esp_sdp_cb_param_t; /*!< SDP callback parameter union type */ + + +/** + * @brief SDP callback function type. + * + * @param event: Event type + * @param param: Point to callback parameter, currently is union type + */ +typedef void (* esp_sdp_cb_t)(esp_sdp_cb_event_t event, esp_sdp_cb_param_t *param); + +/** + * @brief This function is called to init callbacks with SDP module. + * + * @param[in] callback: pointer to the init callback function. + * + * @return + * - ESP_OK: success + * - other: failed + */ +esp_err_t esp_sdp_register_callback(esp_sdp_cb_t callback); + +/** + * @brief This function is called to init SDP module. + * When the operation is completed, the callback function will be called with ESP_SDP_INIT_EVT. + * This function should be called after esp_bluedroid_enable() completes successfully. + * + * @return + * - ESP_OK: success + * - other: failed + */ +esp_err_t esp_sdp_init(void); + +/** + * @brief This function is called to de-initialize SDP module. + * The operation will remove all SDP records, then the callback function will be called + * with ESP_SDP_REMOVE_RECORD_COMP_EVT, and the number of ESP_SDP_REMOVE_RECORD_COMP_EVT is + * equal to the number of SDP records.When the operation is completed, the callback function + * will be called with ESP_SDP_DEINIT_EVT. This function should be called after esp_sdp_init() + * completes successfully. + * + * @return + * - ESP_OK: success + * - other: failed + */ +esp_err_t esp_sdp_deinit(void); + +/** + * @brief This function is called to performs service discovery for the services provided by the given peer device. + * When the operation is completed, the callback function will be called with ESP_SDP_SEARCH_COMP_EVT. + * This funciton must be called after esp_sdp_init() successful and before esp_sdp_deinit(). + * + * @param[in] bd_addr: Remote device bluetooth device address. + * @param[in] uuid: Service UUID of the remote device. + * + * @return + * - ESP_OK: success + * - other: failed + */ +esp_err_t esp_sdp_search_record(esp_bd_addr_t bd_addr, esp_bt_uuid_t uuid); + +/** + * @brief This function is called to create SDP records. + * When the operation is completed, the callback function will be called with ESP_SDP_CREATE_RECORD_COMP_EVT. + * This funciton must be called after esp_sdp_init() successful and before esp_sdp_deinit(). + * + * @param[in] record: The SDP record to create. + * + * @return + * - ESP_OK: success + * - other: failed + */ +esp_err_t esp_sdp_create_record(esp_bluetooth_sdp_record_t *record); + +/** + * @brief This function is called to remove a SDP record. + * When the operation is completed, the callback function will be called with ESP_SDP_REMOVE_RECORD_COMP_EVT. + * This funciton must be called after esp_sdp_init() successful and before esp_sdp_deinit(). + * + * @param[in] record_handle: The SDP record handle. + * + * @return + * - ESP_OK: success + * - other: failed + */ +esp_err_t esp_sdp_remove_record(int record_handle); + +#ifdef __cplusplus +} +#endif + +#endif ///__ESP_SDP_API_H__ diff --git a/components/bt/host/bluedroid/bta/include/bta/bta_sdp_api.h b/components/bt/host/bluedroid/bta/include/bta/bta_sdp_api.h index 1d32b9204f..2d0d0eb4b7 100644 --- a/components/bt/host/bluedroid/bta/include/bta/bta_sdp_api.h +++ b/components/bt/host/bluedroid/bta/include/bta/bta_sdp_api.h @@ -40,12 +40,13 @@ typedef UINT8 tBTA_SDP_STATUS; /* SDP I/F callback events */ /* events received by tBTA_SDP_DM_CBACK */ -#define BTA_SDP_ENABLE_EVT 0 /* SDP service i/f enabled*/ -#define BTA_SDP_SEARCH_EVT 1 /* SDP Service started */ -#define BTA_SDP_SEARCH_COMP_EVT 2 /* SDP search complete */ -#define BTA_SDP_CREATE_RECORD_USER_EVT 3 /* SDP search complete */ -#define BTA_SDP_REMOVE_RECORD_USER_EVT 4 /* SDP search complete */ -#define BTA_SDP_MAX_EVT 5 /* max number of SDP events */ +#define BTA_SDP_ENABLE_EVT 0 /* SDP service enabled*/ +#define BTA_SDP_DISENABLE_EVT 1 /* SDP service disenabled*/ +#define BTA_SDP_SEARCH_EVT 2 /* SDP search started */ +#define BTA_SDP_SEARCH_COMP_EVT 3 /* SDP search complete */ +#define BTA_SDP_CREATE_RECORD_USER_EVT 4 /* SDP create record complete */ +#define BTA_SDP_REMOVE_RECORD_USER_EVT 5 /* SDP remove reocrd complete */ +#define BTA_SDP_MAX_EVT 6 /* max number of SDP events */ #define BTA_SDP_MAX_RECORDS 15 @@ -63,6 +64,7 @@ typedef struct { typedef union { tBTA_SDP_STATUS status; /* BTA_SDP_SEARCH_EVT */ tBTA_SDP_SEARCH_COMP sdp_search_comp; /* BTA_SDP_SEARCH_COMP_EVT */ + int handle; } tBTA_SDP; /* SDP DM Interface callback */ diff --git a/components/bt/host/bluedroid/bta/sdp/bta_sdp_act.c b/components/bt/host/bluedroid/bta/sdp/bta_sdp_act.c index 5ce91a5f03..8f06145ce5 100644 --- a/components/bt/host/bluedroid/bta/sdp/bta_sdp_act.c +++ b/components/bt/host/bluedroid/bta/sdp/bta_sdp_act.c @@ -439,9 +439,10 @@ static void bta_sdp_search_cback(UINT16 result, void *user_data) void bta_sdp_enable(tBTA_SDP_MSG *p_data) { APPL_TRACE_DEBUG("%s in, sdp_active:%d\n", __func__, bta_sdp_cb.sdp_active); - tBTA_SDP_STATUS status = BTA_SDP_SUCCESS; + tBTA_SDP bta_sdp; + bta_sdp.status = BTA_SDP_SUCCESS; bta_sdp_cb.p_dm_cback = p_data->enable.p_cback; - bta_sdp_cb.p_dm_cback(BTA_SDP_ENABLE_EVT, (tBTA_SDP *)&status, NULL); + bta_sdp_cb.p_dm_cback(BTA_SDP_ENABLE_EVT, (tBTA_SDP *)&bta_sdp, NULL); } /******************************************************************************* @@ -523,8 +524,11 @@ void bta_sdp_search(tBTA_SDP_MSG *p_data) void bta_sdp_create_record(tBTA_SDP_MSG *p_data) { APPL_TRACE_DEBUG("%s() event: %d\n", __func__, p_data->record.hdr.event); + tBTA_SDP bta_sdp; + bta_sdp.status = BTA_SDP_SUCCESS; + bta_sdp.handle = (int)p_data->record.user_data; if (bta_sdp_cb.p_dm_cback) { - bta_sdp_cb.p_dm_cback(BTA_SDP_CREATE_RECORD_USER_EVT, NULL, p_data->record.user_data); + bta_sdp_cb.p_dm_cback(BTA_SDP_CREATE_RECORD_USER_EVT, &bta_sdp, p_data->record.user_data); } } @@ -540,8 +544,10 @@ void bta_sdp_create_record(tBTA_SDP_MSG *p_data) void bta_sdp_remove_record(tBTA_SDP_MSG *p_data) { APPL_TRACE_DEBUG("%s() event: %d\n", __func__, p_data->record.hdr.event); + tBTA_SDP bta_sdp; + bta_sdp.status = BTA_SDP_SUCCESS; if (bta_sdp_cb.p_dm_cback) { - bta_sdp_cb.p_dm_cback(BTA_SDP_REMOVE_RECORD_USER_EVT, NULL, p_data->record.user_data); + bta_sdp_cb.p_dm_cback(BTA_SDP_REMOVE_RECORD_USER_EVT, &bta_sdp, p_data->record.user_data); } } diff --git a/components/bt/host/bluedroid/bta/sdp/bta_sdp_api.c b/components/bt/host/bluedroid/bta/sdp/bta_sdp_api.c index e26f93910c..cafb1a4a4c 100644 --- a/components/bt/host/bluedroid/bta/sdp/bta_sdp_api.c +++ b/components/bt/host/bluedroid/bta/sdp/bta_sdp_api.c @@ -102,6 +102,8 @@ tBTA_SDP_STATUS BTA_SdpEnable(tBTA_SDP_DM_CBACK *p_cback) tBTA_SDP_STATUS BTA_SdpDisable(void) { tBTA_SDP_STATUS status = BTA_SDP_SUCCESS; + + bta_sys_deregister(BTA_ID_SDP); #if BTA_DYNAMIC_MEMORY == TRUE /* Free buffer for SDP configuration structure */ osi_free(p_bta_sdp_cfg->p_sdp_db); diff --git a/components/bt/host/bluedroid/btc/profile/std/include/bt_sdp.h b/components/bt/host/bluedroid/btc/profile/std/include/bt_sdp.h index b2da0873a5..63ca09a80f 100644 --- a/components/bt/host/bluedroid/btc/profile/std/include/bt_sdp.h +++ b/components/bt/host/bluedroid/btc/profile/std/include/bt_sdp.h @@ -20,6 +20,7 @@ #include // #include "bluetooth.h" #include "common/bt_defs.h" +#include "esp_bt_defs.h" #define SDP_OPP_SUPPORTED_FORMATS_MAX_LENGTH 15 @@ -38,7 +39,7 @@ typedef enum { typedef struct _bluetooth_sdp_hdr { bluetooth_sdp_types type; - bt_uuid_t uuid; + esp_bt_uuid_t uuid; uint32_t service_name_length; char *service_name; int32_t rfcomm_channel_number; @@ -52,7 +53,7 @@ typedef struct _bluetooth_sdp_hdr { */ typedef struct _bluetooth_sdp_hdr_overlay { bluetooth_sdp_types type; - bt_uuid_t uuid; + esp_bt_uuid_t bt_uuid; uint32_t service_name_length; char *service_name; int32_t rfcomm_channel_number; diff --git a/components/bt/host/bluedroid/btc/profile/std/include/btc_sdp.h b/components/bt/host/bluedroid/btc/profile/std/include/btc_sdp.h new file mode 100644 index 0000000000..60772fa3c4 --- /dev/null +++ b/components/bt/host/bluedroid/btc/profile/std/include/btc_sdp.h @@ -0,0 +1,53 @@ +/* + * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __BTC_SDP_H__ +#define __BTC_SDP_H__ + +#include "btc/btc_task.h" +#include "esp_bt_defs.h" +#include "common/bt_target.h" +#include "bta/bta_sdp_api.h" +#include "bt_sdp.h" + +#if (defined BTC_SDP_INCLUDED && BTC_SDP_INCLUDED == TRUE) + +typedef enum { + BTC_SDP_ACT_INIT = 0, + BTC_SDP_ACT_DEINIT, + BTC_SDP_ACT_SEARCH, + BTC_SDP_ACT_CREATE_RECORD, + BTC_SDP_ACT_REMOVE_RECORD, +} btc_sdp_act_t; + +/* btc_sdp_args_t */ +typedef union { + //BTC_SDP_ACT_SEARCH + struct search_record_arg { + BD_ADDR bd_addr; + tSDP_UUID sdp_uuid; + } search; + + //BTC_SDP_ACT_CREATE_RECORD + struct creat_record_arg { + bluetooth_sdp_record *record; + } creat_record; + + //BTC_SDP_ACT_REMOVE_RECORD + struct remove_record_arg { + int record_handle; + } remove_record; + +} btc_sdp_args_t; + +void btc_sdp_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src); +void btc_sdp_arg_deep_free(btc_msg_t *msg); + +void btc_sdp_call_handler(btc_msg_t *msg); +void btc_sdp_cb_handler(btc_msg_t *msg); + +#endif ///defined BTC_SDP_INCLUDED && BTC_SDP_INCLUDED == TRUE +#endif ///__BTC_SDP_H__ diff --git a/components/bt/host/bluedroid/btc/profile/std/sdp/btc_sdp.c b/components/bt/host/bluedroid/btc/profile/std/sdp/btc_sdp.c new file mode 100644 index 0000000000..41132739ce --- /dev/null +++ b/components/bt/host/bluedroid/btc/profile/std/sdp/btc_sdp.c @@ -0,0 +1,1023 @@ +/* + * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include "btc_sdp.h" +#include "btc/btc_manage.h" +#include "btc/btc_task.h" +#include "bta/bta_sdp_api.h" +#include "bta/bta_sys.h" +#include "bta/utl.h" +#include "bt_sdp.h" +#include "osi/mutex.h" +#include "osi/allocator.h" +#include "esp_sdp_api.h" + +#if (defined BTC_SDP_INCLUDED && BTC_SDP_INCLUDED == TRUE) + +typedef enum { + SDP_RECORD_FREE = 0, + SDP_RECORD_ALLOCED, +} sdp_state_t; + +typedef struct { + sdp_state_t state; + int sdp_handle; + bluetooth_sdp_record* record_data; +} sdp_slot_t; + +typedef struct { + sdp_slot_t *sdp_slots[SDP_MAX_RECORDS]; + osi_mutex_t sdp_slot_mutex; +} sdp_local_param_t; + +#if SDP_DYNAMIC_MEMORY == FALSE +static sdp_local_param_t sdp_local_param; +#else +static sdp_local_param_t *sdp_local_param_ptr; +#define sdp_local_param (*sdp_local_param_ptr) +#endif + +#if SDP_DYNAMIC_MEMORY == FALSE +#define is_sdp_init() (sdp_local_param.sdp_slot_mutex != NULL) +#else +#define is_sdp_init() (&sdp_local_param != NULL && sdp_local_param.sdp_slot_mutex != NULL) +#endif + + +static inline void btc_sdp_cb_to_app(esp_sdp_cb_event_t event, esp_sdp_cb_param_t *param) +{ + esp_sdp_cb_t btc_sdp_cb = (esp_sdp_cb_t)btc_profile_cb_get(BTC_PID_SDP); + if (btc_sdp_cb) { + btc_sdp_cb(event, param); + } +} + +static void sdp_disable_handler(void) +{ + btc_msg_t msg; + bt_status_t status; + + msg.sig = BTC_SIG_API_CB; + msg.pid = BTC_PID_SDP; + msg.act = BTA_SDP_DISENABLE_EVT; + + status = btc_transfer_context(&msg, NULL, 0, NULL); + + if (status != BT_STATUS_SUCCESS) { + BTC_TRACE_ERROR("%s btc_transfer_context failed", __func__); + } +} + +static int get_sdp_records_size(bluetooth_sdp_record* in_record, int count) +{ + bluetooth_sdp_record* record = in_record; + int records_size = 0; + + for(int i = 0; i < count; i++) { + record = &in_record[i]; + records_size += sizeof(bluetooth_sdp_record); + records_size += record->hdr.service_name_length; + if(record->hdr.service_name_length > 0){ + records_size++; /* + '\0' termination of string */ + } + records_size += record->hdr.user1_ptr_len; + records_size += record->hdr.user2_ptr_len; + } + + return records_size; +} + +static void set_sdp_handle(int id, int handle) +{ + sdp_slot_t *slot = NULL; + + BTC_TRACE_DEBUG("%s() id=%d to handle=0x%08x", __func__, id, handle); + + if(id >= SDP_MAX_RECORDS) { + BTC_TRACE_ERROR("%s() failed - id %d is invalid", __func__, id); + return; + } + + osi_mutex_lock(&sdp_local_param.sdp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT); + slot = sdp_local_param.sdp_slots[id]; + if (slot == NULL) { + osi_mutex_unlock(&sdp_local_param.sdp_slot_mutex); + BTC_TRACE_ERROR("%s() id=%d to handle=0x%08x, set failed", __func__, id, handle); + return; + } + slot->sdp_handle = handle; + osi_mutex_unlock(&sdp_local_param.sdp_slot_mutex); +} + +static sdp_slot_t *start_create_sdp(int id) +{ + sdp_slot_t *sdp_slot = NULL; + + if(id >= SDP_MAX_RECORDS) { + BTC_TRACE_ERROR("%s() failed - id %d is invalid", __func__, id); + return NULL; + } + + osi_mutex_lock(&sdp_local_param.sdp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT); + sdp_slot = sdp_local_param.sdp_slots[id]; + if (sdp_slot == NULL) { + BTC_TRACE_ERROR("%s() id = %d ", __func__, id); + } else if(sdp_slot->state != SDP_RECORD_ALLOCED) { + BTC_TRACE_ERROR("%s() failed - state for id %d is state = %d expected %d", __func__, + id, sdp_local_param.sdp_slots[id]->state, SDP_RECORD_ALLOCED); + /* The record have been removed before this event occurred - e.g. deinit */ + sdp_slot = NULL; + } + osi_mutex_unlock(&sdp_local_param.sdp_slot_mutex); + + return sdp_slot; +} + +/* Deep copy all content of in_records into out_records. + * out_records must point to a chunk of memory large enough to contain all + * the data. Use getSdpRecordsSize() to calculate the needed size. */ +static void copy_sdp_records(bluetooth_sdp_record* in_records, bluetooth_sdp_record* out_records, int count) +{ + bluetooth_sdp_record *in_record; + bluetooth_sdp_record *out_record; + char *free_ptr = (char*)(&out_records[count]); /* set pointer to after the last entry */ + + for(int i = 0; i < count; i++) { + in_record = &in_records[i]; + out_record = &out_records[i]; + *out_record = *in_record; + + if(in_record->hdr.service_name == NULL || in_record->hdr.service_name_length == 0) { + out_record->hdr.service_name = NULL; + out_record->hdr.service_name_length = 0; + } else { + out_record->hdr.service_name = free_ptr; // Update service_name pointer + // Copy string + memcpy(free_ptr, in_record->hdr.service_name, in_record->hdr.service_name_length); + free_ptr += in_record->hdr.service_name_length; + *(free_ptr) = '\0'; // Set '\0' termination of string + free_ptr++; + } + if(in_record->hdr.user1_ptr != NULL) { + out_record->hdr.user1_ptr = (UINT8*)free_ptr; // Update pointer + memcpy(free_ptr, in_record->hdr.user1_ptr, in_record->hdr.user1_ptr_len); // Copy content + free_ptr += in_record->hdr.user1_ptr_len; + } + if(in_record->hdr.user2_ptr != NULL) { + out_record->hdr.user2_ptr = (UINT8*)free_ptr; // Update pointer + memcpy(free_ptr, in_record->hdr.user2_ptr, in_record->hdr.user2_ptr_len); // Copy content + free_ptr += in_record->hdr.user2_ptr_len; + } + } +} + +static int alloc_sdp_slot(bluetooth_sdp_record* in_record) +{ + int i; + int record_size = get_sdp_records_size(in_record, 1); + bluetooth_sdp_record *record = NULL; + sdp_slot_t **slot = NULL; + + record = osi_malloc(record_size); + if (record == NULL) { + BTC_TRACE_ERROR("%s() osi_malloc failed!", __func__); + return -1; + } + + copy_sdp_records(in_record, record, 1); + + osi_mutex_lock(&sdp_local_param.sdp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT); + for(i = 0; i < SDP_MAX_RECORDS; i++) + { + slot = &sdp_local_param.sdp_slots[i]; + if ((*slot) == NULL) { + if (((*slot) = (sdp_slot_t *)osi_malloc(sizeof(sdp_slot_t))) == NULL) { + osi_mutex_unlock(&sdp_local_param.sdp_slot_mutex); + BTC_TRACE_ERROR("%s() osi_malloc slot failed!", __func__); + osi_free(record); + return -1; + } + (*slot)->state = SDP_RECORD_ALLOCED; + (*slot)->record_data = record; + break; + } + } + osi_mutex_unlock(&sdp_local_param.sdp_slot_mutex); + if(i >= SDP_MAX_RECORDS) { + BTC_TRACE_ERROR("%s() failed - no more free slots!", __func__); + osi_free(record); + return -1; + } + + return i; +} + +static int free_sdp_slot(int id) +{ + int handle = -1; + bluetooth_sdp_record *record = NULL; + sdp_slot_t *slot = NULL; + + if(id >= SDP_MAX_RECORDS) { + APPL_TRACE_ERROR("%s() failed - id %d is invalid", __func__, id); + return handle; + } + slot = sdp_local_param.sdp_slots[id]; + if (slot == NULL) { + // already freed + return handle; + } + + osi_mutex_lock(&sdp_local_param.sdp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT); + handle = slot->sdp_handle; + if (slot->state != SDP_RECORD_FREE) { + /* safe a copy of the pointer, and free after unlock() */ + record = slot->record_data; + } + osi_mutex_unlock(&sdp_local_param.sdp_slot_mutex); + + if(record != NULL) { + osi_free(record); + } else { + // Record have already been freed + handle = -1; + } + osi_free(slot); + slot = NULL; + + return handle; +} + +/* Create a MAP MAS SDP record based on information stored in a bluetooth_sdp_mas_record */ +static int add_maps_sdp(const bluetooth_sdp_mas_record* rec) +{ + tSDP_PROTOCOL_ELEM protoList [3]; + UINT16 service = UUID_SERVCLASS_MESSAGE_ACCESS; + UINT16 browse = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP; + bool status = true; + UINT32 sdp_handle = 0; + UINT8 temp[4]; + UINT8* p_temp = temp; + + BTC_TRACE_DEBUG("%s(): MASID = 0x%02x, scn 0x%02x, psm = 0x%04x\n service name %s", __func__, + rec->mas_instance_id, rec->hdr.rfcomm_channel_number, + rec->hdr.l2cap_psm, rec->hdr.service_name); + + BTC_TRACE_DEBUG(" msg_types: 0x%02x, feature_bits: 0x%08x", + rec->supported_message_types, rec->supported_features); + + if ((sdp_handle = SDP_CreateRecord()) == 0) { + BTC_TRACE_ERROR("%s() - Unable to register MAPS Service", __func__); + return sdp_handle; + } + + /* add service class */ + status &= SDP_AddServiceClassIdList(sdp_handle, 1, &service); + memset( protoList, 0 , 3*sizeof(tSDP_PROTOCOL_ELEM) ); + + /* add protocol list, including RFCOMM scn */ + protoList[0].protocol_uuid = UUID_PROTOCOL_L2CAP; + protoList[0].num_params = 0; + protoList[1].protocol_uuid = UUID_PROTOCOL_RFCOMM; + protoList[1].num_params = 1; + protoList[1].params[0] = rec->hdr.rfcomm_channel_number; + protoList[2].protocol_uuid = UUID_PROTOCOL_OBEX; + protoList[2].num_params = 0; + status &= SDP_AddProtocolList(sdp_handle, 3, protoList); + + /* Add a name entry */ + status &= SDP_AddAttribute(sdp_handle, + (UINT16)ATTR_ID_SERVICE_NAME, + (UINT8)TEXT_STR_DESC_TYPE, + (UINT32)(rec->hdr.service_name_length + 1), + (UINT8 *)rec->hdr.service_name); + + /* Add in the Bluetooth Profile Descriptor List */ + status &= SDP_AddProfileDescriptorList(sdp_handle, + UUID_SERVCLASS_MAP_PROFILE, + rec->hdr.profile_version); + + /* Add MAS instance ID */ + status &= SDP_AddAttribute(sdp_handle, ATTR_ID_MAS_INSTANCE_ID, UINT_DESC_TYPE, + (UINT32)1, (UINT8*)&rec->mas_instance_id); + + /* Add supported message types */ + status &= SDP_AddAttribute(sdp_handle, ATTR_ID_SUPPORTED_MSG_TYPE, UINT_DESC_TYPE, + (UINT32)1, (UINT8*)&rec->supported_message_types); + + /* Add supported feature */ + UINT32_TO_BE_STREAM(p_temp, rec->supported_features); + status &= SDP_AddAttribute(sdp_handle, ATTR_ID_MAP_SUPPORTED_FEATURES, + UINT_DESC_TYPE, (UINT32)4, temp); + + /* Add the L2CAP PSM if present */ + if(rec->hdr.l2cap_psm != -1) { + p_temp = temp;// The macro modifies p_temp, hence rewind. + UINT16_TO_BE_STREAM(p_temp, rec->hdr.l2cap_psm); + status &= SDP_AddAttribute(sdp_handle, ATTR_ID_GOEP_L2CAP_PSM, + UINT_DESC_TYPE, (UINT32)2, temp); + } + + /* Make the service browseable */ + status &= SDP_AddUuidSequence (sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse); + + if (!status) { + SDP_DeleteRecord(sdp_handle); + sdp_handle = 0; + BTC_TRACE_ERROR("%s() FAILED", __func__); + } else { + bta_sys_add_uuid(service); /* UUID_SERVCLASS_MESSAGE_ACCESS */ + BTC_TRACE_DEBUG("%s(): SDP Registered (handle 0x%08x)", __func__, sdp_handle); + } + + return sdp_handle; +} + +/* Create a MAP MNS SDP record based on information stored in a bluetooth_sdp_mns_record */ +static int add_mapc_sdp(const bluetooth_sdp_mns_record* rec) +{ + tSDP_PROTOCOL_ELEM protoList [3]; + UINT16 service = UUID_SERVCLASS_MESSAGE_NOTIFICATION; + UINT16 browse = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP; + bool status = true; + UINT32 sdp_handle = 0; + UINT8 temp[4]; + UINT8* p_temp = temp; + + BTC_TRACE_DEBUG("%s(): scn 0x%02x, psm = 0x%04x\n service name %s", __func__, + rec->hdr.rfcomm_channel_number, rec->hdr.l2cap_psm, rec->hdr.service_name); + + BTC_TRACE_DEBUG(" feature_bits: 0x%08x", rec->supported_features); + + if ((sdp_handle = SDP_CreateRecord()) == 0) { + BTC_TRACE_ERROR("%s(): Unable to register MAP Notification Service", __func__); + return sdp_handle; + } + + /* add service class */ + status &= SDP_AddServiceClassIdList(sdp_handle, 1, &service); + memset( protoList, 0 , 3*sizeof(tSDP_PROTOCOL_ELEM) ); + + /* add protocol list, including RFCOMM scn */ + protoList[0].protocol_uuid = UUID_PROTOCOL_L2CAP; + protoList[0].num_params = 0; + protoList[1].protocol_uuid = UUID_PROTOCOL_RFCOMM; + protoList[1].num_params = 1; + protoList[1].params[0] = rec->hdr.rfcomm_channel_number; + protoList[2].protocol_uuid = UUID_PROTOCOL_OBEX; + protoList[2].num_params = 0; + status &= SDP_AddProtocolList(sdp_handle, 3, protoList); + + /* Add a name entry */ + status &= SDP_AddAttribute(sdp_handle, + (UINT16)ATTR_ID_SERVICE_NAME, + (UINT8)TEXT_STR_DESC_TYPE, + (UINT32)(rec->hdr.service_name_length + 1), + (UINT8 *)rec->hdr.service_name); + + /* Add in the Bluetooth Profile Descriptor List */ + status &= SDP_AddProfileDescriptorList(sdp_handle, + UUID_SERVCLASS_MAP_PROFILE, + rec->hdr.profile_version); + + /* Add supported feature */ + UINT32_TO_BE_STREAM(p_temp, rec->supported_features); + status &= SDP_AddAttribute(sdp_handle, ATTR_ID_MAP_SUPPORTED_FEATURES, + UINT_DESC_TYPE, (UINT32)4, temp); + + /* Add the L2CAP PSM if present */ + if(rec->hdr.l2cap_psm != -1) { + p_temp = temp;// The macro modifies p_temp, hence rewind. + UINT16_TO_BE_STREAM(p_temp, rec->hdr.l2cap_psm); + status &= SDP_AddAttribute(sdp_handle, ATTR_ID_GOEP_L2CAP_PSM, + UINT_DESC_TYPE, (UINT32)2, temp); + } + + /* Make the service browseable */ + status &= SDP_AddUuidSequence (sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse); + + if (!status) { + SDP_DeleteRecord(sdp_handle); + sdp_handle = 0; + BTC_TRACE_ERROR("%s() FAILED", __func__); + } else { + bta_sys_add_uuid(service); /* UUID_SERVCLASS_MESSAGE_ACCESS */ + BTC_TRACE_DEBUG("%s(): SDP Registered (handle 0x%08x)", __func__, sdp_handle); + } + + return sdp_handle; +} + +/* Create a PBAP Server SDP record based on information stored in a bluetooth_sdp_pse_record */ +static int add_pbaps_sdp(const bluetooth_sdp_pse_record* rec) +{ + tSDP_PROTOCOL_ELEM protoList [3]; + UINT16 service = UUID_SERVCLASS_PBAP_PSE; + UINT16 browse = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP; + bool status = true; + UINT32 sdp_handle = 0; + UINT8 temp[4]; + UINT8* p_temp = temp; + + BTC_TRACE_DEBUG("%s(): scn 0x%02x, psm = 0x%04x\n service name %s", __func__, + rec->hdr.rfcomm_channel_number, rec->hdr.l2cap_psm, rec->hdr.service_name); + + BTC_TRACE_DEBUG(" supported_repositories: 0x%08x, feature_bits: 0x%08x", + rec->supported_repositories, rec->supported_features); + + if ((sdp_handle = SDP_CreateRecord()) == 0) { + BTC_TRACE_ERROR("%s(): Unable to register PBAP Server Service", __func__); + return sdp_handle; + } + + /* add service class */ + status &= SDP_AddServiceClassIdList(sdp_handle, 1, &service); + memset( protoList, 0 , 3*sizeof(tSDP_PROTOCOL_ELEM) ); + + /* add protocol list, including RFCOMM scn */ + protoList[0].protocol_uuid = UUID_PROTOCOL_L2CAP; + protoList[0].num_params = 0; + protoList[1].protocol_uuid = UUID_PROTOCOL_RFCOMM; + protoList[1].num_params = 1; + protoList[1].params[0] = rec->hdr.rfcomm_channel_number; + protoList[2].protocol_uuid = UUID_PROTOCOL_OBEX; + protoList[2].num_params = 0; + status &= SDP_AddProtocolList(sdp_handle, 3, protoList); + + /* Add a name entry */ + status &= SDP_AddAttribute(sdp_handle, + (UINT16)ATTR_ID_SERVICE_NAME, + (UINT8)TEXT_STR_DESC_TYPE, + (UINT32)(rec->hdr.service_name_length + 1), + (UINT8 *)rec->hdr.service_name); + + /* Add in the Bluetooth Profile Descriptor List */ + status &= SDP_AddProfileDescriptorList(sdp_handle, + UUID_SERVCLASS_PHONE_ACCESS, + rec->hdr.profile_version); + + /* Add supported repositories 1 byte */ + status &= SDP_AddAttribute(sdp_handle, ATTR_ID_SUPPORTED_REPOSITORIES, + UINT_DESC_TYPE, (UINT32)1, (UINT8*)&rec->supported_repositories); + + /* Add supported feature 4 bytes*/ + UINT32_TO_BE_STREAM(p_temp, rec->supported_features); + status &= SDP_AddAttribute(sdp_handle, ATTR_ID_PBAP_SUPPORTED_FEATURES, + UINT_DESC_TYPE, (UINT32)4, temp); + + /* Add the L2CAP PSM if present */ + if(rec->hdr.l2cap_psm != -1) { + p_temp = temp;// The macro modifies p_temp, hence rewind. + UINT16_TO_BE_STREAM(p_temp, rec->hdr.l2cap_psm); + status &= SDP_AddAttribute(sdp_handle, ATTR_ID_GOEP_L2CAP_PSM, + UINT_DESC_TYPE, (UINT32)2, temp); + } + + /* Make the service browseable */ + status &= SDP_AddUuidSequence (sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse); + + if (!status) { + SDP_DeleteRecord(sdp_handle); + sdp_handle = 0; + BTC_TRACE_ERROR("%s() FAILED", __func__); + } else { + bta_sys_add_uuid(service); /* UUID_SERVCLASS_MESSAGE_ACCESS */ + BTC_TRACE_DEBUG("%s(): SDP Registered (handle 0x%08x)", __func__, sdp_handle); + } + + return sdp_handle; +} + + +/* Create a OPP Server SDP record based on information stored in a bluetooth_sdp_ops_record */ +static int add_opps_sdp(const bluetooth_sdp_ops_record* rec) +{ + tSDP_PROTOCOL_ELEM protoList [3]; + UINT16 service = UUID_SERVCLASS_OBEX_OBJECT_PUSH; + UINT16 browse = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP; + UINT8 type_len[rec->supported_formats_list_len]; + UINT8 desc_type[rec->supported_formats_list_len]; + UINT8 *type_value[rec->supported_formats_list_len]; + bool status = true; + UINT32 sdp_handle = 0; + UINT8 temp[4]; + UINT8* p_temp = temp; + tBTA_UTL_COD cod; + int i,j; + + BTC_TRACE_DEBUG("%s(): scn 0x%02x, psm = 0x%04x\n service name %s", __func__, + rec->hdr.rfcomm_channel_number, rec->hdr.l2cap_psm, rec->hdr.service_name); + + BTC_TRACE_DEBUG(" supported formats count: %d", + rec->supported_formats_list_len); + + if ((sdp_handle = SDP_CreateRecord()) == 0) { + BTC_TRACE_ERROR("%s(): Unable to register Object Push Server Service", __func__); + return sdp_handle; + } + + /* add service class */ + status &= SDP_AddServiceClassIdList(sdp_handle, 1, &service); + memset( protoList, 0 , 3*sizeof(tSDP_PROTOCOL_ELEM) ); + + /* add protocol list, including RFCOMM scn */ + protoList[0].protocol_uuid = UUID_PROTOCOL_L2CAP; + protoList[0].num_params = 0; + protoList[1].protocol_uuid = UUID_PROTOCOL_RFCOMM; + protoList[1].num_params = 1; + protoList[1].params[0] = rec->hdr.rfcomm_channel_number; + protoList[2].protocol_uuid = UUID_PROTOCOL_OBEX; + protoList[2].num_params = 0; + status &= SDP_AddProtocolList(sdp_handle, 3, protoList); + + /* Add a name entry */ + status &= SDP_AddAttribute(sdp_handle, + (UINT16)ATTR_ID_SERVICE_NAME, + (UINT8)TEXT_STR_DESC_TYPE, + (UINT32)(rec->hdr.service_name_length + 1), + (UINT8 *)rec->hdr.service_name); + + /* Add in the Bluetooth Profile Descriptor List */ + status &= SDP_AddProfileDescriptorList(sdp_handle, + UUID_SERVCLASS_OBEX_OBJECT_PUSH, + rec->hdr.profile_version); + + /* add sequence for supported types */ + for (i = 0, j = 0; i < rec->supported_formats_list_len; i++) { + type_value[j] = (UINT8 *) &rec->supported_formats_list[i]; + desc_type[j] = UINT_DESC_TYPE; + type_len[j++] = 1; + } + + status &= SDP_AddSequence(sdp_handle, (UINT16) ATTR_ID_SUPPORTED_FORMATS_LIST, + (UINT8) rec->supported_formats_list_len, desc_type, type_len, type_value); + + /* Add the L2CAP PSM if present */ + if(rec->hdr.l2cap_psm != -1) { + p_temp = temp;// The macro modifies p_temp, hence rewind. + UINT16_TO_BE_STREAM(p_temp, rec->hdr.l2cap_psm); + status &= SDP_AddAttribute(sdp_handle, ATTR_ID_GOEP_L2CAP_PSM, + UINT_DESC_TYPE, (UINT32)2, temp); + } + + /* Make the service browseable */ + status &= SDP_AddUuidSequence (sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse); + + if (!status) { + SDP_DeleteRecord(sdp_handle); + sdp_handle = 0; + BTC_TRACE_ERROR("%s() FAILED", __func__); + } else { + /* set class of device */ + cod.service = BTM_COD_SERVICE_OBJ_TRANSFER; + utl_set_device_class(&cod, BTA_UTL_SET_COD_SERVICE_CLASS); + + bta_sys_add_uuid(service); /* UUID_SERVCLASS_OBEX_OBJECT_PUSH */ + BTC_TRACE_DEBUG("%s(): SDP Registered (handle 0x%08x)", __func__, sdp_handle); + } + + return sdp_handle; +} + +// Create a Sim Access Profile SDP record based on information stored in a bluetooth_sdp_sap_record. +static int add_saps_sdp(const bluetooth_sdp_sap_record* rec) +{ + tSDP_PROTOCOL_ELEM protoList [2]; + UINT16 services[2]; + UINT16 browse = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP; + bool status = true; + UINT32 sdp_handle = 0; + + BTC_TRACE_DEBUG("%s(): scn 0x%02x, service name %s", __func__, + rec->hdr.rfcomm_channel_number, rec->hdr.service_name); + + if ((sdp_handle = SDP_CreateRecord()) == 0) { + BTC_TRACE_ERROR("%s(): Unable to register SAPS Service", __func__); + return sdp_handle; + } + + services[0] = UUID_SERVCLASS_SAP; + services[1] = UUID_SERVCLASS_GENERIC_TELEPHONY; + + // add service class + status &= SDP_AddServiceClassIdList(sdp_handle, 2, services); + memset(protoList, 0, 2 * sizeof(tSDP_PROTOCOL_ELEM)); + + // add protocol list, including RFCOMM scn + protoList[0].protocol_uuid = UUID_PROTOCOL_L2CAP; + protoList[0].num_params = 0; + protoList[1].protocol_uuid = UUID_PROTOCOL_RFCOMM; + protoList[1].num_params = 1; + protoList[1].params[0] = rec->hdr.rfcomm_channel_number; + status &= SDP_AddProtocolList(sdp_handle, 2, protoList); + + // Add a name entry + status &= SDP_AddAttribute(sdp_handle, + (UINT16)ATTR_ID_SERVICE_NAME, + (UINT8)TEXT_STR_DESC_TYPE, + (UINT32)(rec->hdr.service_name_length + 1), + (UINT8 *)rec->hdr.service_name); + + // Add in the Bluetooth Profile Descriptor List + status &= SDP_AddProfileDescriptorList(sdp_handle, + UUID_SERVCLASS_SAP, + rec->hdr.profile_version); + + // Make the service browseable + status &= SDP_AddUuidSequence (sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse); + + if (!status) { + SDP_DeleteRecord(sdp_handle); + sdp_handle = 0; + BTC_TRACE_ERROR("%s(): FAILED deleting record", __func__); + } else { + bta_sys_add_uuid(UUID_SERVCLASS_SAP); + BTC_TRACE_DEBUG("%s(): SDP Registered (handle 0x%08x)", __func__, sdp_handle); + } + + return sdp_handle; +} + +static int btc_handle_create_record_event(int id) +{ + int handle = -1; + const sdp_slot_t *sdp_slot = NULL; + + BTC_TRACE_DEBUG("Sdp Server %s", __func__); + + sdp_slot = start_create_sdp(id); + if(sdp_slot != NULL) { + bluetooth_sdp_record* record = sdp_slot->record_data; + switch(record->hdr.type) { + case SDP_TYPE_MAP_MAS: + handle = add_maps_sdp(&record->mas); + break; + case SDP_TYPE_MAP_MNS: + handle = add_mapc_sdp(&record->mns); + break; + case SDP_TYPE_PBAP_PSE: + handle = add_pbaps_sdp(&record->pse); + break; + case SDP_TYPE_OPP_SERVER: + handle = add_opps_sdp(&record->ops); + break; + case SDP_TYPE_SAP_SERVER: + handle = add_saps_sdp(&record->sap); + break; + case SDP_TYPE_PBAP_PCE: + // break; not yet supported + default: + BTC_TRACE_DEBUG("Record type %d is not supported",record->hdr.type); + break; + } + if(handle != -1) { + set_sdp_handle(id, handle); + } + } + + return handle; +} + +static bool btc_sdp_remove_record_event(int handle) +{ + bool result = false; + + BTC_TRACE_DEBUG("Sdp Server %s", __func__); + + if(handle != -1 && handle != 0) { + result = SDP_DeleteRecord(handle); + if(result == false) { + BTC_TRACE_ERROR(" Unable to remove handle 0x%08x", handle); + } + } + + return result; +} + +static void btc_sdp_dm_cback(tBTA_SDP_EVT event, tBTA_SDP* p_data, void* user_data) +{ + btc_msg_t msg; + bt_status_t status; + + switch (event) { + case BTA_SDP_CREATE_RECORD_USER_EVT: { + if (p_data->status == BTA_SDP_SUCCESS) { + if(btc_handle_create_record_event((int)user_data) < 0) { + p_data->status = BTA_SDP_FAILURE; + } + } + } + break; + case BTA_SDP_REMOVE_RECORD_USER_EVT: { + if (p_data->status == BTA_SDP_SUCCESS) { + if (btc_sdp_remove_record_event((int)user_data) == false) { + p_data->status = BTA_SDP_FAILURE; + } + } + } + break; + default: + break; + } + + msg.sig = BTC_SIG_API_CB; + msg.pid = BTC_PID_SDP; + msg.act = event; + + status = btc_transfer_context(&msg, p_data, sizeof(tBTA_SDP), NULL); + + if (status != BT_STATUS_SUCCESS) { + BTC_TRACE_ERROR("%s btc_transfer_context failed", __func__); + } +} + +static void btc_sdp_init(void) +{ + esp_sdp_cb_param_t param; + esp_sdp_status_t ret = ESP_SDP_SUCCESS; + + do { + if (is_sdp_init()) { + BTC_TRACE_ERROR("%s SDP has been initiated, shall deinit first!", __func__); + ret = ESP_SDP_NEED_DEINIT; + break; + } + +#if SDP_DYNAMIC_MEMORY == TRUE + if ((sdp_local_param_ptr = (sdp_local_param_t *)osi_malloc(sizeof(sdp_local_param_t))) == NULL) { + BTC_TRACE_ERROR("%s malloc failed\n", __func__); + ret = ESP_SDP_NO_RESOURCE; + break; + } + memset((void *)sdp_local_param_ptr, 0, sizeof(sdp_local_param_t)); +#endif + + if (osi_mutex_new(&sdp_local_param.sdp_slot_mutex) != 0) { +#if SDP_DYNAMIC_MEMORY == TRUE + osi_free(sdp_local_param_ptr); + sdp_local_param_ptr = NULL; +#endif + BTC_TRACE_ERROR("%s osi_mutex_new failed\n", __func__); + ret = ESP_SDP_NO_RESOURCE; + break; + } + + ret = BTA_SdpEnable(btc_sdp_dm_cback); + } while(0); + + if (ret != ESP_SDP_SUCCESS) { + param.init.status = ret; + btc_sdp_cb_to_app(ESP_SDP_INIT_EVT, ¶m); + } +} + +static void btc_sdp_deinit(void) +{ + esp_sdp_cb_param_t param; + esp_sdp_status_t ret = ESP_SDP_SUCCESS; + int handle; + + do { + if (!is_sdp_init()) { + BTC_TRACE_ERROR("%s SDP has not been initiated, shall init first!", __func__); + ret = ESP_SDP_NEED_INIT; + break; + } + + for(int i = 0; i < SDP_MAX_RECORDS; i++) { + handle = free_sdp_slot(i); + if (handle > 0) { + BTA_SdpRemoveRecordByUser((void*)handle); + } + } + // todo + sdp_disable_handler(); + } while(0); + + if (ret != ESP_SDP_SUCCESS) { + param.deinit.status = ret; + btc_sdp_cb_to_app(ESP_SDP_DEINIT_EVT, ¶m); + } +} + +static void btc_sdp_create_record(btc_sdp_args_t *arg) +{ + int handle; + esp_sdp_cb_param_t param; + esp_sdp_status_t ret = ESP_SDP_SUCCESS; + + do { + if (!is_sdp_init()) { + BTC_TRACE_ERROR("%s SDP has not been initiated, shall init first!", __func__); + ret = ESP_SDP_NEED_INIT; + break; + } + + handle = alloc_sdp_slot(arg->creat_record.record); + if (handle < 0) { + ret = ESP_SDP_FAILURE; + break; + } + + BTA_SdpCreateRecordByUser((void *) handle); + } while(0); + + if (ret != ESP_SDP_SUCCESS) { + param.create_record.status = ret; + param.create_record.record_handle = -1; + btc_sdp_cb_to_app(ESP_SDP_CREATE_RECORD_COMP_EVT, ¶m); + } +} + +static void btc_sdp_remove_record(btc_sdp_args_t *arg) +{ + int handle; + esp_sdp_cb_param_t param; + esp_sdp_status_t ret = ESP_SDP_SUCCESS; + + do { + if (!is_sdp_init()) { + BTC_TRACE_ERROR("%s SDP has not been initiated, shall init first!", __func__); + ret = ESP_SDP_NEED_INIT; + break; + } + + /* Get the Record handle, and free the slot */ + /* The application layer record_handle is equivalent to the id of the btc layer */ + handle = free_sdp_slot(arg->remove_record.record_handle); + + BTC_TRACE_DEBUG("Sdp Server %s id=%d to handle=0x%08x", + __func__, arg->remove_record.record_handle, handle); + + /* Pass the actual record handle */ + if(handle > 0) { + BTA_SdpRemoveRecordByUser((void*) handle); + } else { + ret = ESP_SDP_NO_CREATE_RECORD; + break; + } + } while(0); + + if (ret != ESP_SDP_SUCCESS) { + param.create_record.status = ret; + btc_sdp_cb_to_app(ESP_SDP_REMOVE_RECORD_COMP_EVT, ¶m); + } +} + +static void btc_sdp_search(btc_sdp_args_t *arg) +{ + esp_sdp_cb_param_t param = {0}; + esp_sdp_status_t ret = ESP_SDP_SUCCESS; + + do { + if (!is_sdp_init()) { + BTC_TRACE_ERROR("%s SDP has not been initiated, shall init first!", __func__); + ret = ESP_SDP_NEED_INIT; + break; + } + + BTA_SdpSearch(arg->search.bd_addr, &arg->search.sdp_uuid); + } while(0); + + if (ret != ESP_SDP_SUCCESS) { + param.search.status = ret; + btc_sdp_cb_to_app(ESP_SDP_SEARCH_COMP_EVT, ¶m); + } +} + +void btc_sdp_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src) +{ + btc_sdp_args_t *dst = (btc_sdp_args_t *)p_dest; + btc_sdp_args_t *src = (btc_sdp_args_t *)p_src; + + switch (msg->act) { + case BTC_SDP_ACT_CREATE_RECORD: + dst->creat_record.record = (bluetooth_sdp_record *)osi_calloc(sizeof(bluetooth_sdp_record)); + if (dst->creat_record.record) { + memcpy(dst->creat_record.record, src->creat_record.record, sizeof(bluetooth_sdp_record)); + } else { + BTC_TRACE_ERROR("%s %d osi_malloc failed\n", __func__, msg->act); + break; + } + + dst->creat_record.record->hdr.service_name = (char *)osi_calloc(src->creat_record.record->hdr.service_name_length); + if (dst->creat_record.record->hdr.service_name) { + strcpy(dst->creat_record.record->hdr.service_name, src->creat_record.record->hdr.service_name); + } else { + BTC_TRACE_ERROR("%s %d osi_malloc failed\n", __func__, msg->act); + } + break; + default: + break; + } +} + +void btc_sdp_arg_deep_free(btc_msg_t *msg) +{ + btc_sdp_args_t *arg = (btc_sdp_args_t *)msg->arg; + + switch (msg->act) { + case BTC_SDP_ACT_CREATE_RECORD: + if (arg->creat_record.record) { + osi_free(arg->creat_record.record); + } + if (arg->creat_record.record->hdr.service_name) { + osi_free(arg->creat_record.record->hdr.service_name); + } + break; + default: + break; + } +} + +void btc_sdp_call_handler(btc_msg_t *msg) +{ + btc_sdp_args_t *arg = (btc_sdp_args_t *)(msg->arg); + + BTC_TRACE_DEBUG("%s: event = %d\n", __func__, msg->act); + + switch (msg->act) { + case BTC_SDP_ACT_INIT: + btc_sdp_init(); + break; + case BTC_SDP_ACT_DEINIT: + btc_sdp_deinit(); + break; + case BTC_SDP_ACT_SEARCH: + btc_sdp_search(arg); + break; + case BTC_SDP_ACT_CREATE_RECORD: + btc_sdp_create_record(arg); + break; + case BTC_SDP_ACT_REMOVE_RECORD: + btc_sdp_remove_record(arg); + break; + default: + BTC_TRACE_ERROR("%s: Unhandled event (%d)!\n", __func__, msg->act); + break; + } + btc_sdp_arg_deep_free(msg); +} + +void btc_sdp_cb_handler(btc_msg_t *msg) +{ + esp_sdp_cb_param_t param = {0}; + uint8_t event = msg->act; + tBTA_SDP *p_data = (tBTA_SDP *)msg->arg; + + switch(event) { + case BTA_SDP_ENABLE_EVT: + param.init.status = p_data->status; + btc_sdp_cb_to_app(ESP_SDP_INIT_EVT, ¶m); + break; + case BTA_SDP_DISENABLE_EVT: + BTA_SdpDisable(); + osi_mutex_free(&sdp_local_param.sdp_slot_mutex); + #if SDP_DYNAMIC_MEMORY == TRUE + osi_free(sdp_local_param_ptr); + sdp_local_param_ptr = NULL; + #endif + param.deinit.status = ESP_SDP_SUCCESS; + btc_sdp_cb_to_app(ESP_SDP_DEINIT_EVT, ¶m); + break; + case BTA_SDP_SEARCH_COMP_EVT: + param.search.status = p_data->status; + if (param.search.status == ESP_SDP_SUCCESS) { + memcpy(param.search.remote_addr, p_data->sdp_search_comp.remote_addr, sizeof(BD_ADDR)); + memcpy(¶m.search.sdp_uuid, &p_data->sdp_search_comp.uuid, sizeof(tSDP_UUID)); + param.search.record_count = p_data->sdp_search_comp.record_count; + param.search.records = osi_malloc(sizeof(esp_bluetooth_sdp_record_t)*p_data->sdp_search_comp.record_count); + if (param.search.records != NULL) { + memcpy(param.search.records, p_data->sdp_search_comp.records, + sizeof(esp_bluetooth_sdp_record_t)*p_data->sdp_search_comp.record_count); + } else { + BTC_TRACE_ERROR("%s %d osi_malloc failed\n", __func__, event); + param.search.status = ESP_SDP_NO_RESOURCE; + } + } + btc_sdp_cb_to_app(ESP_SDP_SEARCH_COMP_EVT, ¶m); + if (param.search.records != NULL) { + osi_free(param.search.records); + } + break; + case BTA_SDP_CREATE_RECORD_USER_EVT: + param.create_record.status = p_data->status; + param.create_record.record_handle = p_data->handle; + btc_sdp_cb_to_app(ESP_SDP_CREATE_RECORD_COMP_EVT, ¶m); + break; + case BTA_SDP_REMOVE_RECORD_USER_EVT: + param.remove_record.status = p_data->status; + btc_sdp_cb_to_app(ESP_SDP_REMOVE_RECORD_COMP_EVT, ¶m); + break; + default: + BTC_TRACE_DEBUG("%s: Unhandled event (%d)!", __func__, msg->act); + break; + } +} + +#endif ///defined BTC_SDP_INCLUDED && BTC_SDP_INCLUDED == TRUE diff --git a/components/bt/host/bluedroid/common/include/common/bt_target.h b/components/bt/host/bluedroid/common/include/common/bt_target.h index ebc5df3e06..1373c2000b 100644 --- a/components/bt/host/bluedroid/common/include/common/bt_target.h +++ b/components/bt/host/bluedroid/common/include/common/bt_target.h @@ -87,6 +87,7 @@ #define BTA_JV_INCLUDED TRUE #define RFCOMM_INCLUDED TRUE #define BTC_L2CAP_INCLUDED TRUE +#define BTC_SDP_INCLUDED TRUE #define VND_BT_JV_BTA_L2CAP TRUE #endif /* UC_BT_L2CAP_ENABLED */ @@ -1412,7 +1413,7 @@ /* The maximum number of attributes in each record. */ #ifndef SDP_MAX_REC_ATTR -#if defined(HID_DEV_INCLUDED) && (HID_DEV_INCLUDED==TRUE) +#if (defined(HID_DEV_INCLUDED) && (HID_DEV_INCLUDED==TRUE)) || (defined(BTC_SDP_INCLUDED) && (BTC_SDP_INCLUDED==TRUE)) #define SDP_MAX_REC_ATTR 25 #else #define SDP_MAX_REC_ATTR 8