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