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