From: June R. Tate-Gans Date: Thu, 11 Sep 2014 00:05:21 +0000 (-0700) Subject: Refactoring btif_sock_sdp.c for clarity X-Git-Tag: android-x86-7.1-r1~1277^2~140 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=75b22fd55f44923054b411cc7cd2ca312e6fca9e;p=android-x86%2Fsystem-bt.git Refactoring btif_sock_sdp.c for clarity --- diff --git a/btif/src/btif_sock_sdp.c b/btif/src/btif_sock_sdp.c index 00671a0e2..e8f7e27f9 100644 --- a/btif/src/btif_sock_sdp.c +++ b/btif/src/btif_sock_sdp.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright (C) 2009-2012 Broadcom Corporation + * Copyright (C) 2014 Google, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,30 +16,19 @@ * ******************************************************************************/ -/************************************************************************************ - * - * Filename: btif_hf.c - * - * Description: Handsfree Profile Bluetooth Interface - * - * - ***********************************************************************************/ +#define LOG_TAG "BTIF_SOCK_SDP" #include #include #include #include #include +#include -#define LOG_TAG "BTIF_SOCK_SDP" #include "btif_common.h" #include "btif_util.h" - #include "bd.h" - #include "bta_api.h" - - #include "bt_target.h" #include "gki.h" #include "hcimsgs.h" @@ -52,501 +41,511 @@ #include "../bta/pb/bta_pbs_int.h" #include "../include/bta_op_api.h" #include "bta_jv_api.h" -#include - -#define RESERVED_SCN_PBS 19 -#define RESERVED_SCN_OPS 12 - -#define UUID_MAX_LENGTH 16 +// This module provides an abstraction on top of the lower-level SDP database +// code for registration and discovery of various bluetooth sockets. +// +// This code also provides for on-demand registration of "pre-registered" +// services as a backwards compatibility function to third-party applications +// expecting a bluez stack. -#define IS_UUID(u1,u2) !memcmp(u1,u2,UUID_MAX_LENGTH) - - -#define BTM_NUM_PROTO_ELEMS 2 -static int add_sdp_by_uuid(const char *name, const uint8_t *service_uuid, UINT16 channel) -{ - - UINT32 btm_sdp_handle; - - tSDP_PROTOCOL_ELEM proto_elem_list[BTM_NUM_PROTO_ELEMS]; - - /* register the service */ - if ((btm_sdp_handle = SDP_CreateRecord()) != FALSE) - { - /*** Fill out the protocol element sequence for SDP ***/ - proto_elem_list[0].protocol_uuid = UUID_PROTOCOL_L2CAP; - proto_elem_list[0].num_params = 0; - proto_elem_list[1].protocol_uuid = UUID_PROTOCOL_RFCOMM; - proto_elem_list[1].num_params = 1; - - proto_elem_list[1].params[0] = channel; - - if (SDP_AddProtocolList(btm_sdp_handle, BTM_NUM_PROTO_ELEMS, - proto_elem_list)) - { - UINT8 buff[48]; - UINT8 *p, *type_buf[1]; - UINT8 type[1], type_len[1]; - p = type_buf[0] = buff; - type[0] = UUID_DESC_TYPE; - -// UINT8_TO_BE_STREAM (p, (UUID_DESC_TYPE << 3) | SIZE_SIXTEEN_BYTES); - ARRAY_TO_BE_STREAM (p, service_uuid, 16); - type_len[0] = 16; - if( SDP_AddSequence(btm_sdp_handle, (UINT16) ATTR_ID_SERVICE_CLASS_ID_LIST, - 1, type, type_len, type_buf) ) -// if (SDP_AddServiceClassIdList(btm_sdp_handle, 1, &service_uuid)) - { - if ((SDP_AddAttribute(btm_sdp_handle, ATTR_ID_SERVICE_NAME, - TEXT_STR_DESC_TYPE, (UINT32)(strlen(name)+1), - (UINT8 *)name)) ) - { - UINT16 list[1]; - - /* Make the service browseable */ - list[0] = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP; - if ((SDP_AddUuidSequence (btm_sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, - 1, list)) ) - - return btm_sdp_handle; - } - } - } - } - else APPL_TRACE_ERROR("failed to create sdp record, service_name:%s", name); - return 0; -} +// Realm Character Set -- 0 is ASCII +#define BTA_PBS_REALM_CHARSET 0 +// Specifies whether or not client's user id is required during obex +// authentication +#define BTA_PBS_USERID_REQ FALSE -/* Realm Character Set */ -#define BTA_PBS_REALM_CHARSET 0 /* ASCII */ - -/* Specifies whether or not client's user id is required during obex authentication */ -#define BTA_PBS_USERID_REQ FALSE +// TODO(jtgans): Is this really exported to anything anywhere? If so, we should +// stuff it into the header, otherwise, WHY IS IT HERE?! extern const tBTA_PBS_CFG bta_pbs_cfg; -const tBTA_PBS_CFG bta_pbs_cfg = -{ - BTA_PBS_REALM_CHARSET, /* Server only */ - BTA_PBS_USERID_REQ, /* Server only */ - (BTA_PBS_SUPF_DOWNLOAD | BTA_PBS_SURF_BROWSE), - BTA_PBS_REPOSIT_LOCAL, -}; - -static int add_pbap_sdp(const char* p_service_name, int scn) -{ - - tSDP_PROTOCOL_ELEM protoList [3]; - UINT16 pbs_service = UUID_SERVCLASS_PBAP_PSE; - UINT16 browse = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP; - BOOLEAN status = FALSE; - UINT32 sdp_handle = 0; - tBTA_PBS_CFG *p_bta_pbs_cfg = (tBTA_PBS_CFG *)&bta_pbs_cfg; - - APPL_TRACE_DEBUG("add_pbap_sdd:scn %d, service name %s", scn, p_service_name); - if ((sdp_handle = SDP_CreateRecord()) == 0) - { - APPL_TRACE_ERROR("PBS SDP: Unable to register PBS Service"); - return sdp_handle; - } - - /* add service class */ - if (SDP_AddServiceClassIdList(sdp_handle, 1, &pbs_service)) - { - memset( protoList, 0 , 3*sizeof(tSDP_PROTOCOL_ELEM) ); - /* add protocol list, including RFCOMM scn */ - protoList[0].protocol_uuid = UUID_PROTOCOL_L2CAP; - protoList[0].num_params = 0; - protoList[1].protocol_uuid = UUID_PROTOCOL_RFCOMM; - protoList[1].num_params = 1; - protoList[1].params[0] = scn; - protoList[2].protocol_uuid = UUID_PROTOCOL_OBEX; - protoList[2].num_params = 0; - - if (SDP_AddProtocolList(sdp_handle, 3, protoList)) - { - status = TRUE; /* All mandatory fields were successful */ - - /* optional: if name is not "", add a name entry */ - if (*p_service_name != '\0') - SDP_AddAttribute(sdp_handle, - (UINT16)ATTR_ID_SERVICE_NAME, - (UINT8)TEXT_STR_DESC_TYPE, - (UINT32)(strlen(p_service_name) + 1), - (UINT8 *)p_service_name); - - /* Add in the Bluetooth Profile Descriptor List */ - SDP_AddProfileDescriptorList(sdp_handle, - UUID_SERVCLASS_PHONE_ACCESS, - BTA_PBS_DEFAULT_VERSION); - - } /* end of setting mandatory protocol list */ - } /* end of setting mandatory service class */ - - /* add supported feature and repositories */ - if (status) - { - SDP_AddAttribute(sdp_handle, ATTR_ID_SUPPORTED_REPOSITORIES, UINT_DESC_TYPE, - (UINT32)1, (UINT8*)&p_bta_pbs_cfg->supported_repositories); - - /* Make the service browseable */ - SDP_AddUuidSequence (sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse); - } +const tBTA_PBS_CFG bta_pbs_cfg = { + BTA_PBS_REALM_CHARSET, // realm_charset: Server only + BTA_PBS_USERID_REQ, // userid_req: Server only + (BTA_PBS_SUPF_DOWNLOAD | BTA_PBS_SURF_BROWSE), // supported_features + BTA_PBS_REPOSIT_LOCAL, // supported_repositories +}; - if (!status) - { - SDP_DeleteRecord(sdp_handle); - sdp_handle = 0; - APPL_TRACE_ERROR("bta_pbs_sdp_register FAILED"); - } - else - { - bta_sys_add_uuid(pbs_service); /* UUID_SERVCLASS_PBAP_PSE */ - APPL_TRACE_DEBUG("PBS: SDP Registered (handle 0x%08x)", sdp_handle); - } +// object format lookup table +#define OBEX_PUSH_NUM_FORMATS 7 + +static const tBTA_OP_FMT bta_ops_obj_fmt[OBEX_PUSH_NUM_FORMATS] = { + BTA_OP_VCARD21_FMT, + BTA_OP_VCARD30_FMT, + BTA_OP_VCAL_FMT, + BTA_OP_ICAL_FMT, + BTA_OP_VNOTE_FMT, + BTA_OP_VMSG_FMT, + BTA_OP_OTHER_FMT +}; - return sdp_handle; -} +// TODO(jtgans): Figure out if we actually need this define. This is ifndef +// defined in bt_target.h, but nowhere else, so right now, unless something +// overrides this before bt_target.h sets it, it will always be bt_target.h's +// version. +#ifndef BTUI_OPS_FORMATS +#define BTUI_OPS_FORMATS (BTA_OP_VCARD21_MASK \ + | BTA_OP_VCARD30_MASK \ + | BTA_OP_VCAL_MASK \ + | BTA_OP_ICAL_MASK \ + | BTA_OP_VNOTE_MASK \ + | BTA_OP_VMSG_MASK \ + | BTA_OP_ANY_MASK) +#endif -/* This is horrible design - to reserve channel ID's and use them to magically link - * a channel number to a hard coded SDP entry. +/* + * This is horrible design - to reserve channel ID's and use them to magically + * link a channel number to a hard coded SDP entry. + * * TODO: expose a prober SDP API, to avoid hacks like this, and make it possible - * to set useful names for the ServiceName */ + * to set useful names for the ServiceName + */ #define BTA_MAP_MSG_TYPE_EMAIL 0x01 #define BTA_MAP_MSG_TYPE_SMS_GSM 0x02 #define BTA_MAP_MSG_TYPE_SMS_CDMA 0x04 #define BTA_MAP_MSG_TYPE_MMS 0x08 -#define BTA_MAPS_DEFAULT_VERSION 0x0101 /* MAP 1.1 */ -typedef struct -{ - UINT8 mas_id; /* the MAS instance id */ - const char* service_name; /* Description of the MAS instance */ - UINT8 supported_message_types;/* Server supported message types - SMS/MMS/EMAIL */ -} tBTA_MAPS_CFG; -const tBTA_MAPS_CFG bta_maps_cfg_sms = -{ - 0, /* Mas id 0 is for SMS/MMS */ - "MAP SMS", - BTA_MAP_MSG_TYPE_SMS_GSM | BTA_MAP_MSG_TYPE_SMS_CDMA -}; -const tBTA_MAPS_CFG bta_maps_cfg_email = -{ - 1, /* Mas id 1 is for EMAIL */ - "MAP EMAIL", - BTA_MAP_MSG_TYPE_EMAIL -}; -static int add_maps_sdp(const char* p_service_name, int scn) -{ - - tSDP_PROTOCOL_ELEM protoList [3]; - UINT16 service = UUID_SERVCLASS_MESSAGE_ACCESS; - UINT16 browse = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP; - BOOLEAN status = FALSE; - UINT32 sdp_handle = 0; - // TODO: To add support for EMAIL set below depending on the scn to either SMS or Email - const tBTA_MAPS_CFG *p_bta_maps_cfg = &bta_maps_cfg_sms; - - APPL_TRACE_DEBUG("add_maps_sdd:scn %d, service name %s", scn, p_service_name); - - if ((sdp_handle = SDP_CreateRecord()) == 0) - { - APPL_TRACE_ERROR("MAPS SDP: Unable to register MAPS Service"); - return sdp_handle; - } - - /* add service class */ - if (SDP_AddServiceClassIdList(sdp_handle, 1, &service)) - { - memset( protoList, 0 , 3*sizeof(tSDP_PROTOCOL_ELEM) ); - /* add protocol list, including RFCOMM scn */ - protoList[0].protocol_uuid = UUID_PROTOCOL_L2CAP; - protoList[0].num_params = 0; - protoList[1].protocol_uuid = UUID_PROTOCOL_RFCOMM; - protoList[1].num_params = 1; - protoList[1].params[0] = scn; - protoList[2].protocol_uuid = UUID_PROTOCOL_OBEX; - protoList[2].num_params = 0; - - if (SDP_AddProtocolList(sdp_handle, 3, protoList)) - { - status = TRUE; /* All mandatory fields were successful */ - - /* optional: if name is not "", add a name entry */ - SDP_AddAttribute(sdp_handle, - (UINT16)ATTR_ID_SERVICE_NAME, - (UINT8)TEXT_STR_DESC_TYPE, - (UINT32)(strlen(p_bta_maps_cfg->service_name) + 1), - (UINT8 *)p_bta_maps_cfg->service_name); - - /* Add in the Bluetooth Profile Descriptor List */ - SDP_AddProfileDescriptorList(sdp_handle, - UUID_SERVCLASS_MAP_PROFILE, - BTA_MAPS_DEFAULT_VERSION); - - } /* end of setting mandatory protocol list */ - } /* end of setting mandatory service class */ - - /* add supported feature and repositories */ - if (status) - { - SDP_AddAttribute(sdp_handle, ATTR_ID_MAS_INSTANCE_ID, UINT_DESC_TYPE, - (UINT32)1, (UINT8*)&p_bta_maps_cfg->mas_id); - SDP_AddAttribute(sdp_handle, ATTR_ID_SUPPORTED_MSG_TYPE, UINT_DESC_TYPE, - (UINT32)1, (UINT8*)&p_bta_maps_cfg->supported_message_types); - - /* Make the service browseable */ - SDP_AddUuidSequence (sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse); - } - - if (!status) - { - SDP_DeleteRecord(sdp_handle); - sdp_handle = 0; - APPL_TRACE_ERROR("bta_mass_sdp_register FAILED"); - } - else - { - bta_sys_add_uuid(service); /* UUID_SERVCLASS_MESSAGE_ACCESS */ - APPL_TRACE_DEBUG("MAPSS: SDP Registered (handle 0x%08x)", sdp_handle); - } +#define BTA_MAP_MAS_ID_SMSMMS 0 +#define BTA_MAP_MAS_ID_EMAIL 1 - return sdp_handle; -} +// MAP 1.1 +#define BTA_MAP_DEFAULT_VERSION 0x0101 +typedef struct { + UINT8 mas_id; // the MAS instance id + const char *service_name; // Description of the MAS instance + UINT8 supported_message_types; // Server supported message types - SMS/MMS/EMAIL +} tBTA_MAP_CFG; -/* object format lookup table */ -static const tBTA_OP_FMT bta_ops_obj_fmt[] = -{ - BTA_OP_VCARD21_FMT, - BTA_OP_VCARD30_FMT, - BTA_OP_VCAL_FMT, - BTA_OP_ICAL_FMT, - BTA_OP_VNOTE_FMT, - BTA_OP_VMSG_FMT, - BTA_OP_OTHER_FMT +const tBTA_MAP_CFG bta_map_cfg_sms = { + BTA_MAP_MAS_ID_SMSMMS, + "MAP SMS", + BTA_MAP_MSG_TYPE_SMS_GSM | BTA_MAP_MSG_TYPE_SMS_CDMA }; -#define BTA_OPS_NUM_FMTS 7 -#define BTA_OPS_PROTOCOL_COUNT 3 - -#ifndef BTUI_OPS_FORMATS -#define BTUI_OPS_FORMATS (BTA_OP_VCARD21_MASK | BTA_OP_VCARD30_MASK | \ - BTA_OP_VCAL_MASK | BTA_OP_ICAL_MASK | \ - BTA_OP_VNOTE_MASK | BTA_OP_VMSG_MASK | \ - BTA_OP_ANY_MASK ) -#endif +#define RESERVED_SCN_PBS 19 +#define RESERVED_SCN_OPS 12 -static int add_ops_sdp(const char *p_service_name,int scn) -{ - - - tSDP_PROTOCOL_ELEM protoList [BTA_OPS_PROTOCOL_COUNT]; - UINT16 servclass = UUID_SERVCLASS_OBEX_OBJECT_PUSH; - int i, j; - tBTA_UTL_COD cod; - UINT8 desc_type[BTA_OPS_NUM_FMTS]; - UINT8 type_len[BTA_OPS_NUM_FMTS]; - UINT8 *type_value[BTA_OPS_NUM_FMTS]; - UINT16 browse; - UINT32 sdp_handle; - tBTA_OP_FMT_MASK formats = BTUI_OPS_FORMATS; - - APPL_TRACE_DEBUG("scn %d, service name %s", scn, p_service_name); - - sdp_handle = SDP_CreateRecord(); - - /* add service class */ - if (SDP_AddServiceClassIdList(sdp_handle, 1, &servclass)) - { - /* add protocol list, including RFCOMM scn */ - protoList[0].protocol_uuid = UUID_PROTOCOL_L2CAP; - protoList[0].num_params = 0; - protoList[1].protocol_uuid = UUID_PROTOCOL_RFCOMM; - protoList[1].num_params = 1; - protoList[1].params[0] = scn; - protoList[2].protocol_uuid = UUID_PROTOCOL_OBEX; - protoList[2].num_params = 0; - - if (SDP_AddProtocolList(sdp_handle, BTA_OPS_PROTOCOL_COUNT, protoList)) - { - SDP_AddAttribute(sdp_handle, - (UINT16)ATTR_ID_SERVICE_NAME, - (UINT8)TEXT_STR_DESC_TYPE, - (UINT32)(strlen(p_service_name) + 1), - (UINT8 *)p_service_name); - - SDP_AddProfileDescriptorList(sdp_handle, - UUID_SERVCLASS_OBEX_OBJECT_PUSH, - 0x0100); - } - } +#define UUID_MAX_LENGTH 16 +#define UUID_MATCHES(u1, u2) !memcmp(u1, u2, UUID_MAX_LENGTH) + +// Adds a protocol list and service name (if provided) to an SDP record given by +// |sdp_handle|, and marks it as browseable. This is a shortcut for defining a +// set of protocols that includes L2CAP, RFCOMM, and optionally OBEX. If +// |with_obex| is |TRUE|, then an additional OBEX protocol UUID will be included +// at the end of the protocol list. +// +// Returns TRUE if successful, otherwise FALSE. +static BOOLEAN create_base_record(const UINT32 sdp_handle, const char *name, + const UINT16 channel, const BOOLEAN with_obex) { + APPL_TRACE_DEBUG("create_base_record: scn: %d, name: %s, with_obex: %d", + channel, name, with_obex); + + // Setup the protocol list and add it. + tSDP_PROTOCOL_ELEM proto_list[SDP_MAX_LIST_ELEMS]; + int num_proto_elements = with_obex ? 3 : 2; + + memset(proto_list, 0, num_proto_elements * sizeof(tSDP_PROTOCOL_ELEM)); + + proto_list[0].protocol_uuid = UUID_PROTOCOL_L2CAP; + proto_list[0].num_params = 0; + proto_list[1].protocol_uuid = UUID_PROTOCOL_RFCOMM; + proto_list[1].num_params = 1; + proto_list[1].params[0] = channel; + + if (with_obex == TRUE) { + proto_list[2].protocol_uuid = UUID_PROTOCOL_OBEX; + proto_list[2].num_params = 0; + } + + char *stage = "protocol_list"; + if (!SDP_AddProtocolList(sdp_handle, num_proto_elements, proto_list)) + goto error; + + // Add the name to the SDP record. + if (name[0] != '\0') { + stage = "service_name"; + if (!SDP_AddAttribute(sdp_handle, ATTR_ID_SERVICE_NAME, + TEXT_STR_DESC_TYPE, (UINT32)(strlen(name) + 1), + (UINT8 *)name)) + goto error; + } + + // Mark the service as browseable. + UINT16 list = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP; + stage = "browseable"; + if (!SDP_AddUuidSequence(sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &list)) + goto error; + + APPL_TRACE_DEBUG("create_base_record: successfully created base service " + "record, handle: 0x%08x, scn: %d, name: %s, with_obex: %d", + sdp_handle, channel, name, with_obex); + return TRUE; + +error: + APPL_TRACE_ERROR("create_base_record: failed to create base service " + "record, stage: %s, scn: %d, name: %s, with_obex: %d", + stage, channel, name, with_obex); + return FALSE; +} - /* Make the service browseable */ - browse = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP; - SDP_AddUuidSequence (sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse); - - /* add sequence for supported types */ - for (i = 0, j = 0; i < BTA_OPS_NUM_FMTS; i++) - { - if ((formats >> i) & 1) - { - type_value[j] = (UINT8 *) &bta_ops_obj_fmt[i]; - desc_type[j] = UINT_DESC_TYPE; - type_len[j++] = 1; - } - } +// Registers a service with the given |name|, |uuid|, and |channel| in the SDP +// database as a generic L2CAP RFCOMM protocol, storing its |uuid| as a service +// class sequence. +static int add_sdp_by_uuid(const char *name, const uint8_t *uuid, + const UINT16 channel) { + APPL_TRACE_DEBUG("add_sdp_by_uuid: scn: %d, service_name: %s", channel, name); + + UINT32 handle = SDP_CreateRecord(); + if (handle == 0) { + APPL_TRACE_ERROR("add_sdp_by_uuid: failed to create sdp record, " + "scn: %d, service_name: %s", channel, name); + return 0; + } + + // Create the base SDP record. + char *stage = "create_base_record"; + if (!create_base_record(handle, name, channel, FALSE /* with_obex */)) + goto error; + + // Convert the |uuid| into a big-endian representation and add it as a + // sequence. + UINT8 type = UUID_DESC_TYPE; + UINT8 type_len = UUID_MAX_LENGTH; + UINT8 type_buf[48]; + + // Do the conversion to big-endian -- tmp is only used to iterate through the + // UUID array in the macro and serves no other purpose as the conversion + // macros are not hygenic. + { + UINT8 *tmp = type_buf; + ARRAY_TO_BE_STREAM(tmp, uuid, UUID_MAX_LENGTH); + } + + stage = "service_class_sequence"; + if (!SDP_AddSequence(handle, (UINT16)ATTR_ID_SERVICE_CLASS_ID_LIST, + 1, &type, &type_len, (UINT8**)&type_buf)) + goto error; + + + APPL_TRACE_DEBUG("add_sdp_by_uuid: service registered successfully, " + "service_name: %s, handle: 0x%08x", name, handle); + return handle; + +error: + SDP_DeleteRecord(handle); + APPL_TRACE_ERROR("add_sdp_by_uuid: failed to register service " + "stage: %s, service_name: %s", stage, name); + return 0; +} - SDP_AddSequence(sdp_handle, (UINT16) ATTR_ID_SUPPORTED_FORMATS_LIST, - (UINT8) j, desc_type, type_len, type_value); +// Registers a service with the given |name| and |channel| in the SDP +// database as a PBAP protocol. +static int add_pbap_sdp(const char *name, const int channel) { + APPL_TRACE_DEBUG("add_pbap_sdp: scn %d, service_name %s", channel, name); - /* set class of device */ - cod.service = BTM_COD_SERVICE_OBJ_TRANSFER; - utl_set_device_class(&cod, BTA_UTL_SET_COD_SERVICE_CLASS); + UINT32 handle = SDP_CreateRecord(); + if (handle == 0) { + APPL_TRACE_ERROR("add_pbap_sdp: failed to create sdp record, " + "service_name: %s", name); + return 0; + } + + // Create the base SDP record. + char *stage = "create_base_record"; + if (!create_base_record(handle, name, channel, TRUE /* with_obex */)) + goto error; + + // Add service class + UINT16 service = UUID_SERVCLASS_PBAP_PSE; + stage = "service_class"; + if (!SDP_AddServiceClassIdList(handle, 1, &service)) + goto error; + + // Add in the phone access descriptor + stage = "profile_descriptor_list"; + if (!SDP_AddProfileDescriptorList(handle, + UUID_SERVCLASS_PHONE_ACCESS, + BTA_PBS_DEFAULT_VERSION)) + goto error; + + // Set up our supported repositories + stage = "supported_repositories"; + if (!SDP_AddAttribute(handle, ATTR_ID_SUPPORTED_REPOSITORIES, UINT_DESC_TYPE, + 1, (UINT8*)&bta_pbs_cfg.supported_repositories)) + goto error; + + // Notify the system that we've got a new service class UUID. + bta_sys_add_uuid(UUID_SERVCLASS_PBAP_PSE); + APPL_TRACE_DEBUG("add_pbap_sdp: service registered successfully, " + "service_name: %s, handle: 0x%08x", name, handle); + + return handle; + +error: + SDP_DeleteRecord(handle); + APPL_TRACE_ERROR("add_pbap_sdp: failed to register PBAP service, stage: %s, " + "service_name: %s", stage, name); + return 0; +} - bta_sys_add_uuid(servclass); /* UUID_SERVCLASS_OBEX_OBJECT_PUSH */ +// Registers a service with the given |name| and |channel| in the SDP database +// as a MAP protocol. +static int add_maps_sdp(const char *name, const int channel) { + APPL_TRACE_DEBUG("add_maps_sdp: scn %d, service_name %s", channel, + name); - return sdp_handle; + UINT32 handle = SDP_CreateRecord(); + if (handle == 0) { + APPL_TRACE_ERROR("add_maps_sdp: failed to create sdp record, " + "service_name: %s", name); + return 0; + } + + // Create the base SDP record. + char *stage = "create_base_record"; + if (!create_base_record(handle, name, channel, TRUE /* with_obex */)) + goto error; + + // add service class + UINT16 service = UUID_SERVCLASS_MESSAGE_ACCESS; + stage = "service_class"; + if (!SDP_AddServiceClassIdList(handle, 1, &service)) + goto error; + + // TODO: To add support for EMAIL set below depending on the scn to either + // SMS or Email + const tBTA_MAP_CFG *bta_map_cfg = &bta_map_cfg_sms; + + // Add in the Bluetooth Profile Descriptor List + stage = "profile_descriptor_list"; + if (!SDP_AddProfileDescriptorList(handle, + UUID_SERVCLASS_MAP_PROFILE, + BTA_MAP_DEFAULT_VERSION)) + goto error; + + stage = "mas_instance_id"; + if (!SDP_AddAttribute(handle, ATTR_ID_MAS_INSTANCE_ID, UINT_DESC_TYPE, + (UINT32)1, (UINT8*)(&bta_map_cfg->mas_id))) + goto error; + + stage = "support_message_types"; + if (!SDP_AddAttribute(handle, ATTR_ID_SUPPORTED_MSG_TYPE, UINT_DESC_TYPE, + (UINT32)1, + (UINT8*)(&bta_map_cfg->supported_message_types))) + goto error; + + // Notify the system that we've got a new service class UUID. + bta_sys_add_uuid(service); // UUID_SERVCLASS_MESSAGE_ACCESS + APPL_TRACE_DEBUG("ad_maps_sdp: service registered successfully, " + "service_name: %s, handle 0x%08x)", name, handle); + + return handle; + +error: + SDP_DeleteRecord(handle); + APPL_TRACE_ERROR("add_maps_sdp: failed to register MAP service, stage: %s, " + "service_name: %s", stage, name); + return 0; } -#define SPP_NUM_PROTO_ELEMS 2 -static int add_spp_sdp(const char *service_name, int scn) -{ - UINT16 serviceclassid = UUID_SERVCLASS_SERIAL_PORT; - tSDP_PROTOCOL_ELEM proto_elem_list[SPP_NUM_PROTO_ELEMS]; - int sdp_handle; - - APPL_TRACE_DEBUG("scn %d, service name %s", scn, service_name); - - /* register the service */ - if ((sdp_handle = SDP_CreateRecord()) != FALSE) - { - /*** Fill out the protocol element sequence for SDP ***/ - proto_elem_list[0].protocol_uuid = UUID_PROTOCOL_L2CAP; - proto_elem_list[0].num_params = 0; - proto_elem_list[1].protocol_uuid = UUID_PROTOCOL_RFCOMM; - proto_elem_list[1].num_params = 1; - - proto_elem_list[1].params[0] = scn; - - if (SDP_AddProtocolList(sdp_handle, SPP_NUM_PROTO_ELEMS, proto_elem_list)) - { - if (SDP_AddServiceClassIdList(sdp_handle, 1, &serviceclassid)) - { - if ((SDP_AddAttribute(sdp_handle, ATTR_ID_SERVICE_NAME, - TEXT_STR_DESC_TYPE, (UINT32)(strlen(service_name)+1), - (UINT8 *)service_name))) - { - UINT16 list[1]; - /* Make the service browseable */ - list[0] = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP; - SDP_AddUuidSequence (sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, - 1, list); - } - } - } + +// Registers a service with the given |name| and |channel| as an OBEX Push +// protocol. +static int add_ops_sdp(const char *name, const int channel) { + APPL_TRACE_DEBUG("add_ops_sdp: scn %d, service_name %s", channel, name); + + UINT32 handle = SDP_CreateRecord(); + if (handle == 0) { + APPL_TRACE_ERROR("add_ops_sdp: failed to create sdp record, " + "service_name: %s", name); + return 0; + } + + // Create the base SDP record. + char *stage = "create_base_record"; + if (!create_base_record(handle, name, channel, TRUE /* with_obex */)) + goto error; + + // Add service class. + stage = "service_class"; + UINT16 service = UUID_SERVCLASS_OBEX_OBJECT_PUSH; + if (!SDP_AddServiceClassIdList(handle, 1, &service)) + goto error; + + // Add the OBEX push profile descriptor. + stage = "profile_descriptor_list"; + if (!SDP_AddProfileDescriptorList(handle, UUID_SERVCLASS_OBEX_OBJECT_PUSH, + 0x0100)) + goto error; + + // Add sequence for supported types. + UINT8 desc_type[OBEX_PUSH_NUM_FORMATS]; + UINT8 type_len[OBEX_PUSH_NUM_FORMATS]; + UINT8 *type_value[OBEX_PUSH_NUM_FORMATS]; + UINT8 j = 0; + + for (int i = 0; i < OBEX_PUSH_NUM_FORMATS; i++) { + if ((BTUI_OPS_FORMATS >> i) & 1) { + type_value[j] = (UINT8*)(&bta_ops_obj_fmt[i]); + desc_type[j] = UINT_DESC_TYPE; + type_len[j++] = 1; } - return sdp_handle; + } + + stage = "supported_types"; + if (!SDP_AddSequence(handle, (UINT16)ATTR_ID_SUPPORTED_FORMATS_LIST, + j, desc_type, type_len, type_value)) + goto error; + + // Set class of device. + tBTA_UTL_COD cod; + cod.service = BTM_COD_SERVICE_OBJ_TRANSFER; + stage = "class_of_device"; + if (!utl_set_device_class(&cod, BTA_UTL_SET_COD_SERVICE_CLASS)) + goto error; + + // Notify the system that we've got a new service class UUID. + bta_sys_add_uuid(UUID_SERVCLASS_OBEX_OBJECT_PUSH); + APPL_TRACE_DEBUG("ad_maps_sdp: service registered successfully, " + "service_name: %s, handle 0x%08x)", name, handle); + + return handle; + +error: + SDP_DeleteRecord(handle); + APPL_TRACE_ERROR("add_ops_sdp: failed to register OPS service, " + "stage: %s, service_name: %s", stage, name); + return 0; } +// Registers a service with the given |name| and |channel| as a serial port +// profile protocol. +static int add_spp_sdp(const char *name, const int channel) { + APPL_TRACE_DEBUG("add_spp_sdp: scn %d, service_name %s", channel, name); -static int add_rfc_sdp_by_uuid(const char* name, const uint8_t* uuid, int scn) -{ - int handle = 0; + int handle = SDP_CreateRecord(); + if (handle == 0) { + APPL_TRACE_ERROR("add_spp_sdp: failed to create sdp record, " + "service_name: %s", name); + return 0; + } - APPL_TRACE_DEBUG("name:%s, scn:%d", name, scn); + // Create the base SDP record. + char *stage = "create_base_record"; + if (!create_base_record(handle, name, channel, FALSE /* with_obex */)) + goto error; - /* - Bluetooth Socket API relies on having preregistered bluez sdp records for HSAG, HFAG, OPP & PBAP - that are mapped to rc chan 10, 11,12 & 19. Today HSAG and HFAG is routed to BRCM AG and are not - using BT socket API so for now we will need to support OPP and PBAP to enable 3rd party developer - apps running on BRCM Android. + UINT16 service = UUID_SERVCLASS_SERIAL_PORT; + stage = "service_class"; + if (!SDP_AddServiceClassIdList(handle, 1, &service)) + goto error; - To do this we will check the UUID for the requested service and mimic the SDP records of bluez - upon reception. See functions add_opush() and add_pbap() in sdptool.c for actual records - */ + APPL_TRACE_DEBUG("add_spp_sdp: service registered successfully, " + "service_name: %s, handle 0x%08x)", name, handle); - /* special handling for preregistered bluez services (OPP, PBAP) that we need to mimic */ + return handle; - int final_scn = get_reserved_rfc_channel(uuid); - if (final_scn == -1) - { - final_scn=scn; - } - if (IS_UUID(UUID_OBEX_OBJECT_PUSH,uuid)) - { - handle = add_ops_sdp(name,final_scn); - } - else if (IS_UUID(UUID_PBAP_PSE,uuid)) - { - handle = add_pbap_sdp(name, final_scn); //PBAP Server is always 19 - } - else if (IS_UUID(UUID_MAPS_MAS,uuid)) - { - handle = add_maps_sdp(name, final_scn); //MAP Server is always 19 - } - else if (IS_UUID(UUID_SPP, uuid)) - { - handle = add_spp_sdp(name, final_scn); - } - else - { - handle = add_sdp_by_uuid(name, uuid, final_scn); - } - return handle; +error: + SDP_DeleteRecord(handle); + APPL_TRACE_ERROR("add_spp_sdp: failed to register SPP service, " + "stage: %s, service_name: %s", stage, name); + return 0; } -BOOLEAN is_reserved_rfc_channel(int scn) -{ - switch(scn) - { - case RESERVED_SCN_PBS: - case RESERVED_SCN_OPS: - return TRUE; - } - return FALSE; +// Adds an RFCOMM SDP record for a service with the given |name|, |uuid|, and +// |channel|. This function attempts to identify the type of the service based +// upon its |uuid|, and will override the |channel| with a reserved channel +// number if the |uuid| matches one of the preregistered bluez SDP records. +static int add_rfc_sdp_by_uuid(const char *name, const uint8_t *uuid, + const int channel) { + APPL_TRACE_DEBUG("add_rfc_sdp_by_uuid: service_name: %s, channel: %d", name, + channel); + + /* + * Bluetooth Socket API relies on having preregistered bluez sdp records for + * HSAG, HFAG, OPP & PBAP that are mapped to rc chan 10, 11,12 & 19. Today + * HSAG and HFAG is routed to BRCM AG and are not using BT socket API so for + * now we will need to support OPP and PBAP to enable 3rd party developer apps + * running on BRCM Android. + * + * To do this we will check the UUID for the requested service and mimic the + * SDP records of bluez upon reception. See functions add_opush() and + * add_pbap() in sdptool.c for actual records. + */ + + int final_channel = get_reserved_rfc_channel(uuid); + + if (final_channel == -1) { + final_channel = channel; + } + + int handle = 0; + + if (UUID_MATCHES(UUID_OBEX_OBJECT_PUSH, uuid)) { + handle = add_ops_sdp(name, final_channel); + } else if (UUID_MATCHES(UUID_PBAP_PSE,uuid)) { + // PBAP Server is always channel 19 + handle = add_pbap_sdp(name, final_channel); + } else if (UUID_MATCHES(UUID_SPP, uuid)) { + handle = add_spp_sdp(name, final_channel); + } else if (UUID_MATCHES(UUID_MAPS_MAS,uuid)) { + // MAP Server is always channel 19 + handle = add_maps_sdp(name, final_channel); + } else { + handle = add_sdp_by_uuid(name, uuid, final_channel); + } + + return handle; } +BOOLEAN is_reserved_rfc_channel(const int channel) { + switch(channel) { + case RESERVED_SCN_PBS: + case RESERVED_SCN_OPS: + return TRUE; + } -int get_reserved_rfc_channel (const uint8_t* uuid) -{ - if (IS_UUID(UUID_PBAP_PSE,uuid)) - { - return RESERVED_SCN_PBS; - } - else if (IS_UUID(UUID_OBEX_OBJECT_PUSH,uuid)) - { - return RESERVED_SCN_OPS; - } - return -1; + return FALSE; } -int add_rfc_sdp_rec(const char* name, const uint8_t* uuid, int scn) -{ - int sdp_handle = 0; - if(is_uuid_empty(uuid)) - { - switch(scn) - { - case RESERVED_SCN_PBS: // PBAP Reserved port - uuid = UUID_PBAP_PSE; - break; - case RESERVED_SCN_OPS: - uuid = UUID_OBEX_OBJECT_PUSH; - break; - default: - uuid = UUID_SPP; - break; - } - } - sdp_handle = add_rfc_sdp_by_uuid(name, uuid, scn); - return sdp_handle; +int get_reserved_rfc_channel(const uint8_t *uuid) { + if (UUID_MATCHES(UUID_PBAP_PSE, uuid)) { + return RESERVED_SCN_PBS; + } else if (UUID_MATCHES(UUID_OBEX_OBJECT_PUSH, uuid)) { + return RESERVED_SCN_OPS; + } + + return -1; } -void del_rfc_sdp_rec(int handle) -{ - APPL_TRACE_DEBUG("del_rfc_sdp_rec: handle:0x%x", handle); - if(handle != -1 && handle != 0) - BTA_JvDeleteRecord( handle ); +// Adds an SDP record to the SDP database using the given |name|, |uuid|, and +// |channel|. Note that if the |uuid| is empty, the |uuid| will be set based +// upon the |channel| passed in. +int add_rfc_sdp_rec(const char *name, const uint8_t *uuid, const int channel) { + if (is_uuid_empty(uuid)) { + switch(channel) { + case RESERVED_SCN_PBS: // PBAP Reserved port + uuid = UUID_PBAP_PSE; + break; + + case RESERVED_SCN_OPS: + uuid = UUID_OBEX_OBJECT_PUSH; + break; + + default: + uuid = UUID_SPP; + break; + } + } + + return add_rfc_sdp_by_uuid(name, uuid, channel); } +// Deletes an SDP record with the given |handle|. +void del_rfc_sdp_rec(int handle) { + APPL_TRACE_DEBUG("del_rfc_sdp_rec: handle:0x%x", handle); + + if ((handle != -1) && (handle != 0)) + BTA_JvDeleteRecord(handle); +}