sdp_db.c 35 KB

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