1 /****************************************************************************** 2 * 3 * Copyright 2014 The Android Open Source Project 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 * This file contains action functions for SDP search. 21 ******************************************************************************/ 22 23 #include <arpa/inet.h> 24 #include <hardware/bluetooth.h> 25 #include <hardware/bt_sdp.h> 26 #include <stdlib.h> 27 #include <string.h> 28 29 #include "bt_common.h" 30 #include "bt_types.h" 31 #include "bta_api.h" 32 #include "bta_sdp_api.h" 33 #include "bta_sdp_int.h" 34 #include "bta_sys.h" 35 #include "btm_api.h" 36 #include "btm_int.h" 37 #include "osi/include/allocator.h" 38 #include "sdp_api.h" 39 #include "utl.h" 40 41 /***************************************************************************** 42 * Constants 43 ****************************************************************************/ 44 45 static const Uuid UUID_OBEX_OBJECT_PUSH = Uuid::From16Bit(0x1105); 46 static const Uuid UUID_PBAP_PSE = Uuid::From16Bit(0x112F); 47 static const Uuid UUID_MAP_MAS = Uuid::From16Bit(0x1132); 48 static const Uuid UUID_MAP_MNS = Uuid::From16Bit(0x1133); 49 static const Uuid UUID_SAP = Uuid::From16Bit(0x112D); 50 51 static void bta_create_mns_sdp_record(bluetooth_sdp_record* record, 52 tSDP_DISC_REC* p_rec) { 53 tSDP_DISC_ATTR* p_attr; 54 tSDP_PROTOCOL_ELEM pe; 55 uint16_t pversion = 0; 56 record->mns.hdr.type = SDP_TYPE_MAP_MNS; 57 record->mns.hdr.service_name_length = 0; 58 record->mns.hdr.service_name = NULL; 59 record->mns.hdr.rfcomm_channel_number = 0; 60 record->mns.hdr.l2cap_psm = -1; 61 record->mns.hdr.profile_version = 0; 62 record->mns.supported_features = 0x0000001F; // default value if not found 63 64 p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_MAP_SUPPORTED_FEATURES); 65 if (p_attr != NULL) { 66 record->mns.supported_features = p_attr->attr_value.v.u32; 67 } 68 69 p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_SERVICE_NAME); 70 if (p_attr != NULL) { 71 record->mns.hdr.service_name_length = 72 SDP_DISC_ATTR_LEN(p_attr->attr_len_type); 73 record->mns.hdr.service_name = (char*)p_attr->attr_value.v.array; 74 } 75 76 if (SDP_FindProfileVersionInRec(p_rec, UUID_SERVCLASS_MAP_PROFILE, 77 &pversion)) { 78 record->mns.hdr.profile_version = pversion; 79 } 80 81 if (SDP_FindProtocolListElemInRec(p_rec, UUID_PROTOCOL_RFCOMM, &pe)) { 82 record->mns.hdr.rfcomm_channel_number = pe.params[0]; 83 } 84 85 p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_GOEP_L2CAP_PSM); 86 if (p_attr != NULL) { 87 record->mns.hdr.l2cap_psm = p_attr->attr_value.v.u16; 88 } 89 } 90 91 static void bta_create_mas_sdp_record(bluetooth_sdp_record* record, 92 tSDP_DISC_REC* p_rec) { 93 tSDP_DISC_ATTR* p_attr; 94 tSDP_PROTOCOL_ELEM pe; 95 uint16_t pversion = -1; 96 97 record->mas.hdr.type = SDP_TYPE_MAP_MAS; 98 record->mas.hdr.service_name_length = 0; 99 record->mas.hdr.service_name = NULL; 100 record->mas.hdr.rfcomm_channel_number = 0; 101 record->mas.hdr.l2cap_psm = -1; 102 record->mas.hdr.profile_version = 0; 103 record->mas.mas_instance_id = 0; 104 record->mas.supported_features = 0x0000001F; 105 record->mas.supported_message_types = 0; 106 107 p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_MAS_INSTANCE_ID); 108 if (p_attr != NULL) { 109 record->mas.mas_instance_id = p_attr->attr_value.v.u8; 110 } 111 112 p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_SUPPORTED_MSG_TYPE); 113 if (p_attr != NULL) { 114 record->mas.supported_message_types = p_attr->attr_value.v.u8; 115 } 116 117 p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_MAP_SUPPORTED_FEATURES); 118 if (p_attr != NULL) { 119 record->mas.supported_features = p_attr->attr_value.v.u32; 120 } 121 122 p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_SERVICE_NAME); 123 if (p_attr != NULL) { 124 record->mas.hdr.service_name_length = 125 SDP_DISC_ATTR_LEN(p_attr->attr_len_type); 126 record->mas.hdr.service_name = (char*)p_attr->attr_value.v.array; 127 } 128 129 if (SDP_FindProfileVersionInRec(p_rec, UUID_SERVCLASS_MAP_PROFILE, 130 &pversion)) { 131 record->mas.hdr.profile_version = pversion; 132 } 133 134 if (SDP_FindProtocolListElemInRec(p_rec, UUID_PROTOCOL_RFCOMM, &pe)) { 135 record->mas.hdr.rfcomm_channel_number = pe.params[0]; 136 } 137 138 p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_GOEP_L2CAP_PSM); 139 if (p_attr != NULL) { 140 record->mas.hdr.l2cap_psm = p_attr->attr_value.v.u16; 141 } 142 } 143 144 static void bta_create_pse_sdp_record(bluetooth_sdp_record* record, 145 tSDP_DISC_REC* p_rec) { 146 tSDP_DISC_ATTR* p_attr; 147 uint16_t pversion; 148 tSDP_PROTOCOL_ELEM pe; 149 150 record->pse.hdr.type = SDP_TYPE_PBAP_PSE; 151 record->pse.hdr.service_name_length = 0; 152 record->pse.hdr.service_name = NULL; 153 record->pse.hdr.rfcomm_channel_number = 0; 154 record->pse.hdr.l2cap_psm = -1; 155 record->pse.hdr.profile_version = 0; 156 record->pse.supported_features = 0x00000003; 157 record->pse.supported_repositories = 0; 158 159 p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_SUPPORTED_REPOSITORIES); 160 if (p_attr != NULL) { 161 record->pse.supported_repositories = p_attr->attr_value.v.u8; 162 } 163 p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_PBAP_SUPPORTED_FEATURES); 164 if (p_attr != NULL) { 165 record->pse.supported_features = p_attr->attr_value.v.u32; 166 } 167 168 p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_SERVICE_NAME); 169 if (p_attr != NULL) { 170 record->pse.hdr.service_name_length = 171 SDP_DISC_ATTR_LEN(p_attr->attr_len_type); 172 record->pse.hdr.service_name = (char*)p_attr->attr_value.v.array; 173 } 174 175 if (SDP_FindProfileVersionInRec(p_rec, UUID_SERVCLASS_PHONE_ACCESS, 176 &pversion)) { 177 record->pse.hdr.profile_version = pversion; 178 } 179 180 if (SDP_FindProtocolListElemInRec(p_rec, UUID_PROTOCOL_RFCOMM, &pe)) { 181 record->pse.hdr.rfcomm_channel_number = pe.params[0]; 182 } 183 184 p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_GOEP_L2CAP_PSM); 185 if (p_attr != NULL) { 186 record->pse.hdr.l2cap_psm = p_attr->attr_value.v.u16; 187 } 188 } 189 190 static void bta_create_ops_sdp_record(bluetooth_sdp_record* record, 191 tSDP_DISC_REC* p_rec) { 192 tSDP_DISC_ATTR *p_attr, *p_sattr; 193 tSDP_PROTOCOL_ELEM pe; 194 uint16_t pversion = -1; 195 196 record->ops.hdr.type = SDP_TYPE_OPP_SERVER; 197 record->ops.hdr.service_name_length = 0; 198 record->ops.hdr.service_name = NULL; 199 record->ops.hdr.rfcomm_channel_number = 0; 200 record->ops.hdr.l2cap_psm = -1; 201 record->ops.hdr.profile_version = 0; 202 record->ops.supported_formats_list_len = 0; 203 204 p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_SERVICE_NAME); 205 if (p_attr != NULL) { 206 record->ops.hdr.service_name_length = 207 SDP_DISC_ATTR_LEN(p_attr->attr_len_type); 208 record->ops.hdr.service_name = (char*)p_attr->attr_value.v.array; 209 } 210 211 if (SDP_FindProfileVersionInRec(p_rec, UUID_SERVCLASS_OBEX_OBJECT_PUSH, 212 &pversion)) { 213 record->ops.hdr.profile_version = pversion; 214 } 215 216 if (SDP_FindProtocolListElemInRec(p_rec, UUID_PROTOCOL_RFCOMM, &pe)) { 217 record->ops.hdr.rfcomm_channel_number = pe.params[0]; 218 } 219 220 p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_GOEP_L2CAP_PSM); 221 if (p_attr != NULL) { 222 record->ops.hdr.l2cap_psm = p_attr->attr_value.v.u16; 223 } 224 p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_SUPPORTED_FORMATS_LIST); 225 if (p_attr != NULL) { 226 /* Safety check - each entry should itself be a sequence */ 227 if (SDP_DISC_ATTR_TYPE(p_attr->attr_len_type) != DATA_ELE_SEQ_DESC_TYPE) { 228 record->ops.supported_formats_list_len = 0; 229 APPL_TRACE_ERROR( 230 "%s() - supported_formats_list - wrong attribute length/type:" 231 " 0x%02x - expected 0x06", 232 __func__, p_attr->attr_len_type); 233 } else { 234 int count = 0; 235 /* 1 byte for type/length 1 byte for value */ 236 record->ops.supported_formats_list_len = 237 SDP_DISC_ATTR_LEN(p_attr->attr_len_type) / 2; 238 239 /* Extract each value into */ 240 for (p_sattr = p_attr->attr_value.v.p_sub_attr; p_sattr != NULL; 241 p_sattr = p_sattr->p_next_attr) { 242 if ((SDP_DISC_ATTR_TYPE(p_sattr->attr_len_type) == UINT_DESC_TYPE) && 243 (SDP_DISC_ATTR_LEN(p_sattr->attr_len_type) == 1)) { 244 if (count == sizeof(record->ops.supported_formats_list)) { 245 APPL_TRACE_ERROR( 246 "%s() - supported_formats_list - count overflow - " 247 "too many sub attributes!!", 248 __func__); 249 /* If you hit this, new formats have been added, 250 * update SDP_OPP_SUPPORTED_FORMATS_MAX_LENGTH */ 251 break; 252 } 253 record->ops.supported_formats_list[count] = p_sattr->attr_value.v.u8; 254 count++; 255 } else { 256 APPL_TRACE_ERROR( 257 "%s() - supported_formats_list - wrong sub attribute " 258 "length/type: 0x%02x - expected 0x80", 259 __func__, p_sattr->attr_len_type); 260 break; 261 } 262 } 263 if (record->ops.supported_formats_list_len != count) { 264 APPL_TRACE_WARNING( 265 "%s() - supported_formats_list - Length of attribute different " 266 "from the actual number of sub-attributes in the sequence " 267 "att-length: %d - number of elements: %d", 268 __func__, record->ops.supported_formats_list_len, count); 269 } 270 record->ops.supported_formats_list_len = count; 271 } 272 } 273 } 274 275 static void bta_create_sap_sdp_record(bluetooth_sdp_record* record, 276 tSDP_DISC_REC* p_rec) { 277 tSDP_DISC_ATTR* p_attr; 278 tSDP_PROTOCOL_ELEM pe; 279 uint16_t pversion = -1; 280 281 record->sap.hdr.type = SDP_TYPE_MAP_MAS; 282 record->sap.hdr.service_name_length = 0; 283 record->sap.hdr.service_name = NULL; 284 record->sap.hdr.rfcomm_channel_number = 0; 285 record->sap.hdr.l2cap_psm = -1; 286 record->sap.hdr.profile_version = 0; 287 288 p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_SERVICE_NAME); 289 if (p_attr != NULL) { 290 record->sap.hdr.service_name_length = 291 SDP_DISC_ATTR_LEN(p_attr->attr_len_type); 292 record->sap.hdr.service_name = (char*)p_attr->attr_value.v.array; 293 } 294 295 if (SDP_FindProfileVersionInRec(p_rec, UUID_SERVCLASS_SAP, &pversion)) { 296 record->sap.hdr.profile_version = pversion; 297 } 298 299 if (SDP_FindProtocolListElemInRec(p_rec, UUID_PROTOCOL_RFCOMM, &pe)) { 300 record->sap.hdr.rfcomm_channel_number = pe.params[0]; 301 } 302 } 303 304 static void bta_create_raw_sdp_record(bluetooth_sdp_record* record, 305 tSDP_DISC_REC* p_rec) { 306 tSDP_DISC_ATTR* p_attr; 307 tSDP_PROTOCOL_ELEM pe; 308 309 record->hdr.type = SDP_TYPE_RAW; 310 record->hdr.service_name_length = 0; 311 record->hdr.service_name = NULL; 312 record->hdr.rfcomm_channel_number = -1; 313 record->hdr.l2cap_psm = -1; 314 record->hdr.profile_version = -1; 315 316 /* Try to extract a service name */ 317 p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_SERVICE_NAME); 318 if (p_attr != NULL) { 319 record->pse.hdr.service_name_length = 320 SDP_DISC_ATTR_LEN(p_attr->attr_len_type); 321 record->pse.hdr.service_name = (char*)p_attr->attr_value.v.array; 322 } 323 324 /* Try to extract an RFCOMM channel */ 325 if (SDP_FindProtocolListElemInRec(p_rec, UUID_PROTOCOL_RFCOMM, &pe)) { 326 record->pse.hdr.rfcomm_channel_number = pe.params[0]; 327 } 328 record->hdr.user1_ptr_len = p_bta_sdp_cfg->p_sdp_db->raw_size; 329 record->hdr.user1_ptr = p_bta_sdp_cfg->p_sdp_db->raw_data; 330 } 331 332 /** Callback from btm after search is completed */ 333 static void bta_sdp_search_cback(uint16_t result, void* user_data) { 334 tBTA_SDP_STATUS status = BTA_SDP_FAILURE; 335 int count = 0; 336 APPL_TRACE_DEBUG("%s() - res: 0x%x", __func__, result); 337 338 bta_sdp_cb.sdp_active = BTA_SDP_ACTIVE_NONE; 339 340 if (bta_sdp_cb.p_dm_cback == NULL) return; 341 342 Uuid& uuid = *(reinterpret_cast<Uuid*>(user_data)); 343 344 tBTA_SDP_SEARCH_COMP evt_data; 345 memset(&evt_data, 0, sizeof(evt_data)); 346 evt_data.remote_addr = bta_sdp_cb.remote_addr; 347 evt_data.uuid = uuid; 348 349 if (result == SDP_SUCCESS || result == SDP_DB_FULL) { 350 tSDP_DISC_REC* p_rec = NULL; 351 do { 352 p_rec = SDP_FindServiceUUIDInDb(p_bta_sdp_cfg->p_sdp_db, uuid, p_rec); 353 /* generate the matching record data pointer */ 354 if (!p_rec) { 355 APPL_TRACE_DEBUG("%s() - UUID not found", __func__); 356 continue; 357 } 358 359 status = BTA_SDP_SUCCESS; 360 if (uuid == UUID_MAP_MAS) { 361 APPL_TRACE_DEBUG("%s() - found MAP (MAS) uuid", __func__); 362 bta_create_mas_sdp_record(&evt_data.records[count], p_rec); 363 } else if (uuid == UUID_MAP_MNS) { 364 APPL_TRACE_DEBUG("%s() - found MAP (MNS) uuid", __func__); 365 bta_create_mns_sdp_record(&evt_data.records[count], p_rec); 366 } else if (uuid == UUID_PBAP_PSE) { 367 APPL_TRACE_DEBUG("%s() - found PBAP (PSE) uuid", __func__); 368 bta_create_pse_sdp_record(&evt_data.records[count], p_rec); 369 } else if (uuid == UUID_OBEX_OBJECT_PUSH) { 370 APPL_TRACE_DEBUG("%s() - found Object Push Server (OPS) uuid", 371 __func__); 372 bta_create_ops_sdp_record(&evt_data.records[count], p_rec); 373 } else if (uuid == UUID_SAP) { 374 APPL_TRACE_DEBUG("%s() - found SAP uuid", __func__); 375 bta_create_sap_sdp_record(&evt_data.records[count], p_rec); 376 } else { 377 /* we do not have specific structure for this */ 378 APPL_TRACE_DEBUG("%s() - profile not identified. using raw data", 379 __func__); 380 bta_create_raw_sdp_record(&evt_data.records[count], p_rec); 381 p_rec = NULL; // Terminate loop 382 /* For raw, we only extract the first entry, and then return the 383 entire raw data chunk. 384 TODO: Find a way to split the raw data into record chunks, and 385 iterate to extract generic data for each chunk - e.g. rfcomm 386 channel and service name. */ 387 } 388 count++; 389 } while (p_rec != NULL && count < BTA_SDP_MAX_RECORDS); 390 391 evt_data.record_count = count; 392 } 393 evt_data.status = status; 394 395 tBTA_SDP bta_sdp; 396 bta_sdp.sdp_search_comp = evt_data; 397 bta_sdp_cb.p_dm_cback(BTA_SDP_SEARCH_COMP_EVT, &bta_sdp, (void*)&uuid); 398 osi_free(user_data); // We no longer need the user data to track the search 399 } 400 401 /******************************************************************************* 402 * 403 * Function bta_sdp_enable 404 * 405 * Description Initializes the SDP I/F 406 * 407 * Returns void 408 * 409 ******************************************************************************/ 410 void bta_sdp_enable(tBTA_SDP_MSG* p_data) { 411 APPL_TRACE_DEBUG("%s in, sdp_active:%d", __func__, bta_sdp_cb.sdp_active); 412 tBTA_SDP_STATUS status = BTA_SDP_SUCCESS; 413 bta_sdp_cb.p_dm_cback = p_data->enable.p_cback; 414 tBTA_SDP bta_sdp; 415 bta_sdp.status = status; 416 bta_sdp_cb.p_dm_cback(BTA_SDP_ENABLE_EVT, &bta_sdp, NULL); 417 } 418 419 /******************************************************************************* 420 * 421 * Function bta_sdp_search 422 * 423 * Description Discovers all sdp records for an uuid on remote device 424 * 425 * Returns void 426 * 427 ******************************************************************************/ 428 void bta_sdp_search(tBTA_SDP_MSG* p_data) { 429 if (p_data == NULL) { 430 APPL_TRACE_DEBUG("SDP control block handle is null"); 431 return; 432 } 433 tBTA_SDP_STATUS status = BTA_SDP_FAILURE; 434 435 APPL_TRACE_DEBUG("%s in, sdp_active:%d", __func__, bta_sdp_cb.sdp_active); 436 437 const Uuid& uuid = p_data->get_search.uuid; 438 if (bta_sdp_cb.sdp_active != BTA_SDP_ACTIVE_NONE) { 439 /* SDP is still in progress */ 440 status = BTA_SDP_BUSY; 441 if (bta_sdp_cb.p_dm_cback) { 442 tBTA_SDP_SEARCH_COMP result; 443 memset(&result, 0, sizeof(result)); 444 result.uuid = uuid; 445 result.remote_addr = p_data->get_search.bd_addr; 446 result.status = status; 447 tBTA_SDP bta_sdp; 448 bta_sdp.sdp_search_comp = result; 449 bta_sdp_cb.p_dm_cback(BTA_SDP_SEARCH_COMP_EVT, &bta_sdp, NULL); 450 } 451 return; 452 } 453 454 bta_sdp_cb.sdp_active = BTA_SDP_ACTIVE_YES; 455 bta_sdp_cb.remote_addr = p_data->get_search.bd_addr; 456 457 /* initialize the search for the uuid */ 458 APPL_TRACE_DEBUG("%s init discovery with UUID: %s", __func__, 459 uuid.ToString().c_str()); 460 SDP_InitDiscoveryDb(p_bta_sdp_cfg->p_sdp_db, p_bta_sdp_cfg->sdp_db_size, 1, 461 &uuid, 0, NULL); 462 463 Uuid* bta_sdp_search_uuid = (Uuid*)osi_malloc(sizeof(Uuid)); 464 *bta_sdp_search_uuid = uuid; 465 if (!SDP_ServiceSearchAttributeRequest2( 466 p_data->get_search.bd_addr, p_bta_sdp_cfg->p_sdp_db, 467 bta_sdp_search_cback, (void*)bta_sdp_search_uuid)) { 468 bta_sdp_cb.sdp_active = BTA_SDP_ACTIVE_NONE; 469 470 /* failed to start SDP. report the failure right away */ 471 if (bta_sdp_cb.p_dm_cback) { 472 tBTA_SDP_SEARCH_COMP result; 473 memset(&result, 0, sizeof(result)); 474 result.uuid = uuid; 475 result.remote_addr = p_data->get_search.bd_addr; 476 result.status = status; 477 tBTA_SDP bta_sdp; 478 bta_sdp.sdp_search_comp = result; 479 bta_sdp_cb.p_dm_cback(BTA_SDP_SEARCH_COMP_EVT, &bta_sdp, NULL); 480 } 481 } 482 /* 483 else report the result when the cback is called 484 */ 485 } 486 487 /******************************************************************************* 488 * 489 * Function bta_sdp_record 490 * 491 * Description Discovers all sdp records for an uuid on remote device 492 * 493 * Returns void 494 * 495 ******************************************************************************/ 496 void bta_sdp_create_record(tBTA_SDP_MSG* p_data) { 497 APPL_TRACE_DEBUG("%s() event: %d", __func__, p_data->record.hdr.event); 498 if (bta_sdp_cb.p_dm_cback) 499 bta_sdp_cb.p_dm_cback(BTA_SDP_CREATE_RECORD_USER_EVT, NULL, 500 p_data->record.user_data); 501 } 502 503 /******************************************************************************* 504 * 505 * Function bta_sdp_create_record 506 * 507 * Description Discovers all sdp records for an uuid on remote device 508 * 509 * Returns void 510 * 511 ******************************************************************************/ 512 void bta_sdp_remove_record(tBTA_SDP_MSG* p_data) { 513 APPL_TRACE_DEBUG("%s() event: %d", __func__, p_data->record.hdr.event); 514 if (bta_sdp_cb.p_dm_cback) 515 bta_sdp_cb.p_dm_cback(BTA_SDP_REMOVE_RECORD_USER_EVT, NULL, 516 p_data->record.user_data); 517 } 518