The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1 | /****************************************************************************** |
| 2 | * |
| 3 | * Copyright (C) 1999-2012 Broadcom Corporation |
| 4 | * |
| 5 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 6 | * you may not use this file except in compliance with the License. |
| 7 | * You may obtain a copy of the License at: |
| 8 | * |
| 9 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 10 | * |
| 11 | * Unless required by applicable law or agreed to in writing, software |
| 12 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 14 | * See the License for the specific language governing permissions and |
| 15 | * limitations under the License. |
| 16 | * |
| 17 | ******************************************************************************/ |
| 18 | |
| 19 | /****************************************************************************** |
| 20 | * |
| 21 | * this file contains functions that handle the database |
| 22 | * |
| 23 | ******************************************************************************/ |
| 24 | |
| 25 | #include <stdlib.h> |
| 26 | #include <string.h> |
| 27 | #include <stdio.h> |
| 28 | |
| 29 | #include "bt_target.h" |
| 30 | |
| 31 | #include "gki.h" |
| 32 | |
| 33 | #include "l2cdefs.h" |
| 34 | #include "hcidefs.h" |
| 35 | #include "hcimsgs.h" |
| 36 | |
| 37 | #include "sdp_api.h" |
| 38 | #include "sdpint.h" |
| 39 | #include "wbt_api.h" |
| 40 | |
| 41 | #if SDP_SERVER_ENABLED == TRUE |
| 42 | /********************************************************************************/ |
| 43 | /* L O C A L F U N C T I O N P R O T O T Y P E S */ |
| 44 | /********************************************************************************/ |
| 45 | static BOOLEAN find_uuid_in_seq (UINT8 *p , UINT32 seq_len, UINT8 *p_his_uuid, |
| 46 | UINT16 his_len, int nest_level); |
| 47 | |
| 48 | |
| 49 | /******************************************************************************* |
| 50 | ** |
| 51 | ** Function sdp_db_service_search |
| 52 | ** |
| 53 | ** Description This function searches for a record that contains the |
| 54 | ** specified UIDs. It is passed either NULL to start at the |
| 55 | ** beginning, or the previous record found. |
| 56 | ** |
| 57 | ** Returns Pointer to the record, or NULL if not found. |
| 58 | ** |
| 59 | *******************************************************************************/ |
| 60 | tSDP_RECORD *sdp_db_service_search (tSDP_RECORD *p_rec, tSDP_UUID_SEQ *p_seq) |
| 61 | { |
| 62 | UINT16 xx, yy; |
| 63 | tSDP_ATTRIBUTE *p_attr; |
| 64 | tSDP_RECORD *p_end = &sdp_cb.server_db.record[sdp_cb.server_db.num_records]; |
| 65 | |
| 66 | /* If NULL, start at the beginning, else start at the first specified record */ |
| 67 | if (!p_rec) |
| 68 | p_rec = &sdp_cb.server_db.record[0]; |
| 69 | else |
| 70 | p_rec++; |
| 71 | |
| 72 | /* Look through the records. The spec says that a match occurs if */ |
| 73 | /* the record contains all the passed UUIDs in it. */ |
| 74 | for ( ; p_rec < p_end; p_rec++) |
| 75 | { |
| 76 | for (yy = 0; yy < p_seq->num_uids; yy++) |
| 77 | { |
| 78 | p_attr = &p_rec->attribute[0]; |
| 79 | for (xx = 0; xx < p_rec->num_attributes; xx++, p_attr++) |
| 80 | { |
| 81 | if (p_attr->type == UUID_DESC_TYPE) |
| 82 | { |
| 83 | if (sdpu_compare_uuid_arrays (p_attr->value_ptr, p_attr->len, |
| 84 | &p_seq->uuid_entry[yy].value[0], |
| 85 | p_seq->uuid_entry[yy].len)) |
| 86 | break; |
| 87 | } |
| 88 | else if (p_attr->type == DATA_ELE_SEQ_DESC_TYPE) |
| 89 | { |
| 90 | if (find_uuid_in_seq (p_attr->value_ptr, p_attr->len, |
| 91 | &p_seq->uuid_entry[yy].value[0], |
| 92 | p_seq->uuid_entry[yy].len, 0)) |
| 93 | break; |
| 94 | } |
| 95 | } |
| 96 | /* If any UUID was not found, on to the next record */ |
| 97 | if (xx == p_rec->num_attributes) |
| 98 | break; |
| 99 | } |
| 100 | |
| 101 | /* If every UUID was found in the record, return the record */ |
| 102 | if (yy == p_seq->num_uids) |
| 103 | return (p_rec); |
| 104 | } |
| 105 | |
| 106 | /* If here, no more records found */ |
| 107 | return (NULL); |
| 108 | } |
| 109 | |
| 110 | /******************************************************************************* |
| 111 | ** |
| 112 | ** Function find_uuid_in_seq |
| 113 | ** |
| 114 | ** Description This function searches a data element sequenct for a UUID. |
| 115 | ** |
| 116 | ** Returns TRUE if found, else FALSE |
| 117 | ** |
| 118 | *******************************************************************************/ |
| 119 | static BOOLEAN find_uuid_in_seq (UINT8 *p , UINT32 seq_len, UINT8 *p_uuid, |
| 120 | UINT16 uuid_len, int nest_level) |
| 121 | { |
| 122 | UINT8 *p_end = p + seq_len; |
| 123 | UINT8 type; |
| 124 | UINT32 len; |
| 125 | |
| 126 | /* A little safety check to avoid excessive recursion */ |
| 127 | if (nest_level > 3) |
| 128 | return (FALSE); |
| 129 | |
| 130 | while (p < p_end) |
| 131 | { |
| 132 | type = *p++; |
| 133 | p = sdpu_get_len_from_type (p, type, &len); |
| 134 | type = type >> 3; |
| 135 | if (type == UUID_DESC_TYPE) |
| 136 | { |
| 137 | if (sdpu_compare_uuid_arrays (p, len, p_uuid, uuid_len)) |
| 138 | return (TRUE); |
| 139 | } |
| 140 | else if (type == DATA_ELE_SEQ_DESC_TYPE) |
| 141 | { |
| 142 | if (find_uuid_in_seq (p, len, p_uuid, uuid_len, nest_level + 1)) |
| 143 | return (TRUE); |
| 144 | } |
| 145 | p = p + len; |
| 146 | } |
| 147 | |
| 148 | /* If here, failed to match */ |
| 149 | return (FALSE); |
| 150 | } |
| 151 | |
| 152 | /******************************************************************************* |
| 153 | ** |
| 154 | ** Function sdp_db_find_record |
| 155 | ** |
| 156 | ** Description This function searches for a record with a specific handle |
| 157 | ** It is passed the handle of the record. |
| 158 | ** |
| 159 | ** Returns Pointer to the record, or NULL if not found. |
| 160 | ** |
| 161 | *******************************************************************************/ |
| 162 | tSDP_RECORD *sdp_db_find_record (UINT32 handle) |
| 163 | { |
| 164 | tSDP_RECORD *p_rec; |
| 165 | tSDP_RECORD *p_end = &sdp_cb.server_db.record[sdp_cb.server_db.num_records]; |
| 166 | |
| 167 | /* Look through the records for the caller's handle */ |
| 168 | for (p_rec = &sdp_cb.server_db.record[0]; p_rec < p_end; p_rec++) |
| 169 | { |
| 170 | if (p_rec->record_handle == handle) |
| 171 | return (p_rec); |
| 172 | } |
| 173 | |
| 174 | /* Record with that handle not found. */ |
| 175 | return (NULL); |
| 176 | } |
| 177 | |
| 178 | /******************************************************************************* |
| 179 | ** |
| 180 | ** Function sdp_db_find_attr_in_rec |
| 181 | ** |
| 182 | ** Description This function searches a record for specific attributes. |
| 183 | ** It is passed a pointer to the record. If the record contains |
| 184 | ** the specified attribute, (the caller may specify be a range |
| 185 | ** of attributes), the attribute is returned. |
| 186 | ** |
| 187 | ** Returns Pointer to the attribute, or NULL if not found. |
| 188 | ** |
| 189 | *******************************************************************************/ |
| 190 | tSDP_ATTRIBUTE *sdp_db_find_attr_in_rec (tSDP_RECORD *p_rec, UINT16 start_attr, |
| 191 | UINT16 end_attr) |
| 192 | { |
| 193 | tSDP_ATTRIBUTE *p_at; |
| 194 | UINT16 xx; |
| 195 | |
| 196 | /* Note that the attributes in a record are assumed to be in sorted order */ |
| 197 | for (xx = 0, p_at = &p_rec->attribute[0]; xx < p_rec->num_attributes; |
| 198 | xx++, p_at++) |
| 199 | { |
| 200 | if ((p_at->id >= start_attr) && (p_at->id <= end_attr)) |
| 201 | return (p_at); |
| 202 | } |
| 203 | |
| 204 | /* No matching attribute found */ |
| 205 | return (NULL); |
| 206 | } |
| 207 | |
| 208 | |
| 209 | /******************************************************************************* |
| 210 | ** |
| 211 | ** Function sdp_compose_proto_list |
| 212 | ** |
| 213 | ** Description This function is called to compose a data sequence from |
| 214 | ** protocol element list struct pointer |
| 215 | ** |
| 216 | ** Returns the length of the data sequence |
| 217 | ** |
| 218 | *******************************************************************************/ |
| 219 | static int sdp_compose_proto_list( UINT8 *p, UINT16 num_elem, |
| 220 | tSDP_PROTOCOL_ELEM *p_elem_list) |
| 221 | { |
| 222 | UINT16 xx, yy, len; |
| 223 | BOOLEAN is_rfcomm_scn; |
| 224 | UINT8 *p_head = p; |
| 225 | UINT8 *p_len; |
| 226 | |
| 227 | /* First, build the protocol list. This consists of a set of data element |
| 228 | ** sequences, one for each layer. Each layer sequence consists of layer's |
| 229 | ** UUID and optional parameters |
| 230 | */ |
| 231 | for (xx = 0; xx < num_elem; xx++, p_elem_list++) |
| 232 | { |
| 233 | len = 3 + (p_elem_list->num_params * 3); |
| 234 | UINT8_TO_BE_STREAM (p, (DATA_ELE_SEQ_DESC_TYPE << 3) | SIZE_IN_NEXT_BYTE); |
| 235 | |
| 236 | p_len = p; |
| 237 | *p++ = (UINT8) len; |
| 238 | |
| 239 | UINT8_TO_BE_STREAM (p, (UUID_DESC_TYPE << 3) | SIZE_TWO_BYTES); |
| 240 | UINT16_TO_BE_STREAM (p, p_elem_list->protocol_uuid); |
| 241 | |
| 242 | if (p_elem_list->protocol_uuid == UUID_PROTOCOL_RFCOMM) |
| 243 | is_rfcomm_scn = TRUE; |
| 244 | else |
| 245 | is_rfcomm_scn = FALSE; |
| 246 | |
| 247 | for (yy = 0; yy < p_elem_list->num_params; yy++) |
| 248 | { |
| 249 | if (is_rfcomm_scn) |
| 250 | { |
| 251 | UINT8_TO_BE_STREAM (p, (UINT_DESC_TYPE << 3) | SIZE_ONE_BYTE); |
| 252 | UINT8_TO_BE_STREAM (p, p_elem_list->params[yy]); |
| 253 | |
| 254 | *p_len -= 1; |
| 255 | } |
| 256 | else |
| 257 | { |
| 258 | UINT8_TO_BE_STREAM (p, (UINT_DESC_TYPE << 3) | SIZE_TWO_BYTES); |
| 259 | UINT16_TO_BE_STREAM (p, p_elem_list->params[yy]); |
| 260 | } |
| 261 | } |
| 262 | } |
| 263 | return (p - p_head); |
| 264 | } |
| 265 | |
| 266 | #endif /* SDP_SERVER_ENABLED == TRUE */ |
| 267 | |
| 268 | /******************************************************************************* |
| 269 | ** |
| 270 | ** Function SDP_CreateRecord |
| 271 | ** |
| 272 | ** Description This function is called to create a record in the database. |
| 273 | ** This would be through the SDP database maintenance API. The |
| 274 | ** record is created empty, teh application should then call |
| 275 | ** "add_attribute" to add the record's attributes. |
| 276 | ** |
| 277 | ** Returns Record handle if OK, else 0. |
| 278 | ** |
| 279 | *******************************************************************************/ |
| 280 | UINT32 SDP_CreateRecord (void) |
| 281 | { |
| 282 | #if SDP_SERVER_ENABLED == TRUE |
| 283 | UINT32 handle; |
| 284 | UINT8 buf[4]; |
| 285 | tSDP_DB *p_db = &sdp_cb.server_db; |
| 286 | |
| 287 | /* First, check if there is a free record */ |
| 288 | if (p_db->num_records < SDP_MAX_RECORDS) |
| 289 | { |
| 290 | memset (&p_db->record[p_db->num_records], 0, |
| 291 | sizeof (tSDP_RECORD)); |
| 292 | |
| 293 | /* We will use a handle of the first unreserved handle plus last record |
| 294 | ** number + 1 */ |
| 295 | if (p_db->num_records) |
| 296 | handle = p_db->record[p_db->num_records - 1].record_handle + 1; |
| 297 | else |
| 298 | handle = 0x10000; |
| 299 | |
| 300 | p_db->record[p_db->num_records].record_handle = handle; |
| 301 | |
| 302 | p_db->num_records++; |
Sharvil Nanavati | a51c9d9 | 2014-05-04 01:08:21 -0700 | [diff] [blame] | 303 | SDP_TRACE_DEBUG("SDP_CreateRecord ok, num_records:%d", p_db->num_records); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 304 | /* Add the first attribute (the handle) automatically */ |
| 305 | UINT32_TO_BE_FIELD (buf, handle); |
| 306 | SDP_AddAttribute (handle, ATTR_ID_SERVICE_RECORD_HDL, UINT_DESC_TYPE, |
| 307 | 4, buf); |
| 308 | |
| 309 | return (p_db->record[p_db->num_records - 1].record_handle); |
| 310 | } |
Sharvil Nanavati | a51c9d9 | 2014-05-04 01:08:21 -0700 | [diff] [blame] | 311 | else SDP_TRACE_ERROR("SDP_CreateRecord fail, exceed maximum records:%d", SDP_MAX_RECORDS); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 312 | #endif |
| 313 | return (0); |
| 314 | } |
| 315 | |
| 316 | |
| 317 | /******************************************************************************* |
| 318 | ** |
| 319 | ** Function SDP_DeleteRecord |
| 320 | ** |
| 321 | ** Description This function is called to add a record (or all records) |
| 322 | ** from the database. This would be through the SDP database |
| 323 | ** maintenance API. |
| 324 | ** |
| 325 | ** If a record handle of 0 is passed, all records are deleted. |
| 326 | ** |
| 327 | ** Returns TRUE if succeeded, else FALSE |
| 328 | ** |
| 329 | *******************************************************************************/ |
| 330 | BOOLEAN SDP_DeleteRecord (UINT32 handle) |
| 331 | { |
| 332 | #if SDP_SERVER_ENABLED == TRUE |
| 333 | UINT16 xx, yy, zz; |
| 334 | tSDP_RECORD *p_rec = &sdp_cb.server_db.record[0]; |
| 335 | |
| 336 | if (handle == 0 || sdp_cb.server_db.num_records == 0) |
| 337 | { |
| 338 | /* Delete all records in the database */ |
| 339 | sdp_cb.server_db.num_records = 0; |
| 340 | |
| 341 | /* require new DI record to be created in SDP_SetLocalDiRecord */ |
| 342 | sdp_cb.server_db.di_primary_handle = 0; |
| 343 | sdp_cb.server_db.brcm_di_registered = 0; |
| 344 | |
| 345 | return (TRUE); |
| 346 | } |
| 347 | else |
| 348 | { |
| 349 | /* Find the record in the database */ |
| 350 | for (xx = 0; xx < sdp_cb.server_db.num_records; xx++, p_rec++) |
| 351 | { |
| 352 | if (p_rec->record_handle == handle) |
| 353 | { |
| 354 | /* Found it. Shift everything up one */ |
| 355 | for (yy = xx; yy < sdp_cb.server_db.num_records; yy++, p_rec++) |
| 356 | { |
| 357 | *p_rec = *(p_rec + 1); |
| 358 | |
| 359 | /* Adjust the attribute value pointer for each attribute */ |
| 360 | for (zz = 0; zz < p_rec->num_attributes; zz++) |
| 361 | p_rec->attribute[zz].value_ptr -= sizeof(tSDP_RECORD); |
| 362 | } |
| 363 | |
| 364 | sdp_cb.server_db.num_records--; |
| 365 | |
Sharvil Nanavati | a51c9d9 | 2014-05-04 01:08:21 -0700 | [diff] [blame] | 366 | SDP_TRACE_DEBUG("SDP_DeleteRecord ok, num_records:%d", sdp_cb.server_db.num_records); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 367 | /* if we're deleting the primary DI record, clear the */ |
| 368 | /* value in the control block */ |
| 369 | if( sdp_cb.server_db.di_primary_handle == handle ) |
| 370 | { |
| 371 | sdp_cb.server_db.di_primary_handle = 0; |
| 372 | sdp_cb.server_db.brcm_di_registered = 0; |
| 373 | } |
| 374 | |
| 375 | return (TRUE); |
| 376 | } |
| 377 | } |
| 378 | } |
| 379 | #endif |
| 380 | return (FALSE); |
| 381 | } |
| 382 | |
| 383 | |
| 384 | /******************************************************************************* |
| 385 | ** |
| 386 | ** Function SDP_AddAttribute |
| 387 | ** |
| 388 | ** Description This function is called to add an attribute to a record. |
| 389 | ** This would be through the SDP database maintenance API. |
| 390 | ** If the attribute already exists in the record, it is replaced |
| 391 | ** with the new value. |
| 392 | ** |
| 393 | ** NOTE Attribute values must be passed as a Big Endian stream. |
| 394 | ** |
| 395 | ** Returns TRUE if added OK, else FALSE |
| 396 | ** |
| 397 | *******************************************************************************/ |
| 398 | BOOLEAN SDP_AddAttribute (UINT32 handle, UINT16 attr_id, UINT8 attr_type, |
| 399 | UINT32 attr_len, UINT8 *p_val) |
| 400 | { |
| 401 | #if SDP_SERVER_ENABLED == TRUE |
| 402 | UINT16 xx, yy, zz; |
| 403 | tSDP_RECORD *p_rec = &sdp_cb.server_db.record[0]; |
| 404 | |
| 405 | #if (BT_TRACE_VERBOSE == TRUE) |
| 406 | if (sdp_cb.trace_level >= BT_TRACE_LEVEL_DEBUG) |
| 407 | { |
| 408 | if ((attr_type == UINT_DESC_TYPE) || |
| 409 | (attr_type == TWO_COMP_INT_DESC_TYPE) || |
| 410 | (attr_type == UUID_DESC_TYPE) || |
| 411 | (attr_type == DATA_ELE_SEQ_DESC_TYPE) || |
| 412 | (attr_type == DATA_ELE_ALT_DESC_TYPE)) |
| 413 | { |
| 414 | UINT8 num_array[400]; |
| 415 | UINT32 i; |
| 416 | UINT32 len = (attr_len > 200) ? 200 : attr_len; |
| 417 | |
| 418 | num_array[0] ='\0'; |
| 419 | for (i = 0; i < len; i++) |
| 420 | { |
| 421 | sprintf((char *)&num_array[i*2],"%02X",(UINT8)(p_val[i])); |
| 422 | } |
Sharvil Nanavati | a51c9d9 | 2014-05-04 01:08:21 -0700 | [diff] [blame] | 423 | SDP_TRACE_DEBUG("SDP_AddAttribute: handle:%X, id:%04X, type:%d, len:%d, p_val:%p, *p_val:%s", |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 424 | handle,attr_id,attr_type,attr_len,p_val,num_array); |
| 425 | } |
| 426 | else if (attr_type == BOOLEAN_DESC_TYPE) |
| 427 | { |
Sharvil Nanavati | a51c9d9 | 2014-05-04 01:08:21 -0700 | [diff] [blame] | 428 | SDP_TRACE_DEBUG("SDP_AddAttribute: handle:%X, id:%04X, type:%d, len:%d, p_val:%p, *p_val:%d", |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 429 | handle,attr_id,attr_type,attr_len,p_val,*p_val); |
| 430 | } |
| 431 | else |
| 432 | { |
Sharvil Nanavati | a51c9d9 | 2014-05-04 01:08:21 -0700 | [diff] [blame] | 433 | SDP_TRACE_DEBUG("SDP_AddAttribute: handle:%X, id:%04X, type:%d, len:%d, p_val:%p, *p_val:%s", |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 434 | handle,attr_id,attr_type,attr_len,p_val,p_val); |
| 435 | } |
| 436 | } |
| 437 | #endif |
| 438 | |
| 439 | /* Find the record in the database */ |
| 440 | for (zz = 0; zz < sdp_cb.server_db.num_records; zz++, p_rec++) |
| 441 | { |
| 442 | if (p_rec->record_handle == handle) |
| 443 | { |
| 444 | tSDP_ATTRIBUTE *p_attr = &p_rec->attribute[0]; |
| 445 | |
| 446 | /* Found the record. Now, see if the attribute already exists */ |
| 447 | for (xx = 0; xx < p_rec->num_attributes; xx++, p_attr++) |
| 448 | { |
| 449 | /* The attribute exists. replace it */ |
| 450 | if (p_attr->id == attr_id) |
| 451 | { |
| 452 | SDP_DeleteAttribute (handle, attr_id); |
| 453 | break; |
| 454 | } |
| 455 | if (p_attr->id > attr_id) |
| 456 | break; |
| 457 | } |
| 458 | |
| 459 | if (p_rec->num_attributes == SDP_MAX_REC_ATTR) |
| 460 | return (FALSE); |
| 461 | |
| 462 | /* If not found, see if we can allocate a new entry */ |
| 463 | if (xx == p_rec->num_attributes) |
| 464 | p_attr = &p_rec->attribute[p_rec->num_attributes]; |
| 465 | else |
| 466 | { |
| 467 | /* Since the attributes are kept in sorted order, insert ours here */ |
| 468 | for (yy = p_rec->num_attributes; yy > xx; yy--) |
| 469 | p_rec->attribute[yy] = p_rec->attribute[yy - 1]; |
| 470 | } |
| 471 | |
| 472 | p_attr->id = attr_id; |
| 473 | p_attr->type = attr_type; |
| 474 | p_attr->len = attr_len; |
| 475 | |
| 476 | if (p_rec->free_pad_ptr + attr_len >= SDP_MAX_PAD_LEN) |
| 477 | { |
| 478 | /* do truncate only for text string type descriptor */ |
| 479 | if (attr_type == TEXT_STR_DESC_TYPE) |
| 480 | { |
Sharvil Nanavati | a51c9d9 | 2014-05-04 01:08:21 -0700 | [diff] [blame] | 481 | SDP_TRACE_WARNING("SDP_AddAttribute: attr_len:%d too long. truncate to (%d)", |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 482 | attr_len, SDP_MAX_PAD_LEN - p_rec->free_pad_ptr ); |
| 483 | |
| 484 | attr_len = SDP_MAX_PAD_LEN - p_rec->free_pad_ptr; |
| 485 | p_val[SDP_MAX_PAD_LEN - p_rec->free_pad_ptr] = '\0'; |
| 486 | p_val[SDP_MAX_PAD_LEN - p_rec->free_pad_ptr+1] = '\0'; |
| 487 | } |
| 488 | else |
| 489 | attr_len = 0; |
| 490 | } |
| 491 | |
| 492 | if ((attr_len > 0) && (p_val != 0)) |
| 493 | { |
| 494 | p_attr->len = attr_len; |
| 495 | memcpy (&p_rec->attr_pad[p_rec->free_pad_ptr], p_val, (size_t)attr_len); |
| 496 | p_attr->value_ptr = &p_rec->attr_pad[p_rec->free_pad_ptr]; |
| 497 | p_rec->free_pad_ptr += attr_len; |
| 498 | } |
| 499 | else if ((attr_len == 0 && p_attr->len != 0) || /* if truncate to 0 length, simply don't add */ |
| 500 | p_val == 0) |
| 501 | { |
Sharvil Nanavati | a51c9d9 | 2014-05-04 01:08:21 -0700 | [diff] [blame] | 502 | SDP_TRACE_ERROR("SDP_AddAttribute fail, length exceed maximum: ID %d: attr_len:%d ", |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 503 | attr_id, attr_len ); |
| 504 | p_attr->id = p_attr->type = p_attr->len = 0; |
| 505 | return (FALSE); |
| 506 | } |
| 507 | p_rec->num_attributes++; |
| 508 | |
| 509 | /*** Mark DI record as used by Broadcom ***/ |
| 510 | if (handle == sdp_cb.server_db.di_primary_handle && |
| 511 | attr_id == ATTR_ID_EXT_BRCM_VERSION) |
| 512 | sdp_cb.server_db.brcm_di_registered = TRUE; |
| 513 | |
| 514 | return (TRUE); |
| 515 | } |
| 516 | } |
| 517 | #endif |
| 518 | return (FALSE); |
| 519 | } |
| 520 | |
| 521 | |
| 522 | /******************************************************************************* |
| 523 | ** |
| 524 | ** Function SDP_AddSequence |
| 525 | ** |
| 526 | ** Description This function is called to add a sequence to a record. |
| 527 | ** This would be through the SDP database maintenance API. |
| 528 | ** If the sequence already exists in the record, it is replaced |
| 529 | ** with the new sequence. |
| 530 | ** |
| 531 | ** NOTE Element values must be passed as a Big Endian stream. |
| 532 | ** |
| 533 | ** Returns TRUE if added OK, else FALSE |
| 534 | ** |
| 535 | *******************************************************************************/ |
| 536 | BOOLEAN SDP_AddSequence (UINT32 handle, UINT16 attr_id, UINT16 num_elem, |
| 537 | UINT8 type[], UINT8 len[], UINT8 *p_val[]) |
| 538 | { |
| 539 | #if SDP_SERVER_ENABLED == TRUE |
| 540 | UINT16 xx; |
Ganesh Ganapathi Batta | ead3cde | 2013-02-05 15:22:31 -0800 | [diff] [blame] | 541 | UINT8 *p_buff; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 542 | UINT8 *p; |
| 543 | UINT8 *p_head; |
Ganesh Ganapathi Batta | ead3cde | 2013-02-05 15:22:31 -0800 | [diff] [blame] | 544 | BOOLEAN result; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 545 | |
Ganesh Ganapathi Batta | ead3cde | 2013-02-05 15:22:31 -0800 | [diff] [blame] | 546 | if ((p_buff = (UINT8 *) GKI_getbuf(sizeof(UINT8) * SDP_MAX_ATTR_LEN * 2)) == NULL) |
| 547 | { |
Sharvil Nanavati | a51c9d9 | 2014-05-04 01:08:21 -0700 | [diff] [blame] | 548 | SDP_TRACE_ERROR("SDP_AddSequence cannot get a buffer!"); |
Ganesh Ganapathi Batta | ead3cde | 2013-02-05 15:22:31 -0800 | [diff] [blame] | 549 | return (FALSE); |
| 550 | } |
| 551 | p = p_buff; |
| 552 | |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 553 | /* First, build the sequence */ |
| 554 | for (xx = 0; xx < num_elem; xx++) |
| 555 | { |
| 556 | p_head = p; |
| 557 | switch (len[xx]) |
| 558 | { |
| 559 | case 1: |
| 560 | UINT8_TO_BE_STREAM (p, (type[xx] << 3) | SIZE_ONE_BYTE); |
| 561 | break; |
| 562 | case 2: |
| 563 | UINT8_TO_BE_STREAM (p, (type[xx] << 3) | SIZE_TWO_BYTES); |
| 564 | break; |
| 565 | case 4: |
| 566 | UINT8_TO_BE_STREAM (p, (type[xx] << 3) | SIZE_FOUR_BYTES); |
| 567 | break; |
| 568 | case 8: |
| 569 | UINT8_TO_BE_STREAM (p, (type[xx] << 3) | SIZE_EIGHT_BYTES); |
| 570 | break; |
| 571 | case 16: |
| 572 | UINT8_TO_BE_STREAM (p, (type[xx] << 3) | SIZE_SIXTEEN_BYTES); |
| 573 | break; |
| 574 | default: |
| 575 | UINT8_TO_BE_STREAM (p, (type[xx] << 3) | SIZE_IN_NEXT_BYTE); |
| 576 | UINT8_TO_BE_STREAM (p, len[xx]); |
| 577 | break; |
| 578 | } |
| 579 | |
| 580 | ARRAY_TO_BE_STREAM (p, p_val[xx], len[xx]); |
| 581 | |
Ganesh Ganapathi Batta | ead3cde | 2013-02-05 15:22:31 -0800 | [diff] [blame] | 582 | if (p - p_buff > SDP_MAX_ATTR_LEN) |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 583 | { |
| 584 | /* go back to before we add this element */ |
| 585 | p = p_head; |
Ganesh Ganapathi Batta | ead3cde | 2013-02-05 15:22:31 -0800 | [diff] [blame] | 586 | if(p_head == p_buff) |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 587 | { |
| 588 | /* the first element exceed the max length */ |
Sharvil Nanavati | a51c9d9 | 2014-05-04 01:08:21 -0700 | [diff] [blame] | 589 | SDP_TRACE_ERROR ("SDP_AddSequence - too long(attribute is not added)!!"); |
Ganesh Ganapathi Batta | ead3cde | 2013-02-05 15:22:31 -0800 | [diff] [blame] | 590 | GKI_freebuf(p_buff); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 591 | return FALSE; |
| 592 | } |
| 593 | else |
Sharvil Nanavati | a51c9d9 | 2014-05-04 01:08:21 -0700 | [diff] [blame] | 594 | SDP_TRACE_ERROR ("SDP_AddSequence - too long, add %d elements of %d", xx, num_elem); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 595 | break; |
| 596 | } |
| 597 | } |
Ganesh Ganapathi Batta | ead3cde | 2013-02-05 15:22:31 -0800 | [diff] [blame] | 598 | result = SDP_AddAttribute (handle, attr_id, DATA_ELE_SEQ_DESC_TYPE,(UINT32) (p - p_buff), p_buff); |
| 599 | GKI_freebuf(p_buff); |
| 600 | return result; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 601 | #else /* SDP_SERVER_ENABLED == FALSE */ |
| 602 | return (FALSE); |
| 603 | #endif |
| 604 | } |
| 605 | |
| 606 | |
| 607 | /******************************************************************************* |
| 608 | ** |
| 609 | ** Function SDP_AddUuidSequence |
| 610 | ** |
| 611 | ** Description This function is called to add a UUID sequence to a record. |
| 612 | ** This would be through the SDP database maintenance API. |
| 613 | ** If the sequence already exists in the record, it is replaced |
| 614 | ** with the new sequence. |
| 615 | ** |
| 616 | ** Returns TRUE if added OK, else FALSE |
| 617 | ** |
| 618 | *******************************************************************************/ |
| 619 | BOOLEAN SDP_AddUuidSequence (UINT32 handle, UINT16 attr_id, UINT16 num_uuids, |
| 620 | UINT16 *p_uuids) |
| 621 | { |
| 622 | #if SDP_SERVER_ENABLED == TRUE |
| 623 | UINT16 xx; |
Ganesh Ganapathi Batta | ead3cde | 2013-02-05 15:22:31 -0800 | [diff] [blame] | 624 | UINT8 *p_buff; |
| 625 | UINT8 *p; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 626 | INT32 max_len = SDP_MAX_ATTR_LEN -3; |
Ganesh Ganapathi Batta | ead3cde | 2013-02-05 15:22:31 -0800 | [diff] [blame] | 627 | BOOLEAN result; |
| 628 | |
| 629 | if ((p_buff = (UINT8 *) GKI_getbuf(sizeof(UINT8) * SDP_MAX_ATTR_LEN * 2)) == NULL) |
| 630 | { |
Sharvil Nanavati | a51c9d9 | 2014-05-04 01:08:21 -0700 | [diff] [blame] | 631 | SDP_TRACE_ERROR("SDP_AddUuidSequence cannot get a buffer!"); |
Ganesh Ganapathi Batta | ead3cde | 2013-02-05 15:22:31 -0800 | [diff] [blame] | 632 | return (FALSE); |
| 633 | } |
| 634 | p = p_buff; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 635 | |
| 636 | /* First, build the sequence */ |
| 637 | for (xx = 0; xx < num_uuids ; xx++, p_uuids++) |
| 638 | { |
| 639 | UINT8_TO_BE_STREAM (p, (UUID_DESC_TYPE << 3) | SIZE_TWO_BYTES); |
| 640 | UINT16_TO_BE_STREAM (p, *p_uuids); |
| 641 | |
Ganesh Ganapathi Batta | ead3cde | 2013-02-05 15:22:31 -0800 | [diff] [blame] | 642 | if((p - p_buff) > max_len) |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 643 | { |
Sharvil Nanavati | a51c9d9 | 2014-05-04 01:08:21 -0700 | [diff] [blame] | 644 | SDP_TRACE_WARNING ("SDP_AddUuidSequence - too long, add %d uuids of %d", xx, num_uuids); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 645 | break; |
| 646 | } |
| 647 | } |
| 648 | |
Ganesh Ganapathi Batta | ead3cde | 2013-02-05 15:22:31 -0800 | [diff] [blame] | 649 | result = SDP_AddAttribute (handle, attr_id, DATA_ELE_SEQ_DESC_TYPE,(UINT32) (p - p_buff), p_buff); |
| 650 | GKI_freebuf(p_buff); |
| 651 | return result; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 652 | #else /* SDP_SERVER_ENABLED == FALSE */ |
| 653 | return (FALSE); |
| 654 | #endif |
| 655 | } |
| 656 | |
| 657 | /******************************************************************************* |
| 658 | ** |
| 659 | ** Function SDP_AddProtocolList |
| 660 | ** |
| 661 | ** Description This function is called to add a protocol descriptor list to |
| 662 | ** a record. This would be through the SDP database maintenance API. |
| 663 | ** If the protocol list already exists in the record, it is replaced |
| 664 | ** with the new list. |
| 665 | ** |
| 666 | ** Returns TRUE if added OK, else FALSE |
| 667 | ** |
| 668 | *******************************************************************************/ |
| 669 | BOOLEAN SDP_AddProtocolList (UINT32 handle, UINT16 num_elem, |
| 670 | tSDP_PROTOCOL_ELEM *p_elem_list) |
| 671 | { |
| 672 | #if SDP_SERVER_ENABLED == TRUE |
Ganesh Ganapathi Batta | ead3cde | 2013-02-05 15:22:31 -0800 | [diff] [blame] | 673 | UINT8 *p_buff; |
| 674 | int offset; |
| 675 | BOOLEAN result; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 676 | |
Ganesh Ganapathi Batta | ead3cde | 2013-02-05 15:22:31 -0800 | [diff] [blame] | 677 | if ((p_buff = (UINT8 *) GKI_getbuf(sizeof(UINT8) * SDP_MAX_ATTR_LEN * 2)) == NULL) |
| 678 | { |
Sharvil Nanavati | a51c9d9 | 2014-05-04 01:08:21 -0700 | [diff] [blame] | 679 | SDP_TRACE_ERROR("SDP_AddProtocolList cannot get a buffer!"); |
Ganesh Ganapathi Batta | ead3cde | 2013-02-05 15:22:31 -0800 | [diff] [blame] | 680 | return (FALSE); |
| 681 | } |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 682 | |
Ganesh Ganapathi Batta | ead3cde | 2013-02-05 15:22:31 -0800 | [diff] [blame] | 683 | offset = sdp_compose_proto_list(p_buff, num_elem, p_elem_list); |
| 684 | result = SDP_AddAttribute (handle, ATTR_ID_PROTOCOL_DESC_LIST,DATA_ELE_SEQ_DESC_TYPE, (UINT32) offset, p_buff); |
| 685 | GKI_freebuf(p_buff); |
| 686 | return result; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 687 | #else /* SDP_SERVER_ENABLED == FALSE */ |
| 688 | return (FALSE); |
| 689 | #endif |
| 690 | } |
| 691 | |
| 692 | |
| 693 | /******************************************************************************* |
| 694 | ** |
| 695 | ** Function SDP_AddAdditionProtoLists |
| 696 | ** |
| 697 | ** Description This function is called to add a protocol descriptor list to |
| 698 | ** a record. This would be through the SDP database maintenance API. |
| 699 | ** If the protocol list already exists in the record, it is replaced |
| 700 | ** with the new list. |
| 701 | ** |
| 702 | ** Returns TRUE if added OK, else FALSE |
| 703 | ** |
| 704 | *******************************************************************************/ |
| 705 | BOOLEAN SDP_AddAdditionProtoLists (UINT32 handle, UINT16 num_elem, |
| 706 | tSDP_PROTO_LIST_ELEM *p_proto_list) |
| 707 | { |
| 708 | #if SDP_SERVER_ENABLED == TRUE |
| 709 | UINT16 xx; |
Ganesh Ganapathi Batta | ead3cde | 2013-02-05 15:22:31 -0800 | [diff] [blame] | 710 | UINT8 *p_buff; |
| 711 | UINT8 *p; |
| 712 | UINT8 *p_len; |
| 713 | int offset; |
| 714 | BOOLEAN result; |
| 715 | |
| 716 | if ((p_buff = (UINT8 *) GKI_getbuf(sizeof(UINT8) * SDP_MAX_ATTR_LEN * 2)) == NULL) |
| 717 | { |
Sharvil Nanavati | a51c9d9 | 2014-05-04 01:08:21 -0700 | [diff] [blame] | 718 | SDP_TRACE_ERROR("SDP_AddAdditionProtoLists cannot get a buffer!"); |
Ganesh Ganapathi Batta | ead3cde | 2013-02-05 15:22:31 -0800 | [diff] [blame] | 719 | return (FALSE); |
| 720 | } |
| 721 | p = p_buff; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 722 | |
| 723 | /* for each ProtocolDescriptorList */ |
| 724 | for (xx = 0; xx < num_elem; xx++, p_proto_list++) |
| 725 | { |
| 726 | UINT8_TO_BE_STREAM (p, (DATA_ELE_SEQ_DESC_TYPE << 3) | SIZE_IN_NEXT_BYTE); |
| 727 | p_len = p++; |
| 728 | |
| 729 | offset = sdp_compose_proto_list(p, p_proto_list->num_elems, |
| 730 | p_proto_list->list_elem); |
| 731 | p += offset; |
| 732 | |
| 733 | *p_len = (UINT8)(p - p_len - 1); |
| 734 | } |
Ganesh Ganapathi Batta | ead3cde | 2013-02-05 15:22:31 -0800 | [diff] [blame] | 735 | result = SDP_AddAttribute (handle, ATTR_ID_ADDITION_PROTO_DESC_LISTS,DATA_ELE_SEQ_DESC_TYPE, |
| 736 | (UINT32) (p - p_buff), p_buff); |
| 737 | GKI_freebuf(p_buff); |
| 738 | return result; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 739 | |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 740 | #else /* SDP_SERVER_ENABLED == FALSE */ |
| 741 | return (FALSE); |
| 742 | #endif |
| 743 | } |
| 744 | |
| 745 | /******************************************************************************* |
| 746 | ** |
| 747 | ** Function SDP_AddProfileDescriptorList |
| 748 | ** |
| 749 | ** Description This function is called to add a profile descriptor list to |
| 750 | ** a record. This would be through the SDP database maintenance API. |
| 751 | ** If the version already exists in the record, it is replaced |
| 752 | ** with the new one. |
| 753 | ** |
| 754 | ** Returns TRUE if added OK, else FALSE |
| 755 | ** |
| 756 | *******************************************************************************/ |
| 757 | BOOLEAN SDP_AddProfileDescriptorList (UINT32 handle, UINT16 profile_uuid, |
| 758 | UINT16 version) |
| 759 | { |
| 760 | #if SDP_SERVER_ENABLED == TRUE |
Ganesh Ganapathi Batta | ead3cde | 2013-02-05 15:22:31 -0800 | [diff] [blame] | 761 | UINT8 *p_buff; |
| 762 | UINT8 *p; |
| 763 | BOOLEAN result; |
| 764 | |
| 765 | if ((p_buff = (UINT8 *) GKI_getbuf(sizeof(UINT8) * SDP_MAX_ATTR_LEN)) == NULL) |
| 766 | { |
Sharvil Nanavati | a51c9d9 | 2014-05-04 01:08:21 -0700 | [diff] [blame] | 767 | SDP_TRACE_ERROR("SDP_AddProfileDescriptorList cannot get a buffer!"); |
Ganesh Ganapathi Batta | ead3cde | 2013-02-05 15:22:31 -0800 | [diff] [blame] | 768 | return (FALSE); |
| 769 | } |
| 770 | p = p_buff+2; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 771 | |
| 772 | /* First, build the profile descriptor list. This consists of a data element sequence. */ |
| 773 | /* The sequence consists of profile's UUID and version number */ |
| 774 | UINT8_TO_BE_STREAM (p, (UUID_DESC_TYPE << 3) | SIZE_TWO_BYTES); |
| 775 | UINT16_TO_BE_STREAM (p, profile_uuid); |
| 776 | |
| 777 | UINT8_TO_BE_STREAM (p, (UINT_DESC_TYPE << 3) | SIZE_TWO_BYTES); |
| 778 | UINT16_TO_BE_STREAM (p, version); |
| 779 | |
| 780 | /* Add in type and length fields */ |
Ganesh Ganapathi Batta | ead3cde | 2013-02-05 15:22:31 -0800 | [diff] [blame] | 781 | *p_buff = (UINT8) ((DATA_ELE_SEQ_DESC_TYPE << 3) | SIZE_IN_NEXT_BYTE); |
| 782 | *(p_buff+1) = (UINT8) (p - (p_buff+2)); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 783 | |
Ganesh Ganapathi Batta | ead3cde | 2013-02-05 15:22:31 -0800 | [diff] [blame] | 784 | result = SDP_AddAttribute (handle, ATTR_ID_BT_PROFILE_DESC_LIST,DATA_ELE_SEQ_DESC_TYPE, (UINT32) (p - p_buff), p_buff); |
| 785 | GKI_freebuf(p_buff); |
| 786 | return result; |
| 787 | |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 788 | #else /* SDP_SERVER_ENABLED == FALSE */ |
| 789 | return (FALSE); |
| 790 | #endif |
| 791 | } |
| 792 | |
| 793 | |
| 794 | /******************************************************************************* |
| 795 | ** |
| 796 | ** Function SDP_AddLanguageBaseAttrIDList |
| 797 | ** |
| 798 | ** Description This function is called to add a language base attr list to |
| 799 | ** a record. This would be through the SDP database maintenance API. |
| 800 | ** If the version already exists in the record, it is replaced |
| 801 | ** with the new one. |
| 802 | ** |
| 803 | ** Returns TRUE if added OK, else FALSE |
| 804 | ** |
| 805 | *******************************************************************************/ |
| 806 | BOOLEAN SDP_AddLanguageBaseAttrIDList (UINT32 handle, UINT16 lang, |
| 807 | UINT16 char_enc, UINT16 base_id) |
| 808 | { |
| 809 | #if SDP_SERVER_ENABLED == TRUE |
Ganesh Ganapathi Batta | ead3cde | 2013-02-05 15:22:31 -0800 | [diff] [blame] | 810 | UINT8 *p_buff; |
| 811 | UINT8 *p; |
| 812 | BOOLEAN result; |
| 813 | |
| 814 | if ((p_buff = (UINT8 *) GKI_getbuf(sizeof(UINT8) * SDP_MAX_ATTR_LEN)) == NULL) |
| 815 | { |
Sharvil Nanavati | a51c9d9 | 2014-05-04 01:08:21 -0700 | [diff] [blame] | 816 | SDP_TRACE_ERROR("SDP_AddLanguageBaseAttrIDList cannot get a buffer!"); |
Ganesh Ganapathi Batta | ead3cde | 2013-02-05 15:22:31 -0800 | [diff] [blame] | 817 | return (FALSE); |
| 818 | } |
| 819 | p = p_buff; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 820 | |
| 821 | /* First, build the language base descriptor list. This consists of a data */ |
| 822 | /* element sequence. The sequence consists of 9 bytes (3 UINt16 fields) */ |
| 823 | UINT8_TO_BE_STREAM (p, (UINT_DESC_TYPE << 3) | SIZE_TWO_BYTES); |
| 824 | UINT16_TO_BE_STREAM (p, lang); |
| 825 | |
| 826 | UINT8_TO_BE_STREAM (p, (UINT_DESC_TYPE << 3) | SIZE_TWO_BYTES); |
| 827 | UINT16_TO_BE_STREAM (p, char_enc); |
| 828 | |
| 829 | UINT8_TO_BE_STREAM (p, (UINT_DESC_TYPE << 3) | SIZE_TWO_BYTES); |
| 830 | UINT16_TO_BE_STREAM (p, base_id); |
| 831 | |
Ganesh Ganapathi Batta | ead3cde | 2013-02-05 15:22:31 -0800 | [diff] [blame] | 832 | result = SDP_AddAttribute (handle, ATTR_ID_LANGUAGE_BASE_ATTR_ID_LIST,DATA_ELE_SEQ_DESC_TYPE, |
| 833 | (UINT32) (p - p_buff), p_buff); |
| 834 | GKI_freebuf(p_buff); |
| 835 | return result; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 836 | #else /* SDP_SERVER_ENABLED == FALSE */ |
| 837 | return (FALSE); |
| 838 | #endif |
| 839 | } |
| 840 | |
| 841 | |
| 842 | /******************************************************************************* |
| 843 | ** |
| 844 | ** Function SDP_AddServiceClassIdList |
| 845 | ** |
| 846 | ** Description This function is called to add a service list to a record. |
| 847 | ** This would be through the SDP database maintenance API. |
| 848 | ** If the service list already exists in the record, it is replaced |
| 849 | ** with the new list. |
| 850 | ** |
| 851 | ** Returns TRUE if added OK, else FALSE |
| 852 | ** |
| 853 | *******************************************************************************/ |
| 854 | BOOLEAN SDP_AddServiceClassIdList (UINT32 handle, UINT16 num_services, |
| 855 | UINT16 *p_service_uuids) |
| 856 | { |
| 857 | #if SDP_SERVER_ENABLED == TRUE |
| 858 | UINT16 xx; |
Ganesh Ganapathi Batta | ead3cde | 2013-02-05 15:22:31 -0800 | [diff] [blame] | 859 | UINT8 *p_buff; |
| 860 | UINT8 *p; |
| 861 | BOOLEAN result; |
| 862 | |
| 863 | if ((p_buff = (UINT8 *) GKI_getbuf(sizeof(UINT8) * SDP_MAX_ATTR_LEN * 2)) == NULL) |
| 864 | { |
Sharvil Nanavati | a51c9d9 | 2014-05-04 01:08:21 -0700 | [diff] [blame] | 865 | SDP_TRACE_ERROR("SDP_AddServiceClassIdList cannot get a buffer!"); |
Ganesh Ganapathi Batta | ead3cde | 2013-02-05 15:22:31 -0800 | [diff] [blame] | 866 | return (FALSE); |
| 867 | } |
| 868 | p = p_buff; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 869 | |
| 870 | for (xx = 0; xx < num_services; xx++, p_service_uuids++) |
| 871 | { |
| 872 | UINT8_TO_BE_STREAM (p, (UUID_DESC_TYPE << 3) | SIZE_TWO_BYTES); |
| 873 | UINT16_TO_BE_STREAM (p, *p_service_uuids); |
| 874 | } |
| 875 | |
Ganesh Ganapathi Batta | ead3cde | 2013-02-05 15:22:31 -0800 | [diff] [blame] | 876 | result = SDP_AddAttribute (handle, ATTR_ID_SERVICE_CLASS_ID_LIST,DATA_ELE_SEQ_DESC_TYPE, |
| 877 | (UINT32) (p - p_buff), p_buff); |
| 878 | GKI_freebuf(p_buff); |
| 879 | return result; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 880 | #else /* SDP_SERVER_ENABLED == FALSE */ |
| 881 | return (FALSE); |
| 882 | #endif |
| 883 | } |
| 884 | |
| 885 | |
| 886 | /******************************************************************************* |
| 887 | ** |
| 888 | ** Function SDP_DeleteAttribute |
| 889 | ** |
| 890 | ** Description This function is called to delete an attribute from a record. |
| 891 | ** This would be through the SDP database maintenance API. |
| 892 | ** |
| 893 | ** Returns TRUE if deleted OK, else FALSE if not found |
| 894 | ** |
| 895 | *******************************************************************************/ |
| 896 | BOOLEAN SDP_DeleteAttribute (UINT32 handle, UINT16 attr_id) |
| 897 | { |
| 898 | #if SDP_SERVER_ENABLED == TRUE |
| 899 | UINT16 xx, yy; |
| 900 | tSDP_RECORD *p_rec = &sdp_cb.server_db.record[0]; |
| 901 | UINT8 *pad_ptr; |
| 902 | UINT32 len; /* Number of bytes in the entry */ |
| 903 | |
| 904 | /* Find the record in the database */ |
| 905 | for (xx = 0; xx < sdp_cb.server_db.num_records; xx++, p_rec++) |
| 906 | { |
| 907 | if (p_rec->record_handle == handle) |
| 908 | { |
| 909 | tSDP_ATTRIBUTE *p_attr = &p_rec->attribute[0]; |
| 910 | |
Sharvil Nanavati | a51c9d9 | 2014-05-04 01:08:21 -0700 | [diff] [blame] | 911 | SDP_TRACE_API("Deleting attr_id 0x%04x for handle 0x%x", attr_id, handle); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 912 | /* Found it. Now, find the attribute */ |
| 913 | for (xx = 0; xx < p_rec->num_attributes; xx++, p_attr++) |
| 914 | { |
| 915 | if (p_attr->id == attr_id) |
| 916 | { |
| 917 | pad_ptr = p_attr->value_ptr; |
| 918 | len = p_attr->len; |
| 919 | |
| 920 | if (len) |
| 921 | { |
| 922 | for (yy = 0; yy < p_rec->num_attributes; yy++) |
| 923 | { |
| 924 | if( p_rec->attribute[yy].value_ptr > pad_ptr ) |
| 925 | p_rec->attribute[yy].value_ptr -= len; |
| 926 | } |
| 927 | } |
| 928 | |
| 929 | /* Found it. Shift everything up one */ |
| 930 | p_rec->num_attributes--; |
| 931 | |
| 932 | for (yy = xx; yy < p_rec->num_attributes; yy++, p_attr++) |
| 933 | { |
| 934 | *p_attr = *(p_attr + 1); |
| 935 | } |
| 936 | |
| 937 | /* adjust attribute values if needed */ |
| 938 | if (len) |
| 939 | { |
| 940 | xx = (p_rec->free_pad_ptr - ((pad_ptr+len) - |
| 941 | &p_rec->attr_pad[0])); |
| 942 | for( yy=0; yy<xx; yy++, pad_ptr++) |
| 943 | *pad_ptr = *(pad_ptr+len); |
| 944 | p_rec->free_pad_ptr -= len; |
| 945 | } |
| 946 | return (TRUE); |
| 947 | } |
| 948 | } |
| 949 | } |
| 950 | } |
| 951 | #endif |
| 952 | /* If here, not found */ |
| 953 | return (FALSE); |
| 954 | } |
| 955 | |
| 956 | /******************************************************************************* |
| 957 | ** |
| 958 | ** Function SDP_ReadRecord |
| 959 | ** |
| 960 | ** Description This function is called to get the raw data of the record |
| 961 | ** with the given handle from the database. |
| 962 | ** |
| 963 | ** Returns -1, if the record is not found. |
| 964 | ** Otherwise, the offset (0 or 1) to start of data in p_data. |
| 965 | ** |
| 966 | ** The size of data copied into p_data is in *p_data_len. |
| 967 | ** |
| 968 | *******************************************************************************/ |
| 969 | #if (SDP_RAW_DATA_INCLUDED == TRUE) |
| 970 | INT32 SDP_ReadRecord(UINT32 handle, UINT8 *p_data, INT32 *p_data_len) |
| 971 | { |
| 972 | INT32 len = 0; /* Number of bytes in the entry */ |
| 973 | INT32 offset = -1; /* default to not found */ |
| 974 | #if SDP_SERVER_ENABLED == TRUE |
| 975 | tSDP_RECORD *p_rec; |
| 976 | UINT16 start = 0; |
| 977 | UINT16 end = 0xffff; |
| 978 | tSDP_ATTRIBUTE *p_attr; |
| 979 | UINT16 rem_len; |
| 980 | UINT8 *p_rsp; |
| 981 | |
| 982 | /* Find the record in the database */ |
| 983 | p_rec = sdp_db_find_record(handle); |
| 984 | if(p_rec && p_data && p_data_len) |
| 985 | { |
| 986 | p_rsp = &p_data[3]; |
| 987 | while ( (p_attr = sdp_db_find_attr_in_rec (p_rec, start, end)) != NULL) |
| 988 | { |
| 989 | /* Check if attribute fits. Assume 3-byte value type/length */ |
| 990 | rem_len = *p_data_len - (UINT16) (p_rsp - p_data); |
| 991 | |
| 992 | if (p_attr->len > (UINT32)(rem_len - 6)) |
| 993 | break; |
| 994 | |
| 995 | p_rsp = sdpu_build_attrib_entry (p_rsp, p_attr); |
| 996 | |
| 997 | /* next attr id */ |
| 998 | start = p_attr->id + 1; |
| 999 | } |
| 1000 | len = (INT32) (p_rsp - p_data); |
| 1001 | |
| 1002 | /* Put in the sequence header (2 or 3 bytes) */ |
| 1003 | if (len > 255) |
| 1004 | { |
| 1005 | offset = 0; |
| 1006 | p_data[0] = (UINT8) ((DATA_ELE_SEQ_DESC_TYPE << 3) | SIZE_IN_NEXT_WORD); |
| 1007 | p_data[1] = (UINT8) ((len - 3) >> 8); |
| 1008 | p_data[2] = (UINT8) (len - 3); |
| 1009 | } |
| 1010 | else |
| 1011 | { |
| 1012 | offset = 1; |
| 1013 | |
| 1014 | p_data[1] = (UINT8) ((DATA_ELE_SEQ_DESC_TYPE << 3) | SIZE_IN_NEXT_BYTE); |
| 1015 | p_data[2] = (UINT8) (len - 3); |
| 1016 | |
| 1017 | len--; |
| 1018 | } |
| 1019 | *p_data_len = len; |
| 1020 | } |
| 1021 | #endif |
| 1022 | /* If here, not found */ |
| 1023 | return (offset); |
| 1024 | } |
| 1025 | #endif |
| 1026 | |
| 1027 | |
| 1028 | |