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