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