1 /****************************************************************************** 2 * 3 * Copyright 2014 Google, Inc. 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_sock_sdp" 20 21 #include "btif_sock_sdp.h" 22 23 #include <errno.h> 24 #include <sys/socket.h> 25 #include <sys/types.h> 26 27 #include <hardware/bluetooth.h> 28 #include <hardware/bt_sock.h> 29 30 #include "../bta/pb/bta_pbs_int.h" 31 #include "../include/bta_op_api.h" 32 #include "bt_common.h" 33 #include "bt_target.h" 34 #include "bta_api.h" 35 #include "bta_jv_api.h" 36 #include "btif_common.h" 37 #include "btif_sock_util.h" 38 #include "btif_util.h" 39 #include "btm_api.h" 40 #include "btm_int.h" 41 #include "btu.h" 42 #include "hcimsgs.h" 43 #include "sdp_api.h" 44 #include "utl.h" 45 46 using bluetooth::Uuid; 47 48 // This module provides an abstraction on top of the lower-level SDP database 49 // code for registration and discovery of various bluetooth sockets. 50 // 51 // This code also provides for on-demand registration of "pre-registered" 52 // services as a backwards compatibility function to third-party applications 53 // expecting a bluez stack. 54 55 // Realm Character Set -- 0 is ASCII 56 #define BTA_PBS_REALM_CHARSET 0 57 58 // Specifies whether or not client's user id is required during obex 59 // authentication 60 #define BTA_PBS_USERID_REQ FALSE 61 62 static const tBTA_PBS_CFG bta_pbs_cfg = { 63 BTA_PBS_REALM_CHARSET, // realm_charset: Server only 64 BTA_PBS_USERID_REQ, // userid_req: Server only 65 (BTA_PBS_SUPF_DOWNLOAD | BTA_PBS_SURF_BROWSE), // supported_features 66 BTA_PBS_REPOSIT_LOCAL, // supported_repositories 67 }; 68 69 // object format lookup table 70 #define OBEX_PUSH_NUM_FORMATS 7 71 72 static const tBTA_OP_FMT bta_ops_obj_fmt[OBEX_PUSH_NUM_FORMATS] = { 73 BTA_OP_VCARD21_FMT, BTA_OP_VCARD30_FMT, BTA_OP_VCAL_FMT, BTA_OP_ICAL_FMT, 74 BTA_OP_VNOTE_FMT, BTA_OP_VMSG_FMT, BTA_OP_OTHER_FMT}; 75 76 // TODO(jtgans): Figure out if we actually need this define. This is ifndef 77 // defined in bt_target.h, but nowhere else, so right now, unless something 78 // overrides this before bt_target.h sets it, it will always be bt_target.h's 79 // version. 80 #ifndef BTUI_OPS_FORMATS 81 #define BTUI_OPS_FORMATS \ 82 (BTA_OP_VCARD21_MASK | BTA_OP_VCARD30_MASK | BTA_OP_VCAL_MASK | \ 83 BTA_OP_ICAL_MASK | BTA_OP_VNOTE_MASK | BTA_OP_VMSG_MASK | BTA_OP_ANY_MASK) 84 #endif 85 86 #define RESERVED_SCN_PBS 19 87 #define RESERVED_SCN_OPS 12 88 89 #define UUID_MAX_LENGTH 16 90 91 #define SPP_PROFILE_VERSION 0x0102 92 93 // Adds a protocol list and service name (if provided) to an SDP record given by 94 // |sdp_handle|, and marks it as browseable. This is a shortcut for defining a 95 // set of protocols that includes L2CAP, RFCOMM, and optionally OBEX. If 96 // |with_obex| is |true|, then an additional OBEX protocol UUID will be included 97 // at the end of the protocol list. 98 // 99 // Returns true if successful, otherwise false. 100 static bool create_base_record(const uint32_t sdp_handle, const char* name, 101 const uint16_t channel, const bool with_obex) { 102 APPL_TRACE_DEBUG("create_base_record: scn: %d, name: %s, with_obex: %d", 103 channel, name, with_obex); 104 105 // Setup the protocol list and add it. 106 tSDP_PROTOCOL_ELEM proto_list[SDP_MAX_LIST_ELEMS]; 107 int num_proto_elements = with_obex ? 3 : 2; 108 109 memset(proto_list, 0, num_proto_elements * sizeof(tSDP_PROTOCOL_ELEM)); 110 111 proto_list[0].protocol_uuid = UUID_PROTOCOL_L2CAP; 112 proto_list[0].num_params = 0; 113 proto_list[1].protocol_uuid = UUID_PROTOCOL_RFCOMM; 114 proto_list[1].num_params = 1; 115 proto_list[1].params[0] = channel; 116 117 if (with_obex) { 118 proto_list[2].protocol_uuid = UUID_PROTOCOL_OBEX; 119 proto_list[2].num_params = 0; 120 } 121 122 // Mark the service as browseable. 123 uint16_t list = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP; 124 125 const char* stage = "protocol_list"; 126 if (!SDP_AddProtocolList(sdp_handle, num_proto_elements, proto_list)) 127 goto error; 128 129 // Add the name to the SDP record. 130 if (name[0] != '\0') { 131 stage = "service_name"; 132 if (!SDP_AddAttribute(sdp_handle, ATTR_ID_SERVICE_NAME, TEXT_STR_DESC_TYPE, 133 (uint32_t)strlen(name), (uint8_t*)name)) 134 goto error; 135 } 136 137 stage = "browseable"; 138 if (!SDP_AddUuidSequence(sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &list)) 139 goto error; 140 141 APPL_TRACE_DEBUG( 142 "create_base_record: successfully created base service " 143 "record, handle: 0x%08x, scn: %d, name: %s, with_obex: %d", 144 sdp_handle, channel, name, with_obex); 145 return true; 146 147 error: 148 APPL_TRACE_ERROR( 149 "create_base_record: failed to create base service " 150 "record, stage: %s, scn: %d, name: %s, with_obex: %d", 151 stage, channel, name, with_obex); 152 return false; 153 } 154 155 // Registers a service with the given |name|, |uuid|, and |channel| in the SDP 156 // database as a generic L2CAP RFCOMM protocol, storing its |uuid| as a service 157 // class sequence. 158 static int add_sdp_by_uuid(const char* name, const Uuid& uuid, 159 const uint16_t channel) { 160 APPL_TRACE_DEBUG("%s: uuid: %s, scn: %d, service_name: %s", __func__, 161 uuid.ToString().c_str(), channel, name); 162 163 uint32_t handle = SDP_CreateRecord(); 164 if (handle == 0) { 165 APPL_TRACE_ERROR( 166 "%s: failed to create sdp record, scn: %d, service_name: %s", __func__, 167 channel, name); 168 return 0; 169 } 170 171 // Convert the |uuid| into a big-endian representation and add it as a 172 // sequence. 173 uint8_t type = UUID_DESC_TYPE; 174 uint8_t type_len = UUID_MAX_LENGTH; 175 uint8_t type_buf[48]; 176 // Store the address of type buf in a pointer on the stack, so we can pass 177 // a double pointer to SDP_AddSequence 178 uint8_t* type_buf_ptr = type_buf; 179 uint8_t* tmp = type_buf; 180 181 // Create the base SDP record. 182 const char* stage = "create_base_record"; 183 if (!create_base_record(handle, name, channel, false /* with_obex */)) 184 goto error; 185 186 // Do the conversion to big-endian -- tmp is only used to iterate through the 187 // UUID array in the macro and serves no other purpose as the conversion 188 // macros are not hygenic. 189 190 { ARRAY_TO_BE_STREAM(tmp, uuid.To128BitBE().data(), UUID_MAX_LENGTH); } 191 192 stage = "service_class_sequence"; 193 if (!SDP_AddSequence(handle, (uint16_t)ATTR_ID_SERVICE_CLASS_ID_LIST, 1, 194 &type, &type_len, &type_buf_ptr)) 195 goto error; 196 197 APPL_TRACE_DEBUG( 198 "%s: service registered successfully, service_name: %s, handle: 0x%08x", 199 __func__, name, handle); 200 return handle; 201 202 error: 203 SDP_DeleteRecord(handle); 204 APPL_TRACE_ERROR("%s: failed to register service stage: %s, service_name: %s", 205 __func__, stage, name); 206 return 0; 207 } 208 209 // Registers a service with the given |name| and |channel| in the SDP 210 // database as a PBAP protocol. 211 static int add_pbap_sdp(const char* name, const int channel) { 212 APPL_TRACE_DEBUG("add_pbap_sdp: scn %d, service_name %s", channel, name); 213 214 uint32_t handle = SDP_CreateRecord(); 215 if (handle == 0) { 216 APPL_TRACE_ERROR( 217 "add_pbap_sdp: failed to create sdp record, " 218 "service_name: %s", 219 name); 220 return 0; 221 } 222 223 uint16_t service = UUID_SERVCLASS_PBAP_PSE; 224 225 // Create the base SDP record. 226 const char* stage = "create_base_record"; 227 if (!create_base_record(handle, name, channel, true /* with_obex */)) 228 goto error; 229 230 // Add service class 231 stage = "service_class"; 232 if (!SDP_AddServiceClassIdList(handle, 1, &service)) goto error; 233 234 // Add in the phone access descriptor 235 stage = "profile_descriptor_list"; 236 if (!SDP_AddProfileDescriptorList(handle, UUID_SERVCLASS_PHONE_ACCESS, 237 BTA_PBS_DEFAULT_VERSION)) 238 goto error; 239 240 // Set up our supported repositories 241 stage = "supported_repositories"; 242 if (!SDP_AddAttribute(handle, ATTR_ID_SUPPORTED_REPOSITORIES, UINT_DESC_TYPE, 243 1, (uint8_t*)&bta_pbs_cfg.supported_repositories)) 244 goto error; 245 246 // Notify the system that we've got a new service class UUID. 247 bta_sys_add_uuid(UUID_SERVCLASS_PBAP_PSE); 248 APPL_TRACE_DEBUG( 249 "add_pbap_sdp: service registered successfully, " 250 "service_name: %s, handle: 0x%08x", 251 name, handle); 252 253 return handle; 254 255 error: 256 SDP_DeleteRecord(handle); 257 APPL_TRACE_ERROR( 258 "add_pbap_sdp: failed to register PBAP service, stage: %s, " 259 "service_name: %s", 260 stage, name); 261 return 0; 262 } 263 // Registers a service with the given |name| and |channel| as an OBEX Push 264 // protocol. 265 static int add_ops_sdp(const char* name, const int channel) { 266 APPL_TRACE_DEBUG("add_ops_sdp: scn %d, service_name %s", channel, name); 267 268 uint32_t handle = SDP_CreateRecord(); 269 if (handle == 0) { 270 APPL_TRACE_ERROR( 271 "add_ops_sdp: failed to create sdp record, " 272 "service_name: %s", 273 name); 274 return 0; 275 } 276 277 // Add sequence for supported types. 278 uint8_t desc_type[OBEX_PUSH_NUM_FORMATS]; 279 uint8_t type_len[OBEX_PUSH_NUM_FORMATS]; 280 uint8_t* type_value[OBEX_PUSH_NUM_FORMATS]; 281 uint8_t j = 0; 282 283 uint16_t service = UUID_SERVCLASS_OBEX_OBJECT_PUSH; 284 tBTA_UTL_COD cod; 285 286 // Create the base SDP record. 287 const char* stage = "create_base_record"; 288 if (!create_base_record(handle, name, channel, true /* with_obex */)) 289 goto error; 290 291 // Add service class. 292 stage = "service_class"; 293 if (!SDP_AddServiceClassIdList(handle, 1, &service)) goto error; 294 295 // Add the OBEX push profile descriptor. 296 stage = "profile_descriptor_list"; 297 if (!SDP_AddProfileDescriptorList(handle, UUID_SERVCLASS_OBEX_OBJECT_PUSH, 298 0x0100)) 299 goto error; 300 301 for (int i = 0; i < OBEX_PUSH_NUM_FORMATS; i++) { 302 if ((BTUI_OPS_FORMATS >> i) & 1) { 303 type_value[j] = (uint8_t*)(&bta_ops_obj_fmt[i]); 304 desc_type[j] = UINT_DESC_TYPE; 305 type_len[j++] = 1; 306 } 307 } 308 309 stage = "supported_types"; 310 if (!SDP_AddSequence(handle, (uint16_t)ATTR_ID_SUPPORTED_FORMATS_LIST, j, 311 desc_type, type_len, type_value)) 312 goto error; 313 314 // Set class of device. 315 cod.service = BTM_COD_SERVICE_OBJ_TRANSFER; 316 stage = "class_of_device"; 317 if (!utl_set_device_class(&cod, BTA_UTL_SET_COD_SERVICE_CLASS)) goto error; 318 319 // Notify the system that we've got a new service class UUID. 320 bta_sys_add_uuid(UUID_SERVCLASS_OBEX_OBJECT_PUSH); 321 APPL_TRACE_DEBUG( 322 "ad_maps_sdp: service registered successfully, " 323 "service_name: %s, handle 0x%08x)", 324 name, handle); 325 326 return handle; 327 328 error: 329 SDP_DeleteRecord(handle); 330 APPL_TRACE_ERROR( 331 "add_ops_sdp: failed to register OPS service, " 332 "stage: %s, service_name: %s", 333 stage, name); 334 return 0; 335 } 336 337 // Registers a service with the given |name| and |channel| as a serial port 338 // profile protocol. 339 static int add_spp_sdp(const char* name, const int channel) { 340 APPL_TRACE_DEBUG("add_spp_sdp: scn %d, service_name %s", channel, name); 341 342 int handle = SDP_CreateRecord(); 343 if (handle == 0) { 344 APPL_TRACE_ERROR( 345 "add_spp_sdp: failed to create sdp record, " 346 "service_name: %s", 347 name); 348 return 0; 349 } 350 351 // Create the base SDP record. 352 const char* stage = "create_base_record"; 353 uint16_t service = UUID_SERVCLASS_SERIAL_PORT; 354 355 if (!create_base_record(handle, name, channel, false /* with_obex */)) 356 goto error; 357 358 stage = "service_class"; 359 if (!SDP_AddServiceClassIdList(handle, 1, &service)) goto error; 360 361 stage = "profile_descriptor_list"; 362 if (!SDP_AddProfileDescriptorList(handle, UUID_SERVCLASS_SERIAL_PORT, 363 SPP_PROFILE_VERSION)) 364 goto error; 365 366 APPL_TRACE_DEBUG( 367 "add_spp_sdp: service registered successfully, " 368 "service_name: %s, handle 0x%08x)", 369 name, handle); 370 371 return handle; 372 373 error: 374 SDP_DeleteRecord(handle); 375 APPL_TRACE_ERROR( 376 "add_spp_sdp: failed to register SPP service, " 377 "stage: %s, service_name: %s", 378 stage, name); 379 return 0; 380 } 381 382 // Adds an RFCOMM SDP record for a service with the given |name|, |uuid|, and 383 // |channel|. This function attempts to identify the type of the service based 384 // upon its |uuid|, and will override the |channel| with a reserved channel 385 // number if the |uuid| matches one of the preregistered bluez SDP records. 386 static int add_rfc_sdp_by_uuid(const char* name, const Uuid& uuid, 387 const int channel) { 388 APPL_TRACE_DEBUG("%s: uuid: %s, service_name: %s, channel: %d", __func__, 389 uuid.ToString().c_str(), name, channel); 390 391 /* 392 * Bluetooth Socket API relies on having preregistered bluez sdp records for 393 * HSAG, HFAG, OPP & PBAP that are mapped to rc chan 10, 11,12 & 19. Today 394 * HSAG and HFAG is routed to BRCM AG and are not using BT socket API so for 395 * now we will need to support OPP and PBAP to enable 3rd party developer apps 396 * running on BRCM Android. 397 * 398 * To do this we will check the UUID for the requested service and mimic the 399 * SDP records of bluez upon reception. See functions add_opush() and 400 * add_pbap() in sdptool.c for actual records. 401 */ 402 403 int final_channel = get_reserved_rfc_channel(uuid); 404 405 if (final_channel == -1) { 406 final_channel = channel; 407 } 408 409 int handle = 0; 410 411 if (uuid == UUID_OBEX_OBJECT_PUSH) { 412 handle = add_ops_sdp(name, final_channel); 413 } else if (uuid == UUID_PBAP_PSE) { 414 // PBAP Server is always channel 19 415 handle = add_pbap_sdp(name, final_channel); 416 } else if (uuid == UUID_SPP) { 417 handle = add_spp_sdp(name, final_channel); 418 } else if (uuid == UUID_MAP_MAS) { 419 // Record created by new SDP create record interface 420 handle = 0xff; 421 } else { 422 handle = add_sdp_by_uuid(name, uuid, final_channel); 423 } 424 425 return handle; 426 } 427 428 bool is_reserved_rfc_channel(const int channel) { 429 switch (channel) { 430 case RESERVED_SCN_PBS: 431 case RESERVED_SCN_OPS: 432 return true; 433 } 434 435 return false; 436 } 437 438 int get_reserved_rfc_channel(const bluetooth::Uuid& uuid) { 439 if (uuid == UUID_PBAP_PSE) { 440 return RESERVED_SCN_PBS; 441 } else if (uuid == UUID_OBEX_OBJECT_PUSH) { 442 return RESERVED_SCN_OPS; 443 } 444 445 return -1; 446 } 447 448 // Adds an SDP record to the SDP database using the given |name|, |uuid|, and 449 // |channel|. Note that if the |uuid| is empty, the |uuid| will be set based 450 // upon the |channel| passed in. 451 int add_rfc_sdp_rec(const char* name, Uuid uuid, const int channel) { 452 if (uuid.IsEmpty()) { 453 switch (channel) { 454 case RESERVED_SCN_PBS: // PBAP Reserved port 455 uuid = UUID_PBAP_PSE; 456 break; 457 458 case RESERVED_SCN_OPS: 459 uuid = UUID_OBEX_OBJECT_PUSH; 460 break; 461 462 default: 463 uuid = UUID_SPP; 464 break; 465 } 466 } 467 468 return add_rfc_sdp_by_uuid(name, uuid, channel); 469 } 470 471 // Deletes an SDP record with the given |handle|. 472 void del_rfc_sdp_rec(int handle) { 473 APPL_TRACE_DEBUG("del_rfc_sdp_rec: handle:0x%x", handle); 474 475 if ((handle != -1) && (handle != 0)) BTA_JvDeleteRecord(handle); 476 } 477