--- /dev/null
+/******************************************************************************
+ *
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This is the public interface file for the BTA SDP I/F
+ *
+ ******************************************************************************/
+#ifndef BTA_SDP_API_H
+#define BTA_SDP_API_H
+
+#include "bt_sdp.h"
+#include "bt_target.h"
+#include "bt_types.h"
+#include "bta_api.h"
+#include "btm_api.h"
+
+/* status values */
+#define BTA_SDP_SUCCESS 0 /* Successful operation. */
+#define BTA_SDP_FAILURE 1 /* Generic failure. */
+#define BTA_SDP_BUSY 2 /* Temporarily can not handle this request. */
+
+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_MAX_RECORDS 15
+
+typedef UINT16 tBTA_SDP_EVT;
+
+/* data associated with BTA_SDP_DISCOVERY_COMP_EVT */
+typedef struct
+{
+ tBTA_SDP_STATUS status;
+ BD_ADDR remote_addr;
+ tBT_UUID uuid;
+ int record_count;
+ bluetooth_sdp_record records[BTA_SDP_MAX_RECORDS];
+} tBTA_SDP_SEARCH_COMP;
+
+typedef union
+{
+ tBTA_SDP_STATUS status; /* BTA_SDP_SEARCH_EVT */
+ tBTA_SDP_SEARCH_COMP sdp_search_comp; /* BTA_SDP_SEARCH_COMP_EVT */
+} tBTA_SDP;
+
+/* SDP DM Interface callback */
+typedef void (tBTA_SDP_DM_CBACK)(tBTA_SDP_EVT event, tBTA_SDP *p_data, void * user_data);
+
+/* MCE configuration structure */
+typedef struct
+{
+ UINT16 sdp_db_size; /* The size of p_sdp_db */
+ tSDP_DISCOVERY_DB *p_sdp_db; /* The data buffer to keep SDP database */
+} tBTA_SDP_CFG;
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/*******************************************************************************
+**
+** Function BTA_SdpEnable
+**
+** Description Enable the SDP I/F service. When the enable
+** operation is complete the callback function will be
+** called with a BTA_SDP_ENABLE_EVT. This function must
+** be called before other functions in the MCE API are
+** called.
+**
+** Returns BTA_SDP_SUCCESS if successful.
+** BTA_SDP_FAIL if internal failure.
+**
+*******************************************************************************/
+extern tBTA_SDP_STATUS BTA_SdpEnable(tBTA_SDP_DM_CBACK *p_cback);
+
+/*******************************************************************************
+**
+** Function BTA_SdpSearch
+**
+** Description Start a search for sdp records for a specific BD_ADDR with a
+** specific profile uuid.
+** When the search operation is completed, the callback function
+** will be called with a BTA_SDP_SEARCH_EVT.
+** Returns BTA_SDP_SUCCESS if successful.
+** BTA_SDP_FAIL if internal failure.
+**
+*******************************************************************************/
+extern tBTA_SDP_STATUS BTA_SdpSearch(BD_ADDR bd_addr,tSDP_UUID *uuid);
+
+/*******************************************************************************
+**
+** Function BTA_SdpCreateRecordByUser
+**
+** Description This function is used to request a callback to create a SDP
+** record. The registered callback will be called with event
+** BTA_SDP_CREATE_RECORD_USER_EVT.
+**
+** Returns BTA_SDP_SUCCESS, if the request is being processed.
+** BTA_SDP_FAILURE, otherwise.
+**
+*******************************************************************************/
+extern tBTA_SDP_STATUS BTA_SdpCreateRecordByUser(void* user_data);
+
+/*******************************************************************************
+**
+** Function BTA_SdpRemoveRecordByUser
+**
+** Description This function is used to request a callback to remove a SDP
+** record. The registered callback will be called with event
+** BTA_SDP_REMOVE_RECORD_USER_EVT.
+**
+** Returns BTA_SDP_SUCCESS, if the request is being processed.
+** BTA_SDP_FAILURE, otherwise.
+**
+*******************************************************************************/
+extern tBTA_SDP_STATUS BTA_SdpRemoveRecordByUser(void* user_data);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BTA_SDP_API_H */
--- /dev/null
+/******************************************************************************
+ *
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ * This file contains action functions for SDP search.
+ ******************************************************************************/
+
+// #include <hardware/bluetooth.h>
+#include "bt_sdp.h"
+// #include <arpa/inet.h>
+#include "bt_defs.h"
+#include <stdlib.h>
+#include <string.h>
+
+#include "allocator.h"
+#include "bt_types.h"
+#include "gki.h"
+#include "utl.h"
+#include "bta_sys.h"
+#include "bta_api.h"
+#include "bta_sdp_api.h"
+#include "bta_sdp_int.h"
+#include "btm_api.h"
+#include "btm_int.h"
+#include "sdp_api.h"
+
+/*****************************************************************************
+** Constants
+*****************************************************************************/
+
+static const uint8_t UUID_OBEX_OBJECT_PUSH[] = {0x00, 0x00, 0x11, 0x05, 0x00, 0x00, 0x10, 0x00,
+ 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB};
+static const uint8_t UUID_PBAP_PSE[] = {0x00, 0x00, 0x11, 0x2F, 0x00, 0x00, 0x10, 0x00,
+ 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB};
+static const uint8_t UUID_MAP_MAS[] = {0x00, 0x00, 0x11, 0x32, 0x00, 0x00, 0x10, 0x00,
+ 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB};
+static const uint8_t UUID_MAP_MNS[] = {0x00, 0x00, 0x11, 0x33, 0x00, 0x00, 0x10, 0x00,
+ 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB};
+static const uint8_t UUID_SPP[] = {0x00, 0x00, 0x11, 0x01, 0x00, 0x00, 0x10, 0x00,
+ 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB};
+static const uint8_t UUID_SAP[] = {0x00, 0x00, 0x11, 0x2D, 0x00, 0x00, 0x10, 0x00,
+ 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB};
+// TODO:
+// Both the fact that the UUIDs are declared in multiple places, plus the fact
+// that there is a mess of UUID comparison and shortening methods will have to
+// be fixed.
+// The btcore->uuid module should be used for all instances.
+
+#define UUID_MAX_LENGTH 16
+#define IS_UUID(u1,u2) !memcmp(u1,u2,UUID_MAX_LENGTH)
+
+static inline tBT_UUID shorten_sdp_uuid(const tBT_UUID* u)
+{
+ static uint8_t bt_base_uuid[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
+ 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB };
+
+ APPL_TRACE_DEBUG("%s() - uuid len:%d", __func__, u->len);
+ if(u->len != 16)
+ return *u;
+
+ if(memcmp(&u->uu.uuid128[4], &bt_base_uuid[4], 12) != 0)
+ return *u;
+
+ tBT_UUID su;
+ memset(&su, 0, sizeof(su));
+ if(u->uu.uuid128[0] == 0 && u->uu.uuid128[1] == 0)
+ {
+ su.len = 2;
+ uint16_t u16;
+ memcpy(&u16, &u->uu.uuid128[2], sizeof(u16));
+ su.uu.uuid16 = ntohs(u16);
+ } else {
+ su.len = 4;
+ uint32_t u32;
+ memcpy(&u32, &u->uu.uuid128[0], sizeof(u32));
+ su.uu.uuid32 = ntohl(u32);
+ }
+ return su;
+}
+
+static void bta_create_mns_sdp_record(bluetooth_sdp_record *record, tSDP_DISC_REC *p_rec)
+{
+ tSDP_DISCOVERY_DB *db = p_bta_sdp_cfg->p_sdp_db;
+ tSDP_DISC_ATTR *p_attr;
+ tSDP_PROTOCOL_ELEM pe;
+ UINT16 pversion = 0;
+ UINT8 offset = 0;
+ record->mns.hdr.type = SDP_TYPE_MAP_MNS;
+ record->mns.hdr.service_name_length = 0;
+ record->mns.hdr.service_name = NULL;
+ record->mns.hdr.rfcomm_channel_number = 0;
+ record->mns.hdr.l2cap_psm = -1;
+ record->mns.hdr.profile_version = 0;
+ record->mns.supported_features = 0x0000001F; //default value if not found
+
+ if ((p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_MAP_SUPPORTED_FEATURES)) != NULL)
+ {
+ record->mns.supported_features = p_attr->attr_value.v.u32;
+ }
+
+ if ((p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_SERVICE_NAME)) != NULL)
+ {
+ record->mns.hdr.service_name_length = SDP_DISC_ATTR_LEN(p_attr->attr_len_type);
+ record->mns.hdr.service_name = (char *)p_attr->attr_value.v.array;
+ }
+
+ if (SDP_FindProfileVersionInRec(p_rec, UUID_SERVCLASS_MAP_PROFILE, &pversion))
+ {
+ record->mns.hdr.profile_version = pversion;
+ }
+
+ if (SDP_FindProtocolListElemInRec(p_rec, UUID_PROTOCOL_RFCOMM, &pe))
+ {
+ record->mns.hdr.rfcomm_channel_number = pe.params[0];
+ }
+
+ if ((p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_GOEP_L2CAP_PSM)) != NULL)
+ {
+ record->mns.hdr.l2cap_psm = p_attr->attr_value.v.u16;
+ }
+}
+
+static void bta_create_mas_sdp_record(bluetooth_sdp_record *record, tSDP_DISC_REC *p_rec)
+{
+ tSDP_DISCOVERY_DB *db = p_bta_sdp_cfg->p_sdp_db;
+ tSDP_DISC_ATTR *p_attr;
+ tSDP_PROTOCOL_ELEM pe;
+ UINT16 pversion = -1;
+
+ record->mas.hdr.type = SDP_TYPE_MAP_MAS;
+ record->mas.hdr.service_name_length = 0;
+ record->mas.hdr.service_name = NULL;
+ record->mas.hdr.rfcomm_channel_number = 0;
+ record->mas.hdr.l2cap_psm = -1;
+ record->mas.hdr.profile_version = 0;
+ record->mas.mas_instance_id = 0;
+ record->mas.supported_features = 0x0000001F;
+ record->mas.supported_message_types = 0;
+
+ if ((p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_MAS_INSTANCE_ID)) != NULL)
+ {
+ record->mas.mas_instance_id = p_attr->attr_value.v.u8;
+ }
+
+ if ((p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_SUPPORTED_MSG_TYPE)) != NULL)
+ {
+ record->mas.supported_message_types = p_attr->attr_value.v.u8;
+ }
+
+ if ((p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_MAP_SUPPORTED_FEATURES)) != NULL)
+ {
+ record->mas.supported_features = p_attr->attr_value.v.u32;
+ }
+
+ if ((p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_SERVICE_NAME)) != NULL)
+ {
+ record->mas.hdr.service_name_length = SDP_DISC_ATTR_LEN(p_attr->attr_len_type);
+ record->mas.hdr.service_name = (char *)p_attr->attr_value.v.array;
+ }
+
+ if (SDP_FindProfileVersionInRec(p_rec, UUID_SERVCLASS_MAP_PROFILE, &pversion))
+ {
+ record->mas.hdr.profile_version = pversion;
+ }
+
+ if (SDP_FindProtocolListElemInRec(p_rec, UUID_PROTOCOL_RFCOMM, &pe))
+ {
+ record->mas.hdr.rfcomm_channel_number = pe.params[0];
+ }
+
+ if ((p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_GOEP_L2CAP_PSM)) != NULL)
+ {
+ record->mas.hdr.l2cap_psm = p_attr->attr_value.v.u16;
+ }
+}
+
+static void bta_create_pse_sdp_record(bluetooth_sdp_record *record, tSDP_DISC_REC *p_rec)
+{
+ tSDP_DISCOVERY_DB *db = p_bta_sdp_cfg->p_sdp_db;
+ tSDP_DISC_ATTR *p_attr;
+ UINT16 pversion;
+ tSDP_PROTOCOL_ELEM pe;
+
+ record->pse.hdr.type = SDP_TYPE_PBAP_PSE;
+ record->pse.hdr.service_name_length = 0;
+ record->pse.hdr.service_name = NULL;
+ record->pse.hdr.rfcomm_channel_number = 0;
+ record->pse.hdr.l2cap_psm = -1;
+ record->pse.hdr.profile_version = 0;
+ record->pse.supported_features = 0x00000003;
+ record->pse.supported_repositories = 0;
+
+ if ((p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_SUPPORTED_REPOSITORIES)) != NULL)
+ {
+ record->pse.supported_repositories = p_attr->attr_value.v.u8;
+ }
+ if ((p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_PBAP_SUPPORTED_FEATURES)) != NULL)
+ {
+ record->pse.supported_features = p_attr->attr_value.v.u32;
+ }
+
+ if ((p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_SERVICE_NAME)) != NULL)
+ {
+ record->pse.hdr.service_name_length = SDP_DISC_ATTR_LEN(p_attr->attr_len_type);
+ record->pse.hdr.service_name = (char *)p_attr->attr_value.v.array;
+ }
+
+ if (SDP_FindProfileVersionInRec(p_rec, UUID_SERVCLASS_PHONE_ACCESS, &pversion))
+ {
+ record->pse.hdr.profile_version = pversion;
+ }
+
+ if (SDP_FindProtocolListElemInRec(p_rec, UUID_PROTOCOL_RFCOMM, &pe))
+ {
+ record->pse.hdr.rfcomm_channel_number = pe.params[0];
+ }
+
+ if ((p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_GOEP_L2CAP_PSM)) != NULL)
+ {
+ record->pse.hdr.l2cap_psm = p_attr->attr_value.v.u16;
+ }
+}
+
+static void bta_create_ops_sdp_record(bluetooth_sdp_record *record, tSDP_DISC_REC *p_rec)
+{
+ tSDP_DISCOVERY_DB *db = p_bta_sdp_cfg->p_sdp_db;
+ tSDP_DISC_ATTR *p_attr, *p_sattr;
+ tSDP_PROTOCOL_ELEM pe;
+ UINT16 pversion = -1;
+
+ record->ops.hdr.type = SDP_TYPE_OPP_SERVER;
+ record->ops.hdr.service_name_length = 0;
+ record->ops.hdr.service_name = NULL;
+ record->ops.hdr.rfcomm_channel_number = 0;
+ record->ops.hdr.l2cap_psm = -1;
+ record->ops.hdr.profile_version = 0;
+ record->ops.supported_formats_list_len = 0;
+
+ if ((p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_SERVICE_NAME)) != NULL)
+ {
+ record->ops.hdr.service_name_length = SDP_DISC_ATTR_LEN(p_attr->attr_len_type);
+ record->ops.hdr.service_name = (char *)p_attr->attr_value.v.array;
+ }
+
+ if (SDP_FindProfileVersionInRec(p_rec, UUID_SERVCLASS_OBEX_OBJECT_PUSH, &pversion))
+ {
+ record->ops.hdr.profile_version = pversion;
+ }
+
+ if (SDP_FindProtocolListElemInRec(p_rec, UUID_PROTOCOL_RFCOMM, &pe))
+ {
+ record->ops.hdr.rfcomm_channel_number = pe.params[0];
+ }
+
+ if ((p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_GOEP_L2CAP_PSM)) != NULL)
+ {
+ record->ops.hdr.l2cap_psm = p_attr->attr_value.v.u16;
+ }
+ if ((p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_SUPPORTED_FORMATS_LIST)) != NULL)
+ {
+ /* Safety check - each entry should itself be a sequence */
+ if (SDP_DISC_ATTR_TYPE(p_attr->attr_len_type) != DATA_ELE_SEQ_DESC_TYPE) {
+ record->ops.supported_formats_list_len = 0;
+ APPL_TRACE_ERROR("%s() - supported_formats_list - wrong attribute length/type:"
+ " 0x%02x - expected 0x06", __func__, p_attr->attr_len_type);
+ } else {
+ int count = 0;
+ /* 1 byte for type/length 1 byte for value */
+ record->ops.supported_formats_list_len = SDP_DISC_ATTR_LEN(p_attr->attr_len_type)/2;
+
+ /* Extract each value into */
+ for (p_sattr = p_attr->attr_value.v.p_sub_attr;
+ p_sattr != NULL; p_sattr = p_sattr->p_next_attr)
+ {
+ if ((SDP_DISC_ATTR_TYPE(p_sattr->attr_len_type) == UINT_DESC_TYPE)
+ && (SDP_DISC_ATTR_LEN(p_sattr->attr_len_type) == 1))
+ {
+ if (count == sizeof(record->ops.supported_formats_list)) {
+ APPL_TRACE_ERROR("%s() - supported_formats_list - count overflow - "
+ "too many sub attributes!!", __func__);
+ /* If you hit this, new formats have been added,
+ * update SDP_OPP_SUPPORTED_FORMATS_MAX_LENGTH */
+ break;
+ }
+ record->ops.supported_formats_list[count] = p_sattr->attr_value.v.u8;
+ count++;
+ } else {
+ APPL_TRACE_ERROR("%s() - supported_formats_list - wrong sub attribute "
+ "length/type: 0x%02x - expected 0x80", __func__,
+ p_sattr->attr_len_type);
+ break;
+ }
+ }
+ if (record->ops.supported_formats_list_len != count) {
+ APPL_TRACE_WARNING("%s() - supported_formats_list - Length of attribute different "
+ "from the actual number of sub-attributes in the sequence "
+ "att-length: %d - number of elements: %d", __func__,
+ record->ops.supported_formats_list_len , count);
+
+ }
+ record->ops.supported_formats_list_len = count;
+ }
+ }
+}
+
+static void bta_create_sap_sdp_record(bluetooth_sdp_record *record, tSDP_DISC_REC *p_rec)
+{
+ tSDP_DISCOVERY_DB *db = p_bta_sdp_cfg->p_sdp_db;
+ tSDP_DISC_ATTR *p_attr;
+ tSDP_PROTOCOL_ELEM pe;
+ UINT16 pversion = -1;
+
+ record->sap.hdr.type = SDP_TYPE_MAP_MAS;
+ record->sap.hdr.service_name_length = 0;
+ record->sap.hdr.service_name = NULL;
+ record->sap.hdr.rfcomm_channel_number = 0;
+ record->sap.hdr.l2cap_psm = -1;
+ record->sap.hdr.profile_version = 0;
+
+ if ((p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_SERVICE_NAME)) != NULL)
+ {
+ record->sap.hdr.service_name_length = SDP_DISC_ATTR_LEN(p_attr->attr_len_type);
+ record->sap.hdr.service_name = (char *)p_attr->attr_value.v.array;
+ }
+
+ if (SDP_FindProfileVersionInRec(p_rec, UUID_SERVCLASS_SAP, &pversion))
+ {
+ record->sap.hdr.profile_version = pversion;
+ }
+
+ if (SDP_FindProtocolListElemInRec(p_rec, UUID_PROTOCOL_RFCOMM, &pe))
+ {
+ record->sap.hdr.rfcomm_channel_number = pe.params[0];
+ }
+}
+
+static void bta_create_raw_sdp_record(bluetooth_sdp_record *record, tSDP_DISC_REC *p_rec)
+{
+ tSDP_DISCOVERY_DB *db = p_bta_sdp_cfg->p_sdp_db;
+ tSDP_DISC_ATTR *p_attr;
+ UINT16 pversion;
+ tSDP_PROTOCOL_ELEM pe;
+
+ record->hdr.type = SDP_TYPE_RAW;
+ record->hdr.service_name_length = 0;
+ record->hdr.service_name = NULL;
+ record->hdr.rfcomm_channel_number = -1;
+ record->hdr.l2cap_psm = -1;
+ record->hdr.profile_version = -1;
+
+ /* Try to extract a service name */
+ if ((p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_SERVICE_NAME)) != NULL)
+ {
+ record->pse.hdr.service_name_length = SDP_DISC_ATTR_LEN(p_attr->attr_len_type);
+ record->pse.hdr.service_name = (char *)p_attr->attr_value.v.array;
+ }
+
+ /* Try to extract an RFCOMM channel */
+ if (SDP_FindProtocolListElemInRec(p_rec, UUID_PROTOCOL_RFCOMM, &pe))
+ {
+ record->pse.hdr.rfcomm_channel_number = pe.params[0];
+ }
+ record->hdr.user1_ptr_len = p_bta_sdp_cfg->p_sdp_db->raw_size;
+ record->hdr.user1_ptr = p_bta_sdp_cfg->p_sdp_db->raw_data;
+}
+
+
+/*******************************************************************************
+**
+** Function bta_sdp_search_cback
+**
+** Description Callback from btm after search is completed
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_sdp_search_cback(UINT16 result, void * user_data)
+{
+ tSDP_DISC_REC *p_rec = NULL;
+ tBTA_SDP_SEARCH_COMP evt_data = {0}; // We need to zero-initialize
+ tBTA_SDP_STATUS status = BTA_SDP_FAILURE;
+ UINT16 uuid16 = 0;
+ int count = 0;
+ tBT_UUID su;
+ APPL_TRACE_DEBUG("%s() - res: 0x%x", __func__, result);
+
+ bta_sdp_cb.sdp_active = BTA_SDP_ACTIVE_NONE;
+
+ if (bta_sdp_cb.p_dm_cback == NULL) return;
+
+ bdcpy(evt_data.remote_addr, bta_sdp_cb.remote_addr);
+ tBT_UUID *uuid = (tBT_UUID*)user_data;
+ memcpy(&evt_data.uuid, uuid, sizeof(tBT_UUID));
+ su = shorten_sdp_uuid(uuid);
+
+ if (result == SDP_SUCCESS || result == SDP_DB_FULL)
+ {
+ do {
+ p_rec = SDP_FindServiceUUIDInDb(p_bta_sdp_cfg->p_sdp_db, &su, p_rec);
+ /* generate the matching record data pointer */
+ if(p_rec != NULL){
+ status = BTA_SDP_SUCCESS;
+ if (IS_UUID(UUID_MAP_MAS,uuid->uu.uuid128)) {
+ APPL_TRACE_DEBUG("%s() - found MAP (MAS) uuid", __func__);
+ bta_create_mas_sdp_record(&evt_data.records[count], p_rec);
+ } else if (IS_UUID(UUID_MAP_MNS,uuid->uu.uuid128)) {
+ APPL_TRACE_DEBUG("%s() - found MAP (MNS) uuid", __func__);
+ bta_create_mns_sdp_record(&evt_data.records[count], p_rec);
+ } else if (IS_UUID(UUID_PBAP_PSE,uuid->uu.uuid128)){
+ APPL_TRACE_DEBUG("%s() - found PBAP (PSE) uuid", __func__);
+ bta_create_pse_sdp_record(&evt_data.records[count], p_rec);
+ } else if (IS_UUID(UUID_OBEX_OBJECT_PUSH,uuid->uu.uuid128)){
+ APPL_TRACE_DEBUG("%s() - found Object Push Server (OPS) uuid", __func__);
+ bta_create_ops_sdp_record(&evt_data.records[count], p_rec);
+ } else if (IS_UUID(UUID_SAP,uuid->uu.uuid128)) {
+ APPL_TRACE_DEBUG("%s() - found SAP uuid", __func__);
+ bta_create_sap_sdp_record(&evt_data.records[count], p_rec);
+ } else {
+
+ /* we do not have specific structure for this */
+ APPL_TRACE_DEBUG("%s() - profile not identified. using raw data", __func__);
+ bta_create_raw_sdp_record(&evt_data.records[count], p_rec);
+ p_rec = NULL; // Terminate loop
+ /* For raw, we only extract the first entry, and then return the entire
+ raw data chunk.
+ TODO: Find a way to split the raw data into record chunks, and iterate
+ to extract generic data for each chunk - e.g. rfcomm channel and
+ service name. */
+ }
+ count++;
+ } else {
+ APPL_TRACE_DEBUG("%s() - UUID not found", __func__);
+ }
+ } while (p_rec != NULL && count < BTA_SDP_MAX_RECORDS);
+
+ evt_data.record_count = count;
+ }
+ evt_data.status = status;
+
+ bta_sdp_cb.p_dm_cback(BTA_SDP_SEARCH_COMP_EVT, (tBTA_SDP*) &evt_data, (void*)&uuid->uu.uuid128);
+ osi_free(user_data); // We no longer need the user data to track the search
+}
+
+/*******************************************************************************
+**
+** Function bta_sdp_enable
+**
+** Description Initializes the SDP I/F
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_sdp_enable(tBTA_SDP_MSG *p_data)
+{
+ APPL_TRACE_DEBUG("%s in, sdp_active:%d", __func__, bta_sdp_cb.sdp_active);
+ tBTA_SDP_STATUS 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);
+}
+
+/*******************************************************************************
+**
+** Function bta_sdp_search
+**
+** Description Discovers all sdp records for an uuid on remote device
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_sdp_search(tBTA_SDP_MSG *p_data)
+{
+ int x=0;
+ // TODO: Leaks!!! but needed as user-data pointer
+ tBT_UUID *bta_sdp_search_uuid = osi_malloc(sizeof(tBT_UUID));
+ if(p_data == NULL)
+ {
+ APPL_TRACE_DEBUG("SDP control block handle is null");
+ return;
+ }
+ tBTA_SDP_STATUS status = BTA_SDP_FAILURE;
+
+ APPL_TRACE_DEBUG("%s in, sdp_active:%d", __func__, bta_sdp_cb.sdp_active);
+
+ if (bta_sdp_cb.sdp_active != BTA_SDP_ACTIVE_NONE)
+ {
+ /* SDP is still in progress */
+ status = BTA_SDP_BUSY;
+ if(bta_sdp_cb.p_dm_cback) {
+ tBTA_SDP_SEARCH_COMP result = {0};
+ result.uuid = p_data->get_search.uuid;
+ bdcpy(result.remote_addr, p_data->get_search.bd_addr);
+ result.status = status;
+ bta_sdp_cb.p_dm_cback(BTA_SDP_SEARCH_COMP_EVT, (tBTA_SDP *)&result, NULL);
+ }
+ return;
+ }
+
+ bta_sdp_cb.sdp_active = BTA_SDP_ACTIVE_YES;
+ bdcpy(bta_sdp_cb.remote_addr, p_data->get_search.bd_addr);
+ /* set the uuid used in the search */
+ memcpy(bta_sdp_search_uuid, &(p_data->get_search.uuid),sizeof(tBT_UUID));
+
+ /* initialize the search for the uuid */
+ APPL_TRACE_DEBUG("%s init discovery with UUID(len: %d):",
+ __func__, bta_sdp_search_uuid->len);
+ for(x = 0; x<bta_sdp_search_uuid->len;x++){
+ APPL_TRACE_DEBUG("%X",bta_sdp_search_uuid->uu.uuid128[x]);
+ }
+ SDP_InitDiscoveryDb (p_bta_sdp_cfg->p_sdp_db, p_bta_sdp_cfg->sdp_db_size, 1,
+ bta_sdp_search_uuid, 0, NULL);
+
+ if (!SDP_ServiceSearchAttributeRequest2(p_data->get_search.bd_addr, p_bta_sdp_cfg->p_sdp_db,
+ bta_sdp_search_cback, (void*)bta_sdp_search_uuid))
+ {
+ bta_sdp_cb.sdp_active = BTA_SDP_ACTIVE_NONE;
+
+ /* failed to start SDP. report the failure right away */
+ if (bta_sdp_cb.p_dm_cback) {
+ tBTA_SDP_SEARCH_COMP result = {0};
+ result.uuid = p_data->get_search.uuid;
+ bdcpy(result.remote_addr, p_data->get_search.bd_addr);
+ result.status = status;
+ bta_sdp_cb.p_dm_cback(BTA_SDP_SEARCH_COMP_EVT, (tBTA_SDP *)&result, NULL);
+ }
+ }
+ /*
+ else report the result when the cback is called
+ */
+}
+
+/*******************************************************************************
+**
+** Function bta_sdp_record
+**
+** Description Discovers all sdp records for an uuid on remote device
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_sdp_create_record(tBTA_SDP_MSG *p_data)
+{
+ APPL_TRACE_DEBUG("%s() event: %d", __func__, p_data->record.hdr.event);
+ 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);
+}
+
+/*******************************************************************************
+**
+** Function bta_sdp_create_record
+**
+** Description Discovers all sdp records for an uuid on remote device
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_sdp_remove_record(tBTA_SDP_MSG *p_data)
+{
+ APPL_TRACE_DEBUG("%s() event: %d", __func__, p_data->record.hdr.event);
+ 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);
+}
--- /dev/null
+/******************************************************************************
+ *
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This is the implementation of the API for SDP search subsystem
+ *
+ ******************************************************************************/
+
+#include "bta_api.h"
+#include "bta_sys.h"
+#include "bta_sdp_api.h"
+#include "bta_sdp_int.h"
+#include "gki.h"
+#include <string.h>
+// #include "port_api.h"
+#include "sdp_api.h"
+
+/*****************************************************************************
+** Constants
+*****************************************************************************/
+
+static const tBTA_SYS_REG bta_sdp_reg =
+{
+ bta_sdp_sm_execute,
+ NULL
+};
+
+/*******************************************************************************
+**
+** Function BTA_SdpEnable
+**
+** Description Enable the SDP search I/F service. When the enable
+** operation is complete the callback function will be
+** called with a BTA_SDP_ENABLE_EVT. This function must
+** be called before other functions in the SDP search API are
+** called.
+**
+** Returns BTA_SDP_SUCCESS if successful.
+** BTA_SDP_FAIL if internal failure.
+**
+*******************************************************************************/
+tBTA_SDP_STATUS BTA_SdpEnable(tBTA_SDP_DM_CBACK *p_cback)
+{
+ tBTA_SDP_STATUS status = BTA_SDP_FAILURE;
+ tBTA_SDP_API_ENABLE *p_buf;
+
+ APPL_TRACE_API(__FUNCTION__);
+ if(p_cback && FALSE == bta_sys_is_register(BTA_ID_SDP))
+ {
+ memset(&bta_sdp_cb, 0, sizeof(tBTA_SDP_CB));
+
+ /* register with BTA system manager */
+ bta_sys_register(BTA_ID_SDP, &bta_sdp_reg);
+
+ if (p_cback &&
+ (p_buf = (tBTA_SDP_API_ENABLE *) GKI_getbuf(sizeof(tBTA_SDP_API_ENABLE))) != NULL)
+ {
+ p_buf->hdr.event = BTA_SDP_API_ENABLE_EVT;
+ p_buf->p_cback = p_cback;
+ bta_sys_sendmsg(p_buf);
+ status = BTA_SDP_SUCCESS;
+ }
+ }
+ return(status);
+}
+
+/*******************************************************************************
+**
+** Function BTA_SdpSearch
+**
+** Description This function performs service discovery for a specific service
+** on given peer device. When the operation is completed
+** the tBTA_SDP_DM_CBACK callback function will be called with
+** a BTA_SDP_SEARCH_COMPLETE_EVT.
+**
+** Returns BTA_SDP_SUCCESS, if the request is being processed.
+** BTA_SDP_FAILURE, otherwise.
+**
+*******************************************************************************/
+tBTA_SDP_STATUS BTA_SdpSearch(BD_ADDR bd_addr, tSDP_UUID *uuid)
+{
+ tBTA_SDP_STATUS ret = BTA_SDP_FAILURE;
+ tBTA_SDP_API_SEARCH *p_msg;
+
+ APPL_TRACE_API(__FUNCTION__);
+ if ((p_msg = (tBTA_SDP_API_SEARCH *)GKI_getbuf(sizeof(tBTA_SDP_API_SEARCH))) != NULL)
+ {
+ p_msg->hdr.event = BTA_SDP_API_SEARCH_EVT;
+ bdcpy(p_msg->bd_addr, bd_addr);
+ //p_msg->uuid = uuid;
+ memcpy(&(p_msg->uuid), uuid, sizeof(tSDP_UUID));
+ bta_sys_sendmsg(p_msg);
+ ret = BTA_SDP_SUCCESS;
+ }
+
+ return(ret);
+}
+
+/*******************************************************************************
+**
+** Function BTA_SdpCreateRecordByUser
+**
+** Description This function is used to request a callback to create a SDP
+** record. The registered callback will be called with event
+** BTA_SDP_CREATE_RECORD_USER_EVT.
+**
+** Returns BTA_SDP_SUCCESS, if the request is being processed.
+** BTA_SDP_FAILURE, otherwise.
+**
+*******************************************************************************/
+tBTA_SDP_STATUS BTA_SdpCreateRecordByUser(void* user_data)
+{
+ tBTA_SDP_STATUS ret = BTA_SDP_FAILURE;
+ tBTA_SDP_API_RECORD_USER *p_msg;
+
+ APPL_TRACE_API(__FUNCTION__);
+ if ((p_msg = (tBTA_SDP_API_RECORD_USER *)GKI_getbuf(sizeof(tBTA_SDP_API_RECORD_USER))) != NULL)
+ {
+ p_msg->hdr.event = BTA_SDP_API_CREATE_RECORD_USER_EVT;
+ p_msg->user_data = user_data;
+ bta_sys_sendmsg(p_msg);
+ ret = BTA_SDP_SUCCESS;
+ }
+
+ return(ret);
+}
+
+/*******************************************************************************
+**
+** Function BTA_SdpRemoveRecordByUser
+**
+** Description This function is used to request a callback to remove a SDP
+** record. The registered callback will be called with event
+** BTA_SDP_REMOVE_RECORD_USER_EVT.
+**
+** Returns BTA_SDP_SUCCESS, if the request is being processed.
+** BTA_SDP_FAILURE, otherwise.
+**
+*******************************************************************************/
+tBTA_SDP_STATUS BTA_SdpRemoveRecordByUser(void* user_data)
+{
+ tBTA_SDP_STATUS ret = BTA_SDP_FAILURE;
+ tBTA_SDP_API_RECORD_USER *p_msg;
+
+ APPL_TRACE_API(__FUNCTION__);
+ if ((p_msg = (tBTA_SDP_API_RECORD_USER *)GKI_getbuf(sizeof(tBTA_SDP_API_RECORD_USER))) != NULL)
+ {
+ p_msg->hdr.event = BTA_SDP_API_REMOVE_RECORD_USER_EVT;
+ p_msg->user_data = user_data;
+ bta_sys_sendmsg(p_msg);
+ ret = BTA_SDP_SUCCESS;
+ }
+
+ return(ret);
+}
+
+