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