1/******************************************************************************
2 *
3 *  Copyright (C) 2009-2013 Broadcom Corporation
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#include <hardware/bluetooth.h>
21#include <hardware/bt_gatt.h>
22#include <stdio.h>
23#include <stdlib.h>
24#include <errno.h>
25#include <string.h>
26
27#define LOG_TAG "BtGatt.btif_test"
28
29#include "btif_common.h"
30#include "btif_util.h"
31
32#if (defined(BLE_INCLUDED) && (BLE_INCLUDED == TRUE))
33
34#include "bta_api.h"
35#include "bta_gatt_api.h"
36#include "bd.h"
37#include "btif_storage.h"
38#include "bte_appl.h"
39
40#include "btif_gatt.h"
41#include "btif_gatt_util.h"
42#include "btif_dm.h"
43
44#include "gatt_api.h"
45
46/*******************************************************************************
47 * Typedefs & Macros
48 *******************************************************************************/
49
50typedef struct
51{
52    tGATT_IF    gatt_if;
53    UINT16      conn_id;
54} btif_test_cb_t;
55
56/*******************************************************************************
57 * Static variables
58 *******************************************************************************/
59
60static const char * disc_name[GATT_DISC_MAX] =
61{
62    "Unknown",
63    "GATT_DISC_SRVC_ALL",
64    "GATT_DISC_SRVC_BY_UUID",
65    "GATT_DISC_INC_SRVC",
66    "GATT_DISC_CHAR",
67    "GATT_DISC_CHAR_DSCPT"
68};
69
70static btif_test_cb_t test_cb;
71
72/*******************************************************************************
73 * Callback functions
74 *******************************************************************************/
75
76static char * format_uuid(tBT_UUID bt_uuid, char *str_buf)
77{
78    int x = 0;
79
80    if (bt_uuid.len == LEN_UUID_16)
81    {
82        sprintf(str_buf, "0x%04x", bt_uuid.uu.uuid16);
83    }
84    else if (bt_uuid.len == LEN_UUID_128)
85    {
86        x += sprintf(&str_buf[x], "%02x%02x%02x%02x-%02x%02x-%02x%02x",
87                bt_uuid.uu.uuid128[15], bt_uuid.uu.uuid128[14],
88                bt_uuid.uu.uuid128[13], bt_uuid.uu.uuid128[12],
89                bt_uuid.uu.uuid128[11], bt_uuid.uu.uuid128[10],
90                bt_uuid.uu.uuid128[9], bt_uuid.uu.uuid128[8]);
91        sprintf(&str_buf[x], "%02x%02x-%02x%02x%02x%02x%02x%02x",
92                bt_uuid.uu.uuid128[7], bt_uuid.uu.uuid128[6],
93                bt_uuid.uu.uuid128[5], bt_uuid.uu.uuid128[4],
94                bt_uuid.uu.uuid128[3], bt_uuid.uu.uuid128[2],
95                bt_uuid.uu.uuid128[1], bt_uuid.uu.uuid128[0]);
96    }
97    else
98        sprintf(str_buf, "Unknown (len=%d)", bt_uuid.len);
99
100    return str_buf;
101}
102
103static void btif_test_connect_cback(tGATT_IF gatt_if, BD_ADDR bda, UINT16 conn_id,
104                                    BOOLEAN connected, tGATT_DISCONN_REASON reason, tBT_TRANSPORT transport)
105{
106    UNUSED(gatt_if);
107    UNUSED(bda);
108    UNUSED(reason);
109    UNUSED (transport);
110
111    ALOGD("%s: conn_id=%d, connected=%d", __FUNCTION__, conn_id, connected);
112    test_cb.conn_id = connected ? conn_id : 0;
113}
114
115static void btif_test_command_complete_cback(UINT16 conn_id, tGATTC_OPTYPE op,
116                                tGATT_STATUS status, tGATT_CL_COMPLETE *p_data)
117{
118    ALOGD ("%s: op_code=0x%02x, conn_id=0x%x. status=0x%x",
119            __FUNCTION__, op, conn_id, status);
120
121    switch (op)
122    {
123        case GATTC_OPTYPE_READ:
124        case GATTC_OPTYPE_WRITE:
125        case GATTC_OPTYPE_CONFIG:
126        case GATTC_OPTYPE_EXE_WRITE:
127        case GATTC_OPTYPE_NOTIFICATION:
128            break;
129
130        case GATTC_OPTYPE_INDICATION:
131            GATTC_SendHandleValueConfirm(conn_id, p_data->handle);
132            break;
133
134        default:
135            ALOGD ("%s: Unknown op_code (0x%02x)", __FUNCTION__, op);
136            break;
137    }
138}
139
140
141static void btif_test_discovery_result_cback(UINT16 conn_id, tGATT_DISC_TYPE disc_type,
142                                           tGATT_DISC_RES *p_data)
143{
144    char    str_buf[50];
145    UNUSED(conn_id);
146
147    ALOGD("------ GATT Discovery result %-22s -------", disc_name[disc_type]);
148    ALOGD("      Attribute handle: 0x%04x (%d)", p_data->handle, p_data->handle);
149
150    if (disc_type != GATT_DISC_CHAR_DSCPT) {
151        ALOGD("        Attribute type: %s", format_uuid(p_data->type, str_buf));
152    }
153
154    switch (disc_type)
155    {
156        case GATT_DISC_SRVC_ALL:
157            ALOGD("          Handle range: 0x%04x ~ 0x%04x (%d ~ %d)",
158                  p_data->handle, p_data->value.group_value.e_handle,
159                  p_data->handle, p_data->value.group_value.e_handle);
160            ALOGD("          Service UUID: %s",
161                    format_uuid(p_data->value.group_value.service_type, str_buf));
162            break;
163
164        case GATT_DISC_SRVC_BY_UUID:
165            ALOGD("          Handle range: 0x%04x ~ 0x%04x (%d ~ %d)",
166                  p_data->handle, p_data->value.handle,
167                  p_data->handle, p_data->value.handle);
168            break;
169
170        case GATT_DISC_INC_SRVC:
171            ALOGD("          Handle range: 0x%04x ~ 0x%04x (%d ~ %d)",
172                  p_data->value.incl_service.s_handle, p_data->value.incl_service.e_handle,
173                  p_data->value.incl_service.s_handle, p_data->value.incl_service.e_handle);
174            ALOGD("          Service UUID: %s",
175                  format_uuid(p_data->value.incl_service.service_type, str_buf));
176            break;
177
178        case GATT_DISC_CHAR:
179            ALOGD("            Properties: 0x%02x",
180                  p_data->value.dclr_value.char_prop);
181            ALOGD("   Characteristic UUID: %s",
182                  format_uuid(p_data->value.dclr_value.char_uuid, str_buf));
183            break;
184
185        case GATT_DISC_CHAR_DSCPT:
186            ALOGD("       Descriptor UUID: %s", format_uuid(p_data->type, str_buf));
187            break;
188    }
189
190    ALOGD("-----------------------------------------------------------");
191}
192
193static void btif_test_discovery_complete_cback(UINT16 conn_id,
194                                               tGATT_DISC_TYPE disc_type,
195                                               tGATT_STATUS status)
196{
197    UNUSED(conn_id);
198    UNUSED(disc_type);
199    ALOGD("%s: status=%d", __FUNCTION__, status);
200}
201
202static tGATT_CBACK btif_test_callbacks =
203{
204    btif_test_connect_cback ,
205    btif_test_command_complete_cback,
206    btif_test_discovery_result_cback,
207    btif_test_discovery_complete_cback,
208    NULL,
209    NULL,
210    NULL
211};
212
213/*******************************************************************************
214 * Implementation
215 *******************************************************************************/
216
217bt_status_t btif_gattc_test_command_impl(uint16_t command, btgatt_test_params_t* params)
218{
219    switch(command) {
220        case 0x01: /* Enable */
221        {
222            ALOGD("%s: ENABLE - enable=%d", __FUNCTION__, params->u1);
223            if (params->u1)
224            {
225                tBT_UUID app_uuid = {LEN_UUID_128,{0xAE}};
226                test_cb.gatt_if = GATT_Register(&app_uuid, &btif_test_callbacks);
227                GATT_StartIf(test_cb.gatt_if);
228            } else {
229                GATT_Deregister(test_cb.gatt_if);
230                test_cb.gatt_if = 0;
231            }
232            break;
233        }
234
235        case 0x02: /* Connect */
236        {
237            ALOGD("%s: CONNECT - device=%02x:%02x:%02x:%02x:%02x:%02x (dev_type=%d, addr_type=%d)",
238                __FUNCTION__,
239                params->bda1->address[0], params->bda1->address[1],
240                params->bda1->address[2], params->bda1->address[3],
241                params->bda1->address[4], params->bda1->address[5],
242                params->u1, params->u2);
243
244            if (params->u1 == BT_DEVICE_TYPE_BLE)
245                BTM_SecAddBleDevice(params->bda1->address, NULL, BT_DEVICE_TYPE_BLE, params->u2);
246
247            if ( !GATT_Connect(test_cb.gatt_if, params->bda1->address, TRUE, BT_TRANSPORT_LE) )
248            {
249                ALOGE("%s: GATT_Connect failed!", __FUNCTION__);
250            }
251            break;
252        }
253
254        case 0x03: /* Disconnect */
255        {
256            ALOGD("%s: DISCONNECT - conn_id=%d", __FUNCTION__, test_cb.conn_id);
257            GATT_Disconnect(test_cb.conn_id);
258            break;
259        }
260
261        case 0x04: /* Discover */
262        {
263            char buf[50] = {0};
264            tGATT_DISC_PARAM        param;
265            memset(&param, 0, sizeof(tGATT_DISC_PARAM));
266
267            if (params->u1 >= GATT_DISC_MAX)
268            {
269                ALOGE("%s: DISCOVER - Invalid type (%d)!", __FUNCTION__, params->u1);
270                return 0;
271            }
272
273            param.s_handle = params->u2;
274            param.e_handle = params->u3;
275            btif_to_bta_uuid(&param.service, params->uuid1);
276
277            ALOGD("%s: DISCOVER (%s), conn_id=%d, uuid=%s, handles=0x%04x-0x%04x",
278                  __FUNCTION__, disc_name[params->u1], test_cb.conn_id,
279                  format_uuid(param.service, buf), params->u2, params->u3);
280            GATTC_Discover(test_cb.conn_id, params->u1, &param);
281            break;
282        }
283
284        case 0xF0: /* Pairing configuration */
285            ALOGD("%s: Setting pairing config auth=%d, iocaps=%d, keys=%d/%d/%d",
286                  __FUNCTION__, params->u1, params->u2, params->u3, params->u4,
287                  params->u5);
288
289            bte_appl_cfg.ble_auth_req = params->u1;
290            bte_appl_cfg.ble_io_cap = params->u2;
291            bte_appl_cfg.ble_init_key = params->u3;
292            bte_appl_cfg.ble_resp_key = params->u4;
293            bte_appl_cfg.ble_max_key_size = params->u5;
294            break;
295
296        default:
297            ALOGE("%s: UNKNOWN TEST COMMAND 0x%02x", __FUNCTION__, command);
298            break;
299    }
300    return 0;
301}
302
303#endif
304