Home | History | Annotate | Download | only in src
      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) + 1), (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