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