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