1 /******************************************************************************
3 * Copyright (C) 2009-2012 Broadcom Corporation
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:
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 ******************************************************************************/
19 /************************************************************************************
23 * Description: Handsfree Profile Bluetooth Interface
26 ***********************************************************************************/
28 #include <hardware/bluetooth.h>
29 #include <hardware/bt_sock.h>
30 #include <sys/types.h>
31 #include <sys/socket.h>
34 #define LOG_TAG "BTIF_SOCK_SDP"
35 #include "btif_common.h"
36 #include "btif_util.h"
43 #include "bt_target.h"
50 #include "btif_sock_sdp.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>
57 #define RESERVED_SCN_PBS 19
58 #define RESERVED_SCN_OPS 12
60 #define UUID_MAX_LENGTH 16
63 #define IS_UUID(u1,u2) !memcmp(u1,u2,UUID_MAX_LENGTH)
66 #define BTM_NUM_PROTO_ELEMS 2
67 static int add_sdp_by_uuid(const char *name, const uint8_t *service_uuid, UINT16 channel)
70 UINT32 btm_sdp_handle;
72 tSDP_PROTOCOL_ELEM proto_elem_list[BTM_NUM_PROTO_ELEMS];
74 /* register the service */
75 if ((btm_sdp_handle = SDP_CreateRecord()) != FALSE)
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;
83 proto_elem_list[1].params[0] = channel;
85 if (SDP_AddProtocolList(btm_sdp_handle, BTM_NUM_PROTO_ELEMS,
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;
94 // UINT8_TO_BE_STREAM (p, (UUID_DESC_TYPE << 3) | SIZE_SIXTEEN_BYTES);
95 ARRAY_TO_BE_STREAM (p, service_uuid, 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))
101 if ((SDP_AddAttribute(btm_sdp_handle, ATTR_ID_SERVICE_NAME,
102 TEXT_STR_DESC_TYPE, (UINT32)(strlen(name)+1),
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,
112 return btm_sdp_handle;
117 else APPL_TRACE_ERROR1("failed to create sdp record, service_name:%s", name);
122 /* Realm Character Set */
123 #define BTA_PBS_REALM_CHARSET 0 /* ASCII */
125 /* Specifies whether or not client's user id is required during obex authentication */
126 #define BTA_PBS_USERID_REQ FALSE
127 extern const tBTA_PBS_CFG bta_pbs_cfg;
128 const tBTA_PBS_CFG bta_pbs_cfg =
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,
136 static int add_pbap_sdp(const char* p_service_name, int scn)
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;
146 APPL_TRACE_DEBUG2("add_pbap_sdd:scn %d, service name %s", scn, p_service_name);
148 if ((sdp_handle = SDP_CreateRecord()) == 0)
150 APPL_TRACE_ERROR0("PBS SDP: Unable to register PBS Service");
154 /* add service class */
155 if (SDP_AddServiceClassIdList(sdp_handle, 1, &pbs_service))
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;
167 if (SDP_AddProtocolList(sdp_handle, 3, protoList))
169 status = TRUE; /* All mandatory fields were successful */
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);
179 /* Add in the Bluetooth Profile Descriptor List */
180 SDP_AddProfileDescriptorList(sdp_handle,
181 UUID_SERVCLASS_PHONE_ACCESS,
182 BTA_PBS_DEFAULT_VERSION);
184 } /* end of setting mandatory protocol list */
185 } /* end of setting mandatory service class */
187 /* add supported feature and repositories */
190 SDP_AddAttribute(sdp_handle, ATTR_ID_SUPPORTED_REPOSITORIES, UINT_DESC_TYPE,
191 (UINT32)1, (UINT8*)&p_bta_pbs_cfg->supported_repositories);
193 /* Make the service browseable */
194 SDP_AddUuidSequence (sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse);
199 SDP_DeleteRecord(sdp_handle);
201 APPL_TRACE_ERROR0("bta_pbs_sdp_register FAILED");
205 bta_sys_add_uuid(pbs_service); /* UUID_SERVCLASS_PBAP_PSE */
206 APPL_TRACE_DEBUG1("PBS: SDP Registered (handle 0x%08x)", sdp_handle);
212 /* This is horrible design - to reserve channel ID's and use them to magically link
213 * a channel number to a hard coded SDP entry.
214 * TODO: expose a prober SDP API, to avoid hacks like this, and make it possible
215 * to set useful names for the ServiceName */
216 #define BTA_MAP_MSG_TYPE_EMAIL 0x01
217 #define BTA_MAP_MSG_TYPE_SMS_GSM 0x02
218 #define BTA_MAP_MSG_TYPE_SMS_CDMA 0x04
219 #define BTA_MAP_MSG_TYPE_MMS 0x08
221 #define BTA_MAPS_DEFAULT_VERSION 0x0101 /* MAP 1.1 */
224 UINT8 mas_id; /* the MAS instance id */
225 const char* service_name; /* Description of the MAS instance */
226 UINT8 supported_message_types;/* Server supported message types - SMS/MMS/EMAIL */
228 const tBTA_MAPS_CFG bta_maps_cfg_sms =
230 0, /* Mas id 0 is for SMS/MMS */
232 BTA_MAP_MSG_TYPE_SMS_GSM | BTA_MAP_MSG_TYPE_SMS_CDMA
234 const tBTA_MAPS_CFG bta_maps_cfg_email =
236 1, /* Mas id 1 is for EMAIL */
238 BTA_MAP_MSG_TYPE_EMAIL
240 static int add_maps_sdp(const char* p_service_name, int scn)
243 tSDP_PROTOCOL_ELEM protoList [3];
244 UINT16 service = UUID_SERVCLASS_MESSAGE_ACCESS;
245 UINT16 browse = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
246 BOOLEAN status = FALSE;
247 UINT32 sdp_handle = 0;
248 // TODO: To add support for EMAIL set below depending on the scn to either SMS or Email
249 const tBTA_MAPS_CFG *p_bta_maps_cfg = &bta_maps_cfg_sms;
251 APPL_TRACE_DEBUG2("add_maps_sdd:scn %d, service name %s", scn, p_service_name);
253 if ((sdp_handle = SDP_CreateRecord()) == 0)
255 APPL_TRACE_ERROR0("MAPS SDP: Unable to register MAPS Service");
259 /* add service class */
260 if (SDP_AddServiceClassIdList(sdp_handle, 1, &service))
262 memset( protoList, 0 , 3*sizeof(tSDP_PROTOCOL_ELEM) );
263 /* add protocol list, including RFCOMM scn */
264 protoList[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
265 protoList[0].num_params = 0;
266 protoList[1].protocol_uuid = UUID_PROTOCOL_RFCOMM;
267 protoList[1].num_params = 1;
268 protoList[1].params[0] = scn;
269 protoList[2].protocol_uuid = UUID_PROTOCOL_OBEX;
270 protoList[2].num_params = 0;
272 if (SDP_AddProtocolList(sdp_handle, 3, protoList))
274 status = TRUE; /* All mandatory fields were successful */
276 /* optional: if name is not "", add a name entry */
277 SDP_AddAttribute(sdp_handle,
278 (UINT16)ATTR_ID_SERVICE_NAME,
279 (UINT8)TEXT_STR_DESC_TYPE,
280 (UINT32)(strlen(p_bta_maps_cfg->service_name) + 1),
281 (UINT8 *)p_bta_maps_cfg->service_name);
283 /* Add in the Bluetooth Profile Descriptor List */
284 SDP_AddProfileDescriptorList(sdp_handle,
285 UUID_SERVCLASS_MAP_PROFILE,
286 BTA_MAPS_DEFAULT_VERSION);
288 } /* end of setting mandatory protocol list */
289 } /* end of setting mandatory service class */
291 /* add supported feature and repositories */
294 SDP_AddAttribute(sdp_handle, ATTR_ID_MAS_INSTANCE_ID, UINT_DESC_TYPE,
295 (UINT32)1, (UINT8*)&p_bta_maps_cfg->mas_id);
296 SDP_AddAttribute(sdp_handle, ATTR_ID_SUPPORTED_MSG_TYPE, UINT_DESC_TYPE,
297 (UINT32)1, (UINT8*)&p_bta_maps_cfg->supported_message_types);
299 /* Make the service browseable */
300 SDP_AddUuidSequence (sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse);
305 SDP_DeleteRecord(sdp_handle);
307 APPL_TRACE_ERROR0("bta_mass_sdp_register FAILED");
311 bta_sys_add_uuid(service); /* UUID_SERVCLASS_MESSAGE_ACCESS */
312 APPL_TRACE_DEBUG1("MAPSS: SDP Registered (handle 0x%08x)", sdp_handle);
319 /* object format lookup table */
320 static const tBTA_OP_FMT bta_ops_obj_fmt[] =
331 #define BTA_OPS_NUM_FMTS 7
332 #define BTA_OPS_PROTOCOL_COUNT 3
334 #ifndef BTUI_OPS_FORMATS
335 #define BTUI_OPS_FORMATS (BTA_OP_VCARD21_MASK | BTA_OP_VCARD30_MASK | \
336 BTA_OP_VCAL_MASK | BTA_OP_ICAL_MASK | \
337 BTA_OP_VNOTE_MASK | BTA_OP_VMSG_MASK | \
341 static int add_ops_sdp(const char *p_service_name,int scn)
345 tSDP_PROTOCOL_ELEM protoList [BTA_OPS_PROTOCOL_COUNT];
346 UINT16 servclass = UUID_SERVCLASS_OBEX_OBJECT_PUSH;
349 UINT8 desc_type[BTA_OPS_NUM_FMTS];
350 UINT8 type_len[BTA_OPS_NUM_FMTS];
351 UINT8 *type_value[BTA_OPS_NUM_FMTS];
354 tBTA_OP_FMT_MASK formats = BTUI_OPS_FORMATS;
356 APPL_TRACE_DEBUG2("scn %d, service name %s", scn, p_service_name);
358 sdp_handle = SDP_CreateRecord();
360 /* add service class */
361 if (SDP_AddServiceClassIdList(sdp_handle, 1, &servclass))
363 /* add protocol list, including RFCOMM scn */
364 protoList[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
365 protoList[0].num_params = 0;
366 protoList[1].protocol_uuid = UUID_PROTOCOL_RFCOMM;
367 protoList[1].num_params = 1;
368 protoList[1].params[0] = scn;
369 protoList[2].protocol_uuid = UUID_PROTOCOL_OBEX;
370 protoList[2].num_params = 0;
372 if (SDP_AddProtocolList(sdp_handle, BTA_OPS_PROTOCOL_COUNT, protoList))
374 SDP_AddAttribute(sdp_handle,
375 (UINT16)ATTR_ID_SERVICE_NAME,
376 (UINT8)TEXT_STR_DESC_TYPE,
377 (UINT32)(strlen(p_service_name) + 1),
378 (UINT8 *)p_service_name);
380 SDP_AddProfileDescriptorList(sdp_handle,
381 UUID_SERVCLASS_OBEX_OBJECT_PUSH,
386 /* Make the service browseable */
387 browse = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
388 SDP_AddUuidSequence (sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse);
390 /* add sequence for supported types */
391 for (i = 0, j = 0; i < BTA_OPS_NUM_FMTS; i++)
393 if ((formats >> i) & 1)
395 type_value[j] = (UINT8 *) &bta_ops_obj_fmt[i];
396 desc_type[j] = UINT_DESC_TYPE;
401 SDP_AddSequence(sdp_handle, (UINT16) ATTR_ID_SUPPORTED_FORMATS_LIST,
402 (UINT8) j, desc_type, type_len, type_value);
404 /* set class of device */
405 cod.service = BTM_COD_SERVICE_OBJ_TRANSFER;
406 utl_set_device_class(&cod, BTA_UTL_SET_COD_SERVICE_CLASS);
408 bta_sys_add_uuid(servclass); /* UUID_SERVCLASS_OBEX_OBJECT_PUSH */
412 #define SPP_NUM_PROTO_ELEMS 2
413 static int add_spp_sdp(const char *service_name, int scn)
415 UINT16 serviceclassid = UUID_SERVCLASS_SERIAL_PORT;
416 tSDP_PROTOCOL_ELEM proto_elem_list[SPP_NUM_PROTO_ELEMS];
419 APPL_TRACE_DEBUG2("scn %d, service name %s", scn, service_name);
421 /* register the service */
422 if ((sdp_handle = SDP_CreateRecord()) != FALSE)
424 /*** Fill out the protocol element sequence for SDP ***/
425 proto_elem_list[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
426 proto_elem_list[0].num_params = 0;
427 proto_elem_list[1].protocol_uuid = UUID_PROTOCOL_RFCOMM;
428 proto_elem_list[1].num_params = 1;
430 proto_elem_list[1].params[0] = scn;
432 if (SDP_AddProtocolList(sdp_handle, SPP_NUM_PROTO_ELEMS, proto_elem_list))
434 if (SDP_AddServiceClassIdList(sdp_handle, 1, &serviceclassid))
436 if ((SDP_AddAttribute(sdp_handle, ATTR_ID_SERVICE_NAME,
437 TEXT_STR_DESC_TYPE, (UINT32)(strlen(service_name)+1),
438 (UINT8 *)service_name)))
441 /* Make the service browseable */
442 list[0] = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
443 SDP_AddUuidSequence (sdp_handle, ATTR_ID_BROWSE_GROUP_LIST,
454 static int add_rfc_sdp_by_uuid(const char* name, const uint8_t* uuid, int scn)
458 APPL_TRACE_DEBUG2("name:%s, scn:%d", name, scn);
461 Bluetooth Socket API relies on having preregistered bluez sdp records for HSAG, HFAG, OPP & PBAP
462 that are mapped to rc chan 10, 11,12 & 19. Today HSAG and HFAG is routed to BRCM AG and are not
463 using BT socket API so for now we will need to support OPP and PBAP to enable 3rd party developer
464 apps running on BRCM Android.
466 To do this we will check the UUID for the requested service and mimic the SDP records of bluez
467 upon reception. See functions add_opush() and add_pbap() in sdptool.c for actual records
470 /* special handling for preregistered bluez services (OPP, PBAP) that we need to mimic */
472 int final_scn = get_reserved_rfc_channel(uuid);
477 if (IS_UUID(UUID_OBEX_OBJECT_PUSH,uuid))
479 handle = add_ops_sdp(name,final_scn);
481 else if (IS_UUID(UUID_PBAP_PSE,uuid))
483 handle = add_pbap_sdp(name, final_scn); //PBAP Server is always 19
485 else if (IS_UUID(UUID_MAPS_MAS,uuid))
487 handle = add_maps_sdp(name, final_scn); //MAP Server is always 19
489 else if (IS_UUID(UUID_SPP, uuid))
491 handle = add_spp_sdp(name, final_scn);
495 handle = add_sdp_by_uuid(name, uuid, final_scn);
500 BOOLEAN is_reserved_rfc_channel(int scn)
504 case RESERVED_SCN_PBS:
505 case RESERVED_SCN_OPS:
512 int get_reserved_rfc_channel (const uint8_t* uuid)
514 if (IS_UUID(UUID_PBAP_PSE,uuid))
516 return RESERVED_SCN_PBS;
518 else if (IS_UUID(UUID_OBEX_OBJECT_PUSH,uuid))
520 return RESERVED_SCN_OPS;
525 int add_rfc_sdp_rec(const char* name, const uint8_t* uuid, int scn)
528 if(is_uuid_empty(uuid))
532 case RESERVED_SCN_PBS: // PBAP Reserved port
533 uuid = UUID_PBAP_PSE;
535 case RESERVED_SCN_OPS:
536 uuid = UUID_OBEX_OBJECT_PUSH;
543 sdp_handle = add_rfc_sdp_by_uuid(name, uuid, scn);
547 void del_rfc_sdp_rec(int handle)
549 APPL_TRACE_DEBUG1("del_rfc_sdp_rec: handle:0x%x", handle);
550 if(handle != -1 && handle != 0)
551 BTA_JvDeleteRecord( handle );