sdp_main.cc 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679
  1. /******************************************************************************
  2. *
  3. * Copyright 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 the main SDP functions
  21. *
  22. ******************************************************************************/
  23. #include <stdio.h>
  24. #include <stdlib.h>
  25. #include <string.h>
  26. #include "bt_common.h"
  27. #include "bt_target.h"
  28. #include "bt_utils.h"
  29. #include "hcidefs.h"
  30. #include "hcimsgs.h"
  31. #include "l2c_api.h"
  32. #include "l2cdefs.h"
  33. #include "osi/include/osi.h"
  34. #include "btm_api.h"
  35. #include "btu.h"
  36. #include "sdp_api.h"
  37. #include "sdpint.h"
  38. /******************************************************************************/
  39. /* G L O B A L S D P D A T A */
  40. /******************************************************************************/
  41. tSDP_CB sdp_cb;
  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 void sdp_connect_ind(const RawAddress& bd_addr, uint16_t l2cap_cid,
  46. UNUSED_ATTR uint16_t psm, uint8_t l2cap_id);
  47. static void sdp_config_ind(uint16_t l2cap_cid, tL2CAP_CFG_INFO* p_cfg);
  48. static void sdp_config_cfm(uint16_t l2cap_cid, tL2CAP_CFG_INFO* p_cfg);
  49. static void sdp_disconnect_ind(uint16_t l2cap_cid, bool ack_needed);
  50. static void sdp_data_ind(uint16_t l2cap_cid, BT_HDR* p_msg);
  51. static void sdp_connect_cfm(uint16_t l2cap_cid, uint16_t result);
  52. static void sdp_disconnect_cfm(uint16_t l2cap_cid, uint16_t result);
  53. /*******************************************************************************
  54. *
  55. * Function sdp_init
  56. *
  57. * Description This function initializes the SDP unit.
  58. *
  59. * Returns void
  60. *
  61. ******************************************************************************/
  62. void sdp_init(void) {
  63. /* Clears all structures and local SDP database (if Server is enabled) */
  64. memset(&sdp_cb, 0, sizeof(tSDP_CB));
  65. for (int i = 0; i < SDP_MAX_CONNECTIONS; i++) {
  66. sdp_cb.ccb[i].sdp_conn_timer = alarm_new("sdp.sdp_conn_timer");
  67. }
  68. /* Initialize the L2CAP configuration. We only care about MTU and flush */
  69. sdp_cb.l2cap_my_cfg.mtu_present = true;
  70. sdp_cb.l2cap_my_cfg.mtu = SDP_MTU_SIZE;
  71. sdp_cb.l2cap_my_cfg.flush_to_present = true;
  72. sdp_cb.l2cap_my_cfg.flush_to = SDP_FLUSH_TO;
  73. sdp_cb.max_attr_list_size = SDP_MTU_SIZE - 16;
  74. sdp_cb.max_recs_per_search = SDP_MAX_DISC_SERVER_RECS;
  75. #if (SDP_SERVER_ENABLED == TRUE)
  76. /* Register with Security Manager for the specific security level */
  77. if (!BTM_SetSecurityLevel(false, SDP_SERVICE_NAME, BTM_SEC_SERVICE_SDP_SERVER,
  78. SDP_SECURITY_LEVEL, SDP_PSM, 0, 0)) {
  79. SDP_TRACE_ERROR("Security Registration Server failed");
  80. return;
  81. }
  82. #endif
  83. /* Register with Security Manager for the specific security level */
  84. if (!BTM_SetSecurityLevel(true, SDP_SERVICE_NAME, BTM_SEC_SERVICE_SDP_SERVER,
  85. SDP_SECURITY_LEVEL, SDP_PSM, 0, 0)) {
  86. SDP_TRACE_ERROR("Security Registration for Client failed");
  87. return;
  88. }
  89. #if defined(SDP_INITIAL_TRACE_LEVEL)
  90. sdp_cb.trace_level = SDP_INITIAL_TRACE_LEVEL;
  91. #else
  92. sdp_cb.trace_level = BT_TRACE_LEVEL_NONE; /* No traces */
  93. #endif
  94. sdp_cb.reg_info.pL2CA_ConnectInd_Cb = sdp_connect_ind;
  95. sdp_cb.reg_info.pL2CA_ConnectCfm_Cb = sdp_connect_cfm;
  96. sdp_cb.reg_info.pL2CA_ConnectPnd_Cb = NULL;
  97. sdp_cb.reg_info.pL2CA_ConfigInd_Cb = sdp_config_ind;
  98. sdp_cb.reg_info.pL2CA_ConfigCfm_Cb = sdp_config_cfm;
  99. sdp_cb.reg_info.pL2CA_DisconnectInd_Cb = sdp_disconnect_ind;
  100. sdp_cb.reg_info.pL2CA_DisconnectCfm_Cb = sdp_disconnect_cfm;
  101. sdp_cb.reg_info.pL2CA_QoSViolationInd_Cb = NULL;
  102. sdp_cb.reg_info.pL2CA_DataInd_Cb = sdp_data_ind;
  103. sdp_cb.reg_info.pL2CA_CongestionStatus_Cb = NULL;
  104. sdp_cb.reg_info.pL2CA_TxComplete_Cb = NULL;
  105. /* Now, register with L2CAP */
  106. if (!L2CA_Register(SDP_PSM, &sdp_cb.reg_info, true /* enable_snoop */)) {
  107. SDP_TRACE_ERROR("SDP Registration failed");
  108. }
  109. }
  110. void sdp_free(void) {
  111. for (int i = 0; i < SDP_MAX_CONNECTIONS; i++) {
  112. alarm_free(sdp_cb.ccb[i].sdp_conn_timer);
  113. sdp_cb.ccb[i].sdp_conn_timer = NULL;
  114. }
  115. }
  116. #if (SDP_DEBUG == TRUE)
  117. /*******************************************************************************
  118. *
  119. * Function sdp_set_max_attr_list_size
  120. *
  121. * Description This function sets the max attribute list size to use
  122. *
  123. * Returns void
  124. *
  125. ******************************************************************************/
  126. uint16_t sdp_set_max_attr_list_size(uint16_t max_size) {
  127. if (max_size > (sdp_cb.l2cap_my_cfg.mtu - 16))
  128. max_size = sdp_cb.l2cap_my_cfg.mtu - 16;
  129. sdp_cb.max_attr_list_size = max_size;
  130. return sdp_cb.max_attr_list_size;
  131. }
  132. #endif
  133. /*******************************************************************************
  134. *
  135. * Function sdp_connect_ind
  136. *
  137. * Description This function handles an inbound connection indication
  138. * from L2CAP. This is the case where we are acting as a
  139. * server.
  140. *
  141. * Returns void
  142. *
  143. ******************************************************************************/
  144. static void sdp_connect_ind(const RawAddress& bd_addr, uint16_t l2cap_cid,
  145. UNUSED_ATTR uint16_t psm, uint8_t l2cap_id) {
  146. #if (SDP_SERVER_ENABLED == TRUE)
  147. tCONN_CB* p_ccb;
  148. /* Allocate a new CCB. Return if none available. */
  149. p_ccb = sdpu_allocate_ccb();
  150. if (p_ccb == NULL) return;
  151. /* Transition to the next appropriate state, waiting for config setup. */
  152. p_ccb->con_state = SDP_STATE_CFG_SETUP;
  153. /* Save the BD Address and Channel ID. */
  154. p_ccb->device_address = bd_addr;
  155. p_ccb->connection_id = l2cap_cid;
  156. /* Send response to the L2CAP layer. */
  157. L2CA_ConnectRsp(bd_addr, l2cap_id, l2cap_cid, L2CAP_CONN_OK, L2CAP_CONN_OK);
  158. {
  159. tL2CAP_CFG_INFO cfg = sdp_cb.l2cap_my_cfg;
  160. if (cfg.fcr_present) {
  161. SDP_TRACE_DEBUG(
  162. "sdp_connect_ind: mode %u, txwinsz %u, max_trans %u, rtrans_tout "
  163. "%u, mon_tout %u, mps %u",
  164. cfg.fcr.mode, cfg.fcr.tx_win_sz, cfg.fcr.max_transmit,
  165. cfg.fcr.rtrans_tout, cfg.fcr.mon_tout, cfg.fcr.mps);
  166. }
  167. if ((!L2CA_ConfigReq(l2cap_cid, &cfg)) && cfg.fcr_present &&
  168. cfg.fcr.mode != L2CAP_FCR_BASIC_MODE) {
  169. /* FCR not desired; try again in basic mode */
  170. cfg.fcr.mode = L2CAP_FCR_BASIC_MODE;
  171. cfg.fcr_present = false;
  172. L2CA_ConfigReq(l2cap_cid, &cfg);
  173. }
  174. }
  175. SDP_TRACE_EVENT("SDP - Rcvd L2CAP conn ind, sent config req, CID 0x%x",
  176. p_ccb->connection_id);
  177. #else /* No server */
  178. /* Reject the connection */
  179. L2CA_ConnectRsp(bd_addr, l2cap_id, l2cap_cid, L2CAP_CONN_NO_PSM, 0);
  180. #endif
  181. }
  182. /*******************************************************************************
  183. *
  184. * Function sdp_connect_cfm
  185. *
  186. * Description This function handles the connect confirm events
  187. * from L2CAP. This is the case when we are acting as a
  188. * client and have sent a connect request.
  189. *
  190. * Returns void
  191. *
  192. ******************************************************************************/
  193. static void sdp_connect_cfm(uint16_t l2cap_cid, uint16_t result) {
  194. tCONN_CB* p_ccb;
  195. tL2CAP_CFG_INFO cfg;
  196. /* Find CCB based on CID */
  197. p_ccb = sdpu_find_ccb_by_cid(l2cap_cid);
  198. if (p_ccb == NULL) {
  199. SDP_TRACE_WARNING("SDP - Rcvd conn cnf for unknown CID 0x%x", l2cap_cid);
  200. return;
  201. }
  202. /* If the connection response contains success status, then */
  203. /* Transition to the next state and startup the timer. */
  204. if ((result == L2CAP_CONN_OK) && (p_ccb->con_state == SDP_STATE_CONN_SETUP)) {
  205. p_ccb->con_state = SDP_STATE_CFG_SETUP;
  206. cfg = sdp_cb.l2cap_my_cfg;
  207. if (cfg.fcr_present) {
  208. SDP_TRACE_DEBUG(
  209. "sdp_connect_cfm: mode %u, txwinsz %u, max_trans %u, rtrans_tout "
  210. "%u, mon_tout %u, mps %u",
  211. cfg.fcr.mode, cfg.fcr.tx_win_sz, cfg.fcr.max_transmit,
  212. cfg.fcr.rtrans_tout, cfg.fcr.mon_tout, cfg.fcr.mps);
  213. }
  214. if ((!L2CA_ConfigReq(l2cap_cid, &cfg)) && cfg.fcr_present &&
  215. cfg.fcr.mode != L2CAP_FCR_BASIC_MODE) {
  216. /* FCR not desired; try again in basic mode */
  217. cfg.fcr_present = false;
  218. cfg.fcr.mode = L2CAP_FCR_BASIC_MODE;
  219. L2CA_ConfigReq(l2cap_cid, &cfg);
  220. }
  221. SDP_TRACE_EVENT("SDP - got conn cnf, sent cfg req, CID: 0x%x",
  222. p_ccb->connection_id);
  223. } else {
  224. SDP_TRACE_WARNING("SDP - Rcvd conn cnf with error: 0x%x CID 0x%x", result,
  225. p_ccb->connection_id);
  226. /* Tell the user if he has a callback */
  227. if (p_ccb->p_cb || p_ccb->p_cb2) {
  228. uint16_t err = -1;
  229. if ((result == HCI_ERR_HOST_REJECT_SECURITY) ||
  230. (result == HCI_ERR_AUTH_FAILURE) ||
  231. (result == HCI_ERR_PAIRING_NOT_ALLOWED) ||
  232. (result == HCI_ERR_PAIRING_WITH_UNIT_KEY_NOT_SUPPORTED) ||
  233. (result == HCI_ERR_KEY_MISSING))
  234. err = SDP_SECURITY_ERR;
  235. else if (result == HCI_ERR_HOST_REJECT_DEVICE)
  236. err = SDP_CONN_REJECTED;
  237. else
  238. err = SDP_CONN_FAILED;
  239. if (p_ccb->p_cb)
  240. (*p_ccb->p_cb)(err);
  241. else if (p_ccb->p_cb2)
  242. (*p_ccb->p_cb2)(err, p_ccb->user_data);
  243. }
  244. sdpu_release_ccb(p_ccb);
  245. }
  246. }
  247. /*******************************************************************************
  248. *
  249. * Function sdp_config_ind
  250. *
  251. * Description This function processes the L2CAP configuration indication
  252. * event.
  253. *
  254. * Returns void
  255. *
  256. ******************************************************************************/
  257. static void sdp_config_ind(uint16_t l2cap_cid, tL2CAP_CFG_INFO* p_cfg) {
  258. tCONN_CB* p_ccb;
  259. /* Find CCB based on CID */
  260. p_ccb = sdpu_find_ccb_by_cid(l2cap_cid);
  261. if (p_ccb == NULL) {
  262. SDP_TRACE_WARNING("SDP - Rcvd L2CAP cfg ind, unknown CID: 0x%x", l2cap_cid);
  263. return;
  264. }
  265. /* Remember the remote MTU size */
  266. if (!p_cfg->mtu_present) {
  267. /* use min(L2CAP_DEFAULT_MTU,SDP_MTU_SIZE) for GKI buffer size reasons */
  268. p_ccb->rem_mtu_size =
  269. (L2CAP_DEFAULT_MTU > SDP_MTU_SIZE) ? SDP_MTU_SIZE : L2CAP_DEFAULT_MTU;
  270. } else {
  271. if (p_cfg->mtu > SDP_MTU_SIZE)
  272. p_ccb->rem_mtu_size = SDP_MTU_SIZE;
  273. else
  274. p_ccb->rem_mtu_size = p_cfg->mtu;
  275. }
  276. /* For now, always accept configuration from the other side */
  277. p_cfg->flush_to_present = false;
  278. p_cfg->mtu_present = false;
  279. p_cfg->result = L2CAP_CFG_OK;
  280. /* Check peer config request against our rfcomm configuration */
  281. if (p_cfg->fcr_present) {
  282. /* Reject the window size if it is bigger than we want it to be */
  283. if (p_cfg->fcr.mode != L2CAP_FCR_BASIC_MODE) {
  284. if (sdp_cb.l2cap_my_cfg.fcr.mode != L2CAP_FCR_BASIC_MODE &&
  285. p_cfg->fcr.tx_win_sz > sdp_cb.l2cap_my_cfg.fcr.tx_win_sz) {
  286. p_cfg->fcr.tx_win_sz = sdp_cb.l2cap_my_cfg.fcr.tx_win_sz;
  287. p_cfg->result = L2CAP_CFG_UNACCEPTABLE_PARAMS;
  288. SDP_TRACE_DEBUG(
  289. "sdp_config_ind(CONFIG) -> Please try again with SMALLER TX "
  290. "WINDOW");
  291. }
  292. /* Reject if locally we want basic and they don't */
  293. if (sdp_cb.l2cap_my_cfg.fcr.mode == L2CAP_FCR_BASIC_MODE) {
  294. /* Ask for a new setup */
  295. p_cfg->fcr.mode = L2CAP_FCR_BASIC_MODE;
  296. p_cfg->result = L2CAP_CFG_UNACCEPTABLE_PARAMS;
  297. SDP_TRACE_DEBUG(
  298. "sdp_config_ind(CONFIG) -> Please try again with BASIC mode");
  299. }
  300. /* Remain in configure state and give the peer our desired configuration
  301. */
  302. if (p_cfg->result != L2CAP_CFG_OK) {
  303. SDP_TRACE_WARNING(
  304. "SDP - Rcvd cfg ind, Unacceptable Parameters sent cfg cfm, CID: "
  305. "0x%x",
  306. l2cap_cid);
  307. L2CA_ConfigRsp(l2cap_cid, p_cfg);
  308. return;
  309. }
  310. } else /* We agree with peer's request */
  311. p_cfg->fcr_present = false;
  312. }
  313. L2CA_ConfigRsp(l2cap_cid, p_cfg);
  314. SDP_TRACE_EVENT("SDP - Rcvd cfg ind, sent cfg cfm, CID: 0x%x", l2cap_cid);
  315. p_ccb->con_flags |= SDP_FLAGS_HIS_CFG_DONE;
  316. if (p_ccb->con_flags & SDP_FLAGS_MY_CFG_DONE) {
  317. p_ccb->con_state = SDP_STATE_CONNECTED;
  318. if (p_ccb->con_flags & SDP_FLAGS_IS_ORIG) {
  319. sdp_disc_connected(p_ccb);
  320. } else {
  321. /* Start inactivity timer */
  322. alarm_set_on_mloop(p_ccb->sdp_conn_timer, SDP_INACT_TIMEOUT_MS,
  323. sdp_conn_timer_timeout, p_ccb);
  324. }
  325. }
  326. }
  327. /*******************************************************************************
  328. *
  329. * Function sdp_config_cfm
  330. *
  331. * Description This function processes the L2CAP configuration confirmation
  332. * event.
  333. *
  334. * Returns void
  335. *
  336. ******************************************************************************/
  337. static void sdp_config_cfm(uint16_t l2cap_cid, tL2CAP_CFG_INFO* p_cfg) {
  338. tCONN_CB* p_ccb;
  339. SDP_TRACE_EVENT("SDP - Rcvd cfg cfm, CID: 0x%x Result: %d", l2cap_cid,
  340. p_cfg->result);
  341. /* Find CCB based on CID */
  342. p_ccb = sdpu_find_ccb_by_cid(l2cap_cid);
  343. if (p_ccb == NULL) {
  344. SDP_TRACE_WARNING("SDP - Rcvd L2CAP cfg ind, unknown CID: 0x%x", l2cap_cid);
  345. return;
  346. }
  347. /* For now, always accept configuration from the other side */
  348. if (p_cfg->result == L2CAP_CFG_OK) {
  349. p_ccb->con_flags |= SDP_FLAGS_MY_CFG_DONE;
  350. if (p_ccb->con_flags & SDP_FLAGS_HIS_CFG_DONE) {
  351. p_ccb->con_state = SDP_STATE_CONNECTED;
  352. if (p_ccb->con_flags & SDP_FLAGS_IS_ORIG) {
  353. sdp_disc_connected(p_ccb);
  354. } else {
  355. /* Start inactivity timer */
  356. alarm_set_on_mloop(p_ccb->sdp_conn_timer, SDP_INACT_TIMEOUT_MS,
  357. sdp_conn_timer_timeout, p_ccb);
  358. }
  359. }
  360. } else {
  361. /* If peer has rejected FCR and suggested basic then try basic */
  362. if (p_cfg->fcr_present) {
  363. tL2CAP_CFG_INFO cfg = sdp_cb.l2cap_my_cfg;
  364. cfg.fcr_present = false;
  365. L2CA_ConfigReq(l2cap_cid, &cfg);
  366. /* Remain in configure state */
  367. return;
  368. }
  369. sdp_disconnect(p_ccb, SDP_CFG_FAILED);
  370. }
  371. }
  372. /*******************************************************************************
  373. *
  374. * Function sdp_disconnect_ind
  375. *
  376. * Description This function handles a disconnect event from L2CAP. If
  377. * requested to, we ack the disconnect before dropping the CCB
  378. *
  379. * Returns void
  380. *
  381. ******************************************************************************/
  382. static void sdp_disconnect_ind(uint16_t l2cap_cid, bool ack_needed) {
  383. tCONN_CB* p_ccb;
  384. /* Find CCB based on CID */
  385. p_ccb = sdpu_find_ccb_by_cid(l2cap_cid);
  386. if (p_ccb == NULL) {
  387. SDP_TRACE_WARNING("SDP - Rcvd L2CAP disc, unknown CID: 0x%x", l2cap_cid);
  388. return;
  389. }
  390. if (ack_needed) L2CA_DisconnectRsp(l2cap_cid);
  391. SDP_TRACE_EVENT("SDP - Rcvd L2CAP disc, CID: 0x%x", l2cap_cid);
  392. /* Tell the user if he has a callback */
  393. if (p_ccb->p_cb)
  394. (*p_ccb->p_cb)((uint16_t)((p_ccb->con_state == SDP_STATE_CONNECTED)
  395. ? SDP_SUCCESS
  396. : SDP_CONN_FAILED));
  397. else if (p_ccb->p_cb2)
  398. (*p_ccb->p_cb2)(
  399. (uint16_t)((p_ccb->con_state == SDP_STATE_CONNECTED) ? SDP_SUCCESS
  400. : SDP_CONN_FAILED),
  401. p_ccb->user_data);
  402. sdpu_release_ccb(p_ccb);
  403. }
  404. /*******************************************************************************
  405. *
  406. * Function sdp_data_ind
  407. *
  408. * Description This function is called when data is received from L2CAP.
  409. * if we are the originator of the connection, we are the SDP
  410. * client, and the received message is queued for the client.
  411. *
  412. * If we are the destination of the connection, we are the SDP
  413. * server, so the message is passed to the server processing
  414. * function.
  415. *
  416. * Returns void
  417. *
  418. ******************************************************************************/
  419. static void sdp_data_ind(uint16_t l2cap_cid, BT_HDR* p_msg) {
  420. tCONN_CB* p_ccb;
  421. /* Find CCB based on CID */
  422. p_ccb = sdpu_find_ccb_by_cid(l2cap_cid);
  423. if (p_ccb != NULL) {
  424. if (p_ccb->con_state == SDP_STATE_CONNECTED) {
  425. if (p_ccb->con_flags & SDP_FLAGS_IS_ORIG)
  426. sdp_disc_server_rsp(p_ccb, p_msg);
  427. else
  428. sdp_server_handle_client_req(p_ccb, p_msg);
  429. } else {
  430. SDP_TRACE_WARNING(
  431. "SDP - Ignored L2CAP data while in state: %d, CID: 0x%x",
  432. p_ccb->con_state, l2cap_cid);
  433. }
  434. } else {
  435. SDP_TRACE_WARNING("SDP - Rcvd L2CAP data, unknown CID: 0x%x", l2cap_cid);
  436. }
  437. osi_free(p_msg);
  438. }
  439. /*******************************************************************************
  440. *
  441. * Function sdp_conn_originate
  442. *
  443. * Description This function is called from the API to originate a
  444. * connection.
  445. *
  446. * Returns void
  447. *
  448. ******************************************************************************/
  449. tCONN_CB* sdp_conn_originate(const RawAddress& p_bd_addr) {
  450. tCONN_CB* p_ccb;
  451. uint16_t cid;
  452. /* Allocate a new CCB. Return if none available. */
  453. p_ccb = sdpu_allocate_ccb();
  454. if (p_ccb == NULL) {
  455. SDP_TRACE_WARNING("%s: no spare CCB for peer %s", __func__,
  456. p_bd_addr.ToString().c_str());
  457. return (NULL);
  458. }
  459. SDP_TRACE_EVENT("%s: SDP - Originate started for peer %s", __func__,
  460. p_bd_addr.ToString().c_str());
  461. /* We are the originator of this connection */
  462. p_ccb->con_flags |= SDP_FLAGS_IS_ORIG;
  463. /* Save the BD Address and Channel ID. */
  464. p_ccb->device_address = p_bd_addr;
  465. /* Transition to the next appropriate state, waiting for connection confirm.
  466. */
  467. p_ccb->con_state = SDP_STATE_CONN_SETUP;
  468. cid = L2CA_ConnectReq(SDP_PSM, p_bd_addr);
  469. /* Check if L2CAP started the connection process */
  470. if (cid == 0) {
  471. SDP_TRACE_WARNING("%s: SDP - Originate failed for peer %s", __func__,
  472. p_bd_addr.ToString().c_str());
  473. sdpu_release_ccb(p_ccb);
  474. return (NULL);
  475. }
  476. p_ccb->connection_id = cid;
  477. return (p_ccb);
  478. }
  479. /*******************************************************************************
  480. *
  481. * Function sdp_disconnect
  482. *
  483. * Description This function disconnects a connection.
  484. *
  485. * Returns void
  486. *
  487. ******************************************************************************/
  488. void sdp_disconnect(tCONN_CB* p_ccb, uint16_t reason) {
  489. #if (SDP_BROWSE_PLUS == TRUE)
  490. /* If we are browsing for multiple UUIDs ... */
  491. if ((p_ccb->con_state == SDP_STATE_CONNECTED) &&
  492. (p_ccb->con_flags & SDP_FLAGS_IS_ORIG) &&
  493. ((reason == SDP_SUCCESS) || (reason == SDP_NO_RECS_MATCH))) {
  494. /* If the browse found something, do no more searching */
  495. if ((p_ccb->cur_uuid_idx == 0) && (p_ccb->p_db->p_first_rec))
  496. p_ccb->cur_uuid_idx = p_ccb->p_db->num_uuid_filters;
  497. while (++p_ccb->cur_uuid_idx < p_ccb->p_db->num_uuid_filters) {
  498. /* Check we have not already found the UUID (maybe through browse) */
  499. if ((p_ccb->p_db->uuid_filters[p_ccb->cur_uuid_idx].len == 2) &&
  500. (SDP_FindServiceInDb(
  501. p_ccb->p_db,
  502. p_ccb->p_db->uuid_filters[p_ccb->cur_uuid_idx].uu.uuid16, NULL)))
  503. continue;
  504. if ((p_ccb->p_db->uuid_filters[p_ccb->cur_uuid_idx].len > 2) &&
  505. (SDP_FindServiceUUIDInDb(
  506. p_ccb->p_db, &p_ccb->p_db->uuid_filters[p_ccb->cur_uuid_idx],
  507. NULL)))
  508. continue;
  509. p_ccb->cur_handle = 0;
  510. SDP_TRACE_EVENT("SDP - looking for for more, CID: 0x%x",
  511. p_ccb->connection_id);
  512. sdp_disc_connected(p_ccb);
  513. return;
  514. }
  515. }
  516. if ((reason == SDP_NO_RECS_MATCH) && (p_ccb->p_db->p_first_rec))
  517. reason = SDP_SUCCESS;
  518. #endif
  519. SDP_TRACE_EVENT("SDP - disconnect CID: 0x%x", p_ccb->connection_id);
  520. /* Check if we have a connection ID */
  521. if (p_ccb->connection_id != 0) {
  522. L2CA_DisconnectReq(p_ccb->connection_id);
  523. p_ccb->disconnect_reason = reason;
  524. }
  525. /* If at setup state, we may not get callback ind from L2CAP */
  526. /* Call user callback immediately */
  527. if (p_ccb->con_state == SDP_STATE_CONN_SETUP) {
  528. /* Tell the user if he has a callback */
  529. if (p_ccb->p_cb)
  530. (*p_ccb->p_cb)(reason);
  531. else if (p_ccb->p_cb2)
  532. (*p_ccb->p_cb2)(reason, p_ccb->user_data);
  533. sdpu_release_ccb(p_ccb);
  534. }
  535. }
  536. /*******************************************************************************
  537. *
  538. * Function sdp_disconnect_cfm
  539. *
  540. * Description This function handles a disconnect confirm event from L2CAP.
  541. *
  542. * Returns void
  543. *
  544. ******************************************************************************/
  545. static void sdp_disconnect_cfm(uint16_t l2cap_cid,
  546. UNUSED_ATTR uint16_t result) {
  547. tCONN_CB* p_ccb;
  548. /* Find CCB based on CID */
  549. p_ccb = sdpu_find_ccb_by_cid(l2cap_cid);
  550. if (p_ccb == NULL) {
  551. SDP_TRACE_WARNING("SDP - Rcvd L2CAP disc cfm, unknown CID: 0x%x",
  552. l2cap_cid);
  553. return;
  554. }
  555. SDP_TRACE_EVENT("SDP - Rcvd L2CAP disc cfm, CID: 0x%x", l2cap_cid);
  556. /* Tell the user if he has a callback */
  557. if (p_ccb->p_cb)
  558. (*p_ccb->p_cb)(p_ccb->disconnect_reason);
  559. else if (p_ccb->p_cb2)
  560. (*p_ccb->p_cb2)(p_ccb->disconnect_reason, p_ccb->user_data);
  561. sdpu_release_ccb(p_ccb);
  562. }
  563. /*******************************************************************************
  564. *
  565. * Function sdp_conn_timer_timeout
  566. *
  567. * Description This function processes a timeout. Currently, we simply send
  568. * a disconnect request to L2CAP.
  569. *
  570. * Returns void
  571. *
  572. ******************************************************************************/
  573. void sdp_conn_timer_timeout(void* data) {
  574. tCONN_CB* p_ccb = (tCONN_CB*)data;
  575. SDP_TRACE_EVENT("SDP - CCB timeout in state: %d CID: 0x%x", p_ccb->con_state,
  576. p_ccb->connection_id);
  577. L2CA_DisconnectReq(p_ccb->connection_id);
  578. /* Tell the user if he has a callback */
  579. if (p_ccb->p_cb)
  580. (*p_ccb->p_cb)(SDP_CONN_FAILED);
  581. else if (p_ccb->p_cb2)
  582. (*p_ccb->p_cb2)(SDP_CONN_FAILED, p_ccb->user_data);
  583. sdpu_release_ccb(p_ccb);
  584. }