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_sdp.h"
43 #include "btif_sock_util.h"
44 #include "btif_util.h"
45 #include "osi/include/allocator.h"
46 #include "stack/include/sdp_api.h"
47 #include "stack/sdp/sdpint.h"
48 #include "types/bluetooth/uuid.h"
49 #include "utl.h"
50
51 using namespace bluetooth::legacy::stack::sdp;
52
53 // Protects the sdp_slots array from concurrent access.
54 static std::recursive_mutex sdp_lock;
55
56 /**
57 * The need for a state variable have been reduced to two states.
58 * The remaining state control is handled by program flow
59 */
60 typedef enum {
61 SDP_RECORD_FREE = 0,
62 SDP_RECORD_ALLOCED,
63 } sdp_state_t;
64
65 typedef struct {
66 sdp_state_t state;
67 int sdp_handle;
68 bluetooth_sdp_record* record_data;
69 } sdp_slot_t;
70
71 #define MAX_SDP_SLOTS 128
72 static sdp_slot_t sdp_slots[MAX_SDP_SLOTS];
73
74 /*****************************************************************************
75 * LOCAL Functions
76 *****************************************************************************/
77 static int add_maps_sdp(const bluetooth_sdp_mas_record* rec);
78 static int add_mapc_sdp(const bluetooth_sdp_mns_record* rec);
79 static int add_pbapc_sdp(const bluetooth_sdp_pce_record* rec);
80 static int add_pbaps_sdp(const bluetooth_sdp_pse_record* rec);
81 static int add_opps_sdp(const bluetooth_sdp_ops_record* rec);
82 static int add_saps_sdp(const bluetooth_sdp_sap_record* rec);
83 static int add_mps_sdp(const bluetooth_sdp_mps_record* rec);
84 bt_status_t remove_sdp_record(int record_id);
85 static int free_sdp_slot(int id);
86
87 /******************************************************************************
88 * WARNING: Functions below are not called in BTU context.
89 * Introduced to make it possible to create SDP records from JAVA with both a
90 * RFCOMM channel and a L2CAP PSM.
91 * Overall architecture:
92 * 1) JAVA calls createRecord() which returns a pseudo ID which at a later
93 * point will be linked to a specific SDP handle.
94 * 2) createRecord() requests the BTU task(thread) to call a callback in SDP
95 * which creates the actual record, and updates the ID<->SDPHandle map
96 * based on the ID beeing passed to BTA as user_data.
97 *****************************************************************************/
98
init_sdp_slots()99 static void init_sdp_slots() {
100 int i;
101 memset(sdp_slots, 0, sizeof(sdp_slot_t) * MAX_SDP_SLOTS);
102 /* if SDP_RECORD_FREE is zero - no need to set the value */
103 if (SDP_RECORD_FREE != 0) {
104 for (i = 0; i < MAX_SDP_SLOTS; i++) {
105 sdp_slots[i].state = SDP_RECORD_FREE;
106 }
107 }
108 }
109
sdp_server_init()110 bt_status_t sdp_server_init() {
111 BTIF_TRACE_DEBUG("Sdp Server %s", __func__);
112 init_sdp_slots();
113 return BT_STATUS_SUCCESS;
114 }
115
sdp_server_cleanup()116 void sdp_server_cleanup() {
117 BTIF_TRACE_DEBUG("Sdp Server %s", __func__);
118 std::unique_lock<std::recursive_mutex> lock(sdp_lock);
119 int i;
120 for (i = 0; i < MAX_SDP_SLOTS; i++) {
121 /*remove_sdp_record(i); we cannot send messages to the other threads, since
122 * they might
123 * have been shut down already. Just do local cleanup.
124 */
125 free_sdp_slot(i);
126 }
127 }
128
get_sdp_records_size(bluetooth_sdp_record * in_record,int count)129 int get_sdp_records_size(bluetooth_sdp_record* in_record, int count) {
130 bluetooth_sdp_record* record = in_record;
131 int records_size = 0;
132 int i;
133 for (i = 0; i < count; i++) {
134 record = &in_record[i];
135 records_size += sizeof(bluetooth_sdp_record);
136 records_size += record->hdr.service_name_length;
137 if (record->hdr.service_name_length > 0) {
138 records_size++; /* + '\0' termination of string */
139 }
140 records_size += record->hdr.user1_ptr_len;
141 records_size += record->hdr.user2_ptr_len;
142 }
143 return records_size;
144 }
145
146 /* Deep copy all content of in_records into out_records.
147 * out_records must point to a chunk of memory large enough to contain all
148 * the data. Use getSdpRecordsSize() to calculate the needed size. */
copy_sdp_records(bluetooth_sdp_record * in_records,bluetooth_sdp_record * out_records,int count)149 void copy_sdp_records(bluetooth_sdp_record* in_records,
150 bluetooth_sdp_record* out_records, int count) {
151 int i;
152 bluetooth_sdp_record* in_record;
153 bluetooth_sdp_record* out_record;
154 char* free_ptr =
155 (char*)(&out_records[count]); /* set pointer to after the last entry */
156
157 for (i = 0; i < count; i++) {
158 in_record = &in_records[i];
159 out_record = &out_records[i];
160 *out_record = *in_record;
161
162 if (in_record->hdr.service_name == NULL ||
163 in_record->hdr.service_name_length == 0) {
164 out_record->hdr.service_name = NULL;
165 out_record->hdr.service_name_length = 0;
166 } else {
167 out_record->hdr.service_name = free_ptr; // Update service_name pointer
168 // Copy string
169 memcpy(free_ptr, in_record->hdr.service_name,
170 in_record->hdr.service_name_length);
171 free_ptr += in_record->hdr.service_name_length;
172 *(free_ptr) = '\0'; // Set '\0' termination of string
173 free_ptr++;
174 }
175 if (in_record->hdr.user1_ptr != NULL) {
176 out_record->hdr.user1_ptr = (uint8_t*)free_ptr; // Update pointer
177 memcpy(free_ptr, in_record->hdr.user1_ptr,
178 in_record->hdr.user1_ptr_len); // Copy content
179 free_ptr += in_record->hdr.user1_ptr_len;
180 }
181 if (in_record->hdr.user2_ptr != NULL) {
182 out_record->hdr.user2_ptr = (uint8_t*)free_ptr; // Update pointer
183 memcpy(free_ptr, in_record->hdr.user2_ptr,
184 in_record->hdr.user2_ptr_len); // Copy content
185 free_ptr += in_record->hdr.user2_ptr_len;
186 }
187 }
188 return;
189 }
190
191 /* Reserve a slot in sdp_slots, copy data and set a reference to the copy.
192 * The record_data will contain both the record and any data pointed to by
193 * the record.
194 * Currently this covers:
195 * service_name string,
196 * user1_ptr and
197 * user2_ptr. */
alloc_sdp_slot(bluetooth_sdp_record * in_record)198 static int alloc_sdp_slot(bluetooth_sdp_record* in_record) {
199 int record_size = get_sdp_records_size(in_record, 1);
200 /* We are optimists here, and preallocate the record.
201 * This is to reduce the time we hold the sdp_lock. */
202 bluetooth_sdp_record* record = (bluetooth_sdp_record*)osi_malloc(record_size);
203
204 copy_sdp_records(in_record, record, 1);
205 {
206 std::unique_lock<std::recursive_mutex> lock(sdp_lock);
207 for (int i = 0; i < MAX_SDP_SLOTS; i++) {
208 if (sdp_slots[i].state == SDP_RECORD_FREE) {
209 sdp_slots[i].state = SDP_RECORD_ALLOCED;
210 sdp_slots[i].record_data = record;
211 return i;
212 }
213 }
214 }
215 APPL_TRACE_ERROR("%s() failed - no more free slots!", __func__);
216 /* Rearly the optimist is too optimistic, and cleanup is needed...*/
217 osi_free(record);
218 return -1;
219 }
220
free_sdp_slot(int id)221 static int free_sdp_slot(int id) {
222 int handle = -1;
223 bluetooth_sdp_record* record = NULL;
224 if (id < 0 || id >= MAX_SDP_SLOTS) {
225 APPL_TRACE_ERROR("%s() failed - id %d is invalid", __func__, id);
226 return handle;
227 }
228
229 {
230 std::unique_lock<std::recursive_mutex> lock(sdp_lock);
231 handle = sdp_slots[id].sdp_handle;
232 sdp_slots[id].sdp_handle = 0;
233 if (sdp_slots[id].state != SDP_RECORD_FREE) {
234 /* safe a copy of the pointer, and free after unlock() */
235 record = sdp_slots[id].record_data;
236 }
237 sdp_slots[id].state = SDP_RECORD_FREE;
238 }
239
240 if (record != NULL) {
241 osi_free(record);
242 } else {
243 // Record have already been freed
244 handle = -1;
245 }
246 return handle;
247 }
248
249 /***
250 * Use this to get a reference to a SDP slot AND change the state to
251 * SDP_RECORD_CREATE_INITIATED.
252 */
start_create_sdp(int id)253 static const sdp_slot_t* start_create_sdp(int id) {
254 if (id >= MAX_SDP_SLOTS) {
255 APPL_TRACE_ERROR("%s() failed - id %d is invalid", __func__, id);
256 return NULL;
257 }
258
259 std::unique_lock<std::recursive_mutex> lock(sdp_lock);
260 if (sdp_slots[id].state != SDP_RECORD_ALLOCED) {
261 /* The record have been removed before this event occurred - e.g. deinit */
262 APPL_TRACE_ERROR(
263 "%s() failed - state for id %d is "
264 "sdp_slots[id].state = %d expected %d",
265 __func__, id, sdp_slots[id].state, SDP_RECORD_ALLOCED);
266 return NULL;
267 }
268
269 return &(sdp_slots[id]);
270 }
271
set_sdp_handle(int id,int handle)272 static void set_sdp_handle(int id, int handle) {
273 std::unique_lock<std::recursive_mutex> lock(sdp_lock);
274 sdp_slots[id].sdp_handle = handle;
275 }
276
create_sdp_record(bluetooth_sdp_record * record,int * record_handle)277 bt_status_t create_sdp_record(bluetooth_sdp_record* record,
278 int* record_handle) {
279 int handle;
280
281 handle = alloc_sdp_slot(record);
282 BTIF_TRACE_DEBUG("%s() handle = 0x%08x", __func__, handle);
283
284 if (handle < 0) return BT_STATUS_FAIL;
285
286 BTA_SdpCreateRecordByUser(INT_TO_PTR(handle));
287
288 *record_handle = handle;
289
290 return BT_STATUS_SUCCESS;
291 }
292
remove_sdp_record(int record_id)293 bt_status_t remove_sdp_record(int record_id) {
294 int handle;
295
296 if (record_id >= MAX_SDP_SLOTS) {
297 return BT_STATUS_PARM_INVALID;
298 }
299
300 bluetooth_sdp_record* record;
301 bluetooth_sdp_types sdp_type = SDP_TYPE_RAW;
302 {
303 std::unique_lock<std::recursive_mutex> lock(sdp_lock);
304 record = sdp_slots[record_id].record_data;
305 if (record != NULL) {
306 sdp_type = record->hdr.type;
307 }
308 }
309 tBTA_SERVICE_ID service_id = -1;
310 switch (sdp_type) {
311 case SDP_TYPE_MAP_MAS:
312 service_id = BTA_MAP_SERVICE_ID;
313 break;
314 case SDP_TYPE_MAP_MNS:
315 service_id = BTA_MN_SERVICE_ID;
316 break;
317 case SDP_TYPE_PBAP_PSE:
318 service_id = BTA_PBAP_SERVICE_ID;
319 break;
320 case SDP_TYPE_PBAP_PCE:
321 service_id = BTA_PCE_SERVICE_ID;
322 break;
323 default:
324 /* other enumeration values were not enabled in {@link on_create_record_event} */
325 break;
326 }
327 if (service_id > 0) {
328 // {@link btif_disable_service} sets the mask {@link btif_enabled_services}.
329 btif_disable_service(service_id);
330 }
331
332 /* Get the Record handle, and free the slot */
333 handle = free_sdp_slot(record_id);
334 BTIF_TRACE_DEBUG("Sdp Server %s id=%d to handle=0x%08x", __func__, record_id,
335 handle);
336
337 /* Pass the actual record handle */
338 if (handle > 0) {
339 BTA_SdpRemoveRecordByUser(INT_TO_PTR(handle));
340 return BT_STATUS_SUCCESS;
341 }
342 BTIF_TRACE_DEBUG("Sdp Server %s - record already removed - or never created",
343 __func__);
344 return BT_STATUS_FAIL;
345 }
346
347 /******************************************************************************
348 * CALLBACK FUNCTIONS
349 * Called in BTA context to create/remove SDP records.
350 ******************************************************************************/
351
on_create_record_event(int id)352 void on_create_record_event(int id) {
353 /*
354 * 1) Fetch the record pointer, and change its state?
355 * 2) switch on the type to create the correct record
356 * 3) Update state on completion
357 * 4) What to do at fail?
358 * */
359 BTIF_TRACE_DEBUG("Sdp Server %s", __func__);
360 const sdp_slot_t* sdp_slot = start_create_sdp(id);
361 tBTA_SERVICE_ID service_id = -1;
362 bluetooth_sdp_record* record;
363 /* In the case we are shutting down, sdp_slot is NULL */
364 if (sdp_slot != nullptr && (record = sdp_slot->record_data) != nullptr) {
365 int handle = -1;
366 switch (record->hdr.type) {
367 case SDP_TYPE_MAP_MAS:
368 handle = add_maps_sdp(&record->mas);
369 service_id = BTA_MAP_SERVICE_ID;
370 break;
371 case SDP_TYPE_MAP_MNS:
372 handle = add_mapc_sdp(&record->mns);
373 service_id = BTA_MN_SERVICE_ID;
374 break;
375 case SDP_TYPE_PBAP_PSE:
376 handle = add_pbaps_sdp(&record->pse);
377 service_id = BTA_PBAP_SERVICE_ID;
378 break;
379 case SDP_TYPE_OPP_SERVER:
380 handle = add_opps_sdp(&record->ops);
381 break;
382 case SDP_TYPE_SAP_SERVER:
383 handle = add_saps_sdp(&record->sap);
384 break;
385 case SDP_TYPE_PBAP_PCE:
386 handle = add_pbapc_sdp(&record->pce);
387 service_id = BTA_PCE_SERVICE_ID;
388 break;
389 case SDP_TYPE_MPS:
390 handle = add_mps_sdp(&record->mps);
391 break;
392 case SDP_TYPE_RAW:
393 if (record->hdr.rfcomm_channel_number > 0) {
394 handle = add_rfc_sdp_rec(record->hdr.service_name, record->hdr.uuid,
395 record->hdr.rfcomm_channel_number);
396 }
397 break;
398 default:
399 BTIF_TRACE_DEBUG("Record type %d is not supported", record->hdr.type);
400 break;
401 }
402 if (handle != -1) {
403 set_sdp_handle(id, handle);
404 if (service_id > 0) {
405 /**
406 * {@link btif_enable_service} calls {@link btif_dm_enable_service}, which calls {@link
407 * btif_in_execute_service_request}.
408 * - {@link btif_enable_service} sets the mask {@link btif_enabled_services}.
409 * - {@link btif_dm_enable_service} invokes the java callback to return uuids based
410 * on the enabled services mask.
411 * - {@link btif_in_execute_service_request} gates the java callback in {@link
412 * btif_dm_enable_service}.
413 */
414 btif_enable_service(service_id);
415 }
416 }
417 }
418 }
419
on_remove_record_event(int handle)420 void on_remove_record_event(int handle) {
421 BTIF_TRACE_DEBUG("Sdp Server %s", __func__);
422
423 // User data carries the actual SDP handle, not the ID.
424 if (handle != -1 && handle != 0) {
425 bool result;
426 result = get_legacy_stack_sdp_api()->handle.SDP_DeleteRecord(handle);
427 if (!result) {
428 BTIF_TRACE_ERROR(" Unable to remove handle 0x%08x", handle);
429 }
430 }
431 }
432
433 /****
434 * Below the actual functions accessing BTA context data - hence only call from
435 * BTA context!
436 */
437
438 /* Create a MAP MAS SDP record based on information stored in a
439 * bluetooth_sdp_mas_record */
add_maps_sdp(const bluetooth_sdp_mas_record * rec)440 static int add_maps_sdp(const bluetooth_sdp_mas_record* rec) {
441 tSDP_PROTOCOL_ELEM protoList[3];
442 uint16_t service = UUID_SERVCLASS_MESSAGE_ACCESS;
443 uint16_t browse = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
444 bool status = true;
445 uint32_t sdp_handle = 0;
446 uint8_t temp[4];
447 uint8_t* p_temp = temp;
448
449 sdp_handle = get_legacy_stack_sdp_api()->handle.SDP_CreateRecord();
450 if (sdp_handle == 0) {
451 LOG_ERROR("Unable to register MAPS Service");
452 return sdp_handle;
453 }
454
455 /* add service class */
456 status &= get_legacy_stack_sdp_api()->handle.SDP_AddServiceClassIdList(
457 sdp_handle, 1, &service);
458 memset(protoList, 0, 3 * sizeof(tSDP_PROTOCOL_ELEM));
459
460 /* add protocol list, including RFCOMM scn */
461 protoList[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
462 protoList[0].num_params = 0;
463 protoList[1].protocol_uuid = UUID_PROTOCOL_RFCOMM;
464 protoList[1].num_params = 1;
465 protoList[1].params[0] = rec->hdr.rfcomm_channel_number;
466 protoList[2].protocol_uuid = UUID_PROTOCOL_OBEX;
467 protoList[2].num_params = 0;
468 status &= get_legacy_stack_sdp_api()->handle.SDP_AddProtocolList(
469 sdp_handle, 3, protoList);
470
471 /* Add a name entry */
472 status &= get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
473 sdp_handle, (uint16_t)ATTR_ID_SERVICE_NAME, (uint8_t)TEXT_STR_DESC_TYPE,
474 (uint32_t)(rec->hdr.service_name_length + 1),
475 (uint8_t*)rec->hdr.service_name);
476
477 /* Add in the Bluetooth Profile Descriptor List */
478 status &= get_legacy_stack_sdp_api()->handle.SDP_AddProfileDescriptorList(
479 sdp_handle, UUID_SERVCLASS_MAP_PROFILE, rec->hdr.profile_version);
480
481 /* Add MAS instance ID */
482 status &= get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
483 sdp_handle, ATTR_ID_MAS_INSTANCE_ID, UINT_DESC_TYPE, (uint32_t)1,
484 (uint8_t*)&rec->mas_instance_id);
485
486 /* Add supported message types */
487 status &= get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
488 sdp_handle, ATTR_ID_SUPPORTED_MSG_TYPE, UINT_DESC_TYPE, (uint32_t)1,
489 (uint8_t*)&rec->supported_message_types);
490
491 /* Add supported feature */
492 UINT32_TO_BE_STREAM(p_temp, rec->supported_features);
493 status &= get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
494 sdp_handle, ATTR_ID_MAP_SUPPORTED_FEATURES, UINT_DESC_TYPE, (uint32_t)4,
495 temp);
496
497 /* Add the L2CAP PSM if present */
498 if (rec->hdr.l2cap_psm != -1) {
499 p_temp = temp; // The macro modifies p_temp, hence rewind.
500 UINT16_TO_BE_STREAM(p_temp, rec->hdr.l2cap_psm);
501 status &= get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
502 sdp_handle, ATTR_ID_GOEP_L2CAP_PSM, UINT_DESC_TYPE, (uint32_t)2, temp);
503 }
504
505 /* Make the service browseable */
506 status &= get_legacy_stack_sdp_api()->handle.SDP_AddUuidSequence(
507 sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse);
508
509 if (!status) {
510 get_legacy_stack_sdp_api()->handle.SDP_DeleteRecord(sdp_handle);
511 sdp_handle = 0;
512 APPL_TRACE_ERROR("%s() FAILED", __func__);
513 } else {
514 bta_sys_add_uuid(service); /* UUID_SERVCLASS_MESSAGE_ACCESS */
515 APPL_TRACE_DEBUG("%s(): SDP Registered (handle 0x%08x)", __func__,
516 sdp_handle);
517 }
518 return sdp_handle;
519 }
520
521 /* Create a MAP MNS SDP record based on information stored in a
522 * bluetooth_sdp_mns_record */
add_mapc_sdp(const bluetooth_sdp_mns_record * rec)523 static int add_mapc_sdp(const bluetooth_sdp_mns_record* rec) {
524 tSDP_PROTOCOL_ELEM protoList[3];
525 uint16_t service = UUID_SERVCLASS_MESSAGE_NOTIFICATION;
526 uint16_t browse = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
527 bool status = true;
528 uint32_t sdp_handle = 0;
529 uint8_t temp[4];
530 uint8_t* p_temp = temp;
531
532 sdp_handle = get_legacy_stack_sdp_api()->handle.SDP_CreateRecord();
533 if (sdp_handle == 0) {
534 LOG_ERROR("Unable to register MAP Notification Service");
535 return sdp_handle;
536 }
537
538 /* add service class */
539 status &= get_legacy_stack_sdp_api()->handle.SDP_AddServiceClassIdList(
540 sdp_handle, 1, &service);
541 memset(protoList, 0, 3 * sizeof(tSDP_PROTOCOL_ELEM));
542
543 /* add protocol list, including RFCOMM scn */
544 protoList[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
545 protoList[0].num_params = 0;
546 protoList[1].protocol_uuid = UUID_PROTOCOL_RFCOMM;
547 protoList[1].num_params = 1;
548 protoList[1].params[0] = rec->hdr.rfcomm_channel_number;
549 protoList[2].protocol_uuid = UUID_PROTOCOL_OBEX;
550 protoList[2].num_params = 0;
551 status &= get_legacy_stack_sdp_api()->handle.SDP_AddProtocolList(
552 sdp_handle, 3, protoList);
553
554 /* Add a name entry */
555 status &= get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
556 sdp_handle, (uint16_t)ATTR_ID_SERVICE_NAME, (uint8_t)TEXT_STR_DESC_TYPE,
557 (uint32_t)(rec->hdr.service_name_length + 1),
558 (uint8_t*)rec->hdr.service_name);
559
560 /* Add in the Bluetooth Profile Descriptor List */
561 status &= get_legacy_stack_sdp_api()->handle.SDP_AddProfileDescriptorList(
562 sdp_handle, UUID_SERVCLASS_MAP_PROFILE, rec->hdr.profile_version);
563
564 /* Add supported feature */
565 UINT32_TO_BE_STREAM(p_temp, rec->supported_features);
566 status &= get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
567 sdp_handle, ATTR_ID_MAP_SUPPORTED_FEATURES, UINT_DESC_TYPE, (uint32_t)4,
568 temp);
569
570 /* Add the L2CAP PSM if present */
571 if (rec->hdr.l2cap_psm != -1) {
572 p_temp = temp; // The macro modifies p_temp, hence rewind.
573 UINT16_TO_BE_STREAM(p_temp, rec->hdr.l2cap_psm);
574 status &= get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
575 sdp_handle, ATTR_ID_GOEP_L2CAP_PSM, UINT_DESC_TYPE, (uint32_t)2, temp);
576 }
577
578 /* Make the service browseable */
579 status &= get_legacy_stack_sdp_api()->handle.SDP_AddUuidSequence(
580 sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse);
581
582 if (!status) {
583 get_legacy_stack_sdp_api()->handle.SDP_DeleteRecord(sdp_handle);
584 sdp_handle = 0;
585 APPL_TRACE_ERROR("%s() FAILED", __func__);
586 } else {
587 bta_sys_add_uuid(service); /* UUID_SERVCLASS_MESSAGE_ACCESS */
588 APPL_TRACE_DEBUG("%s(): SDP Registered (handle 0x%08x)", __func__,
589 sdp_handle);
590 }
591 return sdp_handle;
592 }
593
594 /* Create a PBAP Client SDP record based on information stored in a
595 * bluetooth_sdp_pce_record */
add_pbapc_sdp(const bluetooth_sdp_pce_record * rec)596 static int add_pbapc_sdp(const bluetooth_sdp_pce_record* rec) {
597 uint16_t service = UUID_SERVCLASS_PBAP_PCE;
598 uint16_t browse = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
599 bool status = true;
600 uint32_t sdp_handle = 0;
601
602 sdp_handle = get_legacy_stack_sdp_api()->handle.SDP_CreateRecord();
603 if (sdp_handle == 0) {
604 LOG_ERROR("Unable to register PBAP Client Service");
605 return sdp_handle;
606 }
607
608 status &= get_legacy_stack_sdp_api()->handle.SDP_AddServiceClassIdList(
609 sdp_handle, 1, &service);
610
611 /* Add a name entry */
612 status &= get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
613 sdp_handle, (uint16_t)ATTR_ID_SERVICE_NAME, (uint8_t)TEXT_STR_DESC_TYPE,
614 (uint32_t)(rec->hdr.service_name_length + 1),
615 (uint8_t*)rec->hdr.service_name);
616
617 /* Add in the Bluetooth Profile Descriptor List */
618 status &= get_legacy_stack_sdp_api()->handle.SDP_AddProfileDescriptorList(
619 sdp_handle, UUID_SERVCLASS_PHONE_ACCESS, rec->hdr.profile_version);
620
621 /* Make the service browseable */
622 status &= get_legacy_stack_sdp_api()->handle.SDP_AddUuidSequence(
623 sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse);
624
625 if (!status) {
626 get_legacy_stack_sdp_api()->handle.SDP_DeleteRecord(sdp_handle);
627 sdp_handle = 0;
628 APPL_TRACE_ERROR("%s() FAILED", __func__);
629 return sdp_handle;
630 }
631 bta_sys_add_uuid(service); /* UUID_SERVCLASS_PBAP_PCE */
632 APPL_TRACE_DEBUG("%s(): SDP Registered (handle 0x%08x)", __func__,
633 sdp_handle);
634 return sdp_handle;
635 }
636
637 /* Create a PBAP Server SDP record based on information stored in a
638 * bluetooth_sdp_pse_record */
add_pbaps_sdp(const bluetooth_sdp_pse_record * rec)639 static int add_pbaps_sdp(const bluetooth_sdp_pse_record* rec) {
640 tSDP_PROTOCOL_ELEM protoList[3];
641 uint16_t service = UUID_SERVCLASS_PBAP_PSE;
642 uint16_t browse = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
643 bool status = true;
644 uint32_t sdp_handle = 0;
645 uint8_t temp[4];
646 uint8_t* p_temp = temp;
647
648 sdp_handle = get_legacy_stack_sdp_api()->handle.SDP_CreateRecord();
649 if (sdp_handle == 0) {
650 LOG_ERROR("Unable to register PBAP Server Service");
651 return sdp_handle;
652 }
653
654 /* add service class */
655 status &= get_legacy_stack_sdp_api()->handle.SDP_AddServiceClassIdList(
656 sdp_handle, 1, &service);
657 memset(protoList, 0, 3 * sizeof(tSDP_PROTOCOL_ELEM));
658
659 /* add protocol list, including RFCOMM scn */
660 protoList[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
661 protoList[0].num_params = 0;
662 protoList[1].protocol_uuid = UUID_PROTOCOL_RFCOMM;
663 protoList[1].num_params = 1;
664 protoList[1].params[0] = rec->hdr.rfcomm_channel_number;
665 protoList[2].protocol_uuid = UUID_PROTOCOL_OBEX;
666 protoList[2].num_params = 0;
667 status &= get_legacy_stack_sdp_api()->handle.SDP_AddProtocolList(
668 sdp_handle, 3, protoList);
669
670 /* Add a name entry */
671 status &= get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
672 sdp_handle, (uint16_t)ATTR_ID_SERVICE_NAME, (uint8_t)TEXT_STR_DESC_TYPE,
673 (uint32_t)(rec->hdr.service_name_length + 1),
674 (uint8_t*)rec->hdr.service_name);
675 if (bluetooth::common::init_flags::
676 pbap_pse_dynamic_version_upgrade_is_enabled()) {
677 /*
678 PBAP 1.1.1 repositories bits
679 Bit 0 = Local Phonebook
680 Bit 1 = SIM card
681 Bit 2~7 reserved for future use */
682 uint8_t supported_repositories_1_1_mask = 0x03;
683 uint8_t supported_repositories_1_1 =
684 ((uint8_t)rec->supported_repositories) &
685 supported_repositories_1_1_mask;
686 status &= get_legacy_stack_sdp_api()->handle.SDP_AddProfileDescriptorList(
687 sdp_handle, UUID_SERVCLASS_PHONE_ACCESS, 0x0101);
688
689 /* Add supported repositories 1 byte */
690 status &= get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
691 sdp_handle, ATTR_ID_SUPPORTED_REPOSITORIES, UINT_DESC_TYPE, (uint32_t)1,
692 (uint8_t*)&supported_repositories_1_1);
693 APPL_TRACE_DEBUG(" supported_repositories_1_1: 0x%x",
694 supported_repositories_1_1);
695 sdp_save_local_pse_record_attributes(
696 rec->hdr.rfcomm_channel_number, rec->hdr.l2cap_psm,
697 rec->hdr.profile_version, rec->supported_features,
698 rec->supported_repositories);
699 } else {
700 /* Add in the Bluetooth Profile Descriptor List */
701 status &= get_legacy_stack_sdp_api()->handle.SDP_AddProfileDescriptorList(
702 sdp_handle, UUID_SERVCLASS_PHONE_ACCESS, rec->hdr.profile_version);
703
704 /* Add supported repositories 1 byte */
705 status &= get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
706 sdp_handle, ATTR_ID_SUPPORTED_REPOSITORIES, UINT_DESC_TYPE, (uint32_t)1,
707 (uint8_t*)&rec->supported_repositories);
708 /* Add supported feature 4 bytes*/
709 UINT32_TO_BE_STREAM(p_temp, rec->supported_features);
710 status &= get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
711 sdp_handle, ATTR_ID_PBAP_SUPPORTED_FEATURES, UINT_DESC_TYPE,
712 (uint32_t)4, temp);
713
714 /* Add the L2CAP PSM if present */
715 if (rec->hdr.l2cap_psm != -1) {
716 p_temp = temp; // The macro modifies p_temp, hence rewind.
717 UINT16_TO_BE_STREAM(p_temp, rec->hdr.l2cap_psm);
718 status &= get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
719 sdp_handle, ATTR_ID_GOEP_L2CAP_PSM, UINT_DESC_TYPE, (uint32_t)2,
720 temp);
721 }
722 #if 0
723 status &= get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
724 sdp_handle, (uint16_t)ATTR_ID_SERVICE_NAME, (uint8_t)TEXT_STR_DESC_TYPE,
725 (uint32_t)(rec->hdr.service_name_length + 1),
726 (uint8_t*)rec->hdr.service_name);
727
728 /* Add in the Bluetooth Profile Descriptor List */
729 status &= get_legacy_stack_sdp_api()->handle.SDP_AddProfileDescriptorList(
730 sdp_handle, UUID_SERVCLASS_PHONE_ACCESS, rec->hdr.profile_version);
731
732 /* Add supported repositories 1 byte */
733 status &= get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
734 sdp_handle, ATTR_ID_SUPPORTED_REPOSITORIES, UINT_DESC_TYPE, (uint32_t)1,
735 (uint8_t*)&rec->supported_repositories);
736
737 /* Add supported feature 4 bytes*/
738 UINT32_TO_BE_STREAM(p_temp, rec->supported_features);
739 status &= get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
740 sdp_handle, ATTR_ID_PBAP_SUPPORTED_FEATURES, UINT_DESC_TYPE, (uint32_t)4,
741 temp);
742
743 /* Add the L2CAP PSM if present */
744 if (rec->hdr.l2cap_psm != -1) {
745 p_temp = temp; // The macro modifies p_temp, hence rewind.
746 UINT16_TO_BE_STREAM(p_temp, rec->hdr.l2cap_psm);
747 status &= get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
748 sdp_handle, ATTR_ID_GOEP_L2CAP_PSM, UINT_DESC_TYPE, (uint32_t)2, temp);
749 #endif
750 }
751
752 /* Make the service browseable */
753 status &= get_legacy_stack_sdp_api()->handle.SDP_AddUuidSequence(
754 sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse);
755
756 if (!status) {
757 get_legacy_stack_sdp_api()->handle.SDP_DeleteRecord(sdp_handle);
758 sdp_handle = 0;
759 APPL_TRACE_ERROR("%s() FAILED", __func__);
760 } else {
761 bta_sys_add_uuid(service); /* UUID_SERVCLASS_MESSAGE_ACCESS */
762 APPL_TRACE_DEBUG("%s(): SDP Registered (handle 0x%08x)", __func__,
763 sdp_handle);
764 }
765 return sdp_handle;
766 }
767
768 /* Create a OPP Server SDP record based on information stored in a
769 * bluetooth_sdp_ops_record */
770 static int add_opps_sdp(const bluetooth_sdp_ops_record* rec) {
771 tSDP_PROTOCOL_ELEM protoList[3];
772 uint16_t service = UUID_SERVCLASS_OBEX_OBJECT_PUSH;
773 uint16_t browse = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
774 uint8_t type_len[rec->supported_formats_list_len];
775 uint8_t desc_type[rec->supported_formats_list_len];
776 uint8_t* type_value[rec->supported_formats_list_len];
777 bool status = true;
778 uint32_t sdp_handle = 0;
779 uint8_t temp[4];
780 uint8_t* p_temp = temp;
781 tBTA_UTL_COD cod;
782 int i, j;
783
784 sdp_handle = get_legacy_stack_sdp_api()->handle.SDP_CreateRecord();
785 if (sdp_handle == 0) {
786 LOG_ERROR("Unable to register Object Push Server Service");
787 return sdp_handle;
788 }
789
790 /* add service class */
791 status &= get_legacy_stack_sdp_api()->handle.SDP_AddServiceClassIdList(
792 sdp_handle, 1, &service);
793 memset(protoList, 0, 3 * sizeof(tSDP_PROTOCOL_ELEM));
794
795 /* add protocol list, including RFCOMM scn */
796 protoList[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
797 protoList[0].num_params = 0;
798 protoList[1].protocol_uuid = UUID_PROTOCOL_RFCOMM;
799 protoList[1].num_params = 1;
800 protoList[1].params[0] = rec->hdr.rfcomm_channel_number;
801 protoList[2].protocol_uuid = UUID_PROTOCOL_OBEX;
802 protoList[2].num_params = 0;
803 status &= get_legacy_stack_sdp_api()->handle.SDP_AddProtocolList(
804 sdp_handle, 3, protoList);
805
806 /* Add a name entry */
807 status &= get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
808 sdp_handle, (uint16_t)ATTR_ID_SERVICE_NAME, (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 &= get_legacy_stack_sdp_api()->handle.SDP_AddProfileDescriptorList(
814 sdp_handle, UUID_SERVCLASS_OBEX_OBJECT_PUSH, rec->hdr.profile_version);
815
816 /* add sequence for supported types */
817 for (i = 0, j = 0; i < rec->supported_formats_list_len; i++) {
818 type_value[j] = (uint8_t*)&rec->supported_formats_list[i];
819 desc_type[j] = UINT_DESC_TYPE;
820 type_len[j++] = 1;
821 }
822
823 status &= get_legacy_stack_sdp_api()->handle.SDP_AddSequence(
824 sdp_handle, (uint16_t)ATTR_ID_SUPPORTED_FORMATS_LIST,
825 (uint8_t)rec->supported_formats_list_len, desc_type, type_len,
826 type_value);
827
828 /* Add the L2CAP PSM if present */
829 if (rec->hdr.l2cap_psm != -1) {
830 p_temp = temp; // The macro modifies p_temp, hence rewind.
831 UINT16_TO_BE_STREAM(p_temp, rec->hdr.l2cap_psm);
832 status &= get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
833 sdp_handle, ATTR_ID_GOEP_L2CAP_PSM, UINT_DESC_TYPE, (uint32_t)2, temp);
834 }
835
836 /* Make the service browseable */
837 status &= get_legacy_stack_sdp_api()->handle.SDP_AddUuidSequence(
838 sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse);
839
840 if (!status) {
841 get_legacy_stack_sdp_api()->handle.SDP_DeleteRecord(sdp_handle);
842 sdp_handle = 0;
843 APPL_TRACE_ERROR("%s() FAILED", __func__);
844 } else {
845 /* set class of device */
846 cod.service = BTM_COD_SERVICE_OBJ_TRANSFER;
847 utl_set_device_class(&cod, BTA_UTL_SET_COD_SERVICE_CLASS);
848
849 bta_sys_add_uuid(service); /* UUID_SERVCLASS_OBEX_OBJECT_PUSH */
850 APPL_TRACE_DEBUG("%s(): SDP Registered (handle 0x%08x)", __func__,
851 sdp_handle);
852 }
853 return sdp_handle;
854 }
855
856 // Create a Sim Access Profile SDP record based on information stored in a
857 // bluetooth_sdp_sap_record.
858 static int add_saps_sdp(const bluetooth_sdp_sap_record* rec) {
859 tSDP_PROTOCOL_ELEM protoList[2];
860 uint16_t services[2];
861 uint16_t browse = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
862 bool status = true;
863 uint32_t sdp_handle = 0;
864
865 sdp_handle = get_legacy_stack_sdp_api()->handle.SDP_CreateRecord();
866 if (sdp_handle == 0) {
867 LOG_ERROR("Unable to register SAPS Service");
868 return sdp_handle;
869 }
870
871 services[0] = UUID_SERVCLASS_SAP;
872 services[1] = UUID_SERVCLASS_GENERIC_TELEPHONY;
873
874 // add service class
875 status &= get_legacy_stack_sdp_api()->handle.SDP_AddServiceClassIdList(
876 sdp_handle, 2, services);
877 memset(protoList, 0, 2 * sizeof(tSDP_PROTOCOL_ELEM));
878
879 // add protocol list, including RFCOMM scn
880 protoList[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
881 protoList[0].num_params = 0;
882 protoList[1].protocol_uuid = UUID_PROTOCOL_RFCOMM;
883 protoList[1].num_params = 1;
884 protoList[1].params[0] = rec->hdr.rfcomm_channel_number;
885 status &= get_legacy_stack_sdp_api()->handle.SDP_AddProtocolList(
886 sdp_handle, 2, protoList);
887
888 // Add a name entry
889 status &= get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
890 sdp_handle, (uint16_t)ATTR_ID_SERVICE_NAME, (uint8_t)TEXT_STR_DESC_TYPE,
891 (uint32_t)(rec->hdr.service_name_length + 1),
892 (uint8_t*)rec->hdr.service_name);
893
894 // Add in the Bluetooth Profile Descriptor List
895 status &= get_legacy_stack_sdp_api()->handle.SDP_AddProfileDescriptorList(
896 sdp_handle, UUID_SERVCLASS_SAP, rec->hdr.profile_version);
897
898 // Make the service browseable
899 status &= get_legacy_stack_sdp_api()->handle.SDP_AddUuidSequence(
900 sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse);
901
902 if (!status) {
903 get_legacy_stack_sdp_api()->handle.SDP_DeleteRecord(sdp_handle);
904 sdp_handle = 0;
905 APPL_TRACE_ERROR("%s(): FAILED deleting record", __func__);
906 } else {
907 bta_sys_add_uuid(UUID_SERVCLASS_SAP);
908 APPL_TRACE_DEBUG("%s(): SDP Registered (handle 0x%08x)", __func__,
909 sdp_handle);
910 }
911 return sdp_handle;
912 }
913
914 /* Create a Multi-Profile Specification SDP record based on information stored
915 * in a bluetooth_sdp_mps_record */
916 static int add_mps_sdp(const bluetooth_sdp_mps_record* rec) {
917 uint16_t service = UUID_SERVCLASS_MPS_SC;
918 uint16_t browse = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
919 bool status = true;
920 uint32_t sdp_handle = 0;
921
922 sdp_handle = get_legacy_stack_sdp_api()->handle.SDP_CreateRecord();
923 if (sdp_handle == 0) {
924 LOG_ERROR("Unable to register MPS record");
925 return sdp_handle;
926 }
927
928 status &= get_legacy_stack_sdp_api()->handle.SDP_AddServiceClassIdList(
929 sdp_handle, 1, &service);
930
931 /* Add in the Bluetooth Profile Descriptor List */
932 status &= get_legacy_stack_sdp_api()->handle.SDP_AddProfileDescriptorList(
933 sdp_handle, UUID_SERVCLASS_MPS_PROFILE, rec->hdr.profile_version);
934
935 /* Add supported scenarios MPSD */
936 status &= get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
937 sdp_handle, ATTR_ID_MPS_SUPPORTED_SCENARIOS_MPSD, UINT_DESC_TYPE,
938 (uint32_t)8, (uint8_t*)&rec->supported_scenarios_mpsd);
939 /* Add supported scenarios MPMD */
940 status &= get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
941 sdp_handle, ATTR_ID_MPS_SUPPORTED_SCENARIOS_MPMD, UINT_DESC_TYPE,
942 (uint32_t)8, (uint8_t*)&rec->supported_scenarios_mpmd);
943 /* Add supported dependencies */
944 status &= get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
945 sdp_handle, ATTR_ID_MPS_SUPPORTED_DEPENDENCIES, UINT_DESC_TYPE,
946 (uint32_t)2, (uint8_t*)&rec->supported_dependencies);
947
948 /* Make the service browseable */
949 status &= get_legacy_stack_sdp_api()->handle.SDP_AddUuidSequence(
950 sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse);
951
952 if (!status) {
953 get_legacy_stack_sdp_api()->handle.SDP_DeleteRecord(sdp_handle);
954 sdp_handle = 0;
955 APPL_TRACE_ERROR("%s() FAILED", __func__);
956 return sdp_handle;
957 }
958 bta_sys_add_uuid(service); /* UUID_SERVCLASS_MPS_SC */
959 APPL_TRACE_DEBUG("%s(): SDP Registered (handle 0x%08x)", __func__,
960 sdp_handle);
961 return sdp_handle;
962 }
963