1/******************************************************************************
2 *
3 * Copyright (C) 2014 Samsung System LSI
4 *
5 *  Licensed under the Apache License, Version 2.0 (the "License");
6 *  you may not use this file except in compliance with the License.
7 *  You may obtain a copy of the License at:
8 *
9 *  http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 *
17 ******************************************************************************/
18
19/************************************************************************************
20 *
21 *  Filename:      btif_sdp.c
22 *  Description:   SDP Bluetooth Interface.
23 *                 Implements the generic message handling and search functionality.
24 *                 References btif_sdp_server.c for SDP record creation.
25 *
26 ***********************************************************************************/
27
28#include <hardware/bluetooth.h>
29#include <hardware/bt_sdp.h>
30#include <stdlib.h>
31#include <string.h>
32
33#define LOG_TAG "BTIF_SDP"
34#include "btif_common.h"
35#include "btif_util.h"
36#include "btif_profile_queue.h"
37#include "bta_api.h"
38#include "bta_sdp_api.h"
39
40/*****************************************************************************
41**  Functions implemented in sdp_server.c
42******************************************************************************/
43bt_status_t sdp_server_init();
44void sdp_server_cleanup();
45bt_status_t create_sdp_record(bluetooth_sdp_record *records, int* record_handles);
46bt_status_t remove_sdp_record(int record_handle);
47void on_create_record_event(int handle);
48void on_remove_record_event(int handle);
49
50// Utility functions:
51int get_sdp_records_size(bluetooth_sdp_record* in_record, int count);
52void copy_sdp_records(bluetooth_sdp_record* in_records,
53        bluetooth_sdp_record* out_records, int count);
54
55
56/*****************************************************************************
57**  Static variables
58******************************************************************************/
59
60static btsdp_callbacks_t *bt_sdp_callbacks = NULL;
61
62static void btif_sdp_search_comp_evt(UINT16 event, char *p_param)
63{
64    tBTA_SDP_SEARCH_COMP *evt_data = (tBTA_SDP_SEARCH_COMP*) p_param;
65    bt_bdaddr_t addr;
66    BTIF_TRACE_DEBUG("%s:  event = %d", __FUNCTION__, event);
67
68    if (event != BTA_SDP_SEARCH_COMP_EVT)
69        return;
70
71    bdcpy(addr.address, evt_data->remote_addr);
72
73    HAL_CBACK(bt_sdp_callbacks, sdp_search_cb, evt_data->status,
74            &addr, (uint8_t*)(evt_data->uuid.uu.uuid128),
75            evt_data->record_count, evt_data->records);
76}
77
78static void sdp_search_comp_copy_cb(UINT16 event, char *p_dest, char *p_src)
79{
80    tBTA_SDP_SEARCH_COMP *p_dest_data =  (tBTA_SDP_SEARCH_COMP *) p_dest;
81    tBTA_SDP_SEARCH_COMP *p_src_data =  (tBTA_SDP_SEARCH_COMP *) p_src;
82
83    if (!p_src)
84        return;
85
86    if (event != BTA_SDP_SEARCH_COMP_EVT)
87        return;
88
89    memcpy(p_dest_data, p_src_data, sizeof(tBTA_SDP_SEARCH_COMP));
90
91    copy_sdp_records(p_src_data->records, p_dest_data->records, p_src_data->record_count);
92}
93
94static void sdp_dm_cback(tBTA_SDP_EVT event, tBTA_SDP *p_data, void *user_data)
95{
96    switch (event)
97    {
98        case BTA_SDP_SEARCH_COMP_EVT:
99        {
100            int size = sizeof(tBTA_SDP);
101            size += get_sdp_records_size(p_data->sdp_search_comp.records,
102                    p_data->sdp_search_comp.record_count);
103
104            /* need to deep copy the record content */
105            btif_transfer_context(btif_sdp_search_comp_evt, event,
106                                    (char*)p_data, size, sdp_search_comp_copy_cb);
107            break;
108        }
109        case BTA_SDP_CREATE_RECORD_USER_EVT:
110        {
111            on_create_record_event((int)user_data);
112            break;
113        }
114        case BTA_SDP_REMOVE_RECORD_USER_EVT:
115        {
116            on_remove_record_event((int)user_data);
117            break;
118        }
119        default:
120            break;
121    }
122}
123
124static bt_status_t init(btsdp_callbacks_t* callbacks)
125{
126    BTIF_TRACE_DEBUG("Sdp Search %s", __FUNCTION__);
127
128    bt_sdp_callbacks = callbacks;
129    sdp_server_init();
130
131    btif_enable_service(BTA_SDP_SERVICE_ID);
132
133    return BT_STATUS_SUCCESS;
134}
135
136static bt_status_t deinit()
137{
138    BTIF_TRACE_DEBUG("Sdp Search %s", __FUNCTION__);
139
140    bt_sdp_callbacks = NULL;
141    sdp_server_cleanup();
142    btif_disable_service(BTA_SDP_SERVICE_ID);
143
144    return BT_STATUS_SUCCESS;
145}
146
147
148static bt_status_t search(bt_bdaddr_t *bd_addr, const uint8_t *uuid)
149{
150    bdstr_t bdstr;
151    tSDP_UUID sdp_uuid;
152    sdp_uuid.len = 16;
153    memcpy(sdp_uuid.uu.uuid128, uuid, sizeof(sdp_uuid.uu.uuid128));
154
155    BTA_SdpSearch(bd_addr->address, &sdp_uuid);
156
157    return BT_STATUS_SUCCESS;
158}
159
160static const btsdp_interface_t sdp_if = {
161    sizeof(btsdp_interface_t),
162    init,
163    deinit,
164    search,
165    create_sdp_record,
166    remove_sdp_record
167};
168
169const btsdp_interface_t *btif_sdp_get_interface(void)
170{
171    BTIF_TRACE_DEBUG("%s", __FUNCTION__);
172    return &sdp_if;
173}
174
175/*******************************************************************************
176**
177** Function         btif_sdp_execute_service
178**
179** Description      Initializes/Shuts down the service
180**
181** Returns          BT_STATUS_SUCCESS on success, BT_STATUS_FAIL otherwise
182**
183*******************************************************************************/
184bt_status_t btif_sdp_execute_service(BOOLEAN b_enable)
185{
186    BTIF_TRACE_DEBUG("%s enable:%d", __FUNCTION__, b_enable);
187
188     if (b_enable)
189     {
190         BTA_SdpEnable(sdp_dm_cback);
191     }
192     else
193     {
194         /* This is called on BT disable so no need to extra cleanup */
195     }
196     return BT_STATUS_SUCCESS;
197}
198
199