Home | History | Annotate | Download | only in src
      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