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