sdp_discovery.c 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026
  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 SDP discovery functions
  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. #include "stack/btu.h"
  34. #include "stack/btm_api.h"
  35. #ifndef SDP_DEBUG_RAW
  36. #define SDP_DEBUG_RAW FALSE
  37. #endif
  38. /********************************************************************************/
  39. /* L O C A L F U N C T I O N P R O T O T Y P E S */
  40. /********************************************************************************/
  41. #if SDP_CLIENT_ENABLED == TRUE
  42. static void process_service_search_rsp (tCONN_CB *p_ccb, UINT8 *p_reply);
  43. static void process_service_attr_rsp (tCONN_CB *p_ccb, UINT8 *p_reply);
  44. static void process_service_search_attr_rsp (tCONN_CB *p_ccb, UINT8 *p_reply);
  45. static UINT8 *save_attr_seq (tCONN_CB *p_ccb, UINT8 *p, UINT8 *p_msg_end);
  46. static tSDP_DISC_REC *add_record (tSDP_DISCOVERY_DB *p_db, BD_ADDR p_bda);
  47. static UINT8 *add_attr (UINT8 *p, tSDP_DISCOVERY_DB *p_db, tSDP_DISC_REC *p_rec,
  48. UINT16 attr_id, tSDP_DISC_ATTR *p_parent_attr, UINT8 nest_level);
  49. /* Safety check in case we go crazy */
  50. #define MAX_NEST_LEVELS 5
  51. /*******************************************************************************
  52. **
  53. ** Function sdpu_build_uuid_seq
  54. **
  55. ** Description This function builds a UUID sequence from the list of
  56. ** passed UUIDs. It is also passed the address of the output
  57. ** buffer.
  58. **
  59. ** Returns Pointer to next byte in the output buffer.
  60. **
  61. *******************************************************************************/
  62. static UINT8 *sdpu_build_uuid_seq (UINT8 *p_out, UINT16 num_uuids, tSDP_UUID *p_uuid_list)
  63. {
  64. UINT16 xx;
  65. UINT8 *p_len;
  66. /* First thing is the data element header */
  67. UINT8_TO_BE_STREAM (p_out, (DATA_ELE_SEQ_DESC_TYPE << 3) | SIZE_IN_NEXT_BYTE);
  68. /* Remember where the length goes. Leave space for it. */
  69. p_len = p_out;
  70. p_out += 1;
  71. /* Now, loop through and put in all the UUID(s) */
  72. for (xx = 0; xx < num_uuids; xx++, p_uuid_list++) {
  73. if (p_uuid_list->len == 2) {
  74. UINT8_TO_BE_STREAM (p_out, (UUID_DESC_TYPE << 3) | SIZE_TWO_BYTES);
  75. UINT16_TO_BE_STREAM (p_out, p_uuid_list->uu.uuid16);
  76. } else if (p_uuid_list->len == 4) {
  77. UINT8_TO_BE_STREAM (p_out, (UUID_DESC_TYPE << 3) | SIZE_FOUR_BYTES);
  78. UINT32_TO_BE_STREAM (p_out, p_uuid_list->uu.uuid32);
  79. } else {
  80. UINT8_TO_BE_STREAM (p_out, (UUID_DESC_TYPE << 3) | SIZE_SIXTEEN_BYTES);
  81. ARRAY_TO_BE_STREAM (p_out, p_uuid_list->uu.uuid128, p_uuid_list->len);
  82. }
  83. }
  84. /* Now, put in the length */
  85. xx = (UINT16)(p_out - p_len - 1);
  86. UINT8_TO_BE_STREAM (p_len, xx);
  87. return (p_out);
  88. }
  89. /*******************************************************************************
  90. **
  91. ** Function sdp_snd_service_search_req
  92. **
  93. ** Description Send a service search request to the SDP server.
  94. **
  95. ** Returns void
  96. **
  97. *******************************************************************************/
  98. static void sdp_snd_service_search_req(tCONN_CB *p_ccb, UINT8 cont_len, UINT8 *p_cont)
  99. {
  100. UINT8 *p, *p_start, *p_param_len;
  101. BT_HDR *p_cmd;
  102. UINT16 param_len;
  103. /* Get a buffer to send the packet to L2CAP */
  104. if ((p_cmd = (BT_HDR *) osi_malloc(SDP_DATA_BUF_SIZE)) == NULL) {
  105. sdp_disconnect (p_ccb, SDP_NO_RESOURCES);
  106. return;
  107. }
  108. p_cmd->offset = L2CAP_MIN_OFFSET;
  109. p = p_start = (UINT8 *)(p_cmd + 1) + L2CAP_MIN_OFFSET;
  110. /* Build a service search request packet */
  111. UINT8_TO_BE_STREAM (p, SDP_PDU_SERVICE_SEARCH_REQ);
  112. UINT16_TO_BE_STREAM (p, p_ccb->transaction_id);
  113. p_ccb->transaction_id++;
  114. /* Skip the length, we need to add it at the end */
  115. p_param_len = p;
  116. p += 2;
  117. /* Build the UID sequence. */
  118. #if (defined(SDP_BROWSE_PLUS) && SDP_BROWSE_PLUS == TRUE)
  119. p = sdpu_build_uuid_seq (p, 1, &p_ccb->p_db->uuid_filters[p_ccb->cur_uuid_idx]);
  120. #else
  121. p = sdpu_build_uuid_seq (p, p_ccb->p_db->num_uuid_filters, p_ccb->p_db->uuid_filters);
  122. #endif
  123. /* Set max service record count */
  124. UINT16_TO_BE_STREAM (p, sdp_cb.max_recs_per_search);
  125. /* Set continuation state */
  126. UINT8_TO_BE_STREAM (p, cont_len);
  127. /* if this is not the first request */
  128. if (cont_len && p_cont) {
  129. memcpy(p, p_cont, cont_len);
  130. p += cont_len;
  131. }
  132. /* Go back and put the parameter length into the buffer */
  133. param_len = (UINT16)(p - p_param_len - 2);
  134. UINT16_TO_BE_STREAM (p_param_len, param_len);
  135. p_ccb->disc_state = SDP_DISC_WAIT_HANDLES;
  136. /* Set the length of the SDP data in the buffer */
  137. p_cmd->len = (UINT16)(p - p_start);
  138. #if (SDP_DEBUG_RAW == TRUE)
  139. SDP_TRACE_WARNING("sdp_snd_service_search_req cont_len :%d disc_state:%d\n", cont_len, p_ccb->disc_state);
  140. #endif
  141. L2CA_DataWrite (p_ccb->connection_id, p_cmd);
  142. /* Start inactivity timer */
  143. btu_start_timer (&p_ccb->timer_entry, BTU_TTYPE_SDP, SDP_INACT_TIMEOUT);
  144. }
  145. /*******************************************************************************
  146. **
  147. ** Function sdp_disc_connected
  148. **
  149. ** Description This function is called when an SDP discovery attempt is
  150. ** connected.
  151. **
  152. ** Returns void
  153. **
  154. *******************************************************************************/
  155. void sdp_disc_connected (tCONN_CB *p_ccb)
  156. {
  157. if (p_ccb->is_attr_search) {
  158. p_ccb->disc_state = SDP_DISC_WAIT_SEARCH_ATTR;
  159. process_service_search_attr_rsp (p_ccb, NULL);
  160. } else {
  161. /* First step is to get a list of the handles from the server. */
  162. /* We are not searching for a specific attribute, so we will */
  163. /* first search for the service, then get all attributes of it */
  164. p_ccb->num_handles = 0;
  165. sdp_snd_service_search_req(p_ccb, 0, NULL);
  166. }
  167. }
  168. /*******************************************************************************
  169. **
  170. ** Function sdp_disc_server_rsp
  171. **
  172. ** Description This function is called when there is a response from
  173. ** the server.
  174. **
  175. ** Returns void
  176. **
  177. *******************************************************************************/
  178. void sdp_disc_server_rsp (tCONN_CB *p_ccb, BT_HDR *p_msg)
  179. {
  180. UINT8 *p, rsp_pdu;
  181. BOOLEAN invalid_pdu = TRUE;
  182. #if (SDP_DEBUG_RAW == TRUE)
  183. SDP_TRACE_WARNING("sdp_disc_server_rsp disc_state:%d\n", p_ccb->disc_state);
  184. #endif
  185. /* stop inactivity timer when we receive a response */
  186. btu_stop_timer (&p_ccb->timer_entry);
  187. /* Got a reply!! Check what we got back */
  188. p = (UINT8 *)(p_msg + 1) + p_msg->offset;
  189. BE_STREAM_TO_UINT8 (rsp_pdu, p);
  190. p_msg->len--;
  191. switch (rsp_pdu) {
  192. case SDP_PDU_SERVICE_SEARCH_RSP:
  193. if (p_ccb->disc_state == SDP_DISC_WAIT_HANDLES) {
  194. process_service_search_rsp (p_ccb, p);
  195. invalid_pdu = FALSE;
  196. }
  197. break;
  198. case SDP_PDU_SERVICE_ATTR_RSP:
  199. if (p_ccb->disc_state == SDP_DISC_WAIT_ATTR) {
  200. process_service_attr_rsp (p_ccb, p);
  201. invalid_pdu = FALSE;
  202. }
  203. break;
  204. case SDP_PDU_SERVICE_SEARCH_ATTR_RSP:
  205. if (p_ccb->disc_state == SDP_DISC_WAIT_SEARCH_ATTR) {
  206. process_service_search_attr_rsp (p_ccb, p);
  207. invalid_pdu = FALSE;
  208. }
  209. break;
  210. }
  211. if (invalid_pdu) {
  212. SDP_TRACE_WARNING ("SDP - Unexp. PDU: %d in state: %d\n", rsp_pdu, p_ccb->disc_state);
  213. sdp_disconnect (p_ccb, SDP_GENERIC_ERROR);
  214. }
  215. }
  216. /******************************************************************************
  217. **
  218. ** Function process_service_search_rsp
  219. **
  220. ** Description This function is called when there is a search response from
  221. ** the server.
  222. **
  223. ** Returns void
  224. **
  225. *******************************************************************************/
  226. static void process_service_search_rsp (tCONN_CB *p_ccb, UINT8 *p_reply)
  227. {
  228. UINT16 xx;
  229. UINT16 total, cur_handles, orig;
  230. UINT8 cont_len;
  231. /* Skip transaction, and param len */
  232. p_reply += 4;
  233. BE_STREAM_TO_UINT16 (total, p_reply);
  234. BE_STREAM_TO_UINT16 (cur_handles, p_reply);
  235. orig = p_ccb->num_handles;
  236. p_ccb->num_handles += cur_handles;
  237. if (p_ccb->num_handles == 0) {
  238. SDP_TRACE_WARNING ("SDP - Rcvd ServiceSearchRsp, no matches\n");
  239. sdp_disconnect (p_ccb, SDP_NO_RECS_MATCH);
  240. return;
  241. }
  242. /* Save the handles that match. We will can only process a certain number. */
  243. if (total > sdp_cb.max_recs_per_search) {
  244. total = sdp_cb.max_recs_per_search;
  245. }
  246. if (p_ccb->num_handles > sdp_cb.max_recs_per_search) {
  247. p_ccb->num_handles = sdp_cb.max_recs_per_search;
  248. }
  249. for (xx = orig; xx < p_ccb->num_handles; xx++) {
  250. BE_STREAM_TO_UINT32 (p_ccb->handles[xx], p_reply);
  251. }
  252. BE_STREAM_TO_UINT8 (cont_len, p_reply);
  253. if (cont_len != 0) {
  254. if (cont_len > SDP_MAX_CONTINUATION_LEN) {
  255. sdp_disconnect (p_ccb, SDP_INVALID_CONT_STATE);
  256. return;
  257. }
  258. /* stay in the same state */
  259. sdp_snd_service_search_req(p_ccb, cont_len, p_reply);
  260. } else {
  261. /* change state */
  262. p_ccb->disc_state = SDP_DISC_WAIT_ATTR;
  263. /* Kick off the first attribute request */
  264. process_service_attr_rsp (p_ccb, NULL);
  265. }
  266. }
  267. /*******************************************************************************
  268. **
  269. ** Function sdp_copy_raw_data
  270. **
  271. ** Description copy the raw data
  272. **
  273. **
  274. ** Returns void
  275. **
  276. *******************************************************************************/
  277. #if (SDP_RAW_DATA_INCLUDED == TRUE)
  278. static void sdp_copy_raw_data (tCONN_CB *p_ccb, BOOLEAN offset)
  279. {
  280. unsigned int cpy_len;
  281. UINT32 list_len;
  282. UINT8 *p;
  283. UINT8 type;
  284. #if (SDP_DEBUG_RAW == TRUE)
  285. UINT8 num_array[SDP_MAX_LIST_BYTE_COUNT];
  286. UINT32 i;
  287. for (i = 0; i < p_ccb->list_len; i++) {
  288. sprintf((char *)&num_array[i * 2], "%02X\n", (UINT8)(p_ccb->rsp_list[i]));
  289. }
  290. SDP_TRACE_WARNING("result :%s\n", num_array);
  291. #endif
  292. if (p_ccb->p_db->raw_data) {
  293. cpy_len = p_ccb->p_db->raw_size - p_ccb->p_db->raw_used;
  294. list_len = p_ccb->list_len;
  295. p = &p_ccb->rsp_list[0];
  296. if (offset) {
  297. type = *p++;
  298. p = sdpu_get_len_from_type (p, type, &list_len);
  299. }
  300. if (list_len < cpy_len ) {
  301. cpy_len = list_len;
  302. }
  303. #if (SDP_DEBUG_RAW == TRUE)
  304. SDP_TRACE_DEBUG("list_len :%d cpy_len:%d raw_size:%d raw_used:%d\n",
  305. list_len, cpy_len, p_ccb->p_db->raw_size, p_ccb->p_db->raw_used);
  306. #endif
  307. if (cpy_len != 0){
  308. memcpy (&p_ccb->p_db->raw_data[p_ccb->p_db->raw_used], p, cpy_len);
  309. p_ccb->p_db->raw_used += cpy_len;
  310. }
  311. }
  312. }
  313. #endif
  314. /*******************************************************************************
  315. **
  316. ** Function process_service_attr_rsp
  317. **
  318. ** Description This function is called when there is a attribute response from
  319. ** the server.
  320. **
  321. ** Returns void
  322. **
  323. *******************************************************************************/
  324. static void process_service_attr_rsp (tCONN_CB *p_ccb, UINT8 *p_reply)
  325. {
  326. UINT8 *p_start, *p_param_len;
  327. UINT16 param_len, list_byte_count;
  328. BOOLEAN cont_request_needed = FALSE;
  329. #if (SDP_DEBUG_RAW == TRUE)
  330. SDP_TRACE_WARNING("process_service_attr_rsp raw inc:%d\n",
  331. SDP_RAW_DATA_INCLUDED);
  332. #endif
  333. /* If p_reply is NULL, we were called after the records handles were read */
  334. if (p_reply) {
  335. #if (SDP_DEBUG_RAW == TRUE)
  336. SDP_TRACE_WARNING("ID & len: 0x%02x-%02x-%02x-%02x\n",
  337. p_reply[0], p_reply[1], p_reply[2], p_reply[3]);
  338. #endif
  339. /* Skip transaction ID and length */
  340. p_reply += 4;
  341. BE_STREAM_TO_UINT16 (list_byte_count, p_reply);
  342. #if (SDP_DEBUG_RAW == TRUE)
  343. SDP_TRACE_WARNING("list_byte_count:%d\n", list_byte_count);
  344. #endif
  345. /* Copy the response to the scratchpad. First, a safety check on the length */
  346. if ((p_ccb->list_len + list_byte_count) > SDP_MAX_LIST_BYTE_COUNT) {
  347. sdp_disconnect (p_ccb, SDP_INVALID_PDU_SIZE);
  348. return;
  349. }
  350. #if (SDP_DEBUG_RAW == TRUE)
  351. SDP_TRACE_WARNING("list_len: %d, list_byte_count: %d\n",
  352. p_ccb->list_len, list_byte_count);
  353. #endif
  354. if (p_ccb->rsp_list == NULL) {
  355. p_ccb->rsp_list = (UINT8 *)osi_malloc (SDP_MAX_LIST_BYTE_COUNT);
  356. if (p_ccb->rsp_list == NULL) {
  357. SDP_TRACE_ERROR ("SDP - no gki buf to save rsp\n");
  358. sdp_disconnect (p_ccb, SDP_NO_RESOURCES);
  359. return;
  360. }
  361. }
  362. memcpy (&p_ccb->rsp_list[p_ccb->list_len], p_reply, list_byte_count);
  363. p_ccb->list_len += list_byte_count;
  364. p_reply += list_byte_count;
  365. #if (SDP_DEBUG_RAW == TRUE)
  366. SDP_TRACE_WARNING("list_len: %d(attr_rsp)\n", p_ccb->list_len);
  367. /* Check if we need to request a continuation */
  368. SDP_TRACE_WARNING("*p_reply:%d(%d)\n", *p_reply, SDP_MAX_CONTINUATION_LEN);
  369. #endif
  370. if (*p_reply) {
  371. if (*p_reply > SDP_MAX_CONTINUATION_LEN) {
  372. sdp_disconnect (p_ccb, SDP_INVALID_CONT_STATE);
  373. return;
  374. }
  375. cont_request_needed = TRUE;
  376. } else {
  377. #if (SDP_RAW_DATA_INCLUDED == TRUE)
  378. SDP_TRACE_WARNING("process_service_attr_rsp\n");
  379. sdp_copy_raw_data (p_ccb, FALSE);
  380. #endif
  381. /* Save the response in the database. Stop on any error */
  382. if (!save_attr_seq (p_ccb, &p_ccb->rsp_list[0], &p_ccb->rsp_list[p_ccb->list_len])) {
  383. sdp_disconnect (p_ccb, SDP_DB_FULL);
  384. return;
  385. }
  386. p_ccb->list_len = 0;
  387. p_ccb->cur_handle++;
  388. }
  389. }
  390. /* Now, ask for the next handle. Re-use the buffer we just got. */
  391. if (p_ccb->cur_handle < p_ccb->num_handles) {
  392. BT_HDR *p_msg = (BT_HDR *) osi_malloc(SDP_DATA_BUF_SIZE);
  393. UINT8 *p;
  394. if (!p_msg) {
  395. sdp_disconnect (p_ccb, SDP_NO_RESOURCES);
  396. return;
  397. }
  398. p_msg->offset = L2CAP_MIN_OFFSET;
  399. p = p_start = (UINT8 *)(p_msg + 1) + L2CAP_MIN_OFFSET;
  400. /* Get all the attributes from the server */
  401. UINT8_TO_BE_STREAM (p, SDP_PDU_SERVICE_ATTR_REQ);
  402. UINT16_TO_BE_STREAM (p, p_ccb->transaction_id);
  403. p_ccb->transaction_id++;
  404. /* Skip the length, we need to add it at the end */
  405. p_param_len = p;
  406. p += 2;
  407. UINT32_TO_BE_STREAM (p, p_ccb->handles[p_ccb->cur_handle]);
  408. /* Max attribute byte count */
  409. UINT16_TO_BE_STREAM (p, sdp_cb.max_attr_list_size);
  410. /* If no attribute filters, build a wildcard attribute sequence */
  411. if (p_ccb->p_db->num_attr_filters) {
  412. p = sdpu_build_attrib_seq (p, p_ccb->p_db->attr_filters, p_ccb->p_db->num_attr_filters);
  413. } else {
  414. p = sdpu_build_attrib_seq (p, NULL, 0);
  415. }
  416. /* Was this a continuation request ? */
  417. if (cont_request_needed) {
  418. memcpy (p, p_reply, *p_reply + 1);
  419. p += *p_reply + 1;
  420. } else {
  421. UINT8_TO_BE_STREAM (p, 0);
  422. }
  423. /* Go back and put the parameter length into the buffer */
  424. param_len = (UINT16)(p - p_param_len - 2);
  425. UINT16_TO_BE_STREAM (p_param_len, param_len);
  426. /* Set the length of the SDP data in the buffer */
  427. p_msg->len = (UINT16)(p - p_start);
  428. L2CA_DataWrite (p_ccb->connection_id, p_msg);
  429. /* Start inactivity timer */
  430. btu_start_timer (&p_ccb->timer_entry, BTU_TTYPE_SDP, SDP_INACT_TIMEOUT);
  431. } else {
  432. sdp_disconnect (p_ccb, SDP_SUCCESS);
  433. return;
  434. }
  435. }
  436. /*******************************************************************************
  437. **
  438. ** Function process_service_search_attr_rsp
  439. **
  440. ** Description This function is called when there is a search attribute
  441. ** response from the server.
  442. **
  443. ** Returns void
  444. **
  445. *******************************************************************************/
  446. static void process_service_search_attr_rsp (tCONN_CB *p_ccb, UINT8 *p_reply)
  447. {
  448. UINT8 *p, *p_start, *p_end, *p_param_len;
  449. UINT8 type;
  450. UINT32 seq_len;
  451. UINT16 param_len, lists_byte_count = 0;
  452. BOOLEAN cont_request_needed = FALSE;
  453. #if (SDP_DEBUG_RAW == TRUE)
  454. SDP_TRACE_WARNING("process_service_search_attr_rsp\n");
  455. #endif
  456. /* If p_reply is NULL, we were called for the initial read */
  457. if (p_reply) {
  458. #if (SDP_DEBUG_RAW == TRUE)
  459. SDP_TRACE_WARNING("ID & len: 0x%02x-%02x-%02x-%02x\n",
  460. p_reply[0], p_reply[1], p_reply[2], p_reply[3]);
  461. #endif
  462. /* Skip transaction ID and length */
  463. p_reply += 4;
  464. BE_STREAM_TO_UINT16 (lists_byte_count, p_reply);
  465. #if (SDP_DEBUG_RAW == TRUE)
  466. SDP_TRACE_WARNING("lists_byte_count:%d\n", lists_byte_count);
  467. #endif
  468. /* Copy the response to the scratchpad. First, a safety check on the length */
  469. if ((p_ccb->list_len + lists_byte_count) > SDP_MAX_LIST_BYTE_COUNT) {
  470. sdp_disconnect (p_ccb, SDP_INVALID_PDU_SIZE);
  471. return;
  472. }
  473. #if (SDP_DEBUG_RAW == TRUE)
  474. SDP_TRACE_WARNING("list_len: %d, list_byte_count: %d\n",
  475. p_ccb->list_len, lists_byte_count);
  476. #endif
  477. if (p_ccb->rsp_list == NULL) {
  478. p_ccb->rsp_list = (UINT8 *)osi_malloc (SDP_MAX_LIST_BYTE_COUNT);
  479. if (p_ccb->rsp_list == NULL) {
  480. SDP_TRACE_ERROR ("SDP - no gki buf to save rsp\n");
  481. sdp_disconnect (p_ccb, SDP_NO_RESOURCES);
  482. return;
  483. }
  484. }
  485. memcpy (&p_ccb->rsp_list[p_ccb->list_len], p_reply, lists_byte_count);
  486. p_ccb->list_len += lists_byte_count;
  487. p_reply += lists_byte_count;
  488. #if (SDP_DEBUG_RAW == TRUE)
  489. SDP_TRACE_WARNING("list_len: %d(search_attr_rsp)\n", p_ccb->list_len);
  490. /* Check if we need to request a continuation */
  491. SDP_TRACE_WARNING("*p_reply:%d(%d)\n", *p_reply, SDP_MAX_CONTINUATION_LEN);
  492. #endif
  493. if (*p_reply) {
  494. if (*p_reply > SDP_MAX_CONTINUATION_LEN) {
  495. sdp_disconnect (p_ccb, SDP_INVALID_CONT_STATE);
  496. return;
  497. }
  498. cont_request_needed = TRUE;
  499. }
  500. }
  501. #if (SDP_DEBUG_RAW == TRUE)
  502. SDP_TRACE_WARNING("cont_request_needed:%d\n", cont_request_needed);
  503. #endif
  504. /* If continuation request (or first time request) */
  505. if ((cont_request_needed) || (!p_reply)) {
  506. BT_HDR *p_msg = (BT_HDR *) osi_malloc(SDP_DATA_BUF_SIZE);
  507. UINT8 *p;
  508. if (!p_msg) {
  509. sdp_disconnect (p_ccb, SDP_NO_RESOURCES);
  510. return;
  511. }
  512. p_msg->offset = L2CAP_MIN_OFFSET;
  513. p = p_start = (UINT8 *)(p_msg + 1) + L2CAP_MIN_OFFSET;
  514. /* Build a service search request packet */
  515. UINT8_TO_BE_STREAM (p, SDP_PDU_SERVICE_SEARCH_ATTR_REQ);
  516. UINT16_TO_BE_STREAM (p, p_ccb->transaction_id);
  517. p_ccb->transaction_id++;
  518. /* Skip the length, we need to add it at the end */
  519. p_param_len = p;
  520. p += 2;
  521. /* Build the UID sequence. */
  522. #if (defined(SDP_BROWSE_PLUS) && SDP_BROWSE_PLUS == TRUE)
  523. p = sdpu_build_uuid_seq (p, 1, &p_ccb->p_db->uuid_filters[p_ccb->cur_uuid_idx]);
  524. #else
  525. p = sdpu_build_uuid_seq (p, p_ccb->p_db->num_uuid_filters, p_ccb->p_db->uuid_filters);
  526. #endif
  527. /* Max attribute byte count */
  528. UINT16_TO_BE_STREAM (p, sdp_cb.max_attr_list_size);
  529. /* If no attribute filters, build a wildcard attribute sequence */
  530. if (p_ccb->p_db->num_attr_filters) {
  531. p = sdpu_build_attrib_seq (p, p_ccb->p_db->attr_filters, p_ccb->p_db->num_attr_filters);
  532. } else {
  533. p = sdpu_build_attrib_seq (p, NULL, 0);
  534. }
  535. /* No continuation for first request */
  536. if (p_reply) {
  537. memcpy (p, p_reply, *p_reply + 1);
  538. p += *p_reply + 1;
  539. } else {
  540. UINT8_TO_BE_STREAM (p, 0);
  541. }
  542. /* Go back and put the parameter length into the buffer */
  543. param_len = p - p_param_len - 2;
  544. UINT16_TO_BE_STREAM (p_param_len, param_len);
  545. /* Set the length of the SDP data in the buffer */
  546. p_msg->len = p - p_start;
  547. L2CA_DataWrite (p_ccb->connection_id, p_msg);
  548. /* Start inactivity timer */
  549. btu_start_timer (&p_ccb->timer_entry, BTU_TTYPE_SDP, SDP_INACT_TIMEOUT);
  550. return;
  551. }
  552. /*******************************************************************/
  553. /* We now have the full response, which is a sequence of sequences */
  554. /*******************************************************************/
  555. #if (SDP_RAW_DATA_INCLUDED == TRUE)
  556. SDP_TRACE_DEBUG("process_service_search_attr_rsp\n");
  557. sdp_copy_raw_data (p_ccb, TRUE);
  558. #endif
  559. p = &p_ccb->rsp_list[0];
  560. /* The contents is a sequence of attribute sequences */
  561. type = *p++;
  562. if ((type >> 3) != DATA_ELE_SEQ_DESC_TYPE) {
  563. SDP_TRACE_WARNING ("SDP - Wrong type: 0x%02x in attr_rsp\n", type);
  564. return;
  565. }
  566. p = sdpu_get_len_from_type (p, type, &seq_len);
  567. p_end = &p_ccb->rsp_list[p_ccb->list_len];
  568. if ((p + seq_len) != p_end) {
  569. sdp_disconnect (p_ccb, SDP_INVALID_CONT_STATE);
  570. return;
  571. }
  572. while (p < p_end) {
  573. p = save_attr_seq (p_ccb, p, &p_ccb->rsp_list[p_ccb->list_len]);
  574. if (!p) {
  575. sdp_disconnect (p_ccb, SDP_DB_FULL);
  576. return;
  577. }
  578. }
  579. /* Since we got everything we need, disconnect the call */
  580. sdp_disconnect (p_ccb, SDP_SUCCESS);
  581. }
  582. /*******************************************************************************
  583. **
  584. ** Function save_attr_seq
  585. **
  586. ** Description This function is called when there is a response from
  587. ** the server.
  588. **
  589. ** Returns pointer to next byte or NULL if error
  590. **
  591. *******************************************************************************/
  592. static UINT8 *save_attr_seq (tCONN_CB *p_ccb, UINT8 *p, UINT8 *p_msg_end)
  593. {
  594. UINT32 seq_len, attr_len;
  595. UINT16 attr_id;
  596. UINT8 type, *p_seq_end;
  597. tSDP_DISC_REC *p_rec;
  598. type = *p++;
  599. if ((type >> 3) != DATA_ELE_SEQ_DESC_TYPE) {
  600. SDP_TRACE_WARNING ("SDP - Wrong type: 0x%02x in attr_rsp\n", type);
  601. return (NULL);
  602. }
  603. p = sdpu_get_len_from_type (p, type, &seq_len);
  604. if ((p + seq_len) > p_msg_end) {
  605. SDP_TRACE_WARNING ("SDP - Bad len in attr_rsp %d\n", seq_len);
  606. return (NULL);
  607. }
  608. /* Create a record */
  609. p_rec = add_record (p_ccb->p_db, p_ccb->device_address);
  610. if (!p_rec) {
  611. SDP_TRACE_WARNING ("SDP - DB full add_record\n");
  612. return (NULL);
  613. }
  614. p_seq_end = p + seq_len;
  615. while (p < p_seq_end) {
  616. /* First get the attribute ID */
  617. type = *p++;
  618. p = sdpu_get_len_from_type (p, type, &attr_len);
  619. if (((type >> 3) != UINT_DESC_TYPE) || (attr_len != 2)) {
  620. SDP_TRACE_WARNING ("SDP - Bad type: 0x%02x or len: %d in attr_rsp\n", type, attr_len);
  621. return (NULL);
  622. }
  623. BE_STREAM_TO_UINT16 (attr_id, p);
  624. /* Now, add the attribute value */
  625. p = add_attr (p, p_ccb->p_db, p_rec, attr_id, NULL, 0);
  626. if (!p) {
  627. SDP_TRACE_WARNING ("SDP - DB full add_attr\n");
  628. return (NULL);
  629. }
  630. }
  631. return (p);
  632. }
  633. /*******************************************************************************
  634. **
  635. ** Function add_record
  636. **
  637. ** Description This function allocates space for a record from the DB.
  638. **
  639. ** Returns pointer to next byte in data stream
  640. **
  641. *******************************************************************************/
  642. tSDP_DISC_REC *add_record (tSDP_DISCOVERY_DB *p_db, BD_ADDR p_bda)
  643. {
  644. tSDP_DISC_REC *p_rec;
  645. /* See if there is enough space in the database */
  646. if (p_db->mem_free < sizeof (tSDP_DISC_REC)) {
  647. return (NULL);
  648. }
  649. p_rec = (tSDP_DISC_REC *) p_db->p_free_mem;
  650. p_db->p_free_mem += sizeof (tSDP_DISC_REC);
  651. p_db->mem_free -= sizeof (tSDP_DISC_REC);
  652. p_rec->p_first_attr = NULL;
  653. p_rec->p_next_rec = NULL;
  654. memcpy (p_rec->remote_bd_addr, p_bda, BD_ADDR_LEN);
  655. /* Add the record to the end of chain */
  656. if (!p_db->p_first_rec) {
  657. p_db->p_first_rec = p_rec;
  658. } else {
  659. tSDP_DISC_REC *p_rec1 = p_db->p_first_rec;
  660. while (p_rec1->p_next_rec) {
  661. p_rec1 = p_rec1->p_next_rec;
  662. }
  663. p_rec1->p_next_rec = p_rec;
  664. }
  665. return (p_rec);
  666. }
  667. #define SDP_ADDITIONAL_LIST_MASK 0x80
  668. /*******************************************************************************
  669. **
  670. ** Function add_attr
  671. **
  672. ** Description This function allocates space for an attribute from the DB
  673. ** and copies the data into it.
  674. **
  675. ** Returns pointer to next byte in data stream
  676. **
  677. *******************************************************************************/
  678. static UINT8 *add_attr (UINT8 *p, tSDP_DISCOVERY_DB *p_db, tSDP_DISC_REC *p_rec,
  679. UINT16 attr_id, tSDP_DISC_ATTR *p_parent_attr, UINT8 nest_level)
  680. {
  681. tSDP_DISC_ATTR *p_attr;
  682. UINT32 attr_len;
  683. UINT32 total_len;
  684. UINT16 attr_type;
  685. UINT16 id;
  686. UINT8 type;
  687. UINT8 *p_end;
  688. UINT8 is_additional_list = nest_level & SDP_ADDITIONAL_LIST_MASK;
  689. nest_level &= ~(SDP_ADDITIONAL_LIST_MASK);
  690. type = *p++;
  691. p = sdpu_get_len_from_type (p, type, &attr_len);
  692. attr_len &= SDP_DISC_ATTR_LEN_MASK;
  693. attr_type = (type >> 3) & 0x0f;
  694. /* See if there is enough space in the database */
  695. if (attr_len > 4) {
  696. total_len = attr_len - 4 + (UINT16)sizeof (tSDP_DISC_ATTR);
  697. } else {
  698. total_len = sizeof (tSDP_DISC_ATTR);
  699. }
  700. /* Ensure it is a multiple of 4 */
  701. total_len = (total_len + 3) & ~3;
  702. /* See if there is enough space in the database */
  703. if (p_db->mem_free < total_len) {
  704. return (NULL);
  705. }
  706. p_attr = (tSDP_DISC_ATTR *) p_db->p_free_mem;
  707. p_attr->attr_id = attr_id;
  708. p_attr->attr_len_type = (UINT16)attr_len | (attr_type << 12);
  709. p_attr->p_next_attr = NULL;
  710. /* Store the attribute value */
  711. switch (attr_type) {
  712. case UINT_DESC_TYPE:
  713. if ( (is_additional_list != 0) && (attr_len == 2) ) {
  714. BE_STREAM_TO_UINT16 (id, p);
  715. if (id != ATTR_ID_PROTOCOL_DESC_LIST) {
  716. p -= 2;
  717. } else {
  718. /* Reserve the memory for the attribute now, as we need to add sub-attributes */
  719. p_db->p_free_mem += sizeof (tSDP_DISC_ATTR);
  720. p_db->mem_free -= sizeof (tSDP_DISC_ATTR);
  721. p_end = p + attr_len;
  722. total_len = 0;
  723. /* SDP_TRACE_DEBUG ("SDP - attr nest level:%d(list)", nest_level); */
  724. if (nest_level >= MAX_NEST_LEVELS) {
  725. SDP_TRACE_ERROR ("SDP - attr nesting too deep\n");
  726. return (p_end);
  727. }
  728. /* Now, add the list entry */
  729. p = add_attr (p, p_db, p_rec, ATTR_ID_PROTOCOL_DESC_LIST, p_attr, (UINT8)(nest_level + 1));
  730. break;
  731. }
  732. }
  733. /* Case falls through */
  734. case TWO_COMP_INT_DESC_TYPE:
  735. switch (attr_len) {
  736. case 1:
  737. p_attr->attr_value.v.u8 = *p++;
  738. break;
  739. case 2:
  740. BE_STREAM_TO_UINT16 (p_attr->attr_value.v.u16, p);
  741. break;
  742. case 4:
  743. BE_STREAM_TO_UINT32 (p_attr->attr_value.v.u32, p);
  744. break;
  745. default:
  746. BE_STREAM_TO_ARRAY (p, p_attr->attr_value.v.array, (INT32)attr_len);
  747. break;
  748. }
  749. break;
  750. case UUID_DESC_TYPE:
  751. switch (attr_len) {
  752. case 2:
  753. BE_STREAM_TO_UINT16 (p_attr->attr_value.v.u16, p);
  754. break;
  755. case 4:
  756. BE_STREAM_TO_UINT32 (p_attr->attr_value.v.u32, p);
  757. if (p_attr->attr_value.v.u32 < 0x10000) {
  758. attr_len = 2;
  759. p_attr->attr_len_type = (UINT16)attr_len | (attr_type << 12);
  760. p_attr->attr_value.v.u16 = (UINT16) p_attr->attr_value.v.u32;
  761. }
  762. break;
  763. case 16:
  764. /* See if we can compress his UUID down to 16 or 32bit UUIDs */
  765. if (sdpu_is_base_uuid (p)) {
  766. if ((p[0] == 0) && (p[1] == 0)) {
  767. p_attr->attr_len_type = (p_attr->attr_len_type & ~SDP_DISC_ATTR_LEN_MASK) | 2;
  768. p += 2;
  769. BE_STREAM_TO_UINT16 (p_attr->attr_value.v.u16, p);
  770. p += MAX_UUID_SIZE - 4;
  771. } else {
  772. p_attr->attr_len_type = (p_attr->attr_len_type & ~SDP_DISC_ATTR_LEN_MASK) | 4;
  773. BE_STREAM_TO_UINT32 (p_attr->attr_value.v.u32, p);
  774. p += MAX_UUID_SIZE - 4;
  775. }
  776. } else {
  777. /* coverity[overrun-local] */
  778. /*
  779. Event overrun-local: Overrun of static array "p_attr->attr_value.v.array" of size 4 at position 15 with index variable "ijk"
  780. False-positive: SDP uses scratch buffer to hold the attribute value.
  781. The actual size of tSDP_DISC_ATVAL does not matter.
  782. If the array size in tSDP_DISC_ATVAL is increase, we would increase the system RAM usage unnecessarily
  783. */
  784. BE_STREAM_TO_ARRAY (p, p_attr->attr_value.v.array, (INT32)attr_len);
  785. }
  786. break;
  787. default:
  788. SDP_TRACE_WARNING ("SDP - bad len in UUID attr: %d\n", attr_len);
  789. return (p + attr_len);
  790. }
  791. break;
  792. case DATA_ELE_SEQ_DESC_TYPE:
  793. case DATA_ELE_ALT_DESC_TYPE:
  794. /* Reserve the memory for the attribute now, as we need to add sub-attributes */
  795. p_db->p_free_mem += sizeof (tSDP_DISC_ATTR);
  796. p_db->mem_free -= sizeof (tSDP_DISC_ATTR);
  797. p_end = p + attr_len;
  798. total_len = 0;
  799. /* SDP_TRACE_DEBUG ("SDP - attr nest level:%d", nest_level); */
  800. if (nest_level >= MAX_NEST_LEVELS) {
  801. SDP_TRACE_ERROR ("SDP - attr nesting too deep\n");
  802. return (p_end);
  803. }
  804. if (is_additional_list != 0 || attr_id == ATTR_ID_ADDITION_PROTO_DESC_LISTS) {
  805. nest_level |= SDP_ADDITIONAL_LIST_MASK;
  806. }
  807. /* SDP_TRACE_DEBUG ("SDP - attr nest level:0x%x(finish)", nest_level); */
  808. while (p < p_end) {
  809. /* Now, add the list entry */
  810. p = add_attr (p, p_db, p_rec, 0, p_attr, (UINT8)(nest_level + 1));
  811. if (!p) {
  812. return (NULL);
  813. }
  814. }
  815. break;
  816. case TEXT_STR_DESC_TYPE:
  817. case URL_DESC_TYPE:
  818. BE_STREAM_TO_ARRAY (p, p_attr->attr_value.v.array, (INT32)attr_len);
  819. break;
  820. case BOOLEAN_DESC_TYPE:
  821. switch (attr_len) {
  822. case 1:
  823. p_attr->attr_value.v.u8 = *p++;
  824. break;
  825. default:
  826. SDP_TRACE_WARNING ("SDP - bad len in boolean attr: %d\n", attr_len);
  827. return (p + attr_len);
  828. }
  829. break;
  830. default: /* switch (attr_type) */
  831. break;
  832. }
  833. p_db->p_free_mem += total_len;
  834. p_db->mem_free -= total_len;
  835. /* Add the attribute to the end of the chain */
  836. if (!p_parent_attr) {
  837. if (!p_rec->p_first_attr) {
  838. p_rec->p_first_attr = p_attr;
  839. } else {
  840. tSDP_DISC_ATTR *p_attr1 = p_rec->p_first_attr;
  841. while (p_attr1->p_next_attr) {
  842. p_attr1 = p_attr1->p_next_attr;
  843. }
  844. p_attr1->p_next_attr = p_attr;
  845. }
  846. } else {
  847. if (!p_parent_attr->attr_value.v.p_sub_attr) {
  848. p_parent_attr->attr_value.v.p_sub_attr = p_attr;
  849. /* SDP_TRACE_DEBUG ("parent:0x%x(id:%d), ch:0x%x(id:%d)",
  850. p_parent_attr, p_parent_attr->attr_id, p_attr, p_attr->attr_id); */
  851. } else {
  852. tSDP_DISC_ATTR *p_attr1 = p_parent_attr->attr_value.v.p_sub_attr;
  853. /* SDP_TRACE_DEBUG ("parent:0x%x(id:%d), ch1:0x%x(id:%d)",
  854. p_parent_attr, p_parent_attr->attr_id, p_attr1, p_attr1->attr_id); */
  855. while (p_attr1->p_next_attr) {
  856. p_attr1 = p_attr1->p_next_attr;
  857. }
  858. p_attr1->p_next_attr = p_attr;
  859. /* SDP_TRACE_DEBUG ("new ch:0x%x(id:%d)", p_attr, p_attr->attr_id); */
  860. }
  861. }
  862. return (p);
  863. }
  864. #endif /* CLIENT_ENABLED == TRUE */