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 <stdint.h>
     22 #include <stdbool.h>
     23 #include <string.h>
     24 #include <sys/types.h>
     25 #include <sys/socket.h>
     26 #include <errno.h>
     27 
     28 #include <hardware/bluetooth.h>
     29 #include <hardware/bt_sock.h>
     30 
     31 #include "btif_common.h"
     32 #include "btif_util.h"
     33 #include "btif_sock_util.h"
     34 #include "bta_api.h"
     35 #include "bt_target.h"
     36 #include "gki.h"
     37 #include "hcimsgs.h"
     38 #include "sdp_api.h"
     39 #include "btu.h"
     40 #include "btm_api.h"
     41 #include "btm_int.h"
     42 #include "btif_sock_sdp.h"
     43 #include "utl.h"
     44 #include "../bta/pb/bta_pbs_int.h"
     45 #include "../include/bta_op_api.h"
     46 #include "bta_jv_api.h"
     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,
     74   BTA_OP_VCARD30_FMT,
     75   BTA_OP_VCAL_FMT,
     76   BTA_OP_ICAL_FMT,
     77   BTA_OP_VNOTE_FMT,
     78   BTA_OP_VMSG_FMT,
     79   BTA_OP_OTHER_FMT
     80 };
     81 
     82 // TODO(jtgans): Figure out if we actually need this define. This is ifndef
     83 // defined in bt_target.h, but nowhere else, so right now, unless something
     84 // overrides this before bt_target.h sets it, it will always be bt_target.h's
     85 // version.
     86 #ifndef BTUI_OPS_FORMATS
     87 #define BTUI_OPS_FORMATS (BTA_OP_VCARD21_MASK   \
     88                           | BTA_OP_VCARD30_MASK \
     89                           | BTA_OP_VCAL_MASK    \
     90                           | BTA_OP_ICAL_MASK    \
     91                           | BTA_OP_VNOTE_MASK   \
     92                           | BTA_OP_VMSG_MASK    \
     93                           | BTA_OP_ANY_MASK)
     94 #endif
     95 
     96 
     97 
     98 #define RESERVED_SCN_PBS 19
     99 #define RESERVED_SCN_OPS 12
    100 
    101 #define UUID_MAX_LENGTH 16
    102 #define UUID_MATCHES(u1, u2) !memcmp(u1, u2, UUID_MAX_LENGTH)
    103 
    104 // Adds a protocol list and service name (if provided) to an SDP record given by
    105 // |sdp_handle|, and marks it as browseable. This is a shortcut for defining a
    106 // set of protocols that includes L2CAP, RFCOMM, and optionally OBEX. If
    107 // |with_obex| is |TRUE|, then an additional OBEX protocol UUID will be included
    108 // at the end of the protocol list.
    109 //
    110 // Returns TRUE if successful, otherwise FALSE.
    111 static bool create_base_record(const uint32_t sdp_handle, const char *name,
    112                                const uint16_t channel, const bool with_obex) {
    113   APPL_TRACE_DEBUG("create_base_record: scn: %d, name: %s, with_obex: %d",
    114                    channel, name, with_obex);
    115 
    116   // Setup the protocol list and add it.
    117   tSDP_PROTOCOL_ELEM proto_list[SDP_MAX_LIST_ELEMS];
    118   int num_proto_elements = with_obex ? 3 : 2;
    119 
    120   memset(proto_list, 0, num_proto_elements * sizeof(tSDP_PROTOCOL_ELEM));
    121 
    122   proto_list[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
    123   proto_list[0].num_params = 0;
    124   proto_list[1].protocol_uuid = UUID_PROTOCOL_RFCOMM;
    125   proto_list[1].num_params = 1;
    126   proto_list[1].params[0] = channel;
    127 
    128   if (with_obex == TRUE) {
    129     proto_list[2].protocol_uuid = UUID_PROTOCOL_OBEX;
    130     proto_list[2].num_params = 0;
    131   }
    132 
    133   char *stage = "protocol_list";
    134   if (!SDP_AddProtocolList(sdp_handle, num_proto_elements, proto_list))
    135     goto error;
    136 
    137   // Add the name to the SDP record.
    138   if (name[0] != '\0') {
    139     stage = "service_name";
    140     if (!SDP_AddAttribute(sdp_handle, ATTR_ID_SERVICE_NAME,
    141                           TEXT_STR_DESC_TYPE, (uint32_t)(strlen(name) + 1),
    142                           (uint8_t *)name))
    143       goto error;
    144   }
    145 
    146   // Mark the service as browseable.
    147   uint16_t list = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
    148   stage = "browseable";
    149   if (!SDP_AddUuidSequence(sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &list))
    150     goto error;
    151 
    152   APPL_TRACE_DEBUG("create_base_record: successfully created base service "
    153                    "record, handle: 0x%08x, scn: %d, name: %s, with_obex: %d",
    154                    sdp_handle, channel, name, with_obex);
    155   return TRUE;
    156 
    157 error:
    158   APPL_TRACE_ERROR("create_base_record: failed to create base service "
    159                    "record, stage: %s, scn: %d, name: %s, with_obex: %d",
    160                    stage, channel, name, with_obex);
    161   return FALSE;
    162 }
    163 
    164 // Registers a service with the given |name|, |uuid|, and |channel| in the SDP
    165 // database as a generic L2CAP RFCOMM protocol, storing its |uuid| as a service
    166 // class sequence.
    167 static int add_sdp_by_uuid(const char *name,  const uint8_t *uuid,
    168                            const uint16_t channel) {
    169   APPL_TRACE_DEBUG("add_sdp_by_uuid: scn: %d, service_name: %s", channel, name);
    170 
    171   uint32_t handle = SDP_CreateRecord();
    172   if (handle == 0) {
    173     APPL_TRACE_ERROR("add_sdp_by_uuid: failed to create sdp record, "
    174                      "scn: %d, service_name: %s", channel, name);
    175     return 0;
    176   }
    177 
    178   // Create the base SDP record.
    179   char *stage = "create_base_record";
    180   if (!create_base_record(handle, name, channel, FALSE /* with_obex */))
    181     goto error;
    182 
    183   // Convert the |uuid| into a big-endian representation and add it as a
    184   // sequence.
    185   uint8_t type = UUID_DESC_TYPE;
    186   uint8_t type_len = UUID_MAX_LENGTH;
    187   uint8_t type_buf[48];
    188   // Store the address of type buf in a pointer on the stack, so we can pass
    189   // a double pointer to SDP_AddSequence
    190   uint8_t *type_buf_ptr = type_buf;
    191 
    192   // Do the conversion to big-endian -- tmp is only used to iterate through the
    193   // UUID array in the macro and serves no other purpose as the conversion
    194   // macros are not hygenic.
    195   {
    196     uint8_t *tmp = type_buf;
    197     ARRAY_TO_BE_STREAM(tmp, uuid, UUID_MAX_LENGTH);
    198   }
    199 
    200   stage = "service_class_sequence";
    201   if (!SDP_AddSequence(handle, (uint16_t)ATTR_ID_SERVICE_CLASS_ID_LIST,
    202                        1, &type, &type_len, &type_buf_ptr))
    203     goto error;
    204 
    205 
    206   APPL_TRACE_DEBUG("add_sdp_by_uuid: service registered successfully, "
    207                    "service_name: %s, handle: 0x%08x", name, handle);
    208   return handle;
    209 
    210 error:
    211   SDP_DeleteRecord(handle);
    212   APPL_TRACE_ERROR("add_sdp_by_uuid: failed to register service "
    213                    "stage: %s, service_name: %s", stage, name);
    214   return 0;
    215 }
    216 
    217 // Registers a service with the given |name| and |channel| in the SDP
    218 // database as a PBAP protocol.
    219 static int add_pbap_sdp(const char *name, const int channel) {
    220   APPL_TRACE_DEBUG("add_pbap_sdp: scn %d, service_name %s", channel, name);
    221 
    222   uint32_t handle = SDP_CreateRecord();
    223   if (handle == 0) {
    224     APPL_TRACE_ERROR("add_pbap_sdp: failed to create sdp record, "
    225                      "service_name: %s", name);
    226     return 0;
    227   }
    228 
    229   // Create the base SDP record.
    230   char *stage = "create_base_record";
    231   if (!create_base_record(handle, name, channel, TRUE /* with_obex */))
    232     goto error;
    233 
    234   // Add service class
    235   uint16_t service = UUID_SERVCLASS_PBAP_PSE;
    236   stage = "service_class";
    237   if (!SDP_AddServiceClassIdList(handle, 1, &service))
    238     goto error;
    239 
    240   // Add in the phone access descriptor
    241   stage = "profile_descriptor_list";
    242   if (!SDP_AddProfileDescriptorList(handle,
    243                                     UUID_SERVCLASS_PHONE_ACCESS,
    244                                     BTA_PBS_DEFAULT_VERSION))
    245     goto error;
    246 
    247   // Set up our supported repositories
    248   stage = "supported_repositories";
    249   if (!SDP_AddAttribute(handle, ATTR_ID_SUPPORTED_REPOSITORIES, UINT_DESC_TYPE,
    250                         1, (uint8_t*)&bta_pbs_cfg.supported_repositories))
    251     goto error;
    252 
    253   // Notify the system that we've got a new service class UUID.
    254   bta_sys_add_uuid(UUID_SERVCLASS_PBAP_PSE);
    255   APPL_TRACE_DEBUG("add_pbap_sdp: service registered successfully, "
    256                    "service_name: %s, handle: 0x%08x", name, handle);
    257 
    258   return handle;
    259 
    260 error:
    261   SDP_DeleteRecord(handle);
    262   APPL_TRACE_ERROR("add_pbap_sdp: failed to register PBAP service, stage: %s, "
    263                    "service_name: %s", stage, name);
    264   return 0;
    265 }
    266 // Registers a service with the given |name| and |channel| as an OBEX Push
    267 // protocol.
    268 static int add_ops_sdp(const char *name, const int channel) {
    269   APPL_TRACE_DEBUG("add_ops_sdp: scn %d, service_name %s", channel, name);
    270 
    271   uint32_t handle = SDP_CreateRecord();
    272   if (handle == 0) {
    273     APPL_TRACE_ERROR("add_ops_sdp: failed to create sdp record, "
    274                      "service_name: %s", name);
    275     return 0;
    276   }
    277 
    278   // Create the base SDP record.
    279   char *stage = "create_base_record";
    280   if (!create_base_record(handle, name, channel, TRUE /* with_obex */))
    281     goto error;
    282 
    283   // Add service class.
    284   stage = "service_class";
    285   uint16_t service = UUID_SERVCLASS_OBEX_OBJECT_PUSH;
    286   if (!SDP_AddServiceClassIdList(handle, 1, &service))
    287     goto error;
    288 
    289   // Add the OBEX push profile descriptor.
    290   stage = "profile_descriptor_list";
    291   if (!SDP_AddProfileDescriptorList(handle, UUID_SERVCLASS_OBEX_OBJECT_PUSH,
    292                                     0x0100))
    293     goto error;
    294 
    295   // Add sequence for supported types.
    296   uint8_t desc_type[OBEX_PUSH_NUM_FORMATS];
    297   uint8_t type_len[OBEX_PUSH_NUM_FORMATS];
    298   uint8_t *type_value[OBEX_PUSH_NUM_FORMATS];
    299   uint8_t j = 0;
    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,
    311                        j, desc_type, type_len, type_value))
    312     goto error;
    313 
    314   // Set class of device.
    315   tBTA_UTL_COD cod;
    316   cod.service = BTM_COD_SERVICE_OBJ_TRANSFER;
    317   stage = "class_of_device";
    318   if (!utl_set_device_class(&cod, BTA_UTL_SET_COD_SERVICE_CLASS))
    319     goto error;
    320 
    321   // Notify the system that we've got a new service class UUID.
    322   bta_sys_add_uuid(UUID_SERVCLASS_OBEX_OBJECT_PUSH);
    323   APPL_TRACE_DEBUG("ad_maps_sdp: service registered successfully, "
    324                    "service_name: %s, handle 0x%08x)", name, handle);
    325 
    326   return handle;
    327 
    328 error:
    329   SDP_DeleteRecord(handle);
    330   APPL_TRACE_ERROR("add_ops_sdp: failed to register OPS service, "
    331                    "stage: %s, service_name: %s", stage, name);
    332   return 0;
    333 }
    334 
    335 // Registers a service with the given |name| and |channel| as a serial port
    336 // profile protocol.
    337 static int add_spp_sdp(const char *name, const int channel) {
    338   APPL_TRACE_DEBUG("add_spp_sdp: scn %d, service_name %s", channel, name);
    339 
    340   int handle = SDP_CreateRecord();
    341   if (handle == 0) {
    342     APPL_TRACE_ERROR("add_spp_sdp: failed to create sdp record, "
    343                      "service_name: %s", name);
    344     return 0;
    345   }
    346 
    347   // Create the base SDP record.
    348   char *stage = "create_base_record";
    349   if (!create_base_record(handle, name, channel, FALSE /* with_obex */))
    350     goto error;
    351 
    352   uint16_t service = UUID_SERVCLASS_SERIAL_PORT;
    353   stage = "service_class";
    354   if (!SDP_AddServiceClassIdList(handle, 1, &service))
    355     goto error;
    356 
    357   APPL_TRACE_DEBUG("add_spp_sdp: service registered successfully, "
    358                    "service_name: %s, handle 0x%08x)", name, handle);
    359 
    360   return handle;
    361 
    362 error:
    363   SDP_DeleteRecord(handle);
    364   APPL_TRACE_ERROR("add_spp_sdp: failed to register SPP service, "
    365                    "stage: %s, service_name: %s", stage, name);
    366   return 0;
    367 }
    368 
    369 // Adds an RFCOMM SDP record for a service with the given |name|, |uuid|, and
    370 // |channel|. This function attempts to identify the type of the service based
    371 // upon its |uuid|, and will override the |channel| with a reserved channel
    372 // number if the |uuid| matches one of the preregistered bluez SDP records.
    373 static int add_rfc_sdp_by_uuid(const char *name, const uint8_t *uuid,
    374                                const int channel) {
    375   APPL_TRACE_DEBUG("add_rfc_sdp_by_uuid: service_name: %s, channel: %d", name,
    376                    channel);
    377 
    378   /*
    379    * Bluetooth Socket API relies on having preregistered bluez sdp records for
    380    * HSAG, HFAG, OPP & PBAP that are mapped to rc chan 10, 11,12 & 19. Today
    381    * HSAG and HFAG is routed to BRCM AG and are not using BT socket API so for
    382    * now we will need to support OPP and PBAP to enable 3rd party developer apps
    383    * running on BRCM Android.
    384    *
    385    * To do this we will check the UUID for the requested service and mimic the
    386    * SDP records of bluez upon reception.  See functions add_opush() and
    387    * add_pbap() in sdptool.c for actual records.
    388    */
    389 
    390   int final_channel = get_reserved_rfc_channel(uuid);
    391 
    392   if (final_channel == -1) {
    393     final_channel = channel;
    394   }
    395 
    396   int handle = 0;
    397 
    398   if (UUID_MATCHES(UUID_OBEX_OBJECT_PUSH, uuid)) {
    399     handle = add_ops_sdp(name, final_channel);
    400   } else if (UUID_MATCHES(UUID_PBAP_PSE,uuid)) {
    401     // PBAP Server is always channel 19
    402     handle = add_pbap_sdp(name, final_channel);
    403   } else if (UUID_MATCHES(UUID_SPP, uuid)) {
    404     handle = add_spp_sdp(name, final_channel);
    405   } else if (UUID_MATCHES(UUID_MAP_MAS,uuid)) {
    406     // Record created by new SDP create record interface
    407     handle = 0xff;
    408   } else {
    409     handle = add_sdp_by_uuid(name, uuid, final_channel);
    410   }
    411 
    412   return handle;
    413 }
    414 
    415 bool is_reserved_rfc_channel(const int channel) {
    416   switch(channel) {
    417     case RESERVED_SCN_PBS:
    418     case RESERVED_SCN_OPS:
    419       return TRUE;
    420   }
    421 
    422   return FALSE;
    423 }
    424 
    425 int get_reserved_rfc_channel(const uint8_t *uuid) {
    426   if (UUID_MATCHES(UUID_PBAP_PSE, uuid)) {
    427     return RESERVED_SCN_PBS;
    428   } else if (UUID_MATCHES(UUID_OBEX_OBJECT_PUSH, uuid)) {
    429     return RESERVED_SCN_OPS;
    430   }
    431 
    432   return -1;
    433 }
    434 
    435 // Adds an SDP record to the SDP database using the given |name|, |uuid|, and
    436 // |channel|. Note that if the |uuid| is empty, the |uuid| will be set based
    437 // upon the |channel| passed in.
    438 int add_rfc_sdp_rec(const char *name, const uint8_t *uuid, const int channel) {
    439   if (is_uuid_empty(uuid)) {
    440     switch(channel) {
    441       case RESERVED_SCN_PBS: // PBAP Reserved port
    442         uuid = UUID_PBAP_PSE;
    443         break;
    444 
    445       case RESERVED_SCN_OPS:
    446         uuid = UUID_OBEX_OBJECT_PUSH;
    447         break;
    448 
    449       default:
    450         uuid = UUID_SPP;
    451         break;
    452     }
    453   }
    454 
    455   return add_rfc_sdp_by_uuid(name, uuid, channel);
    456 }
    457 
    458 // Deletes an SDP record with the given |handle|.
    459 void del_rfc_sdp_rec(int handle) {
    460   APPL_TRACE_DEBUG("del_rfc_sdp_rec: handle:0x%x", handle);
    461 
    462   if ((handle != -1) && (handle != 0))
    463     BTA_JvDeleteRecord(handle);
    464 }
    465