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