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