btif_sock_sdp.c revision 98139d9ecf9f42bffa26b6840659131b0b3258f0
1/****************************************************************************** 2 * 3 * Copyright (C) 2009-2012 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 * 21 * Filename: btif_hf.c 22 * 23 * Description: Handsfree Profile Bluetooth Interface 24 * 25 * 26 ***********************************************************************************/ 27 28#include <hardware/bluetooth.h> 29#include <hardware/bt_sock.h> 30#include <sys/types.h> 31#include <sys/socket.h> 32#include <errno.h> 33 34#define LOG_TAG "BTIF_SOCK_SDP" 35#include "btif_common.h" 36#include "btif_util.h" 37 38#include "bd.h" 39 40#include "bta_api.h" 41 42 43#include "bt_target.h" 44#include "gki.h" 45#include "hcimsgs.h" 46#include "sdp_api.h" 47#include "btu.h" 48#include "btm_api.h" 49#include "btm_int.h" 50#include "btif_sock_sdp.h" 51#include "utl.h" 52#include "../bta/pb/bta_pbs_int.h" 53#include "../include/bta_op_api.h" 54#include "bta_jv_api.h" 55#include <cutils/log.h> 56 57#define RESERVED_SCN_PBS 19 58#define RESERVED_SCN_OPS 12 59 60#define UUID_MAX_LENGTH 16 61 62 63#define IS_UUID(u1,u2) !memcmp(u1,u2,UUID_MAX_LENGTH) 64 65 66#define BTM_NUM_PROTO_ELEMS 2 67static int add_sdp_by_uuid(const char *name, const uint8_t *service_uuid, UINT16 channel) 68{ 69 70 UINT32 btm_sdp_handle; 71 72 tSDP_PROTOCOL_ELEM proto_elem_list[BTM_NUM_PROTO_ELEMS]; 73 74 /* register the service */ 75 if ((btm_sdp_handle = SDP_CreateRecord()) != FALSE) 76 { 77 /*** Fill out the protocol element sequence for SDP ***/ 78 proto_elem_list[0].protocol_uuid = UUID_PROTOCOL_L2CAP; 79 proto_elem_list[0].num_params = 0; 80 proto_elem_list[1].protocol_uuid = UUID_PROTOCOL_RFCOMM; 81 proto_elem_list[1].num_params = 1; 82 83 proto_elem_list[1].params[0] = channel; 84 85 if (SDP_AddProtocolList(btm_sdp_handle, BTM_NUM_PROTO_ELEMS, 86 proto_elem_list)) 87 { 88 UINT8 buff[48]; 89 UINT8 *p, *type_buf[1]; 90 UINT8 type[1], type_len[1]; 91 p = type_buf[0] = buff; 92 type[0] = UUID_DESC_TYPE; 93 94// UINT8_TO_BE_STREAM (p, (UUID_DESC_TYPE << 3) | SIZE_SIXTEEN_BYTES); 95 ARRAY_TO_BE_STREAM (p, service_uuid, 16); 96 type_len[0] = 16; 97 if( SDP_AddSequence(btm_sdp_handle, (UINT16) ATTR_ID_SERVICE_CLASS_ID_LIST, 98 1, type, type_len, type_buf) ) 99// if (SDP_AddServiceClassIdList(btm_sdp_handle, 1, &service_uuid)) 100 { 101 if ((SDP_AddAttribute(btm_sdp_handle, ATTR_ID_SERVICE_NAME, 102 TEXT_STR_DESC_TYPE, (UINT32)(strlen(name)+1), 103 (UINT8 *)name)) ) 104 { 105 UINT16 list[1]; 106 107 /* Make the service browseable */ 108 list[0] = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP; 109 if ((SDP_AddUuidSequence (btm_sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 110 1, list)) ) 111 112 return btm_sdp_handle; 113 } 114 } 115 } 116 } 117 else APPL_TRACE_ERROR1("failed to create sdp record, service_name:%s", name); 118 return 0; 119} 120 121 122/* Realm Character Set */ 123#define BTA_PBS_REALM_CHARSET 0 /* ASCII */ 124 125/* Specifies whether or not client's user id is required during obex authentication */ 126#define BTA_PBS_USERID_REQ FALSE 127extern const tBTA_PBS_CFG bta_pbs_cfg; 128const tBTA_PBS_CFG bta_pbs_cfg = 129{ 130 BTA_PBS_REALM_CHARSET, /* Server only */ 131 BTA_PBS_USERID_REQ, /* Server only */ 132 (BTA_PBS_SUPF_DOWNLOAD | BTA_PBS_SURF_BROWSE), 133 BTA_PBS_REPOSIT_LOCAL, 134}; 135 136static int add_pbap_sdp(const char* p_service_name, int scn) 137{ 138 139 tSDP_PROTOCOL_ELEM protoList [3]; 140 UINT16 pbs_service = UUID_SERVCLASS_PBAP_PSE; 141 UINT16 browse = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP; 142 BOOLEAN status = FALSE; 143 UINT32 sdp_handle = 0; 144 tBTA_PBS_CFG *p_bta_pbs_cfg = (tBTA_PBS_CFG *)&bta_pbs_cfg; 145 146 APPL_TRACE_DEBUG2("add_pbap_sdd:scn %d, service name %s", scn, p_service_name); 147 148 if ((sdp_handle = SDP_CreateRecord()) == 0) 149 { 150 APPL_TRACE_ERROR0("PBS SDP: Unable to register PBS Service"); 151 return sdp_handle; 152 } 153 154 /* add service class */ 155 if (SDP_AddServiceClassIdList(sdp_handle, 1, &pbs_service)) 156 { 157 memset( protoList, 0 , 3*sizeof(tSDP_PROTOCOL_ELEM) ); 158 /* add protocol list, including RFCOMM scn */ 159 protoList[0].protocol_uuid = UUID_PROTOCOL_L2CAP; 160 protoList[0].num_params = 0; 161 protoList[1].protocol_uuid = UUID_PROTOCOL_RFCOMM; 162 protoList[1].num_params = 1; 163 protoList[1].params[0] = scn; 164 protoList[2].protocol_uuid = UUID_PROTOCOL_OBEX; 165 protoList[2].num_params = 0; 166 167 if (SDP_AddProtocolList(sdp_handle, 3, protoList)) 168 { 169 status = TRUE; /* All mandatory fields were successful */ 170 171 /* optional: if name is not "", add a name entry */ 172 if (*p_service_name != '\0') 173 SDP_AddAttribute(sdp_handle, 174 (UINT16)ATTR_ID_SERVICE_NAME, 175 (UINT8)TEXT_STR_DESC_TYPE, 176 (UINT32)(strlen(p_service_name) + 1), 177 (UINT8 *)p_service_name); 178 179 /* Add in the Bluetooth Profile Descriptor List */ 180 SDP_AddProfileDescriptorList(sdp_handle, 181 UUID_SERVCLASS_PHONE_ACCESS, 182 BTA_PBS_DEFAULT_VERSION); 183 184 } /* end of setting mandatory protocol list */ 185 } /* end of setting mandatory service class */ 186 187 /* add supported feature and repositories */ 188 if (status) 189 { 190 SDP_AddAttribute(sdp_handle, ATTR_ID_SUPPORTED_FEATURES, UINT_DESC_TYPE, 191 (UINT32)1, (UINT8*)&p_bta_pbs_cfg->supported_features); 192 SDP_AddAttribute(sdp_handle, ATTR_ID_SUPPORTED_REPOSITORIES, UINT_DESC_TYPE, 193 (UINT32)1, (UINT8*)&p_bta_pbs_cfg->supported_repositories); 194 195 /* Make the service browseable */ 196 SDP_AddUuidSequence (sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse); 197 } 198 199 if (!status) 200 { 201 SDP_DeleteRecord(sdp_handle); 202 sdp_handle = 0; 203 APPL_TRACE_ERROR0("bta_pbs_sdp_register FAILED"); 204 } 205 else 206 { 207 bta_sys_add_uuid(pbs_service); /* UUID_SERVCLASS_PBAP_PSE */ 208 APPL_TRACE_DEBUG1("PBS: SDP Registered (handle 0x%08x)", sdp_handle); 209 } 210 211 return sdp_handle; 212} 213 214/* This is horrible design - to reserve channel ID's and use them to magically link 215 * a channel number to a hard coded SDP entry. 216 * TODO: expose a prober SDP API, to avoid hacks like this, and make it possible 217 * to set useful names for the ServiceName */ 218#define BTA_MAP_MSG_TYPE_EMAIL 0x01 219#define BTA_MAP_MSG_TYPE_SMS_GSM 0x02 220#define BTA_MAP_MSG_TYPE_SMS_CDMA 0x04 221#define BTA_MAP_MSG_TYPE_MMS 0x08 222 223#define BTA_MAPS_DEFAULT_VERSION 0x0101 /* MAP 1.1 */ 224typedef struct 225{ 226 UINT8 mas_id; /* the MAS instance id */ 227 const char* service_name; /* Description of the MAS instance */ 228 UINT8 supported_message_types;/* Server supported message types - SMS/MMS/EMAIL */ 229} tBTA_MAPS_CFG; 230const tBTA_MAPS_CFG bta_maps_cfg_sms_mms = 231{ 232 0, /* Mas id 0 is for SMS/MMS */ 233 "MAP SMS/MMS", 234 BTA_MAP_MSG_TYPE_SMS_GSM | BTA_MAP_MSG_TYPE_SMS_CDMA | BTA_MAP_MSG_TYPE_MMS 235}; 236const tBTA_MAPS_CFG bta_maps_cfg_email = 237{ 238 1, /* Mas id 1 is for EMAIL */ 239 "MAP EMAIL", 240 BTA_MAP_MSG_TYPE_EMAIL 241}; 242static int add_maps_sdp(const char* p_service_name, int scn) 243{ 244 245 tSDP_PROTOCOL_ELEM protoList [3]; 246 UINT16 service = UUID_SERVCLASS_MESSAGE_ACCESS; 247 UINT16 browse = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP; 248 BOOLEAN status = FALSE; 249 UINT32 sdp_handle = 0; 250 // TODO: To add support for EMAIL set below depending on the scn to either SMS or Email 251 const tBTA_MAPS_CFG *p_bta_maps_cfg = &bta_maps_cfg_sms_mms; 252 253 APPL_TRACE_DEBUG2("add_maps_sdd:scn %d, service name %s", scn, p_service_name); 254 255 if ((sdp_handle = SDP_CreateRecord()) == 0) 256 { 257 APPL_TRACE_ERROR0("MAPS SDP: Unable to register MAPS Service"); 258 return sdp_handle; 259 } 260 261 /* add service class */ 262 if (SDP_AddServiceClassIdList(sdp_handle, 1, &service)) 263 { 264 memset( protoList, 0 , 3*sizeof(tSDP_PROTOCOL_ELEM) ); 265 /* add protocol list, including RFCOMM scn */ 266 protoList[0].protocol_uuid = UUID_PROTOCOL_L2CAP; 267 protoList[0].num_params = 0; 268 protoList[1].protocol_uuid = UUID_PROTOCOL_RFCOMM; 269 protoList[1].num_params = 1; 270 protoList[1].params[0] = scn; 271 protoList[2].protocol_uuid = UUID_PROTOCOL_OBEX; 272 protoList[2].num_params = 0; 273 274 if (SDP_AddProtocolList(sdp_handle, 3, protoList)) 275 { 276 status = TRUE; /* All mandatory fields were successful */ 277 278 /* optional: if name is not "", add a name entry */ 279 SDP_AddAttribute(sdp_handle, 280 (UINT16)ATTR_ID_SERVICE_NAME, 281 (UINT8)TEXT_STR_DESC_TYPE, 282 (UINT32)(strlen(p_bta_maps_cfg->service_name) + 1), 283 (UINT8 *)p_bta_maps_cfg->service_name); 284 285 /* Add in the Bluetooth Profile Descriptor List */ 286 SDP_AddProfileDescriptorList(sdp_handle, 287 UUID_SERVCLASS_MAP_PROFILE, 288 BTA_MAPS_DEFAULT_VERSION); 289 290 } /* end of setting mandatory protocol list */ 291 } /* end of setting mandatory service class */ 292 293 /* add supported feature and repositories */ 294 if (status) 295 { 296 SDP_AddAttribute(sdp_handle, ATTR_ID_MAS_INSTANCE_ID, UINT_DESC_TYPE, 297 (UINT32)1, (UINT8*)&p_bta_maps_cfg->mas_id); 298 SDP_AddAttribute(sdp_handle, ATTR_ID_SUPPORTED_MSG_TYPE, UINT_DESC_TYPE, 299 (UINT32)1, (UINT8*)&p_bta_maps_cfg->supported_message_types); 300 301 /* Make the service browseable */ 302 SDP_AddUuidSequence (sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse); 303 } 304 305 if (!status) 306 { 307 SDP_DeleteRecord(sdp_handle); 308 sdp_handle = 0; 309 APPL_TRACE_ERROR0("bta_mass_sdp_register FAILED"); 310 } 311 else 312 { 313 bta_sys_add_uuid(service); /* UUID_SERVCLASS_MESSAGE_ACCESS */ 314 APPL_TRACE_DEBUG1("MAPSS: SDP Registered (handle 0x%08x)", sdp_handle); 315 } 316 317 return sdp_handle; 318} 319 320 321/* object format lookup table */ 322static const tBTA_OP_FMT bta_ops_obj_fmt[] = 323{ 324 BTA_OP_VCARD21_FMT, 325 BTA_OP_VCARD30_FMT, 326 BTA_OP_VCAL_FMT, 327 BTA_OP_ICAL_FMT, 328 BTA_OP_VNOTE_FMT, 329 BTA_OP_VMSG_FMT, 330 BTA_OP_OTHER_FMT 331}; 332 333#define BTA_OPS_NUM_FMTS 7 334#define BTA_OPS_PROTOCOL_COUNT 3 335 336#ifndef BTUI_OPS_FORMATS 337#define BTUI_OPS_FORMATS (BTA_OP_VCARD21_MASK | BTA_OP_VCARD30_MASK | \ 338 BTA_OP_VCAL_MASK | BTA_OP_ICAL_MASK | \ 339 BTA_OP_VNOTE_MASK | BTA_OP_VMSG_MASK | \ 340 BTA_OP_ANY_MASK ) 341#endif 342 343static int add_ops_sdp(const char *p_service_name,int scn) 344{ 345 346 347 tSDP_PROTOCOL_ELEM protoList [BTA_OPS_PROTOCOL_COUNT]; 348 UINT16 servclass = UUID_SERVCLASS_OBEX_OBJECT_PUSH; 349 int i, j; 350 tBTA_UTL_COD cod; 351 UINT8 desc_type[BTA_OPS_NUM_FMTS]; 352 UINT8 type_len[BTA_OPS_NUM_FMTS]; 353 UINT8 *type_value[BTA_OPS_NUM_FMTS]; 354 UINT16 browse; 355 UINT32 sdp_handle; 356 tBTA_OP_FMT_MASK formats = BTUI_OPS_FORMATS; 357 358 APPL_TRACE_DEBUG2("scn %d, service name %s", scn, p_service_name); 359 360 sdp_handle = SDP_CreateRecord(); 361 362 /* add service class */ 363 if (SDP_AddServiceClassIdList(sdp_handle, 1, &servclass)) 364 { 365 /* add protocol list, including RFCOMM scn */ 366 protoList[0].protocol_uuid = UUID_PROTOCOL_L2CAP; 367 protoList[0].num_params = 0; 368 protoList[1].protocol_uuid = UUID_PROTOCOL_RFCOMM; 369 protoList[1].num_params = 1; 370 protoList[1].params[0] = scn; 371 protoList[2].protocol_uuid = UUID_PROTOCOL_OBEX; 372 protoList[2].num_params = 0; 373 374 if (SDP_AddProtocolList(sdp_handle, BTA_OPS_PROTOCOL_COUNT, protoList)) 375 { 376 SDP_AddAttribute(sdp_handle, 377 (UINT16)ATTR_ID_SERVICE_NAME, 378 (UINT8)TEXT_STR_DESC_TYPE, 379 (UINT32)(strlen(p_service_name) + 1), 380 (UINT8 *)p_service_name); 381 382 SDP_AddProfileDescriptorList(sdp_handle, 383 UUID_SERVCLASS_OBEX_OBJECT_PUSH, 384 0x0100); 385 } 386 } 387 388 /* Make the service browseable */ 389 browse = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP; 390 SDP_AddUuidSequence (sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse); 391 392 /* add sequence for supported types */ 393 for (i = 0, j = 0; i < BTA_OPS_NUM_FMTS; i++) 394 { 395 if ((formats >> i) & 1) 396 { 397 type_value[j] = (UINT8 *) &bta_ops_obj_fmt[i]; 398 desc_type[j] = UINT_DESC_TYPE; 399 type_len[j++] = 1; 400 } 401 } 402 403 SDP_AddSequence(sdp_handle, (UINT16) ATTR_ID_SUPPORTED_FORMATS_LIST, 404 (UINT8) j, desc_type, type_len, type_value); 405 406 /* set class of device */ 407 cod.service = BTM_COD_SERVICE_OBJ_TRANSFER; 408 utl_set_device_class(&cod, BTA_UTL_SET_COD_SERVICE_CLASS); 409 410 bta_sys_add_uuid(servclass); /* UUID_SERVCLASS_OBEX_OBJECT_PUSH */ 411 412 return sdp_handle; 413} 414#define SPP_NUM_PROTO_ELEMS 2 415static int add_spp_sdp(const char *service_name, int scn) 416{ 417 UINT16 serviceclassid = UUID_SERVCLASS_SERIAL_PORT; 418 tSDP_PROTOCOL_ELEM proto_elem_list[SPP_NUM_PROTO_ELEMS]; 419 int sdp_handle; 420 421 APPL_TRACE_DEBUG2("scn %d, service name %s", scn, service_name); 422 423 /* register the service */ 424 if ((sdp_handle = SDP_CreateRecord()) != FALSE) 425 { 426 /*** Fill out the protocol element sequence for SDP ***/ 427 proto_elem_list[0].protocol_uuid = UUID_PROTOCOL_L2CAP; 428 proto_elem_list[0].num_params = 0; 429 proto_elem_list[1].protocol_uuid = UUID_PROTOCOL_RFCOMM; 430 proto_elem_list[1].num_params = 1; 431 432 proto_elem_list[1].params[0] = scn; 433 434 if (SDP_AddProtocolList(sdp_handle, SPP_NUM_PROTO_ELEMS, proto_elem_list)) 435 { 436 if (SDP_AddServiceClassIdList(sdp_handle, 1, &serviceclassid)) 437 { 438 if ((SDP_AddAttribute(sdp_handle, ATTR_ID_SERVICE_NAME, 439 TEXT_STR_DESC_TYPE, (UINT32)(strlen(service_name)+1), 440 (UINT8 *)service_name))) 441 { 442 UINT16 list[1]; 443 /* Make the service browseable */ 444 list[0] = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP; 445 SDP_AddUuidSequence (sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 446 1, list); 447 } 448 } 449 } 450 } 451 return sdp_handle; 452} 453 454 455 456static int add_rfc_sdp_by_uuid(const char* name, const uint8_t* uuid, int scn) 457{ 458 int handle = 0; 459 460 APPL_TRACE_DEBUG2("name:%s, scn:%d", name, scn); 461 462 /* 463 Bluetooth Socket API relies on having preregistered bluez sdp records for HSAG, HFAG, OPP & PBAP 464 that are mapped to rc chan 10, 11,12 & 19. Today HSAG and HFAG is routed to BRCM AG and are not 465 using BT socket API so for now we will need to support OPP and PBAP to enable 3rd party developer 466 apps running on BRCM Android. 467 468 To do this we will check the UUID for the requested service and mimic the SDP records of bluez 469 upon reception. See functions add_opush() and add_pbap() in sdptool.c for actual records 470 */ 471 472 /* special handling for preregistered bluez services (OPP, PBAP) that we need to mimic */ 473 474 int final_scn = get_reserved_rfc_channel(uuid); 475 if (final_scn == -1) 476 { 477 final_scn=scn; 478 } 479 if (IS_UUID(UUID_OBEX_OBJECT_PUSH,uuid)) 480 { 481 handle = add_ops_sdp(name,final_scn); 482 } 483 else if (IS_UUID(UUID_PBAP_PSE,uuid)) 484 { 485 handle = add_pbap_sdp(name, final_scn); //PBAP Server is always 19 486 } 487 else if (IS_UUID(UUID_MAPS_MAS,uuid)) 488 { 489 handle = add_maps_sdp(name, final_scn); //MAP Server is always 19 490 } 491 else if (IS_UUID(UUID_SPP, uuid)) 492 { 493 handle = add_spp_sdp(name, final_scn); 494 } 495 else 496 { 497 handle = add_sdp_by_uuid(name, uuid, final_scn); 498 } 499 return handle; 500} 501 502BOOLEAN is_reserved_rfc_channel(int scn) 503{ 504 switch(scn) 505 { 506 case RESERVED_SCN_PBS: 507 case RESERVED_SCN_OPS: 508 return TRUE; 509 } 510 return FALSE; 511} 512 513 514int get_reserved_rfc_channel (const uint8_t* uuid) 515{ 516 if (IS_UUID(UUID_PBAP_PSE,uuid)) 517 { 518 return RESERVED_SCN_PBS; 519 } 520 else if (IS_UUID(UUID_OBEX_OBJECT_PUSH,uuid)) 521 { 522 return RESERVED_SCN_OPS; 523 } 524 return -1; 525} 526 527int add_rfc_sdp_rec(const char* name, const uint8_t* uuid, int scn) 528{ 529 int sdp_handle = 0; 530 if(is_uuid_empty(uuid)) 531 { 532 switch(scn) 533 { 534 case RESERVED_SCN_PBS: // PBAP Reserved port 535 uuid = UUID_PBAP_PSE; 536 break; 537 case RESERVED_SCN_OPS: 538 uuid = UUID_OBEX_OBJECT_PUSH; 539 break; 540 default: 541 uuid = UUID_SPP; 542 break; 543 } 544 } 545 sdp_handle = add_rfc_sdp_by_uuid(name, uuid, scn); 546 return sdp_handle; 547} 548 549void del_rfc_sdp_rec(int handle) 550{ 551 APPL_TRACE_DEBUG1("del_rfc_sdp_rec: handle:0x%x", handle); 552 if(handle != -1 && handle != 0) 553 BTA_JvDeleteRecord( handle ); 554} 555 556