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 "bt_btif_gatt"
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 "btif_storage.h"
37 #include "bte_appl.h"
38 
39 #include "btif_gatt.h"
40 #include "btif_gatt_util.h"
41 #include "btif_dm.h"
42 
43 #include "gatt_api.h"
44 #include "osi/include/log.h"
45 
46 /*******************************************************************************
47  * Typedefs & Macros
48  *******************************************************************************/
49 
50 typedef struct
51 {
52     tGATT_IF    gatt_if;
53     UINT16      conn_id;
54 } btif_test_cb_t;
55 
56 /*******************************************************************************
57  * Static variables
58  *******************************************************************************/
59 
60 static 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 
70 static btif_test_cb_t test_cb;
71 
72 /*******************************************************************************
73  * Callback functions
74  *******************************************************************************/
75 
format_uuid(tBT_UUID bt_uuid,char * str_buf)76 static 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 
btif_test_connect_cback(tGATT_IF gatt_if,BD_ADDR bda,UINT16 conn_id,BOOLEAN connected,tGATT_DISCONN_REASON reason,tBT_TRANSPORT transport)103 static 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     LOG_DEBUG("%s: conn_id=%d, connected=%d", __FUNCTION__, conn_id, connected);
112     test_cb.conn_id = connected ? conn_id : 0;
113 }
114 
btif_test_command_complete_cback(UINT16 conn_id,tGATTC_OPTYPE op,tGATT_STATUS status,tGATT_CL_COMPLETE * p_data)115 static void btif_test_command_complete_cback(UINT16 conn_id, tGATTC_OPTYPE op,
116                                 tGATT_STATUS status, tGATT_CL_COMPLETE *p_data)
117 {
118     LOG_DEBUG ("%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             LOG_DEBUG ("%s: Unknown op_code (0x%02x)", __FUNCTION__, op);
136             break;
137     }
138 }
139 
140 
btif_test_discovery_result_cback(UINT16 conn_id,tGATT_DISC_TYPE disc_type,tGATT_DISC_RES * p_data)141 static 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     LOG_DEBUG("------ GATT Discovery result %-22s -------", disc_name[disc_type]);
148     LOG_DEBUG("      Attribute handle: 0x%04x (%d)", p_data->handle, p_data->handle);
149 
150     if (disc_type != GATT_DISC_CHAR_DSCPT) {
151         LOG_DEBUG("        Attribute type: %s", format_uuid(p_data->type, str_buf));
152     }
153 
154     switch (disc_type)
155     {
156         case GATT_DISC_SRVC_ALL:
157             LOG_DEBUG("          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             LOG_DEBUG("          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             LOG_DEBUG("          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             LOG_DEBUG("          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             LOG_DEBUG("          Service UUID: %s",
175                   format_uuid(p_data->value.incl_service.service_type, str_buf));
176             break;
177 
178         case GATT_DISC_CHAR:
179             LOG_DEBUG("            Properties: 0x%02x",
180                   p_data->value.dclr_value.char_prop);
181             LOG_DEBUG("   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             LOG_DEBUG("       Descriptor UUID: %s", format_uuid(p_data->type, str_buf));
187             break;
188     }
189 
190     LOG_DEBUG("-----------------------------------------------------------");
191 }
192 
btif_test_discovery_complete_cback(UINT16 conn_id,tGATT_DISC_TYPE disc_type,tGATT_STATUS status)193 static 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     LOG_DEBUG("%s: status=%d", __FUNCTION__, status);
200 }
201 
202 static 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 
btif_gattc_test_command_impl(uint16_t command,btgatt_test_params_t * params)217 bt_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             LOG_DEBUG("%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             LOG_DEBUG("%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                 LOG_ERROR("%s: GATT_Connect failed!", __FUNCTION__);
250             }
251             break;
252         }
253 
254         case 0x03: /* Disconnect */
255         {
256             LOG_DEBUG("%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                 LOG_ERROR("%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             LOG_DEBUG("%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             LOG_DEBUG("%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             LOG_ERROR("%s: UNKNOWN TEST COMMAND 0x%02x", __FUNCTION__, command);
298             break;
299     }
300     return 0;
301 }
302 
303 #endif
304