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#define LOG_TAG "bt_btif_sdp"
29
30#include <stdlib.h>
31#include <string.h>
32
33#include <hardware/bluetooth.h>
34#include <hardware/bt_sdp.h>
35
36#include "bta_api.h"
37#include "bta_sdp_api.h"
38#include "btif_common.h"
39#include "btif_profile_queue.h"
40#include "btif_util.h"
41
42/*****************************************************************************
43**  Functions implemented in sdp_server.c
44******************************************************************************/
45bt_status_t sdp_server_init();
46void sdp_server_cleanup();
47bt_status_t create_sdp_record(bluetooth_sdp_record *records, int* record_handles);
48bt_status_t remove_sdp_record(int record_handle);
49void on_create_record_event(int handle);
50void on_remove_record_event(int handle);
51
52// Utility functions:
53int get_sdp_records_size(bluetooth_sdp_record* in_record, int count);
54void copy_sdp_records(bluetooth_sdp_record* in_records,
55        bluetooth_sdp_record* out_records, int count);
56
57/*****************************************************************************
58**  Static variables
59******************************************************************************/
60
61static btsdp_callbacks_t *bt_sdp_callbacks = NULL;
62
63static void btif_sdp_search_comp_evt(UINT16 event, char *p_param)
64{
65    tBTA_SDP_SEARCH_COMP *evt_data = (tBTA_SDP_SEARCH_COMP*) p_param;
66    bt_bdaddr_t addr;
67    BTIF_TRACE_DEBUG("%s:  event = %d", __FUNCTION__, event);
68
69    if (event != BTA_SDP_SEARCH_COMP_EVT)
70        return;
71
72    bdcpy(addr.address, evt_data->remote_addr);
73
74    HAL_CBACK(bt_sdp_callbacks, sdp_search_cb, evt_data->status,
75            &addr, (uint8_t*)(evt_data->uuid.uu.uuid128),
76            evt_data->record_count, evt_data->records);
77}
78
79static void sdp_search_comp_copy_cb(UINT16 event, char *p_dest, char *p_src)
80{
81    tBTA_SDP_SEARCH_COMP *p_dest_data =  (tBTA_SDP_SEARCH_COMP *) p_dest;
82    tBTA_SDP_SEARCH_COMP *p_src_data =  (tBTA_SDP_SEARCH_COMP *) p_src;
83
84    if (!p_src)
85        return;
86
87    if (event != BTA_SDP_SEARCH_COMP_EVT)
88        return;
89
90    maybe_non_aligned_memcpy(p_dest_data, p_src_data, sizeof(*p_src_data));
91
92    copy_sdp_records(p_src_data->records, p_dest_data->records, p_src_data->record_count);
93}
94
95static void sdp_dm_cback(tBTA_SDP_EVT event, tBTA_SDP *p_data, void *user_data)
96{
97    switch (event)
98    {
99        case BTA_SDP_SEARCH_COMP_EVT:
100        {
101            int size = sizeof(tBTA_SDP);
102            size += get_sdp_records_size(p_data->sdp_search_comp.records,
103                    p_data->sdp_search_comp.record_count);
104
105            /* need to deep copy the record content */
106            btif_transfer_context(btif_sdp_search_comp_evt, event,
107                                    (char*)p_data, size, sdp_search_comp_copy_cb);
108            break;
109        }
110        case BTA_SDP_CREATE_RECORD_USER_EVT:
111        {
112            on_create_record_event(PTR_TO_INT(user_data));
113            break;
114        }
115        case BTA_SDP_REMOVE_RECORD_USER_EVT:
116        {
117            on_remove_record_event(PTR_TO_INT(user_data));
118            break;
119        }
120        default:
121            break;
122    }
123}
124
125static bt_status_t init(btsdp_callbacks_t* callbacks)
126{
127    BTIF_TRACE_DEBUG("Sdp Search %s", __FUNCTION__);
128
129    bt_sdp_callbacks = callbacks;
130    sdp_server_init();
131
132    btif_enable_service(BTA_SDP_SERVICE_ID);
133
134    return BT_STATUS_SUCCESS;
135}
136
137static bt_status_t deinit()
138{
139    BTIF_TRACE_DEBUG("Sdp Search %s", __FUNCTION__);
140
141    bt_sdp_callbacks = NULL;
142    sdp_server_cleanup();
143    btif_disable_service(BTA_SDP_SERVICE_ID);
144
145    return BT_STATUS_SUCCESS;
146}
147
148static bt_status_t search(bt_bdaddr_t *bd_addr, const uint8_t *uuid)
149{
150    tSDP_UUID sdp_uuid;
151    sdp_uuid.len = 16;
152    memcpy(sdp_uuid.uu.uuid128, uuid, sizeof(sdp_uuid.uu.uuid128));
153
154    BTA_SdpSearch(bd_addr->address, &sdp_uuid);
155
156    return BT_STATUS_SUCCESS;
157}
158
159static const btsdp_interface_t sdp_if = {
160    sizeof(btsdp_interface_t),
161    init,
162    deinit,
163    search,
164    create_sdp_record,
165    remove_sdp_record
166};
167
168const btsdp_interface_t *btif_sdp_get_interface(void)
169{
170    BTIF_TRACE_DEBUG("%s", __FUNCTION__);
171    return &sdp_if;
172}
173
174/*******************************************************************************
175**
176** Function         btif_sdp_execute_service
177**
178** Description      Initializes/Shuts down the service
179**
180** Returns          BT_STATUS_SUCCESS on success, BT_STATUS_FAIL otherwise
181**
182*******************************************************************************/
183bt_status_t btif_sdp_execute_service(BOOLEAN b_enable)
184{
185    BTIF_TRACE_DEBUG("%s enable:%d", __FUNCTION__, b_enable);
186
187     if (b_enable)
188     {
189         BTA_SdpEnable(sdp_dm_cback);
190     }
191     else
192     {
193         /* This is called on BT disable so no need to extra cleanup */
194     }
195     return BT_STATUS_SUCCESS;
196}
197
198