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