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, &param);
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, &param);
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, &param);
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, &param);
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, &param);
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, &param);
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, &param);
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(&param.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, &param);
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, &param);
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, &param);
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