avdt_ad.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596
  1. /******************************************************************************
  2. *
  3. * Copyright (C) 2002-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 module contains the AVDTP adaption layer.
  21. *
  22. ******************************************************************************/
  23. // #include <assert.h>
  24. #include "common/bt_trace.h"
  25. #include <string.h>
  26. #include "stack/bt_types.h"
  27. #include "common/bt_target.h"
  28. #include "common/bt_defs.h"
  29. #include "stack/avdt_api.h"
  30. #include "stack/avdtc_api.h"
  31. #include "avdt_int.h"
  32. #include "stack/l2c_api.h"
  33. #include "stack/l2cdefs.h"
  34. #include "osi/allocator.h"
  35. #if (defined(AVDT_INCLUDED) && AVDT_INCLUDED == TRUE)
  36. /*******************************************************************************
  37. **
  38. ** Function avdt_ad_type_to_tcid
  39. **
  40. ** Description Derives the TCID from the channel type and SCB.
  41. **
  42. **
  43. ** Returns TCID value.
  44. **
  45. *******************************************************************************/
  46. UINT8 avdt_ad_type_to_tcid(UINT8 type, tAVDT_SCB *p_scb)
  47. {
  48. UINT8 scb_idx;
  49. if (type == AVDT_CHAN_SIG) {
  50. return 0;
  51. } else {
  52. scb_idx = avdt_scb_to_hdl(p_scb) - 1;
  53. /*
  54. AVDT_TRACE_DEBUG("type: %d, tcid: %d", type, ((scb_idx * (AVDT_CHAN_NUM_TYPES - 1)) + type));
  55. */
  56. return ((scb_idx * (AVDT_CHAN_NUM_TYPES - 1)) + type);
  57. }
  58. }
  59. /*******************************************************************************
  60. **
  61. ** Function avdt_ad_tcid_to_type
  62. **
  63. ** Description Derives the channel type from the TCID.
  64. **
  65. **
  66. ** Returns Channel type value.
  67. **
  68. *******************************************************************************/
  69. static UINT8 avdt_ad_tcid_to_type(UINT8 tcid)
  70. {
  71. UINT8 type;
  72. if (tcid == 0) {
  73. type = AVDT_CHAN_SIG;
  74. } else {
  75. /* tcid translates to type based on number of channels, as follows:
  76. ** only media channel : tcid=1,2,3,4,5,6... type=1,1,1,1,1,1...
  77. ** media and report : tcid=1,2,3,4,5,6... type=1,2,1,2,1,2...
  78. ** media, report, recov : tcid=1,2,3,4,5,6... type=1,2,3,1,2,3...
  79. */
  80. type = ((tcid + AVDT_CHAN_NUM_TYPES - 2) % (AVDT_CHAN_NUM_TYPES - 1)) + 1;
  81. }
  82. AVDT_TRACE_DEBUG("tcid: %d, type: %d\n", tcid, type);
  83. return type;
  84. }
  85. /*******************************************************************************
  86. **
  87. ** Function avdt_ad_init
  88. **
  89. ** Description Initialize adaption layer.
  90. **
  91. **
  92. ** Returns Nothing.
  93. **
  94. *******************************************************************************/
  95. void avdt_ad_init(void)
  96. {
  97. int i;
  98. tAVDT_TC_TBL *p_tbl = avdt_cb.ad.tc_tbl;
  99. memset(&avdt_cb.ad, 0, sizeof(tAVDT_AD));
  100. /* make sure the peer_mtu is a valid value */
  101. for (i = 0; i < AVDT_NUM_TC_TBL; i++, p_tbl++) {
  102. p_tbl->peer_mtu = L2CAP_DEFAULT_MTU;
  103. }
  104. }
  105. /*******************************************************************************
  106. **
  107. ** Function avdt_ad_tc_tbl_by_st
  108. **
  109. ** Description Find adaption layer transport channel table entry matching
  110. ** the given state.
  111. **
  112. **
  113. ** Returns Pointer to matching entry. For control channel it returns
  114. ** the matching entry. For media or other it returns the
  115. ** first matching entry (there could be more than one).
  116. **
  117. *******************************************************************************/
  118. tAVDT_TC_TBL *avdt_ad_tc_tbl_by_st(UINT8 type, tAVDT_CCB *p_ccb, UINT8 state)
  119. {
  120. int i;
  121. tAVDT_TC_TBL *p_tbl = avdt_cb.ad.tc_tbl;
  122. UINT8 ccb_idx;
  123. if (p_ccb == NULL) {
  124. /* resending security req */
  125. for (i = 0; i < AVDT_NUM_TC_TBL; i++, p_tbl++) {
  126. /* must be AVDT_CHAN_SIG - tcid always zero */
  127. if ((p_tbl->tcid == 0) &&
  128. (p_tbl->state == state)) {
  129. break;
  130. }
  131. }
  132. } else {
  133. ccb_idx = avdt_ccb_to_idx(p_ccb);
  134. for (i = 0; i < AVDT_NUM_TC_TBL; i++, p_tbl++) {
  135. if (type == AVDT_CHAN_SIG) {
  136. /* if control channel, tcid always zero */
  137. if ((p_tbl->tcid == 0) &&
  138. (p_tbl->ccb_idx == ccb_idx) &&
  139. (p_tbl->state == state)) {
  140. break;
  141. }
  142. } else {
  143. /* if other channel, tcid is always > zero */
  144. if ((p_tbl->tcid > 0) &&
  145. (p_tbl->ccb_idx == ccb_idx) &&
  146. (p_tbl->state == state)) {
  147. break;
  148. }
  149. }
  150. }
  151. }
  152. /* if nothing found return null */
  153. if (i == AVDT_NUM_TC_TBL) {
  154. p_tbl = NULL;
  155. }
  156. return p_tbl;
  157. }
  158. /*******************************************************************************
  159. **
  160. ** Function avdt_ad_tc_tbl_by_lcid
  161. **
  162. ** Description Find adaption layer transport channel table entry by LCID.
  163. **
  164. **
  165. ** Returns Pointer to entry.
  166. **
  167. *******************************************************************************/
  168. tAVDT_TC_TBL *avdt_ad_tc_tbl_by_lcid(UINT16 lcid)
  169. {
  170. UINT8 idx;
  171. idx = avdt_cb.ad.lcid_tbl[lcid - L2CAP_BASE_APPL_CID];
  172. if (idx < AVDT_NUM_TC_TBL) {
  173. return &avdt_cb.ad.tc_tbl[idx];
  174. } else {
  175. return NULL;
  176. }
  177. }
  178. /*******************************************************************************
  179. **
  180. ** Function avdt_ad_tc_tbl_by_type
  181. **
  182. ** Description This function retrieves the transport channel table entry
  183. ** for a particular channel.
  184. **
  185. **
  186. ** Returns Pointer to transport channel table entry.
  187. **
  188. *******************************************************************************/
  189. tAVDT_TC_TBL *avdt_ad_tc_tbl_by_type(UINT8 type, tAVDT_CCB *p_ccb, tAVDT_SCB *p_scb)
  190. {
  191. UINT8 tcid;
  192. int i;
  193. tAVDT_TC_TBL *p_tbl = avdt_cb.ad.tc_tbl;
  194. UINT8 ccb_idx = avdt_ccb_to_idx(p_ccb);
  195. /* get tcid from type, scb */
  196. tcid = avdt_ad_type_to_tcid(type, p_scb);
  197. for (i = 0; i < AVDT_NUM_TC_TBL; i++, p_tbl++) {
  198. if ((p_tbl->tcid == tcid) && (p_tbl->ccb_idx == ccb_idx)) {
  199. break;
  200. }
  201. }
  202. assert(i != AVDT_NUM_TC_TBL);
  203. return p_tbl;
  204. }
  205. /*******************************************************************************
  206. **
  207. ** Function avdt_ad_tc_tbl_alloc
  208. **
  209. ** Description Allocate an entry in the traffic channel table.
  210. **
  211. **
  212. ** Returns Pointer to entry.
  213. **
  214. *******************************************************************************/
  215. tAVDT_TC_TBL *avdt_ad_tc_tbl_alloc(tAVDT_CCB *p_ccb)
  216. {
  217. int i;
  218. tAVDT_TC_TBL *p_tbl = avdt_cb.ad.tc_tbl;
  219. /* find next free entry in tc table */
  220. for (i = 0; i < AVDT_NUM_TC_TBL; i++, p_tbl++) {
  221. if (p_tbl->state == AVDT_AD_ST_UNUSED) {
  222. break;
  223. }
  224. }
  225. /* sanity check */
  226. assert(i != AVDT_NUM_TC_TBL);
  227. /* initialize entry */
  228. p_tbl->peer_mtu = L2CAP_DEFAULT_MTU;
  229. p_tbl->cfg_flags = 0;
  230. p_tbl->ccb_idx = avdt_ccb_to_idx(p_ccb);
  231. p_tbl->state = AVDT_AD_ST_IDLE;
  232. return p_tbl;
  233. }
  234. /*******************************************************************************
  235. **
  236. ** Function avdt_ad_tc_tbl_to_idx
  237. **
  238. ** Description Convert a transport channel table entry to an index.
  239. **
  240. **
  241. ** Returns Index value.
  242. **
  243. *******************************************************************************/
  244. UINT8 avdt_ad_tc_tbl_to_idx(tAVDT_TC_TBL *p_tbl)
  245. {
  246. AVDT_TRACE_DEBUG("avdt_ad_tc_tbl_to_idx: %d\n", (p_tbl - avdt_cb.ad.tc_tbl));
  247. /* use array arithmetic to determine index */
  248. return (UINT8) (p_tbl - avdt_cb.ad.tc_tbl);
  249. }
  250. /*******************************************************************************
  251. **
  252. ** Function avdt_ad_tc_close_ind
  253. **
  254. ** Description This function is called by the L2CAP interface when the
  255. ** L2CAP channel is closed. It looks up the CCB or SCB for
  256. ** the channel and sends it a close event. The reason
  257. ** parameter is the same value passed by the L2CAP
  258. ** callback function.
  259. **
  260. **
  261. ** Returns Nothing.
  262. **
  263. *******************************************************************************/
  264. void avdt_ad_tc_close_ind(tAVDT_TC_TBL *p_tbl, UINT16 reason)
  265. {
  266. tAVDT_CCB *p_ccb;
  267. tAVDT_SCB *p_scb;
  268. tAVDT_SCB_TC_CLOSE close;
  269. // UNUSED(reason);
  270. close.old_tc_state = p_tbl->state;
  271. /* clear avdt_ad_tc_tbl entry */
  272. p_tbl->state = AVDT_AD_ST_UNUSED;
  273. p_tbl->cfg_flags = 0;
  274. p_tbl->peer_mtu = L2CAP_DEFAULT_MTU;
  275. AVDT_TRACE_DEBUG("avdt_ad_tc_close_ind tcid: %d, old: %d\n",
  276. p_tbl->tcid, close.old_tc_state);
  277. /* if signaling channel, notify ccb that channel open */
  278. if (p_tbl->tcid == 0) {
  279. p_ccb = avdt_ccb_by_idx(p_tbl->ccb_idx);
  280. p_ccb->disc_rsn = (reason == AVDT_DISC_RSN_ABNORMAL) ? AVDT_DISC_RSN_ABNORMAL : AVDT_DISC_RSN_NORMAL;
  281. avdt_ccb_event(p_ccb, AVDT_CCB_LL_CLOSE_EVT, NULL);
  282. }
  283. /* if media or other channel, notify scb that channel close */
  284. else {
  285. /* look up scb in stream routing table by ccb, tcid */
  286. p_scb = avdt_scb_by_hdl(avdt_cb.ad.rt_tbl[p_tbl->ccb_idx][p_tbl->tcid].scb_hdl);
  287. if (p_scb != NULL) {
  288. close.tcid = p_tbl->tcid;
  289. close.type = avdt_ad_tcid_to_type(p_tbl->tcid);
  290. close.disc_rsn = (reason == AVDT_DISC_RSN_ABNORMAL) ? AVDT_DISC_RSN_ABNORMAL : AVDT_DISC_RSN_NORMAL;
  291. avdt_scb_event(p_scb, AVDT_SCB_TC_CLOSE_EVT, (tAVDT_SCB_EVT *)&close);
  292. }
  293. }
  294. }
  295. /*******************************************************************************
  296. **
  297. ** Function avdt_ad_tc_open_ind
  298. **
  299. ** Description This function is called by the L2CAP interface when
  300. ** the L2CAP channel is opened. It looks up the CCB or SCB
  301. ** for the channel and sends it an open event.
  302. **
  303. **
  304. ** Returns Nothing.
  305. **
  306. *******************************************************************************/
  307. void avdt_ad_tc_open_ind(tAVDT_TC_TBL *p_tbl)
  308. {
  309. tAVDT_CCB *p_ccb;
  310. tAVDT_SCB *p_scb;
  311. tAVDT_OPEN open;
  312. tAVDT_EVT_HDR evt;
  313. p_tbl->state = AVDT_AD_ST_OPEN;
  314. /* if signaling channel, notify ccb that channel open */
  315. if (p_tbl->tcid == 0) {
  316. /* set the signal channel to use high priority within the ACL link */
  317. L2CA_SetTxPriority(avdt_cb.ad.rt_tbl[p_tbl->ccb_idx][AVDT_CHAN_SIG].lcid, L2CAP_CHNL_PRIORITY_HIGH);
  318. p_ccb = avdt_ccb_by_idx(p_tbl->ccb_idx);
  319. /* use err_param to indicate the role of connection.
  320. * AVDT_ACP, if ACP */
  321. evt.err_param = AVDT_INT;
  322. if (p_tbl->cfg_flags & AVDT_L2C_CFG_CONN_ACP) {
  323. evt.err_param = AVDT_ACP;
  324. }
  325. avdt_ccb_event(p_ccb, AVDT_CCB_LL_OPEN_EVT, (tAVDT_CCB_EVT *)&evt);
  326. }
  327. /* if media or other channel, notify scb that channel open */
  328. else {
  329. /* look up scb in stream routing table by ccb, tcid */
  330. p_scb = avdt_scb_by_hdl(avdt_cb.ad.rt_tbl[p_tbl->ccb_idx][p_tbl->tcid].scb_hdl);
  331. /* put lcid in event data */
  332. if (p_scb != NULL) {
  333. open.peer_mtu = p_tbl->peer_mtu;
  334. open.lcid = avdt_cb.ad.rt_tbl[p_tbl->ccb_idx][p_tbl->tcid].lcid;
  335. open.hdr.err_code = avdt_ad_tcid_to_type(p_tbl->tcid);
  336. avdt_scb_event(p_scb, AVDT_SCB_TC_OPEN_EVT, (tAVDT_SCB_EVT *) &open);
  337. }
  338. }
  339. }
  340. /*******************************************************************************
  341. **
  342. ** Function avdt_ad_tc_cong_ind
  343. **
  344. ** Description This function is called by the L2CAP interface layer when
  345. ** L2CAP calls the congestion callback. It looks up the CCB
  346. ** or SCB for the channel and sends it a congestion event.
  347. ** The is_congested parameter is the same value passed by
  348. ** the L2CAP callback function.
  349. **
  350. **
  351. ** Returns Nothing.
  352. **
  353. *******************************************************************************/
  354. void avdt_ad_tc_cong_ind(tAVDT_TC_TBL *p_tbl, BOOLEAN is_congested)
  355. {
  356. tAVDT_CCB *p_ccb;
  357. tAVDT_SCB *p_scb;
  358. /* if signaling channel, notify ccb of congestion */
  359. if (p_tbl->tcid == 0) {
  360. p_ccb = avdt_ccb_by_idx(p_tbl->ccb_idx);
  361. avdt_ccb_event(p_ccb, AVDT_CCB_LL_CONG_EVT, (tAVDT_CCB_EVT *) &is_congested);
  362. }
  363. /* if media or other channel, notify scb that channel open */
  364. else {
  365. /* look up scb in stream routing table by ccb, tcid */
  366. p_scb = avdt_scb_by_hdl(avdt_cb.ad.rt_tbl[p_tbl->ccb_idx][p_tbl->tcid].scb_hdl);
  367. if (p_scb != NULL) {
  368. avdt_scb_event(p_scb, AVDT_SCB_TC_CONG_EVT, (tAVDT_SCB_EVT *) &is_congested);
  369. }
  370. }
  371. }
  372. /*******************************************************************************
  373. **
  374. ** Function avdt_ad_tc_data_ind
  375. **
  376. ** Description This function is called by the L2CAP interface layer when
  377. ** incoming data is received from L2CAP. It looks up the CCB
  378. ** or SCB for the channel and routes the data accordingly.
  379. **
  380. **
  381. ** Returns Nothing.
  382. **
  383. *******************************************************************************/
  384. void avdt_ad_tc_data_ind(tAVDT_TC_TBL *p_tbl, BT_HDR *p_buf)
  385. {
  386. tAVDT_CCB *p_ccb;
  387. tAVDT_SCB *p_scb;
  388. /* store type (media, recovery, reporting) */
  389. p_buf->layer_specific = avdt_ad_tcid_to_type(p_tbl->tcid);
  390. /* if signaling channel, handle control message */
  391. if (p_tbl->tcid == 0) {
  392. p_ccb = avdt_ccb_by_idx(p_tbl->ccb_idx);
  393. avdt_msg_ind(p_ccb, p_buf);
  394. }
  395. /* if media or other channel, send event to scb */
  396. else {
  397. p_scb = avdt_scb_by_hdl(avdt_cb.ad.rt_tbl[p_tbl->ccb_idx][p_tbl->tcid].scb_hdl);
  398. if (p_scb != NULL) {
  399. avdt_scb_event(p_scb, AVDT_SCB_TC_DATA_EVT, (tAVDT_SCB_EVT *) &p_buf);
  400. } else {
  401. osi_free(p_buf);
  402. AVDT_TRACE_ERROR(" avdt_ad_tc_data_ind buffer freed");
  403. }
  404. }
  405. }
  406. /*******************************************************************************
  407. **
  408. ** Function avdt_ad_write_req
  409. **
  410. ** Description This function is called by a CCB or SCB to send data to a
  411. ** transport channel. It looks up the LCID of the channel
  412. ** based on the type, CCB, and SCB (if present). Then it
  413. ** passes the data to L2CA_DataWrite().
  414. **
  415. **
  416. ** Returns AVDT_AD_SUCCESS, if data accepted, else FALSE
  417. ** AVDT_AD_CONGESTED, if data accepted and the channel is congested
  418. ** AVDT_AD_FAILED, if error
  419. **
  420. *******************************************************************************/
  421. UINT8 avdt_ad_write_req(UINT8 type, tAVDT_CCB *p_ccb, tAVDT_SCB *p_scb, BT_HDR *p_buf)
  422. {
  423. UINT8 tcid;
  424. /* get tcid from type, scb */
  425. tcid = avdt_ad_type_to_tcid(type, p_scb);
  426. return L2CA_DataWrite(avdt_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][tcid].lcid, p_buf);
  427. }
  428. /*******************************************************************************
  429. **
  430. ** Function avdt_ad_open_req
  431. **
  432. ** Description This function is called by a CCB or SCB to open a transport
  433. ** channel. This function allocates and initializes a
  434. ** transport channel table entry. The channel can be opened
  435. ** in two roles: as an initiator or acceptor. When opened
  436. ** as an initiator the function will start an L2CAP connection.
  437. ** When opened as an acceptor the function simply configures
  438. ** the table entry to listen for an incoming channel.
  439. **
  440. **
  441. ** Returns Nothing.
  442. **
  443. *******************************************************************************/
  444. void avdt_ad_open_req(UINT8 type, tAVDT_CCB *p_ccb, tAVDT_SCB *p_scb, UINT8 role)
  445. {
  446. tAVDT_TC_TBL *p_tbl;
  447. UINT16 lcid;
  448. if ((p_tbl = avdt_ad_tc_tbl_alloc(p_ccb)) == NULL) {
  449. AVDT_TRACE_ERROR("avdt_ad_open_req: Cannot allocate p_tbl");
  450. return;
  451. }
  452. p_tbl->tcid = avdt_ad_type_to_tcid(type, p_scb);
  453. AVDT_TRACE_DEBUG("avdt_ad_open_req: type: %d, role: %d, tcid:%d\n",
  454. type, role, p_tbl->tcid);
  455. if (type == AVDT_CHAN_SIG) {
  456. /* if signaling, get mtu from registration control block */
  457. p_tbl->my_mtu = avdt_cb.rcb.ctrl_mtu;
  458. p_tbl->my_flush_to = L2CAP_DEFAULT_FLUSH_TO;
  459. } else {
  460. /* otherwise get mtu from scb */
  461. p_tbl->my_mtu = p_scb->cs.mtu;
  462. p_tbl->my_flush_to = p_scb->cs.flush_to;
  463. /* also set scb_hdl in rt_tbl */
  464. avdt_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][p_tbl->tcid].scb_hdl = avdt_scb_to_hdl(p_scb);
  465. AVDT_TRACE_DEBUG("avdt_cb.ad.rt_tbl[%d][%d].scb_hdl = %d\n",
  466. avdt_ccb_to_idx(p_ccb), p_tbl->tcid,
  467. avdt_scb_to_hdl(p_scb));
  468. }
  469. /* if we're acceptor, we're done; just sit back and listen */
  470. if (role == AVDT_ACP) {
  471. p_tbl->state = AVDT_AD_ST_ACP;
  472. }
  473. /* else we're inititator, start the L2CAP connection */
  474. else {
  475. p_tbl->state = AVDT_AD_ST_CONN;
  476. /* call l2cap connect req */
  477. if ((lcid = L2CA_ConnectReq(AVDT_PSM, p_ccb->peer_addr)) != 0) {
  478. /* if connect req ok, store tcid in lcid table */
  479. avdt_cb.ad.lcid_tbl[lcid - L2CAP_BASE_APPL_CID] = avdt_ad_tc_tbl_to_idx(p_tbl);
  480. AVDT_TRACE_DEBUG("avdt_cb.ad.lcid_tbl[%d] = %d\n",
  481. (lcid - L2CAP_BASE_APPL_CID), avdt_ad_tc_tbl_to_idx(p_tbl));
  482. avdt_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][p_tbl->tcid].lcid = lcid;
  483. AVDT_TRACE_DEBUG("avdt_cb.ad.rt_tbl[%d][%d].lcid = 0x%x\n",
  484. avdt_ccb_to_idx(p_ccb), p_tbl->tcid,
  485. lcid);
  486. } else {
  487. /* if connect req failed, call avdt_ad_tc_close_ind() */
  488. avdt_ad_tc_close_ind(p_tbl, 0);
  489. }
  490. }
  491. }
  492. /*******************************************************************************
  493. **
  494. ** Function avdt_ad_close_req
  495. **
  496. ** Description This function is called by a CCB or SCB to close a
  497. ** transport channel. The function looks up the LCID for the
  498. ** channel and calls L2CA_DisconnectReq().
  499. **
  500. **
  501. ** Returns Nothing.
  502. **
  503. *******************************************************************************/
  504. void avdt_ad_close_req(UINT8 type, tAVDT_CCB *p_ccb, tAVDT_SCB *p_scb)
  505. {
  506. UINT8 tcid;
  507. tAVDT_TC_TBL *p_tbl;
  508. p_tbl = avdt_ad_tc_tbl_by_type(type, p_ccb, p_scb);
  509. AVDT_TRACE_DEBUG("avdt_ad_close_req state: %d\n", p_tbl->state);
  510. switch (p_tbl->state) {
  511. case AVDT_AD_ST_UNUSED:
  512. /* probably for reporting */
  513. break;
  514. case AVDT_AD_ST_ACP:
  515. /* if we're listening on this channel, send ourselves a close ind */
  516. avdt_ad_tc_close_ind(p_tbl, 0);
  517. break;
  518. default:
  519. /* get tcid from type, scb */
  520. tcid = avdt_ad_type_to_tcid(type, p_scb);
  521. /* call l2cap disconnect req */
  522. L2CA_DisconnectReq(avdt_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][tcid].lcid);
  523. }
  524. }
  525. #endif /* #if (defined(AVDT_INCLUDED) && AVDT_INCLUDED == TRUE) */