• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "bt_target.h"  // Must be first to define build configuration
22 
23 #include "bta/include/bta_jv_api.h"
24 #include "bta/include/bta_op_api.h"
25 #include "bta/include/utl.h"
26 #include "bta/pb/bta_pbs_int.h"
27 #include "bta/sys/bta_sys.h"
28 #include "btif/include/btif_sock_sdp.h"
29 #include "stack/include/sdp_api.h"
30 #include "stack/include/sdpdefs.h"
31 #include "types/bluetooth/uuid.h"
32 
33 using namespace bluetooth::legacy::stack::sdp;
34 
35 using bluetooth::Uuid;
36 
37 // This module provides an abstraction on top of the lower-level SDP database
38 // code for registration and discovery of various bluetooth sockets.
39 //
40 // This code also provides for on-demand registration of "pre-registered"
41 // services as a backwards compatibility function to third-party applications
42 // expecting a bluez stack.
43 
44 // Realm Character Set -- 0 is ASCII
45 #define BTA_PBS_REALM_CHARSET 0
46 
47 // Specifies whether or not client's user id is required during obex
48 // authentication
49 #define BTA_PBS_USERID_REQ FALSE
50 
51 static const tBTA_PBS_CFG bta_pbs_cfg = {
52     BTA_PBS_REALM_CHARSET,  // realm_charset: Server only
53     BTA_PBS_USERID_REQ,     // userid_req: Server only
54     (BTA_PBS_SUPF_DOWNLOAD | BTA_PBS_SURF_BROWSE),  // supported_features
55     BTA_PBS_REPOSIT_LOCAL,                          // supported_repositories
56 };
57 
58 // object format lookup table
59 #define OBEX_PUSH_NUM_FORMATS 7
60 
61 static const tBTA_OP_FMT bta_ops_obj_fmt[OBEX_PUSH_NUM_FORMATS] = {
62     BTA_OP_VCARD21_FMT, BTA_OP_VCARD30_FMT, BTA_OP_VCAL_FMT, BTA_OP_ICAL_FMT,
63     BTA_OP_VNOTE_FMT,   BTA_OP_VMSG_FMT,    BTA_OP_OTHER_FMT};
64 
65 // TODO(jtgans): Figure out if we actually need this define. This is ifndef
66 // defined in bt_target.h, but nowhere else, so right now, unless something
67 // overrides this before bt_target.h sets it, it will always be bt_target.h's
68 // version.
69 #ifndef BTUI_OPS_FORMATS
70 #define BTUI_OPS_FORMATS                                          \
71   (BTA_OP_VCARD21_MASK | BTA_OP_VCARD30_MASK | BTA_OP_VCAL_MASK | \
72    BTA_OP_ICAL_MASK | BTA_OP_VNOTE_MASK | BTA_OP_VMSG_MASK | BTA_OP_ANY_MASK)
73 #endif
74 
75 #define RESERVED_SCN_PBS 19
76 #define RESERVED_SCN_OPS 12
77 
78 #define UUID_MAX_LENGTH 16
79 
80 #define SPP_PROFILE_VERSION 0x0102
81 
82 // Adds a protocol list and service name (if provided) to an SDP record given by
83 // |sdp_handle|, and marks it as browseable. This is a shortcut for defining a
84 // set of protocols that includes L2CAP, RFCOMM, and optionally OBEX. If
85 // |with_obex| is |true|, then an additional OBEX protocol UUID will be included
86 // at the end of the protocol list.
87 //
88 // Returns true if successful, otherwise false.
create_base_record(const uint32_t sdp_handle,const char * name,const uint16_t channel,const bool with_obex)89 static bool create_base_record(const uint32_t sdp_handle, const char* name,
90                                const uint16_t channel, const bool with_obex) {
91   APPL_TRACE_DEBUG("create_base_record: scn: %d, name: %s, with_obex: %d",
92                    channel, name, with_obex);
93 
94   // Setup the protocol list and add it.
95   tSDP_PROTOCOL_ELEM proto_list[SDP_MAX_LIST_ELEMS];
96   int num_proto_elements = with_obex ? 3 : 2;
97 
98   memset(proto_list, 0, num_proto_elements * sizeof(tSDP_PROTOCOL_ELEM));
99 
100   proto_list[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
101   proto_list[0].num_params = 0;
102   proto_list[1].protocol_uuid = UUID_PROTOCOL_RFCOMM;
103   proto_list[1].num_params = 1;
104   proto_list[1].params[0] = channel;
105 
106   if (with_obex) {
107     proto_list[2].protocol_uuid = UUID_PROTOCOL_OBEX;
108     proto_list[2].num_params = 0;
109   }
110 
111   // Mark the service as browseable.
112   uint16_t list = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
113 
114   const char* stage = "protocol_list";
115   if (!get_legacy_stack_sdp_api()->handle.SDP_AddProtocolList(
116           sdp_handle, num_proto_elements, proto_list))
117     goto error;
118 
119   // Add the name to the SDP record.
120   if (name[0] != '\0') {
121     stage = "service_name";
122     if (!get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
123             sdp_handle, ATTR_ID_SERVICE_NAME, TEXT_STR_DESC_TYPE,
124             (uint32_t)strlen(name), (uint8_t*)name))
125       goto error;
126   }
127 
128   stage = "browseable";
129   if (!get_legacy_stack_sdp_api()->handle.SDP_AddUuidSequence(
130           sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &list))
131     goto error;
132 
133   APPL_TRACE_DEBUG(
134       "create_base_record: successfully created base service "
135       "record, handle: 0x%08x, scn: %d, name: %s, with_obex: %d",
136       sdp_handle, channel, name, with_obex);
137   return true;
138 
139 error:
140   APPL_TRACE_ERROR(
141       "create_base_record: failed to create base service "
142       "record, stage: %s, scn: %d, name: %s, with_obex: %d",
143       stage, channel, name, with_obex);
144   return false;
145 }
146 
147 // Registers a service with the given |name|, |uuid|, and |channel| in the SDP
148 // database as a generic L2CAP RFCOMM protocol, storing its |uuid| as a service
149 // class sequence.
add_sdp_by_uuid(const char * name,const Uuid & uuid,const uint16_t channel)150 static int add_sdp_by_uuid(const char* name, const Uuid& uuid,
151                            const uint16_t channel) {
152   APPL_TRACE_DEBUG("%s: uuid: %s, scn: %d, service_name: %s", __func__,
153                    uuid.ToString().c_str(), channel, name);
154 
155   uint32_t handle = get_legacy_stack_sdp_api()->handle.SDP_CreateRecord();
156   if (handle == 0) {
157     APPL_TRACE_ERROR(
158         "%s: failed to create sdp record, scn: %d, service_name: %s", __func__,
159         channel, name);
160     return 0;
161   }
162 
163   // Convert the |uuid| into a big-endian representation and add it as a
164   // sequence.
165   uint8_t type = UUID_DESC_TYPE;
166   uint8_t type_len = UUID_MAX_LENGTH;
167   uint8_t type_buf[48];
168   // Store the address of type buf in a pointer on the stack, so we can pass
169   // a double pointer to SDP_AddSequence
170   uint8_t* type_buf_ptr = type_buf;
171   uint8_t* tmp = type_buf;
172 
173   // Create the base SDP record.
174   const char* stage = "create_base_record";
175   if (!create_base_record(handle, name, channel, false /* with_obex */))
176     goto error;
177 
178   // Do the conversion to big-endian -- tmp is only used to iterate through the
179   // UUID array in the macro and serves no other purpose as the conversion
180   // macros are not hygenic.
181 
182   { ARRAY_TO_BE_STREAM(tmp, uuid.To128BitBE().data(), UUID_MAX_LENGTH); }
183 
184   stage = "service_class_sequence";
185   if (!get_legacy_stack_sdp_api()->handle.SDP_AddSequence(
186           handle, (uint16_t)ATTR_ID_SERVICE_CLASS_ID_LIST, 1, &type, &type_len,
187           &type_buf_ptr))
188     goto error;
189 
190   APPL_TRACE_DEBUG(
191       "%s: service registered successfully, service_name: %s, handle: 0x%08x",
192       __func__, name, handle);
193 
194   {
195     // Write the custom 128-bit UUID to EIR
196     tBTA_CUSTOM_UUID curr = {uuid, handle};
197     bta_sys_add_cust_uuid(curr);
198   }
199 
200   return handle;
201 
202 error:
203   get_legacy_stack_sdp_api()->handle.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.
add_pbap_sdp(const char * name,const int channel)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 = get_legacy_stack_sdp_api()->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 (!get_legacy_stack_sdp_api()->handle.SDP_AddServiceClassIdList(handle, 1,
233                                                                     &service))
234     goto error;
235 
236   // Add in the phone access descriptor
237   stage = "profile_descriptor_list";
238   if (!get_legacy_stack_sdp_api()->handle.SDP_AddProfileDescriptorList(
239           handle, UUID_SERVCLASS_PHONE_ACCESS, BTA_PBS_DEFAULT_VERSION))
240     goto error;
241 
242   // Set up our supported repositories
243   stage = "supported_repositories";
244   if (!get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
245           handle, ATTR_ID_SUPPORTED_REPOSITORIES, UINT_DESC_TYPE, 1,
246           (uint8_t*)&bta_pbs_cfg.supported_repositories))
247     goto error;
248 
249   // Notify the system that we've got a new service class UUID.
250   bta_sys_add_uuid(UUID_SERVCLASS_PBAP_PSE);
251   APPL_TRACE_DEBUG(
252       "add_pbap_sdp: service registered successfully, "
253       "service_name: %s, handle: 0x%08x",
254       name, handle);
255 
256   return handle;
257 
258 error:
259   get_legacy_stack_sdp_api()->handle.SDP_DeleteRecord(handle);
260   APPL_TRACE_ERROR(
261       "add_pbap_sdp: failed to register PBAP service, stage: %s, "
262       "service_name: %s",
263       stage, name);
264   return 0;
265 }
266 // Registers a service with the given |name| and |channel| as an OBEX Push
267 // protocol.
add_ops_sdp(const char * name,const int channel)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 = get_legacy_stack_sdp_api()->handle.SDP_CreateRecord();
272   if (handle == 0) {
273     APPL_TRACE_ERROR(
274         "add_ops_sdp: failed to create sdp record, "
275         "service_name: %s",
276         name);
277     return 0;
278   }
279 
280   // Add sequence for supported types.
281   uint8_t desc_type[OBEX_PUSH_NUM_FORMATS];
282   uint8_t type_len[OBEX_PUSH_NUM_FORMATS];
283   uint8_t* type_value[OBEX_PUSH_NUM_FORMATS];
284   uint8_t j = 0;
285 
286   uint16_t service = UUID_SERVCLASS_OBEX_OBJECT_PUSH;
287   tBTA_UTL_COD cod;
288 
289   // Create the base SDP record.
290   const char* stage = "create_base_record";
291   if (!create_base_record(handle, name, channel, true /* with_obex */))
292     goto error;
293 
294   // Add service class.
295   stage = "service_class";
296   if (!get_legacy_stack_sdp_api()->handle.SDP_AddServiceClassIdList(handle, 1,
297                                                                     &service))
298     goto error;
299 
300   // Add the OBEX push profile descriptor.
301   stage = "profile_descriptor_list";
302   if (!get_legacy_stack_sdp_api()->handle.SDP_AddProfileDescriptorList(
303           handle, UUID_SERVCLASS_OBEX_OBJECT_PUSH, 0x0100))
304     goto error;
305 
306   for (int i = 0; i < OBEX_PUSH_NUM_FORMATS; i++) {
307     if ((BTUI_OPS_FORMATS >> i) & 1) {
308       type_value[j] = (uint8_t*)(&bta_ops_obj_fmt[i]);
309       desc_type[j] = UINT_DESC_TYPE;
310       type_len[j++] = 1;
311     }
312   }
313 
314   stage = "supported_types";
315   if (!get_legacy_stack_sdp_api()->handle.SDP_AddSequence(
316           handle, (uint16_t)ATTR_ID_SUPPORTED_FORMATS_LIST, j, desc_type,
317           type_len, type_value))
318     goto error;
319 
320   // Set class of device.
321   cod.service = BTM_COD_SERVICE_OBJ_TRANSFER;
322   stage = "class_of_device";
323   if (!utl_set_device_class(&cod, BTA_UTL_SET_COD_SERVICE_CLASS)) goto error;
324 
325   // Notify the system that we've got a new service class UUID.
326   bta_sys_add_uuid(UUID_SERVCLASS_OBEX_OBJECT_PUSH);
327   APPL_TRACE_DEBUG(
328       "ad_maps_sdp: service registered successfully, "
329       "service_name: %s, handle 0x%08x)",
330       name, handle);
331 
332   return handle;
333 
334 error:
335   get_legacy_stack_sdp_api()->handle.SDP_DeleteRecord(handle);
336   APPL_TRACE_ERROR(
337       "add_ops_sdp: failed to register OPS service, "
338       "stage: %s, service_name: %s",
339       stage, name);
340   return 0;
341 }
342 
343 // Registers a service with the given |name| and |channel| as a serial port
344 // profile protocol.
add_spp_sdp(const char * name,const int channel)345 static int add_spp_sdp(const char* name, const int channel) {
346   APPL_TRACE_DEBUG("add_spp_sdp: scn %d, service_name %s", channel, name);
347 
348   int handle = get_legacy_stack_sdp_api()->handle.SDP_CreateRecord();
349   if (handle == 0) {
350     APPL_TRACE_ERROR(
351         "add_spp_sdp: failed to create sdp record, "
352         "service_name: %s",
353         name);
354     return 0;
355   }
356 
357   // Create the base SDP record.
358   const char* stage = "create_base_record";
359   uint16_t service = UUID_SERVCLASS_SERIAL_PORT;
360 
361   if (!create_base_record(handle, name, channel, false /* with_obex */))
362     goto error;
363 
364   stage = "service_class";
365   if (!get_legacy_stack_sdp_api()->handle.SDP_AddServiceClassIdList(handle, 1,
366                                                                     &service))
367     goto error;
368 
369   stage = "profile_descriptor_list";
370   if (!get_legacy_stack_sdp_api()->handle.SDP_AddProfileDescriptorList(
371           handle, UUID_SERVCLASS_SERIAL_PORT, SPP_PROFILE_VERSION))
372     goto error;
373 
374   APPL_TRACE_DEBUG(
375       "add_spp_sdp: service registered successfully, "
376       "service_name: %s, handle 0x%08x)",
377       name, handle);
378 
379   return handle;
380 
381 error:
382   get_legacy_stack_sdp_api()->handle.SDP_DeleteRecord(handle);
383   APPL_TRACE_ERROR(
384       "add_spp_sdp: failed to register SPP service, "
385       "stage: %s, service_name: %s",
386       stage, name);
387   return 0;
388 }
389 
390 // Adds an RFCOMM SDP record for a service with the given |name|, |uuid|, and
391 // |channel|. This function attempts to identify the type of the service based
392 // upon its |uuid|, and will override the |channel| with a reserved channel
393 // number if the |uuid| matches one of the preregistered bluez SDP records.
add_rfc_sdp_by_uuid(const char * name,const Uuid & uuid,const int channel)394 static int add_rfc_sdp_by_uuid(const char* name, const Uuid& uuid,
395                                const int channel) {
396   APPL_TRACE_DEBUG("%s: uuid: %s, service_name: %s, channel: %d", __func__,
397                    uuid.ToString().c_str(), name, channel);
398 
399   /*
400    * Bluetooth Socket API relies on having preregistered bluez sdp records for
401    * HSAG, HFAG, OPP & PBAP that are mapped to rc chan 10, 11,12 & 19. Today
402    * HSAG and HFAG is routed to BRCM AG and are not using BT socket API so for
403    * now we will need to support OPP and PBAP to enable 3rd party developer apps
404    * running on BRCM Android.
405    *
406    * To do this we will check the UUID for the requested service and mimic the
407    * SDP records of bluez upon reception.  See functions add_opush() and
408    * add_pbap() in sdptool.c for actual records.
409    */
410 
411   int final_channel = get_reserved_rfc_channel(uuid);
412 
413   if (final_channel == -1) {
414     final_channel = channel;
415   }
416 
417   int handle = 0;
418 
419   if (uuid == UUID_OBEX_OBJECT_PUSH) {
420     handle = add_ops_sdp(name, final_channel);
421   } else if (uuid == UUID_PBAP_PSE) {
422     // PBAP Server is always channel 19
423     handle = add_pbap_sdp(name, final_channel);
424   } else if (uuid == UUID_SPP) {
425     handle = add_spp_sdp(name, final_channel);
426   } else if (uuid == UUID_MAP_MAS) {
427     // Record created by new SDP create record interface
428     handle = 0xff;
429   } else {
430     handle = add_sdp_by_uuid(name, uuid, final_channel);
431   }
432 
433   return handle;
434 }
435 
is_reserved_rfc_channel(const int channel)436 bool is_reserved_rfc_channel(const int channel) {
437   switch (channel) {
438     case RESERVED_SCN_PBS:
439     case RESERVED_SCN_OPS:
440       return true;
441   }
442 
443   return false;
444 }
445 
get_reserved_rfc_channel(const bluetooth::Uuid & uuid)446 int get_reserved_rfc_channel(const bluetooth::Uuid& uuid) {
447   if (uuid == UUID_PBAP_PSE) {
448     return RESERVED_SCN_PBS;
449   } else if (uuid == UUID_OBEX_OBJECT_PUSH) {
450     return RESERVED_SCN_OPS;
451   }
452 
453   return -1;
454 }
455 
456 // Adds an SDP record to the SDP database using the given |name|, |uuid|, and
457 // |channel|. Note that if the |uuid| is empty, the |uuid| will be set based
458 // upon the |channel| passed in.
add_rfc_sdp_rec(const char * name,Uuid uuid,const int channel)459 int add_rfc_sdp_rec(const char* name, Uuid uuid, const int channel) {
460   if (uuid.IsEmpty()) {
461     switch (channel) {
462       case RESERVED_SCN_PBS:  // PBAP Reserved port
463         uuid = UUID_PBAP_PSE;
464         break;
465 
466       case RESERVED_SCN_OPS:
467         uuid = UUID_OBEX_OBJECT_PUSH;
468         break;
469 
470       default:
471         uuid = UUID_SPP;
472         break;
473     }
474   }
475 
476   return add_rfc_sdp_by_uuid(name, uuid, channel);
477 }
478 
479 // Deletes an SDP record with the given |handle|.
del_rfc_sdp_rec(int handle)480 void del_rfc_sdp_rec(int handle) {
481   APPL_TRACE_DEBUG("del_rfc_sdp_rec: handle:0x%x", handle);
482 
483   if ((handle != -1) && (handle != 0)) {
484     // Remove the custom 128-bit UUID from EIR
485     const tBTA_CUSTOM_UUID curr = {Uuid::kEmpty, (uint32_t)handle};
486     bta_sys_remove_cust_uuid(curr);
487 
488     BTA_JvDeleteRecord(handle);
489   }
490 }
491