OSDN Git Service

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