1 /*
2 * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <string.h>
8
9 #include "btc_sdp.h"
10 #include "btc/btc_manage.h"
11 #include "btc/btc_task.h"
12 #include "btc/btc_util.h"
13 #include "bta/bta_sdp_api.h"
14 #include "bta/bta_sys.h"
15 #include "bta/utl.h"
16 #include "bt_sdp.h"
17 #include "osi/mutex.h"
18 #include "osi/allocator.h"
19 #include "esp_sdp_api.h"
20
21 #if (defined BTC_SDP_INCLUDED && BTC_SDP_INCLUDED == TRUE)
22
23 typedef enum {
24 SDP_RECORD_FREE = 0,
25 SDP_RECORD_ALLOCED,
26 } sdp_state_t;
27
28 typedef struct {
29 uint8_t state;
30 int sdp_handle;
31 esp_bt_uuid_t uuid;
32 void* record_data;
33 } sdp_slot_t;
34
35 typedef struct {
36 bool search_allowed;
37 sdp_slot_t *sdp_slots[SDP_MAX_RECORDS];
38 osi_mutex_t sdp_slot_mutex;
39 } sdp_local_param_t;
40
41 #if SDP_DYNAMIC_MEMORY == FALSE
42 static sdp_local_param_t sdp_local_param;
43 #else
44 static sdp_local_param_t *sdp_local_param_ptr;
45 #define sdp_local_param (*sdp_local_param_ptr)
46 #endif
47
48 #if SDP_DYNAMIC_MEMORY == FALSE
49 #define is_sdp_init() (sdp_local_param.sdp_slot_mutex != NULL)
50 #else
51 #define is_sdp_init() (&sdp_local_param != NULL && sdp_local_param.sdp_slot_mutex != NULL)
52 #endif
53
btc_sdp_cleanup(void)54 static void btc_sdp_cleanup(void)
55 {
56 #if SDP_DYNAMIC_MEMORY == TRUE
57 if (sdp_local_param_ptr) {
58 #endif
59 if (sdp_local_param.sdp_slot_mutex) {
60 osi_mutex_free(&sdp_local_param.sdp_slot_mutex);
61 sdp_local_param.sdp_slot_mutex = NULL;
62 }
63 #if SDP_DYNAMIC_MEMORY == TRUE
64 osi_free(sdp_local_param_ptr);
65 sdp_local_param_ptr = NULL;
66 }
67 #endif
68 }
69
btc_sdp_cb_to_app(esp_sdp_cb_event_t event,esp_sdp_cb_param_t * param)70 static inline void btc_sdp_cb_to_app(esp_sdp_cb_event_t event, esp_sdp_cb_param_t *param)
71 {
72 esp_sdp_cb_t btc_sdp_cb = (esp_sdp_cb_t)btc_profile_cb_get(BTC_PID_SDP);
73 if (btc_sdp_cb) {
74 btc_sdp_cb(event, param);
75 }
76 }
77
get_sdp_record_size(bluetooth_sdp_record * in_record)78 static int get_sdp_record_size(bluetooth_sdp_record* in_record)
79 {
80 bluetooth_sdp_record *record = in_record;
81 int records_size = 0;
82
83 records_size += sizeof(bluetooth_sdp_record);
84 records_size += record->hdr.service_name_length;
85 if (record->hdr.service_name_length > 0) {
86 records_size++; /* + '\0' termination of string */
87 }
88
89 return records_size;
90 }
91
set_sdp_slot_info(int id,int sdp_handle,esp_bt_uuid_t * uuid)92 static void set_sdp_slot_info(int id, int sdp_handle, esp_bt_uuid_t *uuid)
93 {
94 sdp_slot_t *slot = NULL;
95
96 BTC_TRACE_DEBUG("%s() id=%d to sdp_handle=0x%08x", __func__, id, sdp_handle);
97
98 if(id >= SDP_MAX_RECORDS) {
99 BTC_TRACE_ERROR("%s() failed - id %d is invalid", __func__, id);
100 return;
101 }
102
103 osi_mutex_lock(&sdp_local_param.sdp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT);
104
105 do {
106 slot = sdp_local_param.sdp_slots[id];
107 if (slot == NULL) {
108 BTC_TRACE_ERROR("%s() id = %d ", __func__, id);
109 break;
110 }
111
112 if (slot->state != SDP_RECORD_ALLOCED) {
113 BTC_TRACE_ERROR("%s() failed - state for id %d is state = %d expected %d", __func__, id,
114 sdp_local_param.sdp_slots[id]->state, SDP_RECORD_ALLOCED);
115 break;
116 }
117 slot->sdp_handle = sdp_handle;
118 slot->record_data = NULL;
119 if (uuid) {
120 memcpy(&slot->uuid, uuid, sizeof(esp_bt_uuid_t));
121 } else {
122 memset(&slot->uuid, 0, sizeof(esp_bt_uuid_t));
123 }
124 } while (0);
125
126 osi_mutex_unlock(&sdp_local_param.sdp_slot_mutex);
127 }
128
get_sdp_slot_info(int id,int * sdp_handle,esp_bt_uuid_t * uuid)129 static void get_sdp_slot_info(int id, int *sdp_handle, esp_bt_uuid_t *uuid)
130 {
131 sdp_slot_t *slot = NULL;
132
133 if(id >= SDP_MAX_RECORDS) {
134 BTC_TRACE_ERROR("%s() failed - id %d is invalid", __func__, id);
135 return;
136 }
137
138 osi_mutex_lock(&sdp_local_param.sdp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT);
139
140 do {
141 slot = sdp_local_param.sdp_slots[id];
142 if (slot == NULL) {
143 break;
144 }
145
146 if (slot->state != SDP_RECORD_ALLOCED) {
147 BTC_TRACE_ERROR("%s() failed - state for id %d is state = %d expected %d", __func__, id,
148 sdp_local_param.sdp_slots[id]->state, SDP_RECORD_ALLOCED);
149 break;
150 }
151
152 if (sdp_handle) {
153 *sdp_handle = slot->sdp_handle;
154 }
155
156 if (uuid) {
157 memcpy(uuid, &slot->uuid, sizeof(esp_bt_uuid_t));
158 }
159 } while (0);
160
161 osi_mutex_unlock(&sdp_local_param.sdp_slot_mutex);
162 }
163
get_sdp_slot_id_by_handle(int handle)164 static int get_sdp_slot_id_by_handle(int handle)
165 {
166 sdp_slot_t *slot = NULL;
167
168 osi_mutex_lock(&sdp_local_param.sdp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT);
169
170 for (int i = 0; i < SDP_MAX_RECORDS; i++) {
171 slot = sdp_local_param.sdp_slots[i];
172 if ((slot != NULL) && (slot->sdp_handle == handle)) {
173 osi_mutex_unlock(&sdp_local_param.sdp_slot_mutex);
174 return i;
175 }
176 }
177
178 osi_mutex_unlock(&sdp_local_param.sdp_slot_mutex);
179 return -1;
180 }
181
start_create_sdp(int id)182 static bluetooth_sdp_record *start_create_sdp(int id)
183 {
184 sdp_slot_t *slot = NULL;
185 bluetooth_sdp_record* record_data = NULL;
186
187 if(id >= SDP_MAX_RECORDS) {
188 BTC_TRACE_ERROR("%s() failed - id %d is invalid", __func__, id);
189 return NULL;
190 }
191
192 osi_mutex_lock(&sdp_local_param.sdp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT);
193
194 do {
195 slot = sdp_local_param.sdp_slots[id];
196 if (slot == NULL) {
197 BTC_TRACE_ERROR("%s() id = %d ", __func__, id);
198 break;
199 }
200
201 if (slot->state != SDP_RECORD_ALLOCED) {
202 BTC_TRACE_ERROR("%s() failed - state for id %d is state = %d expected %d", __func__, id,
203 sdp_local_param.sdp_slots[id]->state, SDP_RECORD_ALLOCED);
204 break;
205 }
206 record_data = slot->record_data;
207 } while (0);
208
209 osi_mutex_unlock(&sdp_local_param.sdp_slot_mutex);
210
211 return record_data;
212 }
213
214 /* Deep copy all content of in_records into out_records.
215 * out_records must point to a chunk of memory large enough to contain all
216 * the data. Use getSdpRecordsSize() to calculate the needed size. */
copy_sdp_record_common(bluetooth_sdp_record * in_record,bluetooth_sdp_record * out_record)217 static void copy_sdp_record_common(bluetooth_sdp_record* in_record, bluetooth_sdp_record* out_record)
218 {
219 uint8_t *free_ptr = (uint8_t *)(out_record + 1); /* set pointer to after the last entry */
220
221 memcpy(out_record, in_record, sizeof(bluetooth_sdp_record));
222
223 if (in_record->hdr.service_name == NULL || in_record->hdr.service_name_length == 0) {
224 out_record->hdr.service_name = NULL;
225 out_record->hdr.service_name_length = 0;
226 } else {
227 out_record->hdr.service_name = (char *)free_ptr; // Update service_name pointer
228 // Copy string
229 memcpy(free_ptr, in_record->hdr.service_name, in_record->hdr.service_name_length);
230 free_ptr += in_record->hdr.service_name_length;
231 *(free_ptr) = '\0'; // Set '\0' termination of string
232 free_ptr++;
233 }
234 }
235
copy_sdp_record(bluetooth_sdp_record * in_record,bluetooth_sdp_record * out_record)236 static void copy_sdp_record(bluetooth_sdp_record* in_record, bluetooth_sdp_record* out_record)
237 {
238 copy_sdp_record_common(in_record, out_record);
239 }
240
alloc_sdp_slot(bluetooth_sdp_record * in_record)241 static int alloc_sdp_slot(bluetooth_sdp_record* in_record)
242 {
243 int i;
244 int record_size = get_sdp_record_size(in_record);
245 bluetooth_sdp_record *record = NULL;
246 sdp_slot_t **slot = NULL;
247
248 record = osi_malloc(record_size);
249 if (record == NULL) {
250 BTC_TRACE_ERROR("%s() osi_malloc failed!", __func__);
251 return -1;
252 }
253
254 copy_sdp_record(in_record, record);
255
256 osi_mutex_lock(&sdp_local_param.sdp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT);
257 for (i = 0; i < SDP_MAX_RECORDS; i++) {
258 slot = &sdp_local_param.sdp_slots[i];
259 if ((*slot) == NULL) {
260 if (((*slot) = (sdp_slot_t *)osi_malloc(sizeof(sdp_slot_t))) == NULL) {
261 osi_mutex_unlock(&sdp_local_param.sdp_slot_mutex);
262 BTC_TRACE_ERROR("%s() osi_malloc slot failed!", __func__);
263 osi_free(record);
264 return -1;
265 }
266 (*slot)->state = SDP_RECORD_ALLOCED;
267 (*slot)->record_data = record;
268 break;
269 }
270 }
271 osi_mutex_unlock(&sdp_local_param.sdp_slot_mutex);
272 if(i >= SDP_MAX_RECORDS) {
273 BTC_TRACE_ERROR("%s() failed - no more free slots!", __func__);
274 osi_free(record);
275 return -1;
276 }
277
278 return i;
279 }
280
free_sdp_slot(int id)281 static int free_sdp_slot(int id)
282 {
283 int handle = -1;
284 bluetooth_sdp_record *record = NULL;
285 sdp_slot_t *slot = NULL;
286
287 if(id >= SDP_MAX_RECORDS) {
288 APPL_TRACE_ERROR("%s() failed - id %d is invalid", __func__, id);
289 return handle;
290 }
291 slot = sdp_local_param.sdp_slots[id];
292 if (slot == NULL) {
293 // already freed
294 return handle;
295 }
296
297 osi_mutex_lock(&sdp_local_param.sdp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT);
298 handle = slot->sdp_handle;
299 if (slot->state != SDP_RECORD_FREE) {
300 /* safe a copy of the pointer, and free after unlock() */
301 record = slot->record_data;
302 }
303 osi_mutex_unlock(&sdp_local_param.sdp_slot_mutex);
304
305 if(record != NULL) {
306 osi_free(record);
307 } else {
308 // Record have already been freed
309 handle = -1;
310 }
311 osi_free(sdp_local_param.sdp_slots[id]);
312 sdp_local_param.sdp_slots[id] = NULL;
313
314 return handle;
315 }
316
317 /* Create a raw SDP record based on information stored in a bluetooth_sdp_raw_record */
add_raw_sdp(const bluetooth_sdp_record * rec)318 static int add_raw_sdp(const bluetooth_sdp_record *rec)
319 {
320 tSDP_PROTOCOL_ELEM protoList [2];
321 UINT16 browse = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
322 bool status = true;
323 // Buffer capable to hold 2, 4 and 16-byte UUIDs
324 UINT8 temp[LEN_UUID_128];
325 UINT8* p_temp = temp;
326 UINT32 sdp_handle = 0;
327 const esp_bt_uuid_t *p_uuid = &rec->hdr.uuid;
328
329 BTC_TRACE_DEBUG("%s(): scn 0x%02x, psm = 0x%04x\n service name %s", __func__,
330 rec->hdr.rfcomm_channel_number, rec->hdr.l2cap_psm, rec->hdr.service_name);
331
332 if ((sdp_handle = SDP_CreateRecord()) == 0) {
333 BTC_TRACE_ERROR("%s(): Unable to register raw sdp record", __func__);
334 return sdp_handle;
335 }
336
337 if (p_uuid->len == ESP_UUID_LEN_16) {
338 UINT8_TO_BE_STREAM (p_temp, (UUID_DESC_TYPE << 3) | SIZE_TWO_BYTES);
339 UINT16_TO_BE_STREAM (p_temp, p_uuid->uuid.uuid16);
340 } else if (p_uuid->len == ESP_UUID_LEN_32) {
341 UINT8_TO_BE_STREAM (p_temp, (UUID_DESC_TYPE << 3) | SIZE_FOUR_BYTES);
342 UINT32_TO_BE_STREAM (p_temp, p_uuid->uuid.uuid32);
343 } else if (p_uuid->len == ESP_UUID_LEN_128) {
344 UINT8_TO_BE_STREAM (p_temp, (UUID_DESC_TYPE << 3) | SIZE_SIXTEEN_BYTES);
345 ARRAY_TO_BE_STREAM (p_temp, p_uuid->uuid.uuid128, LEN_UUID_128);
346 } else {
347 SDP_DeleteRecord(sdp_handle);
348 sdp_handle = 0;
349 return sdp_handle;
350 }
351 /* add service class */
352 status &= SDP_AddAttribute(sdp_handle, ATTR_ID_SERVICE_CLASS_ID_LIST,
353 DATA_ELE_SEQ_DESC_TYPE, (UINT32) (p_temp - temp), temp);
354
355 memset( protoList, 0 , 2*sizeof(tSDP_PROTOCOL_ELEM) );
356
357 /* add protocol list, including RFCOMM scn */
358 protoList[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
359 protoList[0].num_params = 0;
360 if (rec->hdr.rfcomm_channel_number < 0) {
361 status &= SDP_AddProtocolList(sdp_handle, 1, protoList);
362 } else {
363 protoList[1].protocol_uuid = UUID_PROTOCOL_RFCOMM;
364 protoList[1].num_params = 1;
365 protoList[1].params[0] = rec->hdr.rfcomm_channel_number;
366 status &= SDP_AddProtocolList(sdp_handle, 2, protoList);
367 }
368
369 /* Add a name entry */
370 status &= SDP_AddAttribute(sdp_handle,
371 (UINT16)ATTR_ID_SERVICE_NAME,
372 (UINT8)TEXT_STR_DESC_TYPE,
373 (UINT32)(rec->hdr.service_name_length + 1),
374 (UINT8 *)rec->hdr.service_name);
375
376 /* Add the L2CAP PSM if present */
377 if(rec->hdr.l2cap_psm != -1) {
378 p_temp = temp;// The macro modifies p_temp, hence rewind.
379 UINT16_TO_BE_STREAM(p_temp, rec->hdr.l2cap_psm);
380 status &= SDP_AddAttribute(sdp_handle, ATTR_ID_GOEP_L2CAP_PSM,
381 UINT_DESC_TYPE, (UINT32)2, temp);
382 }
383
384 /* Make the service browsable */
385 status &= SDP_AddUuidSequence (sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse);
386
387 if (!status) {
388 SDP_DeleteRecord(sdp_handle);
389 sdp_handle = 0;
390 BTC_TRACE_ERROR("%s() FAILED, status = %d", __func__, status);
391 } else {
392 if (p_uuid->len == ESP_UUID_LEN_16) {
393 bta_sys_add_uuid(p_uuid->uuid.uuid16);
394 } else if (p_uuid->len == ESP_UUID_LEN_32) {
395 bta_sys_add_uuid_32(p_uuid->uuid.uuid32);
396 } else if (p_uuid->len == ESP_UUID_LEN_128) {
397 bta_sys_add_uuid_128((UINT8 *)&p_uuid->uuid.uuid128);
398 }
399 BTC_TRACE_DEBUG("%s(): SDP Registered (handle 0x%08x)", __func__, sdp_handle);
400 }
401
402 return sdp_handle;
403 }
404
405 /* Create a MAP MAS SDP record based on information stored in a bluetooth_sdp_mas_record */
add_maps_sdp(const bluetooth_sdp_mas_record * rec)406 static int add_maps_sdp(const bluetooth_sdp_mas_record* rec)
407 {
408 tSDP_PROTOCOL_ELEM protoList [3];
409 UINT16 service = UUID_SERVCLASS_MESSAGE_ACCESS;
410 UINT16 browse = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
411 bool status = true;
412 UINT32 sdp_handle = 0;
413 UINT8 temp[4];
414 UINT8* p_temp = temp;
415
416 BTC_TRACE_DEBUG("%s(): MASID = 0x%02x, scn 0x%02x, psm = 0x%04x\n service name %s", __func__,
417 rec->mas_instance_id, rec->hdr.rfcomm_channel_number,
418 rec->hdr.l2cap_psm, rec->hdr.service_name);
419
420 BTC_TRACE_DEBUG(" msg_types: 0x%02x, feature_bits: 0x%08x",
421 rec->supported_message_types, rec->supported_features);
422
423 if ((sdp_handle = SDP_CreateRecord()) == 0) {
424 BTC_TRACE_ERROR("%s() - Unable to register MAPS Service", __func__);
425 return sdp_handle;
426 }
427
428 /* add service class */
429 status &= SDP_AddServiceClassIdList(sdp_handle, 1, &service);
430 memset( protoList, 0 , 3*sizeof(tSDP_PROTOCOL_ELEM) );
431
432 /* add protocol list, including RFCOMM scn */
433 protoList[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
434 protoList[0].num_params = 0;
435 protoList[1].protocol_uuid = UUID_PROTOCOL_RFCOMM;
436 protoList[1].num_params = 1;
437 protoList[1].params[0] = rec->hdr.rfcomm_channel_number;
438 protoList[2].protocol_uuid = UUID_PROTOCOL_OBEX;
439 protoList[2].num_params = 0;
440 status &= SDP_AddProtocolList(sdp_handle, 3, protoList);
441
442 /* Add a name entry */
443 status &= SDP_AddAttribute(sdp_handle,
444 (UINT16)ATTR_ID_SERVICE_NAME,
445 (UINT8)TEXT_STR_DESC_TYPE,
446 (UINT32)(rec->hdr.service_name_length + 1),
447 (UINT8 *)rec->hdr.service_name);
448
449 /* Add in the Bluetooth Profile Descriptor List */
450 status &= SDP_AddProfileDescriptorList(sdp_handle,
451 UUID_SERVCLASS_MAP_PROFILE,
452 rec->hdr.profile_version);
453
454 /* Add MAS instance ID */
455 status &= SDP_AddAttribute(sdp_handle, ATTR_ID_MAS_INSTANCE_ID, UINT_DESC_TYPE,
456 (UINT32)1, (UINT8*)&rec->mas_instance_id);
457
458 /* Add supported message types */
459 status &= SDP_AddAttribute(sdp_handle, ATTR_ID_SUPPORTED_MSG_TYPE, UINT_DESC_TYPE,
460 (UINT32)1, (UINT8*)&rec->supported_message_types);
461
462 /* Add supported feature */
463 UINT32_TO_BE_STREAM(p_temp, rec->supported_features);
464 status &= SDP_AddAttribute(sdp_handle, ATTR_ID_MAP_SUPPORTED_FEATURES,
465 UINT_DESC_TYPE, (UINT32)4, temp);
466
467 /* Add the L2CAP PSM if present */
468 if(rec->hdr.l2cap_psm != -1) {
469 p_temp = temp;// The macro modifies p_temp, hence rewind.
470 UINT16_TO_BE_STREAM(p_temp, rec->hdr.l2cap_psm);
471 status &= SDP_AddAttribute(sdp_handle, ATTR_ID_GOEP_L2CAP_PSM,
472 UINT_DESC_TYPE, (UINT32)2, temp);
473 }
474
475 /* Make the service browsable */
476 status &= SDP_AddUuidSequence (sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse);
477
478 if (!status) {
479 SDP_DeleteRecord(sdp_handle);
480 sdp_handle = 0;
481 BTC_TRACE_ERROR("%s() FAILED", __func__);
482 } else {
483 bta_sys_add_uuid(service); /* UUID_SERVCLASS_MESSAGE_ACCESS */
484 BTC_TRACE_DEBUG("%s(): SDP Registered (handle 0x%08x)", __func__, sdp_handle);
485 }
486
487 return sdp_handle;
488 }
489
490 /* Create a MAP MNS SDP record based on information stored in a bluetooth_sdp_mns_record */
add_mapc_sdp(const bluetooth_sdp_mns_record * rec)491 static int add_mapc_sdp(const bluetooth_sdp_mns_record* rec)
492 {
493 tSDP_PROTOCOL_ELEM protoList [3];
494 UINT16 service = UUID_SERVCLASS_MESSAGE_NOTIFICATION;
495 UINT16 browse = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
496 bool status = true;
497 UINT32 sdp_handle = 0;
498 UINT8 temp[4];
499 UINT8* p_temp = temp;
500
501 BTC_TRACE_DEBUG("%s(): scn 0x%02x, psm = 0x%04x\n service name %s", __func__,
502 rec->hdr.rfcomm_channel_number, rec->hdr.l2cap_psm, rec->hdr.service_name);
503
504 BTC_TRACE_DEBUG(" feature_bits: 0x%08x", rec->supported_features);
505
506 if ((sdp_handle = SDP_CreateRecord()) == 0) {
507 BTC_TRACE_ERROR("%s(): Unable to register MAP Notification Service", __func__);
508 return sdp_handle;
509 }
510
511 /* add service class */
512 status &= SDP_AddServiceClassIdList(sdp_handle, 1, &service);
513 memset( protoList, 0 , 3*sizeof(tSDP_PROTOCOL_ELEM) );
514
515 /* add protocol list, including RFCOMM scn */
516 protoList[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
517 protoList[0].num_params = 0;
518 protoList[1].protocol_uuid = UUID_PROTOCOL_RFCOMM;
519 protoList[1].num_params = 1;
520 protoList[1].params[0] = rec->hdr.rfcomm_channel_number;
521 protoList[2].protocol_uuid = UUID_PROTOCOL_OBEX;
522 protoList[2].num_params = 0;
523 status &= SDP_AddProtocolList(sdp_handle, 3, protoList);
524
525 /* Add a name entry */
526 status &= SDP_AddAttribute(sdp_handle,
527 (UINT16)ATTR_ID_SERVICE_NAME,
528 (UINT8)TEXT_STR_DESC_TYPE,
529 (UINT32)(rec->hdr.service_name_length + 1),
530 (UINT8 *)rec->hdr.service_name);
531
532 /* Add in the Bluetooth Profile Descriptor List */
533 status &= SDP_AddProfileDescriptorList(sdp_handle,
534 UUID_SERVCLASS_MAP_PROFILE,
535 rec->hdr.profile_version);
536
537 /* Add supported feature */
538 UINT32_TO_BE_STREAM(p_temp, rec->supported_features);
539 status &= SDP_AddAttribute(sdp_handle, ATTR_ID_MAP_SUPPORTED_FEATURES,
540 UINT_DESC_TYPE, (UINT32)4, temp);
541
542 /* Add the L2CAP PSM if present */
543 if(rec->hdr.l2cap_psm != -1) {
544 p_temp = temp;// The macro modifies p_temp, hence rewind.
545 UINT16_TO_BE_STREAM(p_temp, rec->hdr.l2cap_psm);
546 status &= SDP_AddAttribute(sdp_handle, ATTR_ID_GOEP_L2CAP_PSM,
547 UINT_DESC_TYPE, (UINT32)2, temp);
548 }
549
550 /* Make the service browsable */
551 status &= SDP_AddUuidSequence (sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse);
552
553 if (!status) {
554 SDP_DeleteRecord(sdp_handle);
555 sdp_handle = 0;
556 BTC_TRACE_ERROR("%s() FAILED", __func__);
557 } else {
558 bta_sys_add_uuid(service); /* UUID_SERVCLASS_MESSAGE_ACCESS */
559 BTC_TRACE_DEBUG("%s(): SDP Registered (handle 0x%08x)", __func__, sdp_handle);
560 }
561
562 return sdp_handle;
563 }
564
565 /* Create a PBAP Server SDP record based on information stored in a bluetooth_sdp_pse_record */
add_pbaps_sdp(const bluetooth_sdp_pse_record * rec)566 static int add_pbaps_sdp(const bluetooth_sdp_pse_record* rec)
567 {
568 tSDP_PROTOCOL_ELEM protoList [3];
569 UINT16 service = UUID_SERVCLASS_PBAP_PSE;
570 UINT16 browse = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
571 bool status = true;
572 UINT32 sdp_handle = 0;
573 UINT8 temp[4];
574 UINT8* p_temp = temp;
575
576 BTC_TRACE_DEBUG("%s(): scn 0x%02x, psm = 0x%04x\n service name %s", __func__,
577 rec->hdr.rfcomm_channel_number, rec->hdr.l2cap_psm, rec->hdr.service_name);
578
579 BTC_TRACE_DEBUG(" supported_repositories: 0x%08x, feature_bits: 0x%08x",
580 rec->supported_repositories, rec->supported_features);
581
582 if ((sdp_handle = SDP_CreateRecord()) == 0) {
583 BTC_TRACE_ERROR("%s(): Unable to register PBAP Server Service", __func__);
584 return sdp_handle;
585 }
586
587 /* add service class */
588 status &= SDP_AddServiceClassIdList(sdp_handle, 1, &service);
589 memset( protoList, 0 , 3*sizeof(tSDP_PROTOCOL_ELEM) );
590
591 /* add protocol list, including RFCOMM scn */
592 protoList[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
593 protoList[0].num_params = 0;
594 protoList[1].protocol_uuid = UUID_PROTOCOL_RFCOMM;
595 protoList[1].num_params = 1;
596 protoList[1].params[0] = rec->hdr.rfcomm_channel_number;
597 protoList[2].protocol_uuid = UUID_PROTOCOL_OBEX;
598 protoList[2].num_params = 0;
599 status &= SDP_AddProtocolList(sdp_handle, 3, protoList);
600
601 /* Add a name entry */
602 status &= SDP_AddAttribute(sdp_handle,
603 (UINT16)ATTR_ID_SERVICE_NAME,
604 (UINT8)TEXT_STR_DESC_TYPE,
605 (UINT32)(rec->hdr.service_name_length + 1),
606 (UINT8 *)rec->hdr.service_name);
607
608 /* Add in the Bluetooth Profile Descriptor List */
609 status &= SDP_AddProfileDescriptorList(sdp_handle,
610 UUID_SERVCLASS_PHONE_ACCESS,
611 rec->hdr.profile_version);
612
613 /* Add supported repositories 1 byte */
614 status &= SDP_AddAttribute(sdp_handle, ATTR_ID_SUPPORTED_REPOSITORIES,
615 UINT_DESC_TYPE, (UINT32)1, (UINT8*)&rec->supported_repositories);
616
617 /* Add supported feature 4 bytes*/
618 UINT32_TO_BE_STREAM(p_temp, rec->supported_features);
619 status &= SDP_AddAttribute(sdp_handle, ATTR_ID_PBAP_SUPPORTED_FEATURES,
620 UINT_DESC_TYPE, (UINT32)4, temp);
621
622 /* Add the L2CAP PSM if present */
623 if(rec->hdr.l2cap_psm != -1) {
624 p_temp = temp;// The macro modifies p_temp, hence rewind.
625 UINT16_TO_BE_STREAM(p_temp, rec->hdr.l2cap_psm);
626 status &= SDP_AddAttribute(sdp_handle, ATTR_ID_GOEP_L2CAP_PSM,
627 UINT_DESC_TYPE, (UINT32)2, temp);
628 }
629
630 /* Make the service browsable */
631 status &= SDP_AddUuidSequence (sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse);
632
633 if (!status) {
634 SDP_DeleteRecord(sdp_handle);
635 sdp_handle = 0;
636 BTC_TRACE_ERROR("%s() FAILED, status = %d", __func__, status);
637 } else {
638 bta_sys_add_uuid(service); /* UUID_SERVCLASS_MESSAGE_ACCESS */
639 BTC_TRACE_DEBUG("%s(): SDP Registered (handle 0x%08x)", __func__, sdp_handle);
640 }
641
642 return sdp_handle;
643 }
644
645 /* Create a PBAP Client SDP record based on information stored in a bluetooth_sdp_pse_record */
add_pbapc_sdp(const bluetooth_sdp_pce_record * rec)646 static int add_pbapc_sdp(const bluetooth_sdp_pce_record* rec)
647 {
648 UINT16 service = UUID_SERVCLASS_PBAP_PCE;
649 UINT16 browse = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
650 bool status = true;
651 UINT32 sdp_handle = 0;
652
653 BTC_TRACE_DEBUG("%s(): scn 0x%02x, psm = 0x%04x\n service name %s", __func__,
654 rec->hdr.rfcomm_channel_number, rec->hdr.l2cap_psm, rec->hdr.service_name);
655
656 if ((sdp_handle = SDP_CreateRecord()) == 0) {
657 BTC_TRACE_ERROR("%s(): Unable to register PBAP Client Service", __func__);
658 return sdp_handle;
659 }
660
661 /* add service class */
662 status &= SDP_AddServiceClassIdList(sdp_handle, 1, &service);
663
664 /* Add a name entry */
665 status &= SDP_AddAttribute(sdp_handle,
666 (UINT16)ATTR_ID_SERVICE_NAME,
667 (UINT8)TEXT_STR_DESC_TYPE,
668 (UINT32)(rec->hdr.service_name_length + 1),
669 (UINT8 *)rec->hdr.service_name);
670
671 /* Add in the Bluetooth Profile Descriptor List */
672 status &= SDP_AddProfileDescriptorList(sdp_handle,
673 UUID_SERVCLASS_PHONE_ACCESS,
674 rec->hdr.profile_version);
675
676 /* Make the service browsable */
677 status &= SDP_AddUuidSequence (sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse);
678
679 if (!status) {
680 SDP_DeleteRecord(sdp_handle);
681 sdp_handle = 0;
682 BTC_TRACE_ERROR("%s() FAILED, status = %d", __func__, status);
683 } else {
684 bta_sys_add_uuid(service); /* UUID_SERVCLASS_MESSAGE_ACCESS */
685 BTC_TRACE_DEBUG("%s(): SDP Registered (handle 0x%08x)", __func__, sdp_handle);
686 }
687
688 return sdp_handle;
689 }
690
691
692 /* Create a OPP Server SDP record based on information stored in a bluetooth_sdp_ops_record */
add_opps_sdp(const bluetooth_sdp_ops_record * rec)693 static int add_opps_sdp(const bluetooth_sdp_ops_record* rec)
694 {
695 tSDP_PROTOCOL_ELEM protoList [3];
696 UINT16 service = UUID_SERVCLASS_OBEX_OBJECT_PUSH;
697 UINT16 browse = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
698 UINT8 type_len[rec->supported_formats_list_len];
699 UINT8 desc_type[rec->supported_formats_list_len];
700 UINT8 *type_value[rec->supported_formats_list_len];
701 bool status = true;
702 UINT32 sdp_handle = 0;
703 UINT8 temp[4];
704 UINT8* p_temp = temp;
705 tBTA_UTL_COD cod;
706 int i,j;
707
708 BTC_TRACE_DEBUG("%s(): scn 0x%02x, psm = 0x%04x\n service name %s", __func__,
709 rec->hdr.rfcomm_channel_number, rec->hdr.l2cap_psm, rec->hdr.service_name);
710
711 BTC_TRACE_DEBUG(" supported formats count: %d",
712 rec->supported_formats_list_len);
713
714 if ((sdp_handle = SDP_CreateRecord()) == 0) {
715 BTC_TRACE_ERROR("%s(): Unable to register Object Push Server Service", __func__);
716 return sdp_handle;
717 }
718
719 /* add service class */
720 status &= SDP_AddServiceClassIdList(sdp_handle, 1, &service);
721 memset( protoList, 0 , 3*sizeof(tSDP_PROTOCOL_ELEM) );
722
723 /* add protocol list, including RFCOMM scn */
724 protoList[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
725 protoList[0].num_params = 0;
726 protoList[1].protocol_uuid = UUID_PROTOCOL_RFCOMM;
727 protoList[1].num_params = 1;
728 protoList[1].params[0] = rec->hdr.rfcomm_channel_number;
729 protoList[2].protocol_uuid = UUID_PROTOCOL_OBEX;
730 protoList[2].num_params = 0;
731 status &= SDP_AddProtocolList(sdp_handle, 3, protoList);
732
733 /* Add a name entry */
734 status &= SDP_AddAttribute(sdp_handle,
735 (UINT16)ATTR_ID_SERVICE_NAME,
736 (UINT8)TEXT_STR_DESC_TYPE,
737 (UINT32)(rec->hdr.service_name_length + 1),
738 (UINT8 *)rec->hdr.service_name);
739
740 /* Add in the Bluetooth Profile Descriptor List */
741 status &= SDP_AddProfileDescriptorList(sdp_handle,
742 UUID_SERVCLASS_OBEX_OBJECT_PUSH,
743 rec->hdr.profile_version);
744
745 /* add sequence for supported types */
746 for (i = 0, j = 0; i < rec->supported_formats_list_len; i++) {
747 type_value[j] = (UINT8 *) &rec->supported_formats_list[i];
748 desc_type[j] = UINT_DESC_TYPE;
749 type_len[j++] = 1;
750 }
751
752 status &= SDP_AddSequence(sdp_handle, (UINT16) ATTR_ID_SUPPORTED_FORMATS_LIST,
753 (UINT8) rec->supported_formats_list_len, desc_type, type_len, type_value);
754
755 /* Add the L2CAP PSM if present */
756 if(rec->hdr.l2cap_psm != -1) {
757 p_temp = temp;// The macro modifies p_temp, hence rewind.
758 UINT16_TO_BE_STREAM(p_temp, rec->hdr.l2cap_psm);
759 status &= SDP_AddAttribute(sdp_handle, ATTR_ID_GOEP_L2CAP_PSM,
760 UINT_DESC_TYPE, (UINT32)2, temp);
761 }
762
763 /* Make the service browsable */
764 status &= SDP_AddUuidSequence (sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse);
765
766 if (!status) {
767 SDP_DeleteRecord(sdp_handle);
768 sdp_handle = 0;
769 BTC_TRACE_ERROR("%s() FAILED", __func__);
770 } else {
771 /* set class of device */
772 cod.service = BTM_COD_SERVICE_OBJ_TRANSFER;
773 utl_set_device_class(&cod, BTA_UTL_SET_COD_SERVICE_CLASS);
774
775 bta_sys_add_uuid(service); /* UUID_SERVCLASS_OBEX_OBJECT_PUSH */
776 BTC_TRACE_DEBUG("%s(): SDP Registered (handle 0x%08x)", __func__, sdp_handle);
777 }
778
779 return sdp_handle;
780 }
781
782 // Create a Sim Access Profile SDP record based on information stored in a bluetooth_sdp_sap_record.
add_saps_sdp(const bluetooth_sdp_sap_record * rec)783 static int add_saps_sdp(const bluetooth_sdp_sap_record* rec)
784 {
785 tSDP_PROTOCOL_ELEM protoList [2];
786 UINT16 services[2];
787 UINT16 browse = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
788 bool status = true;
789 UINT32 sdp_handle = 0;
790
791 BTC_TRACE_DEBUG("%s(): scn 0x%02x, service name %s", __func__,
792 rec->hdr.rfcomm_channel_number, rec->hdr.service_name);
793
794 if ((sdp_handle = SDP_CreateRecord()) == 0) {
795 BTC_TRACE_ERROR("%s(): Unable to register SAPS Service", __func__);
796 return sdp_handle;
797 }
798
799 services[0] = UUID_SERVCLASS_SAP;
800 services[1] = UUID_SERVCLASS_GENERIC_TELEPHONY;
801
802 // add service class
803 status &= SDP_AddServiceClassIdList(sdp_handle, 2, services);
804 memset(protoList, 0, 2 * sizeof(tSDP_PROTOCOL_ELEM));
805
806 // add protocol list, including RFCOMM scn
807 protoList[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
808 protoList[0].num_params = 0;
809 protoList[1].protocol_uuid = UUID_PROTOCOL_RFCOMM;
810 protoList[1].num_params = 1;
811 protoList[1].params[0] = rec->hdr.rfcomm_channel_number;
812 status &= SDP_AddProtocolList(sdp_handle, 2, protoList);
813
814 // Add a name entry
815 status &= SDP_AddAttribute(sdp_handle,
816 (UINT16)ATTR_ID_SERVICE_NAME,
817 (UINT8)TEXT_STR_DESC_TYPE,
818 (UINT32)(rec->hdr.service_name_length + 1),
819 (UINT8 *)rec->hdr.service_name);
820
821 // Add in the Bluetooth Profile Descriptor List
822 status &= SDP_AddProfileDescriptorList(sdp_handle,
823 UUID_SERVCLASS_SAP,
824 rec->hdr.profile_version);
825
826 // Make the service browsable
827 status &= SDP_AddUuidSequence (sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse);
828
829 if (!status) {
830 SDP_DeleteRecord(sdp_handle);
831 sdp_handle = 0;
832 BTC_TRACE_ERROR("%s(): FAILED deleting record", __func__);
833 } else {
834 bta_sys_add_uuid(UUID_SERVCLASS_SAP);
835 BTC_TRACE_DEBUG("%s(): SDP Registered (handle 0x%08x)", __func__, sdp_handle);
836 }
837
838 return sdp_handle;
839 }
840
btc_handle_create_record_event(int id)841 static int btc_handle_create_record_event(int id)
842 {
843 int sdp_handle = 0;
844 bluetooth_sdp_record *record = start_create_sdp(id);
845 esp_bt_uuid_t service_uuid = {0};
846
847 BTC_TRACE_DEBUG("Sdp Server %s", __func__);
848
849 if (record != NULL) {
850 switch (record->hdr.type) {
851 case SDP_TYPE_RAW:
852 sdp_handle = add_raw_sdp(record);
853 memcpy(&service_uuid, &record->hdr.uuid, sizeof(esp_bt_uuid_t));
854 break;
855 case SDP_TYPE_MAP_MAS:
856 sdp_handle = add_maps_sdp(&record->mas);
857 service_uuid.len = ESP_UUID_LEN_16;
858 service_uuid.uuid.uuid16 = UUID_SERVCLASS_MESSAGE_ACCESS;
859 break;
860 case SDP_TYPE_MAP_MNS:
861 sdp_handle = add_mapc_sdp(&record->mns);
862 service_uuid.len = ESP_UUID_LEN_16;
863 service_uuid.uuid.uuid16 = UUID_SERVCLASS_MESSAGE_NOTIFICATION;
864 break;
865 case SDP_TYPE_PBAP_PSE:
866 sdp_handle = add_pbaps_sdp(&record->pse);
867 service_uuid.len = ESP_UUID_LEN_16;
868 service_uuid.uuid.uuid16 = UUID_SERVCLASS_PBAP_PSE;
869 break;
870 case SDP_TYPE_PBAP_PCE:
871 sdp_handle = add_pbapc_sdp(&record->pce);
872 service_uuid.len = ESP_UUID_LEN_16;
873 service_uuid.uuid.uuid16 = UUID_SERVCLASS_PBAP_PCE;
874 break;
875 case SDP_TYPE_OPP_SERVER:
876 sdp_handle = add_opps_sdp(&record->ops);
877 service_uuid.len = ESP_UUID_LEN_16;
878 service_uuid.uuid.uuid16 = UUID_SERVCLASS_OBEX_OBJECT_PUSH;
879 break;
880 case SDP_TYPE_SAP_SERVER:
881 sdp_handle = add_saps_sdp(&record->sap);
882 service_uuid.len = ESP_UUID_LEN_16;
883 service_uuid.uuid.uuid16 = UUID_SERVCLASS_SAP;
884 break;
885 default:
886 BTC_TRACE_DEBUG("Record type %d is not supported", record->hdr.type);
887 break;
888 }
889
890 if(sdp_handle != 0) {
891 set_sdp_slot_info(id, sdp_handle, &service_uuid);
892 // free the record, since not use it anymore
893 osi_free(record);
894 } else {
895 sdp_handle = -1;
896 }
897 } else {
898 sdp_handle = -1;
899 }
900
901 if (sdp_handle == -1) {
902 free_sdp_slot(id);
903 }
904
905 return sdp_handle;
906 }
907
btc_sdp_remove_record_event(int id,int * p_sdp_handle)908 static bool btc_sdp_remove_record_event(int id, int *p_sdp_handle)
909 {
910 BTC_TRACE_DEBUG("Sdp Server %s", __func__);
911
912 bool result = false;
913 int sdp_handle = -1;
914 esp_bt_uuid_t service_uuid = {0};
915
916 get_sdp_slot_info(id, &sdp_handle, &service_uuid);
917
918 if (sdp_handle > 0) {
919 do {
920 result = SDP_DeleteRecord(sdp_handle);
921 if (!result) {
922 BTC_TRACE_ERROR("Unable to remove handle 0x%08x", sdp_handle);
923 break;
924 }
925
926 if (service_uuid.len == ESP_UUID_LEN_16) {
927 bta_sys_remove_uuid(service_uuid.uuid.uuid16);
928 } else if (service_uuid.len == ESP_UUID_LEN_32) {
929 bta_sys_remove_uuid_32(service_uuid.uuid.uuid32);
930 } else if (service_uuid.len == ESP_UUID_LEN_128) {
931 bta_sys_remove_uuid_128((UINT8 *)&service_uuid.uuid.uuid128);
932 }
933 } while (0);
934
935 if (p_sdp_handle) {
936 *p_sdp_handle = sdp_handle;
937 }
938 }
939
940 return result;
941 }
942
btc_sdp_cb_arg_deep_copy(btc_msg_t * msg,void * p_dest,void * p_src)943 static void btc_sdp_cb_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src)
944 {
945 switch (msg->act) {
946 case BTA_SDP_SEARCH_COMP_EVT: {
947 tBTA_SDP_SEARCH_COMP *src_search_comp = (tBTA_SDP_SEARCH_COMP *)p_src;
948 tBTA_SDP_SEARCH_COMP *dest_search_comp = (tBTA_SDP_SEARCH_COMP *)p_dest;
949 int record_count = src_search_comp->record_count;
950
951 for (int i = 0; i < record_count; i++) {
952 bluetooth_sdp_record *src_record = &src_search_comp->records[i];
953 bluetooth_sdp_record *dest_record = &dest_search_comp->records[i];
954 // deep copy service name
955 uint32_t src_service_name_length = src_record->hdr.service_name_length;
956 char *src_service_name = src_record->hdr.service_name;
957 dest_record->hdr.service_name_length = 0;
958 dest_record->hdr.service_name = NULL;
959 if (src_service_name && src_service_name_length) {
960 char *service_name = (char *)osi_malloc(src_service_name_length + 1);
961 if (service_name) {
962 memcpy(service_name, src_service_name, src_service_name_length);
963 service_name[src_service_name_length] = '\0';
964
965 dest_record->hdr.service_name_length = src_service_name_length;
966 dest_record->hdr.service_name = service_name;
967 } else {
968 BTC_TRACE_ERROR("%s malloc service name failed, orig service name:%s", __func__, src_service_name);
969 }
970 }
971
972 // deep copy user1_ptr fow RAW type
973 int src_user1_ptr_len = src_record->hdr.user1_ptr_len;
974 uint8_t *src_user1_ptr = src_record->hdr.user1_ptr;
975 dest_record->hdr.user1_ptr_len = 0;
976 dest_record->hdr.user1_ptr = NULL;
977 if (src_record->hdr.type == SDP_TYPE_RAW && src_user1_ptr && src_user1_ptr_len) {
978 uint8_t *user1_ptr = (uint8_t *)osi_malloc(src_user1_ptr_len);
979 if (user1_ptr) {
980 memcpy(user1_ptr, src_user1_ptr, src_user1_ptr_len);
981
982 dest_record->hdr.user1_ptr_len = src_user1_ptr_len;
983 dest_record->hdr.user1_ptr = user1_ptr;
984 } else {
985 BTC_TRACE_ERROR("%s malloc user1_ptr failed", __func__);
986 }
987 }
988 }
989
990 break;
991 }
992 default:
993 break;
994 }
995 }
996
btc_sdp_cb_arg_deep_free(btc_msg_t * msg)997 static void btc_sdp_cb_arg_deep_free(btc_msg_t *msg)
998 {
999 switch (msg->act) {
1000 case BTA_SDP_SEARCH_COMP_EVT: {
1001 tBTA_SDP_SEARCH_COMP *search_comp = (tBTA_SDP_SEARCH_COMP *)msg->arg;
1002 for (size_t i = 0; i < search_comp->record_count; i++) {
1003 bluetooth_sdp_record *record = &search_comp->records[i];
1004 if (record->hdr.service_name) {
1005 osi_free(record->hdr.service_name);
1006 }
1007
1008 if (record->hdr.user1_ptr) {
1009 osi_free(record->hdr.user1_ptr);
1010 }
1011 }
1012
1013 break;
1014 }
1015 default:
1016 break;
1017 }
1018 }
1019
btc_sdp_dm_cback(tBTA_SDP_EVT event,tBTA_SDP * p_data,void * user_data)1020 static void btc_sdp_dm_cback(tBTA_SDP_EVT event, tBTA_SDP* p_data, void* user_data)
1021 {
1022 btc_msg_t msg;
1023 bt_status_t status;
1024
1025 switch (event) {
1026 case BTA_SDP_CREATE_RECORD_USER_EVT: {
1027 if (p_data->sdp_create_record.status == BTA_SDP_SUCCESS) {
1028 p_data->sdp_create_record.handle = btc_handle_create_record_event((int)user_data);
1029 if (p_data->sdp_create_record.handle < 0) {
1030 p_data->sdp_create_record.status = BTA_SDP_FAILURE;
1031 }
1032 }
1033 }
1034 break;
1035 case BTA_SDP_REMOVE_RECORD_USER_EVT: {
1036 if (p_data->sdp_remove_record.status == BTA_SDP_SUCCESS) {
1037 if (btc_sdp_remove_record_event((int)user_data, &p_data->sdp_remove_record.handle) == false) {
1038 p_data->sdp_remove_record.status = BTA_SDP_FAILURE;
1039 }
1040 }
1041 }
1042 break;
1043 default:
1044 break;
1045 }
1046
1047 msg.sig = BTC_SIG_API_CB;
1048 msg.pid = BTC_PID_SDP;
1049 msg.act = event;
1050
1051 status = btc_transfer_context(&msg, p_data, sizeof(tBTA_SDP), btc_sdp_cb_arg_deep_copy, btc_sdp_cb_arg_deep_free);
1052
1053 if (status != BT_STATUS_SUCCESS) {
1054 BTC_TRACE_ERROR("%s btc_transfer_context failed", __func__);
1055 }
1056 }
1057
btc_sdp_init(void)1058 static void btc_sdp_init(void)
1059 {
1060 esp_sdp_cb_param_t param;
1061 esp_sdp_status_t ret = ESP_SDP_SUCCESS;
1062
1063 do {
1064 if (is_sdp_init()) {
1065 BTC_TRACE_ERROR("%s SDP has been initiated, shall deinit first!", __func__);
1066 ret = ESP_SDP_NEED_DEINIT;
1067 break;
1068 }
1069
1070 #if SDP_DYNAMIC_MEMORY == TRUE
1071 if ((sdp_local_param_ptr = (sdp_local_param_t *)osi_malloc(sizeof(sdp_local_param_t))) == NULL) {
1072 BTC_TRACE_ERROR("%s malloc failed\n", __func__);
1073 ret = ESP_SDP_NO_RESOURCE;
1074 break;
1075 }
1076 #endif
1077 memset(&sdp_local_param, 0, sizeof(sdp_local_param_t));
1078
1079 if (osi_mutex_new(&sdp_local_param.sdp_slot_mutex) != 0) {
1080 BTC_TRACE_ERROR("%s osi_mutex_new failed\n", __func__);
1081 ret = ESP_SDP_NO_RESOURCE;
1082 break;
1083 }
1084
1085 ret = BTA_SdpEnable(btc_sdp_dm_cback);
1086 if (ret != ESP_SDP_SUCCESS) {
1087 BTC_TRACE_ERROR("%s BTA_SdpEnable failed, ret = %d\n", __func__, ret);
1088 ret = ESP_SDP_FAILURE;
1089 break;
1090 }
1091
1092 sdp_local_param.search_allowed = true;
1093 } while(0);
1094
1095 if (ret != ESP_SDP_SUCCESS) {
1096 btc_sdp_cleanup();
1097 param.init.status = ret;
1098 btc_sdp_cb_to_app(ESP_SDP_INIT_EVT, ¶m);
1099 }
1100 }
1101
btc_sdp_deinit(void)1102 static void btc_sdp_deinit(void)
1103 {
1104 esp_sdp_cb_param_t param;
1105 esp_sdp_status_t ret = ESP_SDP_SUCCESS;
1106
1107 do {
1108 if (!is_sdp_init()) {
1109 BTC_TRACE_ERROR("%s SDP has not been initiated, shall init first!", __func__);
1110 ret = ESP_SDP_NEED_INIT;
1111 break;
1112 }
1113
1114 for(int i = 0; i < SDP_MAX_RECORDS; i++) {
1115 int sdp_handle = -1;
1116 get_sdp_slot_info(i, &sdp_handle, NULL);
1117 if (sdp_handle > 0) {
1118 BTA_SdpRemoveRecordByUser((void*)i);
1119 }
1120 }
1121 BTA_SdpDisable();
1122 } while(0);
1123
1124 if (ret != ESP_SDP_SUCCESS) {
1125 param.deinit.status = ret;
1126 btc_sdp_cb_to_app(ESP_SDP_DEINIT_EVT, ¶m);
1127 }
1128 }
1129
btc_sdp_create_record(btc_sdp_args_t * arg)1130 static void btc_sdp_create_record(btc_sdp_args_t *arg)
1131 {
1132 int slot_id;
1133 esp_sdp_cb_param_t param;
1134 esp_sdp_status_t ret = ESP_SDP_SUCCESS;
1135
1136 do {
1137 if (!is_sdp_init()) {
1138 BTC_TRACE_ERROR("%s SDP has not been initiated, shall init first!", __func__);
1139 ret = ESP_SDP_NEED_INIT;
1140 break;
1141 }
1142
1143 slot_id = alloc_sdp_slot(arg->create_record.record);
1144 if (slot_id < 0) {
1145 ret = ESP_SDP_FAILURE;
1146 break;
1147 }
1148
1149 BTA_SdpCreateRecordByUser((void *) slot_id);
1150 } while(0);
1151
1152 if (ret != ESP_SDP_SUCCESS) {
1153 param.create_record.status = ret;
1154 param.create_record.record_handle = -1;
1155 btc_sdp_cb_to_app(ESP_SDP_CREATE_RECORD_COMP_EVT, ¶m);
1156 }
1157 }
1158
btc_sdp_remove_record(btc_sdp_args_t * arg)1159 static void btc_sdp_remove_record(btc_sdp_args_t *arg)
1160 {
1161 esp_sdp_cb_param_t param;
1162 esp_sdp_status_t ret = ESP_SDP_SUCCESS;
1163
1164 do {
1165 if (!is_sdp_init()) {
1166 BTC_TRACE_ERROR("%s SDP has not been initiated, shall init first!", __func__);
1167 ret = ESP_SDP_NEED_INIT;
1168 break;
1169 }
1170
1171 /* Get the Record handle, and free the slot */
1172 /* The application layer record_handle is equivalent to the id of the btc layer */
1173 int slot_id = get_sdp_slot_id_by_handle(arg->remove_record.record_handle);
1174 if (slot_id < 0) {
1175 BTC_TRACE_ERROR("%s SDP record with handle %d not found", __func__, arg->remove_record.record_handle);
1176 ret = ESP_SDP_NO_CREATE_RECORD;
1177 break;
1178 }
1179
1180 BTA_SdpRemoveRecordByUser((void *)slot_id);
1181 } while(0);
1182
1183 if (ret != ESP_SDP_SUCCESS) {
1184 param.create_record.status = ret;
1185 btc_sdp_cb_to_app(ESP_SDP_REMOVE_RECORD_COMP_EVT, ¶m);
1186 }
1187 }
1188
btc_sdp_search(btc_sdp_args_t * arg)1189 static void btc_sdp_search(btc_sdp_args_t *arg)
1190 {
1191 esp_sdp_cb_param_t param = {0};
1192 esp_sdp_status_t ret = ESP_SDP_SUCCESS;
1193
1194 do {
1195 if (!is_sdp_init()) {
1196 BTC_TRACE_ERROR("%s SDP has not been initiated, shall init first!", __func__);
1197 ret = ESP_SDP_NEED_INIT;
1198 break;
1199 }
1200
1201 if (!sdp_local_param.search_allowed) {
1202 BTC_TRACE_ERROR("%s SDP search is not allowed!", __func__);
1203 ret = ESP_SDP_NO_RESOURCE;
1204 break;
1205 }
1206
1207 BTA_SdpSearch(arg->search.bd_addr, &arg->search.sdp_uuid);
1208 /**
1209 * ESP_SDP_SEARCH_COMP_EVT will refer service name in BTA sdp database, so it is not allowed to be search until
1210 * the previous search is completed
1211 */
1212 sdp_local_param.search_allowed = false;
1213 } while(0);
1214
1215 if (ret != ESP_SDP_SUCCESS) {
1216 param.search.status = ret;
1217 btc_sdp_cb_to_app(ESP_SDP_SEARCH_COMP_EVT, ¶m);
1218 }
1219 }
1220
btc_sdp_arg_deep_copy(btc_msg_t * msg,void * p_dest,void * p_src)1221 void btc_sdp_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src)
1222 {
1223 switch (msg->act) {
1224 case BTC_SDP_ACT_CREATE_RECORD: {
1225 bluetooth_sdp_record **dst_record = &((btc_sdp_args_t *)p_dest)->create_record.record;
1226 bluetooth_sdp_record *src_record = ((btc_sdp_args_t *)p_src)->create_record.record;
1227 bluetooth_sdp_record *record = (bluetooth_sdp_record *)osi_calloc(get_sdp_record_size(src_record));
1228 if (record) {
1229 copy_sdp_record(src_record, record);
1230 } else {
1231 BTC_TRACE_ERROR("%s %d osi_malloc failed\n", __func__, msg->act);
1232 break;
1233 }
1234
1235 *dst_record = record;
1236 break;
1237 }
1238 default:
1239 break;
1240 }
1241 }
1242
btc_sdp_arg_deep_free(btc_msg_t * msg)1243 void btc_sdp_arg_deep_free(btc_msg_t *msg)
1244 {
1245 switch (msg->act) {
1246 case BTC_SDP_ACT_CREATE_RECORD: {
1247 btc_sdp_args_t *arg = (btc_sdp_args_t *)msg->arg;
1248 bluetooth_sdp_record *record = arg->create_record.record;
1249 if (record) {
1250 osi_free(record);
1251 }
1252 break;
1253 }
1254 default:
1255 break;
1256 }
1257 }
1258
btc_sdp_call_handler(btc_msg_t * msg)1259 void btc_sdp_call_handler(btc_msg_t *msg)
1260 {
1261 btc_sdp_args_t *arg = (btc_sdp_args_t *)(msg->arg);
1262
1263 BTC_TRACE_DEBUG("%s: event = %d\n", __func__, msg->act);
1264
1265 switch (msg->act) {
1266 case BTC_SDP_ACT_INIT:
1267 btc_sdp_init();
1268 break;
1269 case BTC_SDP_ACT_DEINIT:
1270 btc_sdp_deinit();
1271 break;
1272 case BTC_SDP_ACT_SEARCH:
1273 btc_sdp_search(arg);
1274 break;
1275 case BTC_SDP_ACT_CREATE_RECORD:
1276 btc_sdp_create_record(arg);
1277 break;
1278 case BTC_SDP_ACT_REMOVE_RECORD:
1279 btc_sdp_remove_record(arg);
1280 break;
1281 default:
1282 BTC_TRACE_ERROR("%s: Unhandled event (%d)!\n", __func__, msg->act);
1283 break;
1284 }
1285 btc_sdp_arg_deep_free(msg);
1286 }
1287
btc_sdp_cb_handler(btc_msg_t * msg)1288 void btc_sdp_cb_handler(btc_msg_t *msg)
1289 {
1290 esp_sdp_cb_param_t param = {0};
1291 uint8_t event = msg->act;
1292 tBTA_SDP *p_data = (tBTA_SDP *)msg->arg;
1293
1294 switch(event) {
1295 case BTA_SDP_ENABLE_EVT:
1296 param.init.status = p_data->status;
1297 btc_sdp_cb_to_app(ESP_SDP_INIT_EVT, ¶m);
1298 break;
1299 case BTA_SDP_DISABLE_EVT:
1300 BTA_SdpCleanup();
1301 btc_sdp_cleanup();
1302 param.deinit.status = ESP_SDP_SUCCESS;
1303 btc_sdp_cb_to_app(ESP_SDP_DEINIT_EVT, ¶m);
1304 break;
1305 case BTA_SDP_SEARCH_COMP_EVT:
1306 // SDP search completed, now can be searched again
1307 sdp_local_param.search_allowed = true;
1308
1309 param.search.status = p_data->sdp_search_comp.status;
1310 memcpy(param.search.remote_addr, p_data->sdp_search_comp.remote_addr, sizeof(BD_ADDR));
1311 bta_to_btc_uuid(¶m.search.sdp_uuid, &p_data->sdp_search_comp.uuid);
1312 param.search.record_count = p_data->sdp_search_comp.record_count;
1313 param.search.records = (esp_bluetooth_sdp_record_t *)p_data->sdp_search_comp.records;
1314 btc_sdp_cb_to_app(ESP_SDP_SEARCH_COMP_EVT, ¶m);
1315 break;
1316 case BTA_SDP_CREATE_RECORD_USER_EVT:
1317 param.create_record.status = p_data->sdp_create_record.status;
1318 param.create_record.record_handle = p_data->sdp_create_record.handle;
1319 btc_sdp_cb_to_app(ESP_SDP_CREATE_RECORD_COMP_EVT, ¶m);
1320 break;
1321 case BTA_SDP_REMOVE_RECORD_USER_EVT:
1322 if (p_data->sdp_remove_record.status == BTA_SDP_SUCCESS) {
1323 int slot_id = get_sdp_slot_id_by_handle(p_data->sdp_remove_record.handle);
1324 if (slot_id < 0) {
1325 p_data->sdp_remove_record.status = ESP_SDP_NO_CREATE_RECORD;
1326 break;
1327 } else {
1328 free_sdp_slot(slot_id);
1329 }
1330 }
1331
1332 param.remove_record.status = p_data->sdp_remove_record.status;
1333 btc_sdp_cb_to_app(ESP_SDP_REMOVE_RECORD_COMP_EVT, ¶m);
1334 break;
1335 default:
1336 BTC_TRACE_DEBUG("%s: Unhandled event (%d)!", __func__, msg->act);
1337 break;
1338 }
1339
1340 btc_sdp_cb_arg_deep_free(msg);
1341 }
1342
1343 #endif ///defined BTC_SDP_INCLUDED && BTC_SDP_INCLUDED == TRUE
1344