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 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 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 ALOGD("%s: conn_id=%d, connected=%d", __FUNCTION__, conn_id, connected); 112 test_cb.conn_id = connected ? conn_id : 0; 113 } 114 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 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 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 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 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 ALOGD("%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 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 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(¶m, 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(¶m.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, ¶m); 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