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