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
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)103 static void btif_test_connect_cback(tGATT_IF gatt_if, BD_ADDR bda, UINT16 conn_id,
104 BOOLEAN connected, tGATT_DISCONN_REASON reason)
105 {
106 ALOGD("%s: conn_id=%d, connected=%d", __FUNCTION__, conn_id, connected);
107 test_cb.conn_id = connected ? conn_id : 0;
108 }
109
btif_test_command_complete_cback(UINT16 conn_id,tGATTC_OPTYPE op,tGATT_STATUS status,tGATT_CL_COMPLETE * p_data)110 static void btif_test_command_complete_cback(UINT16 conn_id, tGATTC_OPTYPE op,
111 tGATT_STATUS status, tGATT_CL_COMPLETE *p_data)
112 {
113 ALOGD ("%s: op_code=0x%02x, conn_id=0x%x. status=0x%x",
114 __FUNCTION__, op, conn_id, status);
115
116 switch (op)
117 {
118 case GATTC_OPTYPE_READ:
119 case GATTC_OPTYPE_WRITE:
120 case GATTC_OPTYPE_CONFIG:
121 case GATTC_OPTYPE_EXE_WRITE:
122 case GATTC_OPTYPE_NOTIFICATION:
123 break;
124
125 case GATTC_OPTYPE_INDICATION:
126 GATTC_SendHandleValueConfirm(conn_id, p_data->handle);
127 break;
128
129 default:
130 ALOGD ("%s: Unknown op_code (0x%02x)", __FUNCTION__, op);
131 break;
132 }
133 }
134
135
btif_test_discovery_result_cback(UINT16 conn_id,tGATT_DISC_TYPE disc_type,tGATT_DISC_RES * p_data)136 static void btif_test_discovery_result_cback(UINT16 conn_id, tGATT_DISC_TYPE disc_type,
137 tGATT_DISC_RES *p_data)
138 {
139 char str_buf[50];
140
141 ALOGD("------ GATT Discovery result %-22s -------", disc_name[disc_type]);
142 ALOGD(" Attribute handle: 0x%04x (%d)", p_data->handle, p_data->handle);
143
144 if (disc_type != GATT_DISC_CHAR_DSCPT) {
145 ALOGD(" Attribute type: %s", format_uuid(p_data->type, str_buf));
146 }
147
148 switch (disc_type)
149 {
150 case GATT_DISC_SRVC_ALL:
151 ALOGD(" Handle range: 0x%04x ~ 0x%04x (%d ~ %d)",
152 p_data->handle, p_data->value.group_value.e_handle,
153 p_data->handle, p_data->value.group_value.e_handle);
154 ALOGD(" Service UUID: %s",
155 format_uuid(p_data->value.group_value.service_type, str_buf));
156 break;
157
158 case GATT_DISC_SRVC_BY_UUID:
159 ALOGD(" Handle range: 0x%04x ~ 0x%04x (%d ~ %d)",
160 p_data->handle, p_data->value.handle,
161 p_data->handle, p_data->value.handle);
162 break;
163
164 case GATT_DISC_INC_SRVC:
165 ALOGD(" Handle range: 0x%04x ~ 0x%04x (%d ~ %d)",
166 p_data->value.incl_service.s_handle, p_data->value.incl_service.e_handle,
167 p_data->value.incl_service.s_handle, p_data->value.incl_service.e_handle);
168 ALOGD(" Service UUID: %s",
169 format_uuid(p_data->value.incl_service.service_type, str_buf));
170 break;
171
172 case GATT_DISC_CHAR:
173 ALOGD(" Properties: 0x%02x",
174 p_data->value.dclr_value.char_prop);
175 ALOGD(" Characteristic UUID: %s",
176 format_uuid(p_data->value.dclr_value.char_uuid, str_buf));
177 break;
178
179 case GATT_DISC_CHAR_DSCPT:
180 ALOGD(" Descriptor UUID: %s", format_uuid(p_data->type, str_buf));
181 break;
182 }
183
184 ALOGD("-----------------------------------------------------------");
185 }
186
btif_test_discovery_complete_cback(UINT16 conn_id,tGATT_DISC_TYPE disc_type,tGATT_STATUS status)187 static void btif_test_discovery_complete_cback(UINT16 conn_id,
188 tGATT_DISC_TYPE disc_type,
189 tGATT_STATUS status)
190 {
191 ALOGD("%s: status=%d", __FUNCTION__, status);
192 }
193
194 static tGATT_CBACK btif_test_callbacks =
195 {
196 btif_test_connect_cback ,
197 btif_test_command_complete_cback,
198 btif_test_discovery_result_cback,
199 btif_test_discovery_complete_cback,
200 NULL,
201 NULL
202 };
203
204 /*******************************************************************************
205 * Implementation
206 *******************************************************************************/
207
btif_gattc_test_command_impl(uint16_t command,btgatt_test_params_t * params)208 bt_status_t btif_gattc_test_command_impl(uint16_t command, btgatt_test_params_t* params)
209 {
210 switch(command) {
211 case 0x01: /* Enable */
212 {
213 ALOGD("%s: ENABLE - enable=%d", __FUNCTION__, params->u1);
214 if (params->u1)
215 {
216 tBT_UUID app_uuid = {LEN_UUID_128,{0xAE}};
217 test_cb.gatt_if = GATT_Register(&app_uuid, &btif_test_callbacks);
218 GATT_StartIf(test_cb.gatt_if);
219 } else {
220 GATT_Deregister(test_cb.gatt_if);
221 test_cb.gatt_if = 0;
222 }
223 break;
224 }
225
226 case 0x02: /* Connect */
227 {
228 ALOGD("%s: CONNECT - device=%02x:%02x:%02x:%02x:%02x:%02x (dev_type=%d)",
229 __FUNCTION__,
230 params->bda1->address[0], params->bda1->address[1],
231 params->bda1->address[2], params->bda1->address[3],
232 params->bda1->address[4], params->bda1->address[5],
233 params->u1);
234
235 if (params->u1 == BT_DEVICE_TYPE_BLE)
236 BTM_SecAddBleDevice(params->bda1->address, NULL, BT_DEVICE_TYPE_BLE, 0);
237
238 if ( !GATT_Connect(test_cb.gatt_if, params->bda1->address, TRUE) )
239 {
240 ALOGE("%s: GATT_Connect failed!", __FUNCTION__);
241 }
242 break;
243 }
244
245 case 0x03: /* Disconnect */
246 {
247 ALOGD("%s: DISCONNECT - conn_id=%d", __FUNCTION__, test_cb.conn_id);
248 GATT_Disconnect(test_cb.conn_id);
249 break;
250 }
251
252 case 0x04: /* Discover */
253 {
254 char buf[50] = {0};
255 tGATT_DISC_PARAM param;
256 memset(¶m, 0, sizeof(tGATT_DISC_PARAM));
257
258 if (params->u1 >= GATT_DISC_MAX)
259 {
260 ALOGE("%s: DISCOVER - Invalid type (%d)!", __FUNCTION__, params->u1);
261 return 0;
262 }
263
264 param.s_handle = params->u2;
265 param.e_handle = params->u3;
266 btif_to_bta_uuid(¶m.service, params->uuid1);
267
268 ALOGD("%s: DISCOVER (%s), conn_id=%d, uuid=%s, handles=0x%04x-0x%04x",
269 __FUNCTION__, disc_name[params->u1], test_cb.conn_id,
270 format_uuid(param.service, buf), params->u2, params->u3);
271 GATTC_Discover(test_cb.conn_id, params->u1, ¶m);
272 break;
273 }
274
275 case 0xF0: /* Pairing configuration */
276 ALOGD("%s: Setting pairing config auth=%d, iocaps=%d, keys=%d/%d/%d",
277 __FUNCTION__, 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 ALOGE("%s: UNKNOWN TEST COMMAND 0x%02x", __FUNCTION__, command);
289 break;
290 }
291 return 0;
292 }
293
294 #endif
295