• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
2  *
3  * Copyright 2014 Samsung System LSI
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 /*******************************************************************************
20  *
21  *  Filename:      btif_sdp_server.cc
22  *  Description:   SDP server Bluetooth Interface to create and remove SDP
23  *                 records.
24  *                 To be used in combination with the RFCOMM/L2CAP(LE) sockets.
25  *
26  *
27  ******************************************************************************/
28 
29 #define LOG_TAG "bt_btif_sdp_server"
30 
31 #include <hardware/bluetooth.h>
32 #include <hardware/bt_sdp.h>
33 #include <pthread.h>
34 #include <stdlib.h>
35 #include <string.h>
36 
37 #include <mutex>
38 
39 #include "bta_sdp_api.h"
40 #include "bta_sys.h"
41 #include "btif_common.h"
42 #include "btif_sock_util.h"
43 #include "btif_util.h"
44 #include "osi/include/allocator.h"
45 #include "types/bluetooth/uuid.h"
46 #include "utl.h"
47 
48 // Protects the sdp_slots array from concurrent access.
49 static std::recursive_mutex sdp_lock;
50 
51 /**
52  * The need for a state variable have been reduced to two states.
53  * The remaining state control is handled by program flow
54  */
55 typedef enum {
56   SDP_RECORD_FREE = 0,
57   SDP_RECORD_ALLOCED,
58 } sdp_state_t;
59 
60 typedef struct {
61   sdp_state_t state;
62   int sdp_handle;
63   bluetooth_sdp_record* record_data;
64 } sdp_slot_t;
65 
66 #define MAX_SDP_SLOTS 128
67 static sdp_slot_t sdp_slots[MAX_SDP_SLOTS];
68 
69 /*****************************************************************************
70  * LOCAL Functions
71  *****************************************************************************/
72 static int add_maps_sdp(const bluetooth_sdp_mas_record* rec);
73 static int add_mapc_sdp(const bluetooth_sdp_mns_record* rec);
74 static int add_pbapc_sdp(const bluetooth_sdp_pce_record* rec);
75 static int add_pbaps_sdp(const bluetooth_sdp_pse_record* rec);
76 static int add_opps_sdp(const bluetooth_sdp_ops_record* rec);
77 static int add_saps_sdp(const bluetooth_sdp_sap_record* rec);
78 bt_status_t remove_sdp_record(int record_id);
79 static int free_sdp_slot(int id);
80 
81 /******************************************************************************
82  * WARNING: Functions below are not called in BTU context.
83  * Introduced to make it possible to create SDP records from JAVA with both a
84  * RFCOMM channel and a L2CAP PSM.
85  * Overall architecture:
86  *  1) JAVA calls createRecord() which returns a pseudo ID which at a later
87  *     point will be linked to a specific SDP handle.
88  *  2) createRecord() requests the BTU task(thread) to call a callback in SDP
89  *     which creates the actual record, and updates the ID<->SDPHandle map
90  *     based on the ID beeing passed to BTA as user_data.
91  *****************************************************************************/
92 
init_sdp_slots()93 static void init_sdp_slots() {
94   int i;
95   memset(sdp_slots, 0, sizeof(sdp_slot_t) * MAX_SDP_SLOTS);
96   /* if SDP_RECORD_FREE is zero - no need to set the value */
97   if (SDP_RECORD_FREE != 0) {
98     for (i = 0; i < MAX_SDP_SLOTS; i++) {
99       sdp_slots[i].state = SDP_RECORD_FREE;
100     }
101   }
102 }
103 
sdp_server_init()104 bt_status_t sdp_server_init() {
105   BTIF_TRACE_DEBUG("Sdp Server %s", __func__);
106   init_sdp_slots();
107   return BT_STATUS_SUCCESS;
108 }
109 
sdp_server_cleanup()110 void sdp_server_cleanup() {
111   BTIF_TRACE_DEBUG("Sdp Server %s", __func__);
112   std::unique_lock<std::recursive_mutex> lock(sdp_lock);
113   int i;
114   for (i = 0; i < MAX_SDP_SLOTS; i++) {
115     /*remove_sdp_record(i); we cannot send messages to the other threads, since
116     * they might
117     *                       have been shut down already. Just do local cleanup.
118     */
119     free_sdp_slot(i);
120   }
121 }
122 
get_sdp_records_size(bluetooth_sdp_record * in_record,int count)123 int get_sdp_records_size(bluetooth_sdp_record* in_record, int count) {
124   bluetooth_sdp_record* record = in_record;
125   int records_size = 0;
126   int i;
127   for (i = 0; i < count; i++) {
128     record = &in_record[i];
129     records_size += sizeof(bluetooth_sdp_record);
130     records_size += record->hdr.service_name_length;
131     if (record->hdr.service_name_length > 0) {
132       records_size++; /* + '\0' termination of string */
133     }
134     records_size += record->hdr.user1_ptr_len;
135     records_size += record->hdr.user2_ptr_len;
136   }
137   return records_size;
138 }
139 
140 /* Deep copy all content of in_records into out_records.
141  * out_records must point to a chunk of memory large enough to contain all
142  * the data. Use getSdpRecordsSize() to calculate the needed size. */
copy_sdp_records(bluetooth_sdp_record * in_records,bluetooth_sdp_record * out_records,int count)143 void copy_sdp_records(bluetooth_sdp_record* in_records,
144                       bluetooth_sdp_record* out_records, int count) {
145   int i;
146   bluetooth_sdp_record* in_record;
147   bluetooth_sdp_record* out_record;
148   char* free_ptr =
149       (char*)(&out_records[count]); /* set pointer to after the last entry */
150 
151   for (i = 0; i < count; i++) {
152     in_record = &in_records[i];
153     out_record = &out_records[i];
154     *out_record = *in_record;
155 
156     if (in_record->hdr.service_name == NULL ||
157         in_record->hdr.service_name_length == 0) {
158       out_record->hdr.service_name = NULL;
159       out_record->hdr.service_name_length = 0;
160     } else {
161       out_record->hdr.service_name = free_ptr;  // Update service_name pointer
162       // Copy string
163       memcpy(free_ptr, in_record->hdr.service_name,
164              in_record->hdr.service_name_length);
165       free_ptr += in_record->hdr.service_name_length;
166       *(free_ptr) = '\0';  // Set '\0' termination of string
167       free_ptr++;
168     }
169     if (in_record->hdr.user1_ptr != NULL) {
170       out_record->hdr.user1_ptr = (uint8_t*)free_ptr;  // Update pointer
171       memcpy(free_ptr, in_record->hdr.user1_ptr,
172              in_record->hdr.user1_ptr_len);  // Copy content
173       free_ptr += in_record->hdr.user1_ptr_len;
174     }
175     if (in_record->hdr.user2_ptr != NULL) {
176       out_record->hdr.user2_ptr = (uint8_t*)free_ptr;  // Update pointer
177       memcpy(free_ptr, in_record->hdr.user2_ptr,
178              in_record->hdr.user2_ptr_len);  // Copy content
179       free_ptr += in_record->hdr.user2_ptr_len;
180     }
181   }
182   return;
183 }
184 
185 /* Reserve a slot in sdp_slots, copy data and set a reference to the copy.
186  * The record_data will contain both the record and any data pointed to by
187  * the record.
188  * Currently this covers:
189  *   service_name string,
190  *   user1_ptr and
191  *   user2_ptr. */
alloc_sdp_slot(bluetooth_sdp_record * in_record)192 static int alloc_sdp_slot(bluetooth_sdp_record* in_record) {
193   int record_size = get_sdp_records_size(in_record, 1);
194   /* We are optimists here, and preallocate the record.
195    * This is to reduce the time we hold the sdp_lock. */
196   bluetooth_sdp_record* record = (bluetooth_sdp_record*)osi_malloc(record_size);
197 
198   copy_sdp_records(in_record, record, 1);
199   {
200     std::unique_lock<std::recursive_mutex> lock(sdp_lock);
201     for (int i = 0; i < MAX_SDP_SLOTS; i++) {
202       if (sdp_slots[i].state == SDP_RECORD_FREE) {
203         sdp_slots[i].state = SDP_RECORD_ALLOCED;
204         sdp_slots[i].record_data = record;
205         return i;
206       }
207     }
208   }
209   APPL_TRACE_ERROR("%s() failed - no more free slots!", __func__);
210   /* Rearly the optimist is too optimistic, and cleanup is needed...*/
211   osi_free(record);
212   return -1;
213 }
214 
free_sdp_slot(int id)215 static int free_sdp_slot(int id) {
216   int handle = -1;
217   bluetooth_sdp_record* record = NULL;
218   if (id < 0 || id >= MAX_SDP_SLOTS) {
219     APPL_TRACE_ERROR("%s() failed - id %d is invalid", __func__, id);
220     return handle;
221   }
222 
223   {
224     std::unique_lock<std::recursive_mutex> lock(sdp_lock);
225     handle = sdp_slots[id].sdp_handle;
226     sdp_slots[id].sdp_handle = 0;
227     if (sdp_slots[id].state != SDP_RECORD_FREE) {
228       /* safe a copy of the pointer, and free after unlock() */
229       record = sdp_slots[id].record_data;
230     }
231     sdp_slots[id].state = SDP_RECORD_FREE;
232   }
233 
234   if (record != NULL) {
235     osi_free(record);
236   } else {
237     // Record have already been freed
238     handle = -1;
239   }
240   return handle;
241 }
242 
243 /***
244  * Use this to get a reference to a SDP slot AND change the state to
245  * SDP_RECORD_CREATE_INITIATED.
246  */
start_create_sdp(int id)247 static const sdp_slot_t* start_create_sdp(int id) {
248   if (id >= MAX_SDP_SLOTS) {
249     APPL_TRACE_ERROR("%s() failed - id %d is invalid", __func__, id);
250     return NULL;
251   }
252 
253   std::unique_lock<std::recursive_mutex> lock(sdp_lock);
254   if (sdp_slots[id].state != SDP_RECORD_ALLOCED) {
255     /* The record have been removed before this event occurred - e.g. deinit */
256     APPL_TRACE_ERROR(
257         "%s() failed - state for id %d is "
258         "sdp_slots[id].state = %d expected %d",
259         __func__, id, sdp_slots[id].state, SDP_RECORD_ALLOCED);
260     return NULL;
261   }
262 
263   return &(sdp_slots[id]);
264 }
265 
set_sdp_handle(int id,int handle)266 static void set_sdp_handle(int id, int handle) {
267   std::unique_lock<std::recursive_mutex> lock(sdp_lock);
268   sdp_slots[id].sdp_handle = handle;
269 }
270 
create_sdp_record(bluetooth_sdp_record * record,int * record_handle)271 bt_status_t create_sdp_record(bluetooth_sdp_record* record,
272                               int* record_handle) {
273   int handle;
274 
275   handle = alloc_sdp_slot(record);
276   BTIF_TRACE_DEBUG("%s() handle = 0x%08x", __func__, handle);
277 
278   if (handle < 0) return BT_STATUS_FAIL;
279 
280   BTA_SdpCreateRecordByUser(INT_TO_PTR(handle));
281 
282   *record_handle = handle;
283 
284   return BT_STATUS_SUCCESS;
285 }
286 
remove_sdp_record(int record_id)287 bt_status_t remove_sdp_record(int record_id) {
288   int handle;
289 
290   if (record_id >= MAX_SDP_SLOTS) {
291     return BT_STATUS_PARM_INVALID;
292   }
293 
294   bluetooth_sdp_record* record;
295   bluetooth_sdp_types sdp_type = SDP_TYPE_RAW;
296   {
297     std::unique_lock<std::recursive_mutex> lock(sdp_lock);
298     record = sdp_slots[record_id].record_data;
299     if (record != NULL) {
300       sdp_type = record->hdr.type;
301     }
302   }
303   tBTA_SERVICE_ID service_id = -1;
304   switch (sdp_type) {
305     case SDP_TYPE_MAP_MAS:
306       service_id = BTA_MAP_SERVICE_ID;
307       break;
308     case SDP_TYPE_MAP_MNS:
309       service_id = BTA_MN_SERVICE_ID;
310       break;
311     case SDP_TYPE_PBAP_PSE:
312       service_id = BTA_PBAP_SERVICE_ID;
313       break;
314     case SDP_TYPE_PBAP_PCE:
315       service_id = BTA_PCE_SERVICE_ID;
316       break;
317     default:
318       /* other enumeration values were not enabled in {@link on_create_record_event} */
319       break;
320   }
321   if (service_id > 0) {
322     // {@link btif_disable_service} sets the mask {@link btif_enabled_services}.
323     btif_disable_service(service_id);
324   }
325 
326   /* Get the Record handle, and free the slot */
327   handle = free_sdp_slot(record_id);
328   BTIF_TRACE_DEBUG("Sdp Server %s id=%d to handle=0x%08x", __func__, record_id,
329                    handle);
330 
331   /* Pass the actual record handle */
332   if (handle > 0) {
333     BTA_SdpRemoveRecordByUser(INT_TO_PTR(handle));
334     return BT_STATUS_SUCCESS;
335   }
336   BTIF_TRACE_DEBUG("Sdp Server %s - record already removed - or never created",
337                    __func__);
338   return BT_STATUS_FAIL;
339 }
340 
341 /******************************************************************************
342  * CALLBACK FUNCTIONS
343  * Called in BTA context to create/remove SDP records.
344  ******************************************************************************/
345 
on_create_record_event(int id)346 void on_create_record_event(int id) {
347   /*
348    * 1) Fetch the record pointer, and change its state?
349    * 2) switch on the type to create the correct record
350    * 3) Update state on completion
351    * 4) What to do at fail?
352    * */
353   BTIF_TRACE_DEBUG("Sdp Server %s", __func__);
354   const sdp_slot_t* sdp_slot = start_create_sdp(id);
355   tBTA_SERVICE_ID service_id = -1;
356   bluetooth_sdp_record* record;
357   /* In the case we are shutting down, sdp_slot is NULL */
358   if (sdp_slot != nullptr && (record = sdp_slot->record_data) != nullptr) {
359     int handle = -1;
360     switch (record->hdr.type) {
361       case SDP_TYPE_MAP_MAS:
362         handle = add_maps_sdp(&record->mas);
363         service_id = BTA_MAP_SERVICE_ID;
364         break;
365       case SDP_TYPE_MAP_MNS:
366         handle = add_mapc_sdp(&record->mns);
367         service_id = BTA_MN_SERVICE_ID;
368         break;
369       case SDP_TYPE_PBAP_PSE:
370         handle = add_pbaps_sdp(&record->pse);
371         service_id = BTA_PBAP_SERVICE_ID;
372         break;
373       case SDP_TYPE_OPP_SERVER:
374         handle = add_opps_sdp(&record->ops);
375         break;
376       case SDP_TYPE_SAP_SERVER:
377         handle = add_saps_sdp(&record->sap);
378         break;
379       case SDP_TYPE_PBAP_PCE:
380         handle = add_pbapc_sdp(&record->pce);
381         service_id = BTA_PCE_SERVICE_ID;
382         break;
383       default:
384         BTIF_TRACE_DEBUG("Record type %d is not supported", record->hdr.type);
385         break;
386     }
387     if (handle != -1) {
388       set_sdp_handle(id, handle);
389       if (service_id > 0) {
390         /**
391          * {@link btif_enable_service} calls {@link btif_dm_enable_service}, which calls {@link
392          * btif_in_execute_service_request}.
393          *     - {@link btif_enable_service} sets the mask {@link btif_enabled_services}.
394          *     - {@link btif_dm_enable_service} invokes the java callback to return uuids based
395          *       on the enabled services mask.
396          *     - {@link btif_in_execute_service_request} gates the java callback in {@link
397          *       btif_dm_enable_service}.
398          */
399         btif_enable_service(service_id);
400       }
401     }
402   }
403 }
404 
on_remove_record_event(int handle)405 void on_remove_record_event(int handle) {
406   BTIF_TRACE_DEBUG("Sdp Server %s", __func__);
407 
408   // User data carries the actual SDP handle, not the ID.
409   if (handle != -1 && handle != 0) {
410     bool result;
411     result = SDP_DeleteRecord(handle);
412     if (!result) {
413       BTIF_TRACE_ERROR("  Unable to remove handle 0x%08x", handle);
414     }
415   }
416 }
417 
418 /****
419  * Below the actual functions accessing BTA context data - hence only call from
420  * BTA context!
421  */
422 
423 /* Create a MAP MAS SDP record based on information stored in a
424  * bluetooth_sdp_mas_record */
add_maps_sdp(const bluetooth_sdp_mas_record * rec)425 static int add_maps_sdp(const bluetooth_sdp_mas_record* rec) {
426   tSDP_PROTOCOL_ELEM protoList[3];
427   uint16_t service = UUID_SERVCLASS_MESSAGE_ACCESS;
428   uint16_t browse = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
429   bool status = true;
430   uint32_t sdp_handle = 0;
431   uint8_t temp[4];
432   uint8_t* p_temp = temp;
433 
434   sdp_handle = SDP_CreateRecord();
435   if (sdp_handle == 0) {
436     LOG_ERROR("Unable to register MAPS Service");
437     return sdp_handle;
438   }
439 
440   /* add service class */
441   status &= SDP_AddServiceClassIdList(sdp_handle, 1, &service);
442   memset(protoList, 0, 3 * sizeof(tSDP_PROTOCOL_ELEM));
443 
444   /* add protocol list, including RFCOMM scn */
445   protoList[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
446   protoList[0].num_params = 0;
447   protoList[1].protocol_uuid = UUID_PROTOCOL_RFCOMM;
448   protoList[1].num_params = 1;
449   protoList[1].params[0] = rec->hdr.rfcomm_channel_number;
450   protoList[2].protocol_uuid = UUID_PROTOCOL_OBEX;
451   protoList[2].num_params = 0;
452   status &= SDP_AddProtocolList(sdp_handle, 3, protoList);
453 
454   /* Add a name entry */
455   status &= SDP_AddAttribute(sdp_handle, (uint16_t)ATTR_ID_SERVICE_NAME,
456                              (uint8_t)TEXT_STR_DESC_TYPE,
457                              (uint32_t)(rec->hdr.service_name_length + 1),
458                              (uint8_t*)rec->hdr.service_name);
459 
460   /* Add in the Bluetooth Profile Descriptor List */
461   status &= SDP_AddProfileDescriptorList(sdp_handle, UUID_SERVCLASS_MAP_PROFILE,
462                                          rec->hdr.profile_version);
463 
464   /* Add MAS instance ID */
465   status &=
466       SDP_AddAttribute(sdp_handle, ATTR_ID_MAS_INSTANCE_ID, UINT_DESC_TYPE,
467                        (uint32_t)1, (uint8_t*)&rec->mas_instance_id);
468 
469   /* Add supported message types */
470   status &=
471       SDP_AddAttribute(sdp_handle, ATTR_ID_SUPPORTED_MSG_TYPE, UINT_DESC_TYPE,
472                        (uint32_t)1, (uint8_t*)&rec->supported_message_types);
473 
474   /* Add supported feature */
475   UINT32_TO_BE_STREAM(p_temp, rec->supported_features);
476   status &= SDP_AddAttribute(sdp_handle, ATTR_ID_MAP_SUPPORTED_FEATURES,
477                              UINT_DESC_TYPE, (uint32_t)4, temp);
478 
479   /* Add the L2CAP PSM if present */
480   if (rec->hdr.l2cap_psm != -1) {
481     p_temp = temp;  // The macro modifies p_temp, hence rewind.
482     UINT16_TO_BE_STREAM(p_temp, rec->hdr.l2cap_psm);
483     status &= SDP_AddAttribute(sdp_handle, ATTR_ID_GOEP_L2CAP_PSM,
484                                UINT_DESC_TYPE, (uint32_t)2, temp);
485   }
486 
487   /* Make the service browseable */
488   status &=
489       SDP_AddUuidSequence(sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse);
490 
491   if (!status) {
492     SDP_DeleteRecord(sdp_handle);
493     sdp_handle = 0;
494     APPL_TRACE_ERROR("%s() FAILED", __func__);
495   } else {
496     bta_sys_add_uuid(service); /* UUID_SERVCLASS_MESSAGE_ACCESS */
497     APPL_TRACE_DEBUG("%s():  SDP Registered (handle 0x%08x)", __func__,
498                      sdp_handle);
499   }
500   return sdp_handle;
501 }
502 
503 /* Create a MAP MNS SDP record based on information stored in a
504  * bluetooth_sdp_mns_record */
add_mapc_sdp(const bluetooth_sdp_mns_record * rec)505 static int add_mapc_sdp(const bluetooth_sdp_mns_record* rec) {
506   tSDP_PROTOCOL_ELEM protoList[3];
507   uint16_t service = UUID_SERVCLASS_MESSAGE_NOTIFICATION;
508   uint16_t browse = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
509   bool status = true;
510   uint32_t sdp_handle = 0;
511   uint8_t temp[4];
512   uint8_t* p_temp = temp;
513 
514   sdp_handle = SDP_CreateRecord();
515   if (sdp_handle == 0) {
516     LOG_ERROR("Unable to register MAP Notification Service");
517     return sdp_handle;
518   }
519 
520   /* add service class */
521   status &= SDP_AddServiceClassIdList(sdp_handle, 1, &service);
522   memset(protoList, 0, 3 * sizeof(tSDP_PROTOCOL_ELEM));
523 
524   /* add protocol list, including RFCOMM scn */
525   protoList[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
526   protoList[0].num_params = 0;
527   protoList[1].protocol_uuid = UUID_PROTOCOL_RFCOMM;
528   protoList[1].num_params = 1;
529   protoList[1].params[0] = rec->hdr.rfcomm_channel_number;
530   protoList[2].protocol_uuid = UUID_PROTOCOL_OBEX;
531   protoList[2].num_params = 0;
532   status &= SDP_AddProtocolList(sdp_handle, 3, protoList);
533 
534   /* Add a name entry */
535   status &= SDP_AddAttribute(sdp_handle, (uint16_t)ATTR_ID_SERVICE_NAME,
536                              (uint8_t)TEXT_STR_DESC_TYPE,
537                              (uint32_t)(rec->hdr.service_name_length + 1),
538                              (uint8_t*)rec->hdr.service_name);
539 
540   /* Add in the Bluetooth Profile Descriptor List */
541   status &= SDP_AddProfileDescriptorList(sdp_handle, UUID_SERVCLASS_MAP_PROFILE,
542                                          rec->hdr.profile_version);
543 
544   /* Add supported feature */
545   UINT32_TO_BE_STREAM(p_temp, rec->supported_features);
546   status &= SDP_AddAttribute(sdp_handle, ATTR_ID_MAP_SUPPORTED_FEATURES,
547                              UINT_DESC_TYPE, (uint32_t)4, temp);
548 
549   /* Add the L2CAP PSM if present */
550   if (rec->hdr.l2cap_psm != -1) {
551     p_temp = temp;  // The macro modifies p_temp, hence rewind.
552     UINT16_TO_BE_STREAM(p_temp, rec->hdr.l2cap_psm);
553     status &= SDP_AddAttribute(sdp_handle, ATTR_ID_GOEP_L2CAP_PSM,
554                                UINT_DESC_TYPE, (uint32_t)2, temp);
555   }
556 
557   /* Make the service browseable */
558   status &=
559       SDP_AddUuidSequence(sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse);
560 
561   if (!status) {
562     SDP_DeleteRecord(sdp_handle);
563     sdp_handle = 0;
564     APPL_TRACE_ERROR("%s() FAILED", __func__);
565   } else {
566     bta_sys_add_uuid(service); /* UUID_SERVCLASS_MESSAGE_ACCESS */
567     APPL_TRACE_DEBUG("%s():  SDP Registered (handle 0x%08x)", __func__,
568                      sdp_handle);
569   }
570   return sdp_handle;
571 }
572 
573 /* Create a PBAP Client SDP record based on information stored in a
574  * bluetooth_sdp_pce_record */
add_pbapc_sdp(const bluetooth_sdp_pce_record * rec)575 static int add_pbapc_sdp(const bluetooth_sdp_pce_record* rec) {
576   uint16_t service = UUID_SERVCLASS_PBAP_PCE;
577   uint16_t browse = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
578   bool status = true;
579   uint32_t sdp_handle = 0;
580 
581   sdp_handle = SDP_CreateRecord();
582   if (sdp_handle == 0) {
583     LOG_ERROR("Unable to register PBAP Client Service");
584     return sdp_handle;
585   }
586 
587   status &= SDP_AddServiceClassIdList(sdp_handle, 1, &service);
588 
589   /* Add a name entry */
590   status &= SDP_AddAttribute(sdp_handle, (uint16_t)ATTR_ID_SERVICE_NAME,
591                              (uint8_t)TEXT_STR_DESC_TYPE,
592                              (uint32_t)(rec->hdr.service_name_length + 1),
593                              (uint8_t*)rec->hdr.service_name);
594 
595   /* Add in the Bluetooth Profile Descriptor List */
596   status &= SDP_AddProfileDescriptorList(
597       sdp_handle, UUID_SERVCLASS_PHONE_ACCESS, rec->hdr.profile_version);
598 
599   /* Make the service browseable */
600   status &=
601       SDP_AddUuidSequence(sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse);
602 
603   if (!status) {
604     SDP_DeleteRecord(sdp_handle);
605     sdp_handle = 0;
606     APPL_TRACE_ERROR("%s() FAILED", __func__);
607     return sdp_handle;
608   }
609   bta_sys_add_uuid(service); /* UUID_SERVCLASS_PBAP_PCE */
610   APPL_TRACE_DEBUG("%s():  SDP Registered (handle 0x%08x)", __func__,
611                    sdp_handle);
612   return sdp_handle;
613 }
614 
615 /* Create a PBAP Server SDP record based on information stored in a
616  * bluetooth_sdp_pse_record */
add_pbaps_sdp(const bluetooth_sdp_pse_record * rec)617 static int add_pbaps_sdp(const bluetooth_sdp_pse_record* rec) {
618   tSDP_PROTOCOL_ELEM protoList[3];
619   uint16_t service = UUID_SERVCLASS_PBAP_PSE;
620   uint16_t browse = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
621   bool status = true;
622   uint32_t sdp_handle = 0;
623   uint8_t temp[4];
624   uint8_t* p_temp = temp;
625 
626   sdp_handle = SDP_CreateRecord();
627   if (sdp_handle == 0) {
628     LOG_ERROR("Unable to register PBAP Server Service");
629     return sdp_handle;
630   }
631 
632   /* add service class */
633   status &= SDP_AddServiceClassIdList(sdp_handle, 1, &service);
634   memset(protoList, 0, 3 * sizeof(tSDP_PROTOCOL_ELEM));
635 
636   /* add protocol list, including RFCOMM scn */
637   protoList[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
638   protoList[0].num_params = 0;
639   protoList[1].protocol_uuid = UUID_PROTOCOL_RFCOMM;
640   protoList[1].num_params = 1;
641   protoList[1].params[0] = rec->hdr.rfcomm_channel_number;
642   protoList[2].protocol_uuid = UUID_PROTOCOL_OBEX;
643   protoList[2].num_params = 0;
644   status &= SDP_AddProtocolList(sdp_handle, 3, protoList);
645 
646   /* Add a name entry */
647   status &= SDP_AddAttribute(sdp_handle, (uint16_t)ATTR_ID_SERVICE_NAME,
648                              (uint8_t)TEXT_STR_DESC_TYPE,
649                              (uint32_t)(rec->hdr.service_name_length + 1),
650                              (uint8_t*)rec->hdr.service_name);
651 
652   /* Add in the Bluetooth Profile Descriptor List */
653   status &= SDP_AddProfileDescriptorList(
654       sdp_handle, UUID_SERVCLASS_PHONE_ACCESS, rec->hdr.profile_version);
655 
656   /* Add supported repositories 1 byte */
657   status &= SDP_AddAttribute(sdp_handle, ATTR_ID_SUPPORTED_REPOSITORIES,
658                              UINT_DESC_TYPE, (uint32_t)1,
659                              (uint8_t*)&rec->supported_repositories);
660 
661   /* Add supported feature 4 bytes*/
662   UINT32_TO_BE_STREAM(p_temp, rec->supported_features);
663   status &= SDP_AddAttribute(sdp_handle, ATTR_ID_PBAP_SUPPORTED_FEATURES,
664                              UINT_DESC_TYPE, (uint32_t)4, temp);
665 
666   /* Add the L2CAP PSM if present */
667   if (rec->hdr.l2cap_psm != -1) {
668     p_temp = temp;  // The macro modifies p_temp, hence rewind.
669     UINT16_TO_BE_STREAM(p_temp, rec->hdr.l2cap_psm);
670     status &= SDP_AddAttribute(sdp_handle, ATTR_ID_GOEP_L2CAP_PSM,
671                                UINT_DESC_TYPE, (uint32_t)2, temp);
672   }
673 
674   /* Make the service browseable */
675   status &=
676       SDP_AddUuidSequence(sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse);
677 
678   if (!status) {
679     SDP_DeleteRecord(sdp_handle);
680     sdp_handle = 0;
681     APPL_TRACE_ERROR("%s() FAILED", __func__);
682   } else {
683     bta_sys_add_uuid(service); /* UUID_SERVCLASS_MESSAGE_ACCESS */
684     APPL_TRACE_DEBUG("%s():  SDP Registered (handle 0x%08x)", __func__,
685                      sdp_handle);
686   }
687   return sdp_handle;
688 }
689 
690 /* Create a OPP Server SDP record based on information stored in a
691  * bluetooth_sdp_ops_record */
add_opps_sdp(const bluetooth_sdp_ops_record * rec)692 static int add_opps_sdp(const bluetooth_sdp_ops_record* rec) {
693   tSDP_PROTOCOL_ELEM protoList[3];
694   uint16_t service = UUID_SERVCLASS_OBEX_OBJECT_PUSH;
695   uint16_t browse = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
696   uint8_t type_len[rec->supported_formats_list_len];
697   uint8_t desc_type[rec->supported_formats_list_len];
698   uint8_t* type_value[rec->supported_formats_list_len];
699   bool status = true;
700   uint32_t sdp_handle = 0;
701   uint8_t temp[4];
702   uint8_t* p_temp = temp;
703   tBTA_UTL_COD cod;
704   int i, j;
705 
706   sdp_handle = SDP_CreateRecord();
707   if (sdp_handle == 0) {
708     LOG_ERROR("Unable to register Object Push Server Service");
709     return sdp_handle;
710   }
711 
712   /* add service class */
713   status &= SDP_AddServiceClassIdList(sdp_handle, 1, &service);
714   memset(protoList, 0, 3 * sizeof(tSDP_PROTOCOL_ELEM));
715 
716   /* add protocol list, including RFCOMM scn */
717   protoList[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
718   protoList[0].num_params = 0;
719   protoList[1].protocol_uuid = UUID_PROTOCOL_RFCOMM;
720   protoList[1].num_params = 1;
721   protoList[1].params[0] = rec->hdr.rfcomm_channel_number;
722   protoList[2].protocol_uuid = UUID_PROTOCOL_OBEX;
723   protoList[2].num_params = 0;
724   status &= SDP_AddProtocolList(sdp_handle, 3, protoList);
725 
726   /* Add a name entry */
727   status &= SDP_AddAttribute(sdp_handle, (uint16_t)ATTR_ID_SERVICE_NAME,
728                              (uint8_t)TEXT_STR_DESC_TYPE,
729                              (uint32_t)(rec->hdr.service_name_length + 1),
730                              (uint8_t*)rec->hdr.service_name);
731 
732   /* Add in the Bluetooth Profile Descriptor List */
733   status &= SDP_AddProfileDescriptorList(
734       sdp_handle, UUID_SERVCLASS_OBEX_OBJECT_PUSH, rec->hdr.profile_version);
735 
736   /* add sequence for supported types */
737   for (i = 0, j = 0; i < rec->supported_formats_list_len; i++) {
738     type_value[j] = (uint8_t*)&rec->supported_formats_list[i];
739     desc_type[j] = UINT_DESC_TYPE;
740     type_len[j++] = 1;
741   }
742 
743   status &=
744       SDP_AddSequence(sdp_handle, (uint16_t)ATTR_ID_SUPPORTED_FORMATS_LIST,
745                       (uint8_t)rec->supported_formats_list_len, desc_type,
746                       type_len, type_value);
747 
748   /* Add the L2CAP PSM if present */
749   if (rec->hdr.l2cap_psm != -1) {
750     p_temp = temp;  // The macro modifies p_temp, hence rewind.
751     UINT16_TO_BE_STREAM(p_temp, rec->hdr.l2cap_psm);
752     status &= SDP_AddAttribute(sdp_handle, ATTR_ID_GOEP_L2CAP_PSM,
753                                UINT_DESC_TYPE, (uint32_t)2, temp);
754   }
755 
756   /* Make the service browseable */
757   status &=
758       SDP_AddUuidSequence(sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse);
759 
760   if (!status) {
761     SDP_DeleteRecord(sdp_handle);
762     sdp_handle = 0;
763     APPL_TRACE_ERROR("%s() FAILED", __func__);
764   } else {
765     /* set class of device */
766     cod.service = BTM_COD_SERVICE_OBJ_TRANSFER;
767     utl_set_device_class(&cod, BTA_UTL_SET_COD_SERVICE_CLASS);
768 
769     bta_sys_add_uuid(service); /* UUID_SERVCLASS_OBEX_OBJECT_PUSH */
770     APPL_TRACE_DEBUG("%s():  SDP Registered (handle 0x%08x)", __func__,
771                      sdp_handle);
772   }
773   return sdp_handle;
774 }
775 
776 // Create a Sim Access Profile SDP record based on information stored in a
777 // bluetooth_sdp_sap_record.
add_saps_sdp(const bluetooth_sdp_sap_record * rec)778 static int add_saps_sdp(const bluetooth_sdp_sap_record* rec) {
779   tSDP_PROTOCOL_ELEM protoList[2];
780   uint16_t services[2];
781   uint16_t browse = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
782   bool status = true;
783   uint32_t sdp_handle = 0;
784 
785   sdp_handle = SDP_CreateRecord();
786   if (sdp_handle == 0) {
787     LOG_ERROR("Unable to register SAPS Service");
788     return sdp_handle;
789   }
790 
791   services[0] = UUID_SERVCLASS_SAP;
792   services[1] = UUID_SERVCLASS_GENERIC_TELEPHONY;
793 
794   // add service class
795   status &= SDP_AddServiceClassIdList(sdp_handle, 2, services);
796   memset(protoList, 0, 2 * sizeof(tSDP_PROTOCOL_ELEM));
797 
798   // add protocol list, including RFCOMM scn
799   protoList[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
800   protoList[0].num_params = 0;
801   protoList[1].protocol_uuid = UUID_PROTOCOL_RFCOMM;
802   protoList[1].num_params = 1;
803   protoList[1].params[0] = rec->hdr.rfcomm_channel_number;
804   status &= SDP_AddProtocolList(sdp_handle, 2, protoList);
805 
806   // Add a name entry
807   status &= SDP_AddAttribute(sdp_handle, (uint16_t)ATTR_ID_SERVICE_NAME,
808                              (uint8_t)TEXT_STR_DESC_TYPE,
809                              (uint32_t)(rec->hdr.service_name_length + 1),
810                              (uint8_t*)rec->hdr.service_name);
811 
812   // Add in the Bluetooth Profile Descriptor List
813   status &= SDP_AddProfileDescriptorList(sdp_handle, UUID_SERVCLASS_SAP,
814                                          rec->hdr.profile_version);
815 
816   // Make the service browseable
817   status &=
818       SDP_AddUuidSequence(sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse);
819 
820   if (!status) {
821     SDP_DeleteRecord(sdp_handle);
822     sdp_handle = 0;
823     APPL_TRACE_ERROR("%s(): FAILED deleting record", __func__);
824   } else {
825     bta_sys_add_uuid(UUID_SERVCLASS_SAP);
826     APPL_TRACE_DEBUG("%s(): SDP Registered (handle 0x%08x)", __func__,
827                      sdp_handle);
828   }
829   return sdp_handle;
830 }
831