avct_l2c.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406
  1. /******************************************************************************
  2. *
  3. * Copyright (C) 2003-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 AVCTP module interfaces to L2CAP
  21. *
  22. ******************************************************************************/
  23. #include <string.h>
  24. #include "stack/bt_types.h"
  25. #include "common/bt_target.h"
  26. #include "common/bt_defs.h"
  27. #include "stack/avct_api.h"
  28. #include "avct_int.h"
  29. #include "stack/l2c_api.h"
  30. #include "stack/l2cdefs.h"
  31. #include "osi/allocator.h"
  32. #if (defined(AVCT_INCLUDED) && AVCT_INCLUDED == TRUE)
  33. /* Configuration flags. */
  34. #define AVCT_L2C_CFG_IND_DONE (1<<0)
  35. #define AVCT_L2C_CFG_CFM_DONE (1<<1)
  36. /* callback function declarations */
  37. void avct_l2c_connect_ind_cback(BD_ADDR bd_addr, UINT16 lcid, UINT16 psm, UINT8 id);
  38. void avct_l2c_connect_cfm_cback(UINT16 lcid, UINT16 result);
  39. void avct_l2c_config_cfm_cback(UINT16 lcid, tL2CAP_CFG_INFO *p_cfg);
  40. void avct_l2c_config_ind_cback(UINT16 lcid, tL2CAP_CFG_INFO *p_cfg);
  41. void avct_l2c_disconnect_ind_cback(UINT16 lcid, BOOLEAN ack_needed);
  42. void avct_l2c_disconnect_cfm_cback(UINT16 lcid, UINT16 result);
  43. void avct_l2c_congestion_ind_cback(UINT16 lcid, BOOLEAN is_congested);
  44. void avct_l2c_data_ind_cback(UINT16 lcid, BT_HDR *p_buf);
  45. /* L2CAP callback function structure */
  46. const tL2CAP_APPL_INFO avct_l2c_appl = {
  47. avct_l2c_connect_ind_cback,
  48. avct_l2c_connect_cfm_cback,
  49. NULL,
  50. avct_l2c_config_ind_cback,
  51. avct_l2c_config_cfm_cback,
  52. avct_l2c_disconnect_ind_cback,
  53. avct_l2c_disconnect_cfm_cback,
  54. NULL,
  55. avct_l2c_data_ind_cback,
  56. avct_l2c_congestion_ind_cback,
  57. NULL /* tL2CA_TX_COMPLETE_CB */
  58. };
  59. /*******************************************************************************
  60. **
  61. ** Function avct_l2c_is_passive
  62. **
  63. ** Description check is the CCB associated with the given LCB was created
  64. ** as passive
  65. **
  66. ** Returns TRUE, if the given LCB is created as AVCT_PASSIVE
  67. **
  68. *******************************************************************************/
  69. static BOOLEAN avct_l2c_is_passive (tAVCT_LCB *p_lcb)
  70. {
  71. BOOLEAN is_passive = FALSE;
  72. tAVCT_CCB *p_ccb = &avct_cb.ccb[0];
  73. int i;
  74. for (i = 0; i < AVCT_NUM_CONN; i++, p_ccb++) {
  75. if (p_ccb->allocated && (p_ccb->p_lcb == p_lcb)) {
  76. AVCT_TRACE_DEBUG("avct_l2c_is_ct control:x%x", p_ccb->cc.control);
  77. if (p_ccb->cc.control & AVCT_PASSIVE) {
  78. is_passive = TRUE;
  79. break;
  80. }
  81. }
  82. }
  83. return is_passive;
  84. }
  85. /*******************************************************************************
  86. **
  87. ** Function avct_l2c_connect_ind_cback
  88. **
  89. ** Description This is the L2CAP connect indication callback function.
  90. **
  91. **
  92. ** Returns void
  93. **
  94. *******************************************************************************/
  95. void avct_l2c_connect_ind_cback(BD_ADDR bd_addr, UINT16 lcid, UINT16 psm, UINT8 id)
  96. {
  97. tAVCT_LCB *p_lcb;
  98. UINT16 result = L2CAP_CONN_OK;
  99. tL2CAP_CFG_INFO cfg;
  100. UNUSED(psm);
  101. /* do we already have a channel for this peer? */
  102. if ((p_lcb = avct_lcb_by_bd(bd_addr)) == NULL) {
  103. /* no, allocate lcb */
  104. if ((p_lcb = avct_lcb_alloc(bd_addr)) == NULL) {
  105. /* no ccb available, reject L2CAP connection */
  106. result = L2CAP_CONN_NO_RESOURCES;
  107. }
  108. }
  109. /* else we already have a channel for this peer */
  110. else {
  111. if (!avct_l2c_is_passive (p_lcb) || (p_lcb->ch_state == AVCT_CH_OPEN)) {
  112. /* this LCB included CT role - reject */
  113. result = L2CAP_CONN_NO_RESOURCES;
  114. } else {
  115. /* TG role only - accept the connection from CT. move the channel ID to the conflict list */
  116. p_lcb->conflict_lcid = p_lcb->ch_lcid;
  117. AVCT_TRACE_DEBUG("avct_l2c_connect_ind_cback conflict_lcid:0x%x", p_lcb->conflict_lcid);
  118. }
  119. }
  120. if (p_lcb) {
  121. AVCT_TRACE_DEBUG("avct_l2c_connect_ind_cback: 0x%x, res: %d, ch_state: %d",
  122. lcid, result, p_lcb->ch_state);
  123. }
  124. /* Send L2CAP connect rsp */
  125. L2CA_ConnectRsp(bd_addr, id, lcid, result, 0);
  126. /* if result ok, proceed with connection */
  127. if (result == L2CAP_CONN_OK) {
  128. /* store LCID */
  129. p_lcb->ch_lcid = lcid;
  130. /* transition to configuration state */
  131. p_lcb->ch_state = AVCT_CH_CFG;
  132. /* Send L2CAP config req */
  133. memset(&cfg, 0, sizeof(tL2CAP_CFG_INFO));
  134. cfg.mtu_present = TRUE;
  135. cfg.mtu = avct_cb.mtu;
  136. L2CA_ConfigReq(lcid, &cfg);
  137. AVCT_TRACE_DEBUG("avct_l2c snd Cfg Req");
  138. }
  139. #if (BT_USE_TRACES == TRUE)
  140. if (p_lcb) {
  141. AVCT_TRACE_DEBUG("ch_state cni: %d ", p_lcb->ch_state);
  142. }
  143. #endif
  144. }
  145. /*******************************************************************************
  146. **
  147. ** Function avct_l2c_connect_cfm_cback
  148. **
  149. ** Description This is the L2CAP connect confirm callback function.
  150. **
  151. **
  152. ** Returns void
  153. **
  154. *******************************************************************************/
  155. void avct_l2c_connect_cfm_cback(UINT16 lcid, UINT16 result)
  156. {
  157. tAVCT_LCB *p_lcb;
  158. tL2CAP_CFG_INFO cfg;
  159. /* look up lcb for this channel */
  160. if ((p_lcb = avct_lcb_by_lcid(lcid)) != NULL) {
  161. AVCT_TRACE_DEBUG("avct_l2c_connect_cfm_cback lcid:0x%x result: %d ch_state: %d, conflict_lcid:0x%x",
  162. lcid, result, p_lcb->ch_state, p_lcb->conflict_lcid);
  163. /* if in correct state */
  164. if (p_lcb->ch_state == AVCT_CH_CONN) {
  165. /* if result successful */
  166. if (result == L2CAP_CONN_OK) {
  167. /* set channel state */
  168. p_lcb->ch_state = AVCT_CH_CFG;
  169. /* Send L2CAP config req */
  170. memset(&cfg, 0, sizeof(tL2CAP_CFG_INFO));
  171. cfg.mtu_present = TRUE;
  172. cfg.mtu = avct_cb.mtu;
  173. L2CA_ConfigReq(lcid, &cfg);
  174. AVCT_TRACE_DEBUG("avct_l2c snd Cfg Req");
  175. }
  176. /* else failure */
  177. else {
  178. AVCT_TRACE_DEBUG("avct_l2c_connect_cfm_cback conflict_lcid:0x%x", p_lcb->conflict_lcid);
  179. if (p_lcb->conflict_lcid == lcid) {
  180. p_lcb->conflict_lcid = 0;
  181. } else {
  182. avct_lcb_event(p_lcb, AVCT_LCB_LL_CLOSE_EVT, (tAVCT_LCB_EVT *) &result);
  183. }
  184. }
  185. } else if (p_lcb->conflict_lcid == lcid) {
  186. /* we must be in AVCT_CH_CFG state for the ch_lcid channel */
  187. AVCT_TRACE_DEBUG("avct_l2c_connect_cfm_cback ch_state: %d, conflict_lcid:0x%x", p_lcb->ch_state, p_lcb->conflict_lcid);
  188. if (result == L2CAP_CONN_OK) {
  189. /* just in case the peer also accepts our connection - Send L2CAP disconnect req */
  190. L2CA_DisconnectReq(lcid);
  191. }
  192. p_lcb->conflict_lcid = 0;
  193. }
  194. AVCT_TRACE_DEBUG("ch_state cnc: %d ", p_lcb->ch_state);
  195. }
  196. }
  197. /*******************************************************************************
  198. **
  199. ** Function avct_l2c_config_cfm_cback
  200. **
  201. ** Description This is the L2CAP config confirm callback function.
  202. **
  203. **
  204. ** Returns void
  205. **
  206. *******************************************************************************/
  207. void avct_l2c_config_cfm_cback(UINT16 lcid, tL2CAP_CFG_INFO *p_cfg)
  208. {
  209. tAVCT_LCB *p_lcb;
  210. /* look up lcb for this channel */
  211. if ((p_lcb = avct_lcb_by_lcid(lcid)) != NULL) {
  212. AVCT_TRACE_DEBUG("avct_l2c_config_cfm_cback: 0x%x, ch_state: %d, res: %d",
  213. lcid, p_lcb->ch_state, p_cfg->result);
  214. /* if in correct state */
  215. if (p_lcb->ch_state == AVCT_CH_CFG) {
  216. /* if result successful */
  217. if (p_cfg->result == L2CAP_CFG_OK) {
  218. /* update flags */
  219. p_lcb->ch_flags |= AVCT_L2C_CFG_CFM_DONE;
  220. /* if configuration complete */
  221. if (p_lcb->ch_flags & AVCT_L2C_CFG_IND_DONE) {
  222. p_lcb->ch_state = AVCT_CH_OPEN;
  223. avct_lcb_event(p_lcb, AVCT_LCB_LL_OPEN_EVT, NULL);
  224. }
  225. }
  226. /* else failure */
  227. else {
  228. AVCT_TRACE_DEBUG("ERROR avct_l2c_config_cfm_cback L2CA_DisconnectReq %d ", p_lcb->ch_state);
  229. /* store result value */
  230. p_lcb->ch_result = p_cfg->result;
  231. /* Send L2CAP disconnect req */
  232. L2CA_DisconnectReq(lcid);
  233. }
  234. }
  235. AVCT_TRACE_DEBUG("ch_state cfc: %d ", p_lcb->ch_state);
  236. }
  237. }
  238. /*******************************************************************************
  239. **
  240. ** Function avct_l2c_config_ind_cback
  241. **
  242. ** Description This is the L2CAP config indication callback function.
  243. **
  244. **
  245. ** Returns void
  246. **
  247. *******************************************************************************/
  248. void avct_l2c_config_ind_cback(UINT16 lcid, tL2CAP_CFG_INFO *p_cfg)
  249. {
  250. tAVCT_LCB *p_lcb;
  251. /* look up lcb for this channel */
  252. if ((p_lcb = avct_lcb_by_lcid(lcid)) != NULL) {
  253. AVCT_TRACE_DEBUG("avct_l2c_config_ind_cback: 0x%x, ch_state: %d", lcid, p_lcb->ch_state);
  254. /* store the mtu in tbl */
  255. if (p_cfg->mtu_present) {
  256. p_lcb->peer_mtu = p_cfg->mtu;
  257. } else {
  258. p_lcb->peer_mtu = L2CAP_DEFAULT_MTU;
  259. }
  260. /* send L2CAP configure response */
  261. memset(p_cfg, 0, sizeof(tL2CAP_CFG_INFO));
  262. p_cfg->result = L2CAP_CFG_OK;
  263. L2CA_ConfigRsp(lcid, p_cfg);
  264. /* if first config ind */
  265. if ((p_lcb->ch_flags & AVCT_L2C_CFG_IND_DONE) == 0) {
  266. /* update flags */
  267. p_lcb->ch_flags |= AVCT_L2C_CFG_IND_DONE;
  268. /* if configuration complete */
  269. if (p_lcb->ch_flags & AVCT_L2C_CFG_CFM_DONE) {
  270. p_lcb->ch_state = AVCT_CH_OPEN;
  271. avct_lcb_event(p_lcb, AVCT_LCB_LL_OPEN_EVT, NULL);
  272. }
  273. }
  274. AVCT_TRACE_DEBUG("ch_state cfi: %d ", p_lcb->ch_state);
  275. }
  276. }
  277. /*******************************************************************************
  278. **
  279. ** Function avct_l2c_disconnect_ind_cback
  280. **
  281. ** Description This is the L2CAP disconnect indication callback function.
  282. **
  283. **
  284. ** Returns void
  285. **
  286. *******************************************************************************/
  287. void avct_l2c_disconnect_ind_cback(UINT16 lcid, BOOLEAN ack_needed)
  288. {
  289. tAVCT_LCB *p_lcb;
  290. UINT16 result = AVCT_RESULT_FAIL;
  291. /* look up lcb for this channel */
  292. if ((p_lcb = avct_lcb_by_lcid(lcid)) != NULL) {
  293. AVCT_TRACE_DEBUG("avct_l2c_disconnect_ind_cback: 0x%x, ch_state: %d", lcid, p_lcb->ch_state);
  294. if (ack_needed) {
  295. /* send L2CAP disconnect response */
  296. L2CA_DisconnectRsp(lcid);
  297. }
  298. avct_lcb_event(p_lcb, AVCT_LCB_LL_CLOSE_EVT, (tAVCT_LCB_EVT *) &result);
  299. AVCT_TRACE_DEBUG("ch_state di: %d ", p_lcb->ch_state);
  300. }
  301. }
  302. /*******************************************************************************
  303. **
  304. ** Function avct_l2c_disconnect_cfm_cback
  305. **
  306. ** Description This is the L2CAP disconnect confirm callback function.
  307. **
  308. **
  309. ** Returns void
  310. **
  311. *******************************************************************************/
  312. void avct_l2c_disconnect_cfm_cback(UINT16 lcid, UINT16 result)
  313. {
  314. tAVCT_LCB *p_lcb;
  315. UINT16 res;
  316. /* look up lcb for this channel */
  317. if ((p_lcb = avct_lcb_by_lcid(lcid)) != NULL) {
  318. AVCT_TRACE_DEBUG("avct_l2c_disconnect_cfm_cback: 0x%x, ch_state: %d, res: %d",
  319. lcid, p_lcb->ch_state, result);
  320. /* result value may be previously stored */
  321. res = (p_lcb->ch_result != 0) ? p_lcb->ch_result : result;
  322. p_lcb->ch_result = 0;
  323. avct_lcb_event(p_lcb, AVCT_LCB_LL_CLOSE_EVT, (tAVCT_LCB_EVT *) &res);
  324. AVCT_TRACE_DEBUG("ch_state dc: %d ", p_lcb->ch_state);
  325. }
  326. }
  327. /*******************************************************************************
  328. **
  329. ** Function avct_l2c_congestion_ind_cback
  330. **
  331. ** Description This is the L2CAP congestion indication callback function.
  332. **
  333. **
  334. ** Returns void
  335. **
  336. *******************************************************************************/
  337. void avct_l2c_congestion_ind_cback(UINT16 lcid, BOOLEAN is_congested)
  338. {
  339. tAVCT_LCB *p_lcb;
  340. AVCT_TRACE_DEBUG("avct_l2c_congestion_ind_cback: 0x%x", lcid);
  341. /* look up lcb for this channel */
  342. if ((p_lcb = avct_lcb_by_lcid(lcid)) != NULL) {
  343. avct_lcb_event(p_lcb, AVCT_LCB_LL_CONG_EVT, (tAVCT_LCB_EVT *) &is_congested);
  344. }
  345. }
  346. /*******************************************************************************
  347. **
  348. ** Function avct_l2c_data_ind_cback
  349. **
  350. ** Description This is the L2CAP data indication callback function.
  351. **
  352. **
  353. ** Returns void
  354. **
  355. *******************************************************************************/
  356. void avct_l2c_data_ind_cback(UINT16 lcid, BT_HDR *p_buf)
  357. {
  358. tAVCT_LCB *p_lcb;
  359. AVCT_TRACE_DEBUG("avct_l2c_data_ind_cback: 0x%x", lcid);
  360. /* look up lcb for this channel */
  361. if ((p_lcb = avct_lcb_by_lcid(lcid)) != NULL) {
  362. avct_lcb_event(p_lcb, AVCT_LCB_LL_MSG_EVT, (tAVCT_LCB_EVT *) &p_buf);
  363. } else { /* prevent buffer leak */
  364. AVCT_TRACE_WARNING("ERROR -> avct_l2c_data_ind_cback drop buffer");
  365. osi_free(p_buf);
  366. }
  367. }
  368. #endif /* #if (defined(AVCT_INCLUDED) && AVCT_INCLUDED == TRUE) */