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