l2c_csm.c 53 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263
  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 the L2CAP channel state machine
  21. *
  22. ******************************************************************************/
  23. #include <stdlib.h>
  24. #include <string.h>
  25. #include <stdio.h>
  26. #include "common/bt_target.h"
  27. #include "stack/hcidefs.h"
  28. #include "stack/hcimsgs.h"
  29. #include "stack/l2cdefs.h"
  30. #include "l2c_int.h"
  31. #include "btm_int.h"
  32. #include "stack/btu.h"
  33. #include "stack/hcimsgs.h"
  34. #include "osi/allocator.h"
  35. #if (L2CAP_COC_INCLUDED == TRUE)
  36. /********************************************************************************/
  37. /* L O C A L F U N C T I O N P R O T O T Y P E S */
  38. /********************************************************************************/
  39. static void l2c_csm_closed (tL2C_CCB *p_ccb, UINT16 event, void *p_data);
  40. static void l2c_csm_orig_w4_sec_comp (tL2C_CCB *p_ccb, UINT16 event, void *p_data);
  41. static void l2c_csm_term_w4_sec_comp (tL2C_CCB *p_ccb, UINT16 event, void *p_data);
  42. static void l2c_csm_w4_l2cap_connect_rsp (tL2C_CCB *p_ccb, UINT16 event, void *p_data);
  43. static void l2c_csm_w4_l2ca_connect_rsp (tL2C_CCB *p_ccb, UINT16 event, void *p_data);
  44. static void l2c_csm_config (tL2C_CCB *p_ccb, UINT16 event, void *p_data);
  45. static void l2c_csm_open (tL2C_CCB *p_ccb, UINT16 event, void *p_data);
  46. static void l2c_csm_w4_l2cap_disconnect_rsp (tL2C_CCB *p_ccb, UINT16 event, void *p_data);
  47. static void l2c_csm_w4_l2ca_disconnect_rsp (tL2C_CCB *p_ccb, UINT16 event, void *p_data);
  48. #if (BT_TRACE_VERBOSE == TRUE)
  49. static char *l2c_csm_get_event_name (UINT16 event);
  50. #endif
  51. /*******************************************************************************
  52. **
  53. ** Function l2c_csm_execute
  54. **
  55. ** Description This function executes the state machine.
  56. **
  57. ** Returns void
  58. **
  59. *******************************************************************************/
  60. void l2c_csm_execute (tL2C_CCB *p_ccb, UINT16 event, void *p_data)
  61. {
  62. switch (p_ccb->chnl_state) {
  63. case CST_CLOSED:
  64. l2c_csm_closed (p_ccb, event, p_data);
  65. break;
  66. case CST_ORIG_W4_SEC_COMP:
  67. l2c_csm_orig_w4_sec_comp (p_ccb, event, p_data);
  68. break;
  69. case CST_TERM_W4_SEC_COMP:
  70. l2c_csm_term_w4_sec_comp (p_ccb, event, p_data);
  71. break;
  72. case CST_W4_L2CAP_CONNECT_RSP:
  73. l2c_csm_w4_l2cap_connect_rsp (p_ccb, event, p_data);
  74. break;
  75. case CST_W4_L2CA_CONNECT_RSP:
  76. l2c_csm_w4_l2ca_connect_rsp (p_ccb, event, p_data);
  77. break;
  78. case CST_CONFIG:
  79. l2c_csm_config (p_ccb, event, p_data);
  80. break;
  81. case CST_OPEN:
  82. l2c_csm_open (p_ccb, event, p_data);
  83. break;
  84. case CST_W4_L2CAP_DISCONNECT_RSP:
  85. l2c_csm_w4_l2cap_disconnect_rsp (p_ccb, event, p_data);
  86. break;
  87. case CST_W4_L2CA_DISCONNECT_RSP:
  88. l2c_csm_w4_l2ca_disconnect_rsp (p_ccb, event, p_data);
  89. break;
  90. default:
  91. L2CAP_TRACE_DEBUG("Unhandled event! event = %d", event);
  92. break;
  93. }
  94. }
  95. /*******************************************************************************
  96. **
  97. ** Function l2c_csm_closed
  98. **
  99. ** Description This function handles events when the channel is in
  100. ** CLOSED state. This state exists only when the link is
  101. ** being initially established.
  102. **
  103. ** Returns void
  104. **
  105. *******************************************************************************/
  106. static void l2c_csm_closed (tL2C_CCB *p_ccb, UINT16 event, void *p_data)
  107. {
  108. tL2C_CONN_INFO *p_ci = (tL2C_CONN_INFO *)p_data;
  109. UINT16 local_cid = p_ccb->local_cid;
  110. tL2CA_DISCONNECT_IND_CB *disconnect_ind;
  111. tL2CA_CONNECT_CFM_CB *connect_cfm;
  112. if (p_ccb->p_rcb == NULL) {
  113. #if (BT_TRACE_VERBOSE == TRUE)
  114. L2CAP_TRACE_ERROR ("L2CAP - LCID: 0x%04x st: CLOSED evt: %s p_rcb == NULL", p_ccb->local_cid, l2c_csm_get_event_name (event));
  115. #else
  116. L2CAP_TRACE_ERROR ("L2CAP - LCID: 0x%04x st: CLOSED evt: 0x%04x p_rcb == NULL", p_ccb->local_cid, event);
  117. #endif
  118. return;
  119. }
  120. #if (L2CAP_UCD_INCLUDED == TRUE)
  121. if ( local_cid == L2CAP_CONNECTIONLESS_CID ) {
  122. /* check if this event can be processed by UCD */
  123. if ( l2c_ucd_process_event (p_ccb, event, p_data) ) {
  124. /* The event is processed by UCD state machine */
  125. return;
  126. }
  127. }
  128. #endif
  129. disconnect_ind = p_ccb->p_rcb->api.pL2CA_DisconnectInd_Cb;
  130. connect_cfm = p_ccb->p_rcb->api.pL2CA_ConnectCfm_Cb;
  131. #if (BT_TRACE_VERBOSE == TRUE)
  132. L2CAP_TRACE_EVENT ("L2CAP - LCID: 0x%04x st: CLOSED evt: %s", p_ccb->local_cid, l2c_csm_get_event_name (event));
  133. #else
  134. L2CAP_TRACE_EVENT ("L2CAP - st: CLOSED evt: %d", event);
  135. #endif
  136. switch (event) {
  137. case L2CEVT_LP_DISCONNECT_IND: /* Link was disconnected */
  138. L2CAP_TRACE_API ("L2CAP - Calling Disconnect_Ind_Cb(), CID: 0x%04x No Conf Needed", p_ccb->local_cid);
  139. l2cu_release_ccb (p_ccb);
  140. (*disconnect_ind)(local_cid, FALSE);
  141. break;
  142. case L2CEVT_LP_CONNECT_CFM: /* Link came up */
  143. p_ccb->chnl_state = CST_ORIG_W4_SEC_COMP;
  144. btm_sec_l2cap_access_req (p_ccb->p_lcb->remote_bd_addr, p_ccb->p_rcb->psm,
  145. p_ccb->p_lcb->handle, TRUE, &l2c_link_sec_comp, p_ccb);
  146. break;
  147. case L2CEVT_LP_CONNECT_CFM_NEG: /* Link failed */
  148. /* Disconnect unless ACL collision and upper layer wants to handle it */
  149. if (p_ci->status != HCI_ERR_CONNECTION_EXISTS
  150. || !btm_acl_notif_conn_collision(p_ccb->p_lcb->remote_bd_addr)) {
  151. L2CAP_TRACE_API ("L2CAP - Calling ConnectCfm_Cb(), CID: 0x%04x Status: %d", p_ccb->local_cid, p_ci->status);
  152. l2cu_release_ccb (p_ccb);
  153. (*connect_cfm)(local_cid, p_ci->status);
  154. }
  155. break;
  156. case L2CEVT_L2CA_CONNECT_REQ: /* API connect request */
  157. /* Cancel sniff mode if needed */
  158. {
  159. tBTM_PM_PWR_MD settings;
  160. // btla-specific ++
  161. memset((void *)&settings, 0, sizeof(settings));
  162. // btla-specific --
  163. settings.mode = BTM_PM_MD_ACTIVE;
  164. /* COVERITY
  165. Event uninit_use_in_call: Using uninitialized value "settings" (field "settings".timeout uninitialized) in call to function "BTM_SetPowerMode" [details]
  166. Event uninit_use_in_call: Using uninitialized value "settings.max" in call to function "BTM_SetPowerMode" [details]
  167. Event uninit_use_in_call: Using uninitialized value "settings.min" in call to function "BTM_SetPowerMode"
  168. // FALSE-POSITIVE error from Coverity test-tool. Please do NOT remove following comment.
  169. // coverity[uninit_use_in_call] False-positive: setting the mode to BTM_PM_MD_ACTIVE only uses settings.mode the other data members of tBTM_PM_PWR_MD are ignored
  170. */
  171. BTM_SetPowerMode (BTM_PM_SET_ONLY_ID, p_ccb->p_lcb->remote_bd_addr, &settings);
  172. }
  173. /* If sec access does not result in started SEC_COM or COMP_NEG are already processed */
  174. if (btm_sec_l2cap_access_req (p_ccb->p_lcb->remote_bd_addr, p_ccb->p_rcb->psm,
  175. p_ccb->p_lcb->handle, TRUE, &l2c_link_sec_comp, p_ccb) == BTM_CMD_STARTED) {
  176. p_ccb->chnl_state = CST_ORIG_W4_SEC_COMP;
  177. }
  178. break;
  179. case L2CEVT_SEC_COMP:
  180. p_ccb->chnl_state = CST_W4_L2CAP_CONNECT_RSP;
  181. /* Wait for the info resp in this state before sending connect req (if needed) */
  182. if (!p_ccb->p_lcb->w4_info_rsp) {
  183. /* Need to have at least one compatible channel to continue */
  184. if (!l2c_fcr_chk_chan_modes(p_ccb)) {
  185. l2cu_release_ccb (p_ccb);
  186. (*p_ccb->p_rcb->api.pL2CA_ConnectCfm_Cb)(local_cid, L2CAP_CONN_NO_LINK);
  187. } else {
  188. l2cu_send_peer_connect_req (p_ccb);
  189. btu_start_timer (&p_ccb->timer_entry, BTU_TTYPE_L2CAP_CHNL, L2CAP_CHNL_CONNECT_TOUT);
  190. }
  191. }
  192. break;
  193. case L2CEVT_SEC_COMP_NEG: /* something is really bad with security */
  194. L2CAP_TRACE_API ("L2CAP - Calling ConnectCfm_Cb(), CID: 0x%04x Status: %d", p_ccb->local_cid, L2CAP_CONN_TIMEOUT);
  195. l2cu_release_ccb (p_ccb);
  196. (*connect_cfm)(local_cid, L2CAP_CONN_SECURITY_BLOCK);
  197. break;
  198. case L2CEVT_L2CAP_CONNECT_REQ: /* Peer connect request */
  199. /* stop link timer to avoid race condition between A2MP, Security, and L2CAP */
  200. btu_stop_timer (&p_ccb->p_lcb->timer_entry);
  201. /* Cancel sniff mode if needed */
  202. {
  203. tBTM_PM_PWR_MD settings;
  204. // btla-specific ++
  205. memset((void *)&settings, 0, sizeof(settings));
  206. // btla-specific --
  207. settings.mode = BTM_PM_MD_ACTIVE;
  208. /* COVERITY
  209. Event uninit_use_in_call: Using uninitialized value "settings" (field "settings".timeout uninitialized) in call to function "BTM_SetPowerMode" [details]
  210. Event uninit_use_in_call: Using uninitialized value "settings.max" in call to function "BTM_SetPowerMode" [details]
  211. Event uninit_use_in_call: Using uninitialized value "settings.min" in call to function "BTM_SetPowerMode"
  212. // FALSE-POSITIVE error from Coverity test-tool. Please do NOT remove following comment.
  213. // coverity[uninit_use_in_call] False-positive: setting the mode to BTM_PM_MD_ACTIVE only uses settings.mode the other data members of tBTM_PM_PWR_MD are ignored
  214. */
  215. BTM_SetPowerMode (BTM_PM_SET_ONLY_ID, p_ccb->p_lcb->remote_bd_addr, &settings);
  216. }
  217. p_ccb->chnl_state = CST_TERM_W4_SEC_COMP;
  218. if (btm_sec_l2cap_access_req (p_ccb->p_lcb->remote_bd_addr, p_ccb->p_rcb->psm,
  219. p_ccb->p_lcb->handle, FALSE, &l2c_link_sec_comp, p_ccb) == BTM_CMD_STARTED) {
  220. /* started the security process, tell the peer to set a longer timer */
  221. l2cu_send_peer_connect_rsp(p_ccb, L2CAP_CONN_PENDING, 0);
  222. }
  223. break;
  224. case L2CEVT_TIMEOUT:
  225. L2CAP_TRACE_API ("L2CAP - Calling ConnectCfm_Cb(), CID: 0x%04x Status: %d", p_ccb->local_cid, L2CAP_CONN_TIMEOUT);
  226. l2cu_release_ccb (p_ccb);
  227. (*connect_cfm)(local_cid, L2CAP_CONN_TIMEOUT);
  228. break;
  229. case L2CEVT_L2CAP_DATA: /* Peer data packet rcvd */
  230. case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data to send */
  231. osi_free (p_data);
  232. break;
  233. case L2CEVT_L2CA_DISCONNECT_REQ: /* Upper wants to disconnect */
  234. l2cu_release_ccb (p_ccb);
  235. break;
  236. }
  237. }
  238. /*******************************************************************************
  239. **
  240. ** Function l2c_csm_orig_w4_sec_comp
  241. **
  242. ** Description This function handles events when the channel is in
  243. ** CST_ORIG_W4_SEC_COMP state.
  244. **
  245. ** Returns void
  246. **
  247. *******************************************************************************/
  248. static void l2c_csm_orig_w4_sec_comp (tL2C_CCB *p_ccb, UINT16 event, void *p_data)
  249. {
  250. tL2CA_DISCONNECT_IND_CB *disconnect_ind = p_ccb->p_rcb->api.pL2CA_DisconnectInd_Cb;
  251. tL2CA_CONNECT_CFM_CB *connect_cfm = p_ccb->p_rcb->api.pL2CA_ConnectCfm_Cb;
  252. UINT16 local_cid = p_ccb->local_cid;
  253. #if (BT_TRACE_VERBOSE == TRUE)
  254. L2CAP_TRACE_EVENT ("L2CAP - LCID: 0x%04x st: ORIG_W4_SEC_COMP evt: %s", p_ccb->local_cid, l2c_csm_get_event_name (event));
  255. #else
  256. L2CAP_TRACE_EVENT ("L2CAP - st: ORIG_W4_SEC_COMP evt: %d", event);
  257. #endif
  258. #if (L2CAP_UCD_INCLUDED == TRUE)
  259. if ( local_cid == L2CAP_CONNECTIONLESS_CID ) {
  260. /* check if this event can be processed by UCD */
  261. if ( l2c_ucd_process_event (p_ccb, event, p_data) ) {
  262. /* The event is processed by UCD state machine */
  263. return;
  264. }
  265. }
  266. #endif
  267. switch (event) {
  268. case L2CEVT_LP_DISCONNECT_IND: /* Link was disconnected */
  269. L2CAP_TRACE_API ("L2CAP - Calling Disconnect_Ind_Cb(), CID: 0x%04x No Conf Needed", p_ccb->local_cid);
  270. l2cu_release_ccb (p_ccb);
  271. (*disconnect_ind)(local_cid, FALSE);
  272. break;
  273. case L2CEVT_SEC_RE_SEND_CMD: /* BTM has enough info to proceed */
  274. case L2CEVT_LP_CONNECT_CFM: /* Link came up */
  275. btm_sec_l2cap_access_req (p_ccb->p_lcb->remote_bd_addr, p_ccb->p_rcb->psm,
  276. p_ccb->p_lcb->handle, TRUE, &l2c_link_sec_comp, p_ccb);
  277. break;
  278. case L2CEVT_SEC_COMP: /* Security completed success */
  279. /* Wait for the info resp in this state before sending connect req (if needed) */
  280. p_ccb->chnl_state = CST_W4_L2CAP_CONNECT_RSP;
  281. if (!p_ccb->p_lcb->w4_info_rsp) {
  282. /* Need to have at least one compatible channel to continue */
  283. if (!l2c_fcr_chk_chan_modes(p_ccb)) {
  284. l2cu_release_ccb (p_ccb);
  285. (*connect_cfm)(local_cid, L2CAP_CONN_NO_LINK);
  286. } else {
  287. btu_start_timer (&p_ccb->timer_entry, BTU_TTYPE_L2CAP_CHNL, L2CAP_CHNL_CONNECT_TOUT);
  288. l2cu_send_peer_connect_req (p_ccb); /* Start Connection */
  289. }
  290. }
  291. break;
  292. case L2CEVT_SEC_COMP_NEG:
  293. L2CAP_TRACE_API ("L2CAP - Calling ConnectCfm_Cb(), CID: 0x%04x Status: %d", p_ccb->local_cid, HCI_ERR_AUTH_FAILURE);
  294. /* If last channel immediately disconnect the ACL for better security.
  295. Also prevents a race condition between BTM and L2CAP */
  296. if ( (p_ccb == p_ccb->p_lcb->ccb_queue.p_first_ccb) && (p_ccb == p_ccb->p_lcb->ccb_queue.p_last_ccb) ) {
  297. p_ccb->p_lcb->idle_timeout = 0;
  298. }
  299. l2cu_release_ccb (p_ccb);
  300. (*connect_cfm)(local_cid, HCI_ERR_AUTH_FAILURE);
  301. break;
  302. case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data to send */
  303. case L2CEVT_L2CAP_DATA: /* Peer data packet rcvd */
  304. osi_free (p_data);
  305. break;
  306. case L2CEVT_L2CA_DISCONNECT_REQ: /* Upper wants to disconnect */
  307. /* Tell security manager to abort */
  308. btm_sec_abort_access_req (p_ccb->p_lcb->remote_bd_addr);
  309. l2cu_release_ccb (p_ccb);
  310. break;
  311. }
  312. }
  313. /*******************************************************************************
  314. **
  315. ** Function l2c_csm_term_w4_sec_comp
  316. **
  317. ** Description This function handles events when the channel is in
  318. ** CST_TERM_W4_SEC_COMP state.
  319. **
  320. ** Returns void
  321. **
  322. *******************************************************************************/
  323. static void l2c_csm_term_w4_sec_comp (tL2C_CCB *p_ccb, UINT16 event, void *p_data)
  324. {
  325. #if (BT_TRACE_VERBOSE == TRUE)
  326. L2CAP_TRACE_EVENT ("L2CAP - LCID: 0x%04x st: TERM_W4_SEC_COMP evt: %s", p_ccb->local_cid, l2c_csm_get_event_name (event));
  327. #else
  328. L2CAP_TRACE_EVENT ("L2CAP - st: TERM_W4_SEC_COMP evt: %d", event);
  329. #endif
  330. #if (L2CAP_UCD_INCLUDED == TRUE)
  331. if ( p_ccb->local_cid == L2CAP_CONNECTIONLESS_CID ) {
  332. /* check if this event can be processed by UCD */
  333. if ( l2c_ucd_process_event (p_ccb, event, p_data) ) {
  334. /* The event is processed by UCD state machine */
  335. return;
  336. }
  337. }
  338. #endif
  339. switch (event) {
  340. case L2CEVT_LP_DISCONNECT_IND: /* Link was disconnected */
  341. /* Tell security manager to abort */
  342. btm_sec_abort_access_req (p_ccb->p_lcb->remote_bd_addr);
  343. l2cu_release_ccb (p_ccb);
  344. break;
  345. case L2CEVT_SEC_COMP:
  346. p_ccb->chnl_state = CST_W4_L2CA_CONNECT_RSP;
  347. /* Wait for the info resp in next state before sending connect ind (if needed) */
  348. if (!p_ccb->p_lcb->w4_info_rsp) {
  349. /* Don't need to get info from peer or already retrieved so continue */
  350. btu_start_timer (&p_ccb->timer_entry, BTU_TTYPE_L2CAP_CHNL, L2CAP_CHNL_CONNECT_TOUT);
  351. L2CAP_TRACE_API ("L2CAP - Calling Connect_Ind_Cb(), CID: 0x%04x", p_ccb->local_cid);
  352. (*p_ccb->p_rcb->api.pL2CA_ConnectInd_Cb) (p_ccb->p_lcb->remote_bd_addr, p_ccb->local_cid,
  353. p_ccb->p_rcb->psm, p_ccb->remote_id);
  354. } else {
  355. /*
  356. ** L2CAP Connect Response will be sent out by 3 sec timer expiration
  357. ** because Bluesoleil doesn't respond to L2CAP Information Request.
  358. ** Bluesoleil seems to disconnect ACL link as failure case, because
  359. ** it takes too long (4~7secs) to get response.
  360. ** product version : Bluesoleil 2.1.1.0 EDR Release 060123
  361. ** stack version : 05.04.11.20060119
  362. */
  363. /* Waiting for the info resp, tell the peer to set a longer timer */
  364. l2cu_send_peer_connect_rsp(p_ccb, L2CAP_CONN_PENDING, 0);
  365. }
  366. break;
  367. case L2CEVT_SEC_COMP_NEG:
  368. if (((tL2C_CONN_INFO *)p_data)->status == BTM_DELAY_CHECK) {
  369. /* start a timer - encryption change not received before L2CAP connect req */
  370. btu_start_timer (&p_ccb->timer_entry, BTU_TTYPE_L2CAP_CHNL, L2CAP_DELAY_CHECK_SM4);
  371. } else {
  372. l2cu_send_peer_connect_rsp (p_ccb, L2CAP_CONN_SECURITY_BLOCK, 0);
  373. l2cu_release_ccb (p_ccb);
  374. }
  375. break;
  376. case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data to send */
  377. case L2CEVT_L2CAP_DATA: /* Peer data packet rcvd */
  378. osi_free (p_data);
  379. break;
  380. case L2CEVT_L2CA_DISCONNECT_REQ: /* Upper wants to disconnect */
  381. l2cu_release_ccb (p_ccb);
  382. break;
  383. case L2CEVT_L2CAP_DISCONNECT_REQ: /* Peer disconnected request */
  384. l2cu_send_peer_disc_rsp (p_ccb->p_lcb, p_ccb->remote_id, p_ccb->local_cid, p_ccb->remote_cid);
  385. /* Tell security manager to abort */
  386. btm_sec_abort_access_req (p_ccb->p_lcb->remote_bd_addr);
  387. l2cu_release_ccb (p_ccb);
  388. break;
  389. case L2CEVT_TIMEOUT:
  390. /* SM4 related. */
  391. if (!btsnd_hcic_disconnect (p_ccb->p_lcb->handle, HCI_ERR_AUTH_FAILURE)) {
  392. L2CAP_TRACE_API ("L2CAP - Calling btsnd_hcic_disconnect for handle %i failed", p_ccb->p_lcb->handle);
  393. btu_start_timer (&p_ccb->timer_entry, BTU_TTYPE_L2CAP_CHNL, 1);
  394. }
  395. break;
  396. case L2CEVT_SEC_RE_SEND_CMD: /* BTM has enough info to proceed */
  397. btm_sec_l2cap_access_req (p_ccb->p_lcb->remote_bd_addr, p_ccb->p_rcb->psm,
  398. p_ccb->p_lcb->handle, FALSE, &l2c_link_sec_comp, p_ccb);
  399. break;
  400. }
  401. }
  402. /*******************************************************************************
  403. **
  404. ** Function l2c_csm_w4_l2cap_connect_rsp
  405. **
  406. ** Description This function handles events when the channel is in
  407. ** CST_W4_L2CAP_CONNECT_RSP state.
  408. **
  409. ** Returns void
  410. **
  411. *******************************************************************************/
  412. static void l2c_csm_w4_l2cap_connect_rsp (tL2C_CCB *p_ccb, UINT16 event, void *p_data)
  413. {
  414. tL2C_CONN_INFO *p_ci = (tL2C_CONN_INFO *)p_data;
  415. tL2CA_DISCONNECT_IND_CB *disconnect_ind = p_ccb->p_rcb->api.pL2CA_DisconnectInd_Cb;
  416. tL2CA_CONNECT_CFM_CB *connect_cfm = p_ccb->p_rcb->api.pL2CA_ConnectCfm_Cb;
  417. UINT16 local_cid = p_ccb->local_cid;
  418. #if (BT_TRACE_VERBOSE == TRUE)
  419. L2CAP_TRACE_EVENT ("L2CAP - LCID: 0x%04x st: W4_L2CAP_CON_RSP evt: %s", p_ccb->local_cid, l2c_csm_get_event_name (event));
  420. #else
  421. L2CAP_TRACE_EVENT ("L2CAP - st: W4_L2CAP_CON_RSP evt: %d", event);
  422. #endif
  423. switch (event) {
  424. case L2CEVT_LP_DISCONNECT_IND: /* Link was disconnected */
  425. /* Send disc indication unless peer to peer race condition AND normal disconnect */
  426. /* *((UINT8 *)p_data) != HCI_ERR_PEER_USER happens when peer device try to disconnect for normal reason */
  427. p_ccb->chnl_state = CST_CLOSED;
  428. if ((p_ccb->flags & CCB_FLAG_NO_RETRY) || !p_data || (*((UINT8 *)p_data) != HCI_ERR_PEER_USER)) {
  429. L2CAP_TRACE_API ("L2CAP - Calling Disconnect_Ind_Cb(), CID: 0x%04x No Conf Needed",
  430. p_ccb->local_cid);
  431. l2cu_release_ccb (p_ccb);
  432. (*disconnect_ind)(local_cid, FALSE);
  433. }
  434. p_ccb->flags |= CCB_FLAG_NO_RETRY;
  435. break;
  436. case L2CEVT_L2CAP_CONNECT_RSP: /* Got peer connect confirm */
  437. p_ccb->remote_cid = p_ci->remote_cid;
  438. p_ccb->chnl_state = CST_CONFIG;
  439. btu_start_timer (&p_ccb->timer_entry, BTU_TTYPE_L2CAP_CHNL, L2CAP_CHNL_CFG_TIMEOUT);
  440. L2CAP_TRACE_API ("L2CAP - Calling Connect_Cfm_Cb(), CID: 0x%04x, Success", p_ccb->local_cid);
  441. (*p_ccb->p_rcb->api.pL2CA_ConnectCfm_Cb)(local_cid, L2CAP_CONN_OK);
  442. break;
  443. case L2CEVT_L2CAP_CONNECT_RSP_PND: /* Got peer connect pending */
  444. p_ccb->remote_cid = p_ci->remote_cid;
  445. btu_start_timer (&p_ccb->timer_entry, BTU_TTYPE_L2CAP_CHNL, L2CAP_CHNL_CONNECT_TOUT_EXT);
  446. if (p_ccb->p_rcb->api.pL2CA_ConnectPnd_Cb) {
  447. L2CAP_TRACE_API ("L2CAP - Calling Connect_Pnd_Cb(), CID: 0x%04x", p_ccb->local_cid);
  448. (*p_ccb->p_rcb->api.pL2CA_ConnectPnd_Cb)(p_ccb->local_cid);
  449. }
  450. break;
  451. case L2CEVT_L2CAP_CONNECT_RSP_NEG: /* Peer rejected connection */
  452. L2CAP_TRACE_API ("L2CAP - Calling Connect_Cfm_Cb(), CID: 0x%04x, Failure Code: %d", p_ccb->local_cid, p_ci->l2cap_result);
  453. l2cu_release_ccb (p_ccb);
  454. (*connect_cfm)(local_cid, p_ci->l2cap_result);
  455. break;
  456. case L2CEVT_TIMEOUT:
  457. L2CAP_TRACE_API ("L2CAP - Calling Connect_Cfm_Cb(), CID: 0x%04x, Timeout", p_ccb->local_cid);
  458. l2cu_release_ccb (p_ccb);
  459. (*connect_cfm)(local_cid, L2CAP_CONN_TIMEOUT);
  460. break;
  461. case L2CEVT_L2CA_DISCONNECT_REQ: /* Upper wants to disconnect */
  462. /* If we know peer CID from connect pending, we can send disconnect */
  463. if (p_ccb->remote_cid != 0) {
  464. l2cu_send_peer_disc_req (p_ccb);
  465. p_ccb->chnl_state = CST_W4_L2CAP_DISCONNECT_RSP;
  466. btu_start_timer (&p_ccb->timer_entry, BTU_TTYPE_L2CAP_CHNL, L2CAP_CHNL_DISCONNECT_TOUT);
  467. } else {
  468. l2cu_release_ccb (p_ccb);
  469. }
  470. break;
  471. case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data to send */
  472. case L2CEVT_L2CAP_DATA: /* Peer data packet rcvd */
  473. osi_free (p_data);
  474. break;
  475. case L2CEVT_L2CAP_INFO_RSP:
  476. /* Need to have at least one compatible channel to continue */
  477. if (!l2c_fcr_chk_chan_modes(p_ccb)) {
  478. l2cu_release_ccb (p_ccb);
  479. (*connect_cfm)(local_cid, L2CAP_CONN_NO_LINK);
  480. } else {
  481. /* We have feature info, so now send peer connect request */
  482. btu_start_timer (&p_ccb->timer_entry, BTU_TTYPE_L2CAP_CHNL, L2CAP_CHNL_CONNECT_TOUT);
  483. l2cu_send_peer_connect_req (p_ccb); /* Start Connection */
  484. }
  485. break;
  486. }
  487. }
  488. /*******************************************************************************
  489. **
  490. ** Function l2c_csm_w4_l2ca_connect_rsp
  491. **
  492. ** Description This function handles events when the channel is in
  493. ** CST_W4_L2CA_CONNECT_RSP state.
  494. **
  495. ** Returns void
  496. **
  497. *******************************************************************************/
  498. static void l2c_csm_w4_l2ca_connect_rsp (tL2C_CCB *p_ccb, UINT16 event, void *p_data)
  499. {
  500. tL2C_CONN_INFO *p_ci;
  501. tL2CA_DISCONNECT_IND_CB *disconnect_ind = p_ccb->p_rcb->api.pL2CA_DisconnectInd_Cb;
  502. UINT16 local_cid = p_ccb->local_cid;
  503. #if (BT_TRACE_VERBOSE == TRUE)
  504. L2CAP_TRACE_EVENT ("L2CAP - LCID: 0x%04x st: W4_L2CA_CON_RSP evt: %s", p_ccb->local_cid, l2c_csm_get_event_name (event));
  505. #else
  506. L2CAP_TRACE_EVENT ("L2CAP - st: W4_L2CA_CON_RSP evt: %d", event);
  507. #endif
  508. switch (event) {
  509. case L2CEVT_LP_DISCONNECT_IND: /* Link was disconnected */
  510. L2CAP_TRACE_API ("L2CAP - Calling Disconnect_Ind_Cb(), CID: 0x%04x No Conf Needed", p_ccb->local_cid);
  511. l2cu_release_ccb (p_ccb);
  512. (*disconnect_ind)(local_cid, FALSE);
  513. break;
  514. case L2CEVT_L2CA_CONNECT_RSP:
  515. p_ci = (tL2C_CONN_INFO *)p_data;
  516. /* Result should be OK or PENDING */
  517. if ((!p_ci) || (p_ci->l2cap_result == L2CAP_CONN_OK)) {
  518. l2cu_send_peer_connect_rsp (p_ccb, L2CAP_CONN_OK, 0);
  519. p_ccb->chnl_state = CST_CONFIG;
  520. btu_start_timer (&p_ccb->timer_entry, BTU_TTYPE_L2CAP_CHNL, L2CAP_CHNL_CFG_TIMEOUT);
  521. } else {
  522. /* If pending, stay in same state and start extended timer */
  523. l2cu_send_peer_connect_rsp (p_ccb, p_ci->l2cap_result, p_ci->l2cap_status);
  524. btu_start_timer (&p_ccb->timer_entry, BTU_TTYPE_L2CAP_CHNL, L2CAP_CHNL_CONNECT_TOUT_EXT);
  525. }
  526. break;
  527. case L2CEVT_L2CA_CONNECT_RSP_NEG:
  528. p_ci = (tL2C_CONN_INFO *)p_data;
  529. l2cu_send_peer_connect_rsp (p_ccb, p_ci->l2cap_result, p_ci->l2cap_status);
  530. l2cu_release_ccb (p_ccb);
  531. break;
  532. case L2CEVT_TIMEOUT:
  533. l2cu_send_peer_connect_rsp (p_ccb, L2CAP_CONN_NO_PSM, 0);
  534. L2CAP_TRACE_API ("L2CAP - Calling Disconnect_Ind_Cb(), CID: 0x%04x No Conf Needed", p_ccb->local_cid);
  535. l2cu_release_ccb (p_ccb);
  536. (*disconnect_ind)(local_cid, FALSE);
  537. break;
  538. case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data to send */
  539. case L2CEVT_L2CAP_DATA: /* Peer data packet rcvd */
  540. osi_free (p_data);
  541. break;
  542. case L2CEVT_L2CA_DISCONNECT_REQ: /* Upper wants to disconnect */
  543. l2cu_send_peer_disc_req (p_ccb);
  544. p_ccb->chnl_state = CST_W4_L2CAP_DISCONNECT_RSP;
  545. btu_start_timer (&p_ccb->timer_entry, BTU_TTYPE_L2CAP_CHNL, L2CAP_CHNL_DISCONNECT_TOUT);
  546. break;
  547. case L2CEVT_L2CAP_INFO_RSP:
  548. /* We have feature info, so now give the upper layer connect IND */
  549. btu_start_timer (&p_ccb->timer_entry, BTU_TTYPE_L2CAP_CHNL, L2CAP_CHNL_CONNECT_TOUT);
  550. L2CAP_TRACE_API ("L2CAP - Calling Connect_Ind_Cb(), CID: 0x%04x", p_ccb->local_cid);
  551. (*p_ccb->p_rcb->api.pL2CA_ConnectInd_Cb) (p_ccb->p_lcb->remote_bd_addr,
  552. p_ccb->local_cid,
  553. p_ccb->p_rcb->psm,
  554. p_ccb->remote_id);
  555. break;
  556. }
  557. }
  558. /*******************************************************************************
  559. **
  560. ** Function l2c_csm_config
  561. **
  562. ** Description This function handles events when the channel is in
  563. ** CONFIG state.
  564. **
  565. ** Returns void
  566. **
  567. *******************************************************************************/
  568. static void l2c_csm_config (tL2C_CCB *p_ccb, UINT16 event, void *p_data)
  569. {
  570. tL2CAP_CFG_INFO *p_cfg = (tL2CAP_CFG_INFO *)p_data;
  571. tL2CA_DISCONNECT_IND_CB *disconnect_ind = p_ccb->p_rcb->api.pL2CA_DisconnectInd_Cb;
  572. UINT16 local_cid = p_ccb->local_cid;
  573. UINT8 cfg_result;
  574. #if (BT_TRACE_VERBOSE == TRUE)
  575. L2CAP_TRACE_EVENT ("L2CAP - LCID: 0x%04x st: CONFIG evt: %s", p_ccb->local_cid, l2c_csm_get_event_name (event));
  576. #else
  577. L2CAP_TRACE_EVENT ("L2CAP - st: CONFIG evt: %d", event);
  578. #endif
  579. switch (event) {
  580. case L2CEVT_LP_DISCONNECT_IND: /* Link was disconnected */
  581. L2CAP_TRACE_API ("L2CAP - Calling Disconnect_Ind_Cb(), CID: 0x%04x No Conf Needed", p_ccb->local_cid);
  582. l2cu_release_ccb (p_ccb);
  583. (*disconnect_ind)(local_cid, FALSE);
  584. break;
  585. case L2CEVT_L2CAP_CONFIG_REQ: /* Peer config request */
  586. if ((cfg_result = l2cu_process_peer_cfg_req (p_ccb, p_cfg)) == L2CAP_PEER_CFG_OK) {
  587. L2CAP_TRACE_EVENT ("L2CAP - Calling Config_Req_Cb(), CID: 0x%04x, C-bit %d",
  588. p_ccb->local_cid, (p_cfg->flags & L2CAP_CFG_FLAGS_MASK_CONT));
  589. (*p_ccb->p_rcb->api.pL2CA_ConfigInd_Cb)(p_ccb->local_cid, p_cfg);
  590. } else if (cfg_result == L2CAP_PEER_CFG_DISCONNECT) {
  591. /* Disconnect if channels are incompatible */
  592. L2CAP_TRACE_EVENT ("L2CAP - incompatible configurations disconnect");
  593. l2cu_disconnect_chnl (p_ccb);
  594. } else { /* Return error to peer so he can renegotiate if possible */
  595. L2CAP_TRACE_EVENT ("L2CAP - incompatible configurations trying reconfig");
  596. l2cu_send_peer_config_rsp (p_ccb, p_cfg);
  597. }
  598. break;
  599. case L2CEVT_L2CAP_CONFIG_RSP: /* Peer config response */
  600. l2cu_process_peer_cfg_rsp (p_ccb, p_cfg);
  601. if (p_cfg->result != L2CAP_CFG_PENDING) {
  602. /* TBD: When config options grow beyong minimum MTU (48 bytes)
  603. * logic needs to be added to handle responses with
  604. * continuation bit set in flags field.
  605. * 1. Send additional config request out until C-bit is cleared in response
  606. */
  607. p_ccb->config_done |= OB_CFG_DONE;
  608. if (p_ccb->config_done & IB_CFG_DONE) {
  609. /* Verify two sides are in compatible modes before continuing */
  610. if (p_ccb->our_cfg.fcr.mode != p_ccb->peer_cfg.fcr.mode) {
  611. l2cu_send_peer_disc_req (p_ccb);
  612. L2CAP_TRACE_WARNING ("L2CAP - Calling Disconnect_Ind_Cb(Incompatible CFG), CID: 0x%04x No Conf Needed", p_ccb->local_cid);
  613. l2cu_release_ccb (p_ccb);
  614. (*disconnect_ind)(local_cid, FALSE);
  615. break;
  616. }
  617. p_ccb->config_done |= RECONFIG_FLAG;
  618. p_ccb->chnl_state = CST_OPEN;
  619. l2c_link_adjust_chnl_allocation ();
  620. btu_stop_timer (&p_ccb->timer_entry);
  621. /* If using eRTM and waiting for an ACK, restart the ACK timer */
  622. if (p_ccb->fcrb.wait_ack) {
  623. l2c_fcr_start_timer(p_ccb);
  624. }
  625. /*
  626. ** check p_ccb->our_cfg.fcr.mon_tout and p_ccb->our_cfg.fcr.rtrans_tout
  627. ** we may set them to zero when sending config request during renegotiation
  628. */
  629. if ((p_ccb->our_cfg.fcr.mode == L2CAP_FCR_ERTM_MODE)
  630. && ((p_ccb->our_cfg.fcr.mon_tout == 0) || (p_ccb->our_cfg.fcr.rtrans_tout))) {
  631. l2c_fcr_adj_monitor_retran_timeout (p_ccb);
  632. }
  633. #if (L2CAP_ERTM_STATS == TRUE)
  634. p_ccb->fcrb.connect_tick_count = osi_time_get_os_boottime_ms();
  635. #endif
  636. /* See if we can forward anything on the hold queue */
  637. if (!fixed_queue_is_empty(p_ccb->xmit_hold_q)) {
  638. l2c_link_check_send_pkts (p_ccb->p_lcb, NULL, NULL);
  639. }
  640. }
  641. }
  642. L2CAP_TRACE_API ("L2CAP - Calling Config_Rsp_Cb(), CID: 0x%04x", p_ccb->local_cid);
  643. (*p_ccb->p_rcb->api.pL2CA_ConfigCfm_Cb)(p_ccb->local_cid, p_cfg);
  644. break;
  645. case L2CEVT_L2CAP_CONFIG_RSP_NEG: /* Peer config error rsp */
  646. /* Disable the Timer */
  647. btu_stop_timer (&p_ccb->timer_entry);
  648. /* If failure was channel mode try to renegotiate */
  649. if (l2c_fcr_renegotiate_chan(p_ccb, p_cfg) == FALSE) {
  650. L2CAP_TRACE_API ("L2CAP - Calling Config_Rsp_Cb(), CID: 0x%04x, Failure: %d", p_ccb->local_cid, p_cfg->result);
  651. (*p_ccb->p_rcb->api.pL2CA_ConfigCfm_Cb)(p_ccb->local_cid, p_cfg);
  652. }
  653. break;
  654. case L2CEVT_L2CAP_DISCONNECT_REQ: /* Peer disconnected request */
  655. btu_start_timer (&p_ccb->timer_entry, BTU_TTYPE_L2CAP_CHNL, L2CAP_CHNL_DISCONNECT_TOUT);
  656. p_ccb->chnl_state = CST_W4_L2CA_DISCONNECT_RSP;
  657. L2CAP_TRACE_API ("L2CAP - Calling Disconnect_Ind_Cb(), CID: 0x%04x Conf Needed", p_ccb->local_cid);
  658. (*p_ccb->p_rcb->api.pL2CA_DisconnectInd_Cb)(p_ccb->local_cid, TRUE);
  659. break;
  660. case L2CEVT_L2CA_CONFIG_REQ: /* Upper layer config req */
  661. l2cu_process_our_cfg_req (p_ccb, p_cfg);
  662. l2cu_send_peer_config_req (p_ccb, p_cfg);
  663. btu_start_timer (&p_ccb->timer_entry, BTU_TTYPE_L2CAP_CHNL, L2CAP_CHNL_CFG_TIMEOUT);
  664. break;
  665. case L2CEVT_L2CA_CONFIG_RSP: /* Upper layer config rsp */
  666. l2cu_process_our_cfg_rsp (p_ccb, p_cfg);
  667. /* Not finished if continuation flag is set */
  668. if ( (p_cfg->flags & L2CAP_CFG_FLAGS_MASK_CONT) || (p_cfg->result == L2CAP_CFG_PENDING) ) {
  669. /* Send intermediate response; remain in cfg state */
  670. l2cu_send_peer_config_rsp (p_ccb, p_cfg);
  671. break;
  672. }
  673. /* Local config done; clear cached configuration in case reconfig takes place later */
  674. p_ccb->peer_cfg.mtu_present = FALSE;
  675. p_ccb->peer_cfg.flush_to_present = FALSE;
  676. p_ccb->peer_cfg.qos_present = FALSE;
  677. p_ccb->config_done |= IB_CFG_DONE;
  678. if (p_ccb->config_done & OB_CFG_DONE) {
  679. /* Verify two sides are in compatible modes before continuing */
  680. if (p_ccb->our_cfg.fcr.mode != p_ccb->peer_cfg.fcr.mode) {
  681. l2cu_send_peer_disc_req (p_ccb);
  682. L2CAP_TRACE_WARNING ("L2CAP - Calling Disconnect_Ind_Cb(Incompatible CFG), CID: 0x%04x No Conf Needed", p_ccb->local_cid);
  683. l2cu_release_ccb (p_ccb);
  684. (*disconnect_ind)(local_cid, FALSE);
  685. break;
  686. }
  687. p_ccb->config_done |= RECONFIG_FLAG;
  688. p_ccb->chnl_state = CST_OPEN;
  689. l2c_link_adjust_chnl_allocation ();
  690. btu_stop_timer (&p_ccb->timer_entry);
  691. }
  692. l2cu_send_peer_config_rsp (p_ccb, p_cfg);
  693. /* If using eRTM and waiting for an ACK, restart the ACK timer */
  694. if (p_ccb->fcrb.wait_ack) {
  695. l2c_fcr_start_timer(p_ccb);
  696. }
  697. #if (L2CAP_ERTM_STATS == TRUE)
  698. p_ccb->fcrb.connect_tick_count = osi_time_get_os_boottime_ms();
  699. #endif
  700. /* See if we can forward anything on the hold queue */
  701. if ( (p_ccb->chnl_state == CST_OPEN) &&
  702. (!fixed_queue_is_empty(p_ccb->xmit_hold_q))) {
  703. l2c_link_check_send_pkts (p_ccb->p_lcb, NULL, NULL);
  704. }
  705. break;
  706. case L2CEVT_L2CA_CONFIG_RSP_NEG: /* Upper layer config reject */
  707. l2cu_send_peer_config_rsp (p_ccb, p_cfg);
  708. btu_start_timer (&p_ccb->timer_entry, BTU_TTYPE_L2CAP_CHNL, L2CAP_CHNL_CFG_TIMEOUT);
  709. break;
  710. case L2CEVT_L2CA_DISCONNECT_REQ: /* Upper wants to disconnect */
  711. l2cu_send_peer_disc_req (p_ccb);
  712. p_ccb->chnl_state = CST_W4_L2CAP_DISCONNECT_RSP;
  713. btu_start_timer (&p_ccb->timer_entry, BTU_TTYPE_L2CAP_CHNL, L2CAP_CHNL_DISCONNECT_TOUT);
  714. break;
  715. case L2CEVT_L2CAP_DATA: /* Peer data packet rcvd */
  716. L2CAP_TRACE_API ("L2CAP - Calling DataInd_Cb(), CID: 0x%04x", p_ccb->local_cid);
  717. #if (L2CAP_NUM_FIXED_CHNLS > 0)
  718. if (p_ccb->local_cid >= L2CAP_FIRST_FIXED_CHNL &&
  719. p_ccb->local_cid <= L2CAP_LAST_FIXED_CHNL) {
  720. if (p_ccb->local_cid < L2CAP_BASE_APPL_CID) {
  721. if (l2cb.fixed_reg[p_ccb->local_cid - L2CAP_FIRST_FIXED_CHNL].pL2CA_FixedData_Cb) {
  722. (*l2cb.fixed_reg[p_ccb->local_cid - L2CAP_FIRST_FIXED_CHNL].pL2CA_FixedData_Cb)
  723. (p_ccb->local_cid, p_ccb->p_lcb->remote_bd_addr, (BT_HDR *)p_data);
  724. } else {
  725. osi_free (p_data);
  726. }
  727. break;
  728. }
  729. }
  730. #endif
  731. (*p_ccb->p_rcb->api.pL2CA_DataInd_Cb)(p_ccb->local_cid, (BT_HDR *)p_data);
  732. break;
  733. case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data to send */
  734. if (p_ccb->config_done & OB_CFG_DONE) {
  735. l2c_enqueue_peer_data (p_ccb, (BT_HDR *)p_data);
  736. } else {
  737. osi_free (p_data);
  738. }
  739. break;
  740. case L2CEVT_TIMEOUT:
  741. l2cu_send_peer_disc_req (p_ccb);
  742. L2CAP_TRACE_API ("L2CAP - Calling Disconnect_Ind_Cb(), CID: 0x%04x No Conf Needed",
  743. p_ccb->local_cid);
  744. l2cu_release_ccb (p_ccb);
  745. (*disconnect_ind)(local_cid, FALSE);
  746. break;
  747. }
  748. }
  749. /*******************************************************************************
  750. **
  751. ** Function l2c_csm_open
  752. **
  753. ** Description This function handles events when the channel is in
  754. ** OPEN state.
  755. **
  756. ** Returns void
  757. **
  758. *******************************************************************************/
  759. static void l2c_csm_open (tL2C_CCB *p_ccb, UINT16 event, void *p_data)
  760. {
  761. UINT16 local_cid = p_ccb->local_cid;
  762. tL2CAP_CFG_INFO *p_cfg;
  763. tL2C_CHNL_STATE tempstate;
  764. UINT8 tempcfgdone;
  765. UINT8 cfg_result;
  766. #if (BT_TRACE_VERBOSE == TRUE)
  767. L2CAP_TRACE_EVENT ("L2CAP - LCID: 0x%04x st: OPEN evt: %s",
  768. p_ccb->local_cid, l2c_csm_get_event_name (event));
  769. #else
  770. L2CAP_TRACE_EVENT ("L2CAP - st: OPEN evt: %d", event);
  771. #endif
  772. #if (L2CAP_UCD_INCLUDED == TRUE)
  773. if ( local_cid == L2CAP_CONNECTIONLESS_CID ) {
  774. /* check if this event can be processed by UCD */
  775. if ( l2c_ucd_process_event (p_ccb, event, p_data) ) {
  776. /* The event is processed by UCD state machine */
  777. return;
  778. }
  779. }
  780. #endif
  781. switch (event) {
  782. case L2CEVT_LP_DISCONNECT_IND: /* Link was disconnected */
  783. L2CAP_TRACE_API ("L2CAP - Calling Disconnect_Ind_Cb(), CID: 0x%04x No Conf Needed",
  784. p_ccb->local_cid);
  785. l2cu_release_ccb (p_ccb);
  786. if (p_ccb->p_rcb) {
  787. (*p_ccb->p_rcb->api.pL2CA_DisconnectInd_Cb)(local_cid, FALSE);
  788. }
  789. break;
  790. case L2CEVT_LP_QOS_VIOLATION_IND: /* QOS violation */
  791. /* Tell upper layer. If service guaranteed, then clear the channel */
  792. if (p_ccb->p_rcb->api.pL2CA_QoSViolationInd_Cb) {
  793. (*p_ccb->p_rcb->api.pL2CA_QoSViolationInd_Cb)(p_ccb->p_lcb->remote_bd_addr);
  794. }
  795. break;
  796. case L2CEVT_L2CAP_CONFIG_REQ: /* Peer config request */
  797. p_cfg = (tL2CAP_CFG_INFO *)p_data;
  798. tempstate = p_ccb->chnl_state;
  799. tempcfgdone = p_ccb->config_done;
  800. p_ccb->chnl_state = CST_CONFIG;
  801. p_ccb->config_done &= ~CFG_DONE_MASK;
  802. btu_start_timer (&p_ccb->timer_entry, BTU_TTYPE_L2CAP_CHNL, L2CAP_CHNL_CFG_TIMEOUT);
  803. if ((cfg_result = l2cu_process_peer_cfg_req (p_ccb, p_cfg)) == L2CAP_PEER_CFG_OK) {
  804. (*p_ccb->p_rcb->api.pL2CA_ConfigInd_Cb)(p_ccb->local_cid, p_cfg);
  805. }
  806. /* Error in config parameters: reset state and config flag */
  807. else if (cfg_result == L2CAP_PEER_CFG_UNACCEPTABLE) {
  808. btu_stop_timer(&p_ccb->timer_entry);
  809. p_ccb->chnl_state = tempstate;
  810. p_ccb->config_done = tempcfgdone;
  811. l2cu_send_peer_config_rsp (p_ccb, p_cfg);
  812. } else { /* L2CAP_PEER_CFG_DISCONNECT */
  813. /* Disconnect if channels are incompatible
  814. * Note this should not occur if reconfigure
  815. * since this should have never passed original config.
  816. */
  817. l2cu_disconnect_chnl (p_ccb);
  818. }
  819. break;
  820. case L2CEVT_L2CAP_DISCONNECT_REQ: /* Peer disconnected request */
  821. // btla-specific ++
  822. /* Make sure we are not in sniff mode */
  823. {
  824. tBTM_PM_PWR_MD settings;
  825. memset((void *)&settings, 0, sizeof(settings));
  826. settings.mode = BTM_PM_MD_ACTIVE;
  827. BTM_SetPowerMode (BTM_PM_SET_ONLY_ID, p_ccb->p_lcb->remote_bd_addr, &settings);
  828. }
  829. // btla-specific --
  830. p_ccb->chnl_state = CST_W4_L2CA_DISCONNECT_RSP;
  831. btu_start_timer (&p_ccb->timer_entry, BTU_TTYPE_L2CAP_CHNL, L2CAP_CHNL_DISCONNECT_TOUT);
  832. L2CAP_TRACE_API ("L2CAP - Calling Disconnect_Ind_Cb(), CID: 0x%04x Conf Needed", p_ccb->local_cid);
  833. (*p_ccb->p_rcb->api.pL2CA_DisconnectInd_Cb)(p_ccb->local_cid, TRUE);
  834. break;
  835. case L2CEVT_L2CAP_DATA: /* Peer data packet rcvd */
  836. if ((p_ccb->p_rcb) && (p_ccb->p_rcb->api.pL2CA_DataInd_Cb)) {
  837. (*p_ccb->p_rcb->api.pL2CA_DataInd_Cb)(p_ccb->local_cid, (BT_HDR *)p_data);
  838. }
  839. break;
  840. case L2CEVT_L2CA_DISCONNECT_REQ: /* Upper wants to disconnect */
  841. /* Make sure we are not in sniff mode */
  842. {
  843. tBTM_PM_PWR_MD settings;
  844. memset((void *)&settings, 0, sizeof(settings));
  845. settings.mode = BTM_PM_MD_ACTIVE;
  846. BTM_SetPowerMode (BTM_PM_SET_ONLY_ID, p_ccb->p_lcb->remote_bd_addr, &settings);
  847. }
  848. l2cu_send_peer_disc_req (p_ccb);
  849. p_ccb->chnl_state = CST_W4_L2CAP_DISCONNECT_RSP;
  850. btu_start_timer (&p_ccb->timer_entry, BTU_TTYPE_L2CAP_CHNL, L2CAP_CHNL_DISCONNECT_TOUT);
  851. break;
  852. case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data to send */
  853. l2c_enqueue_peer_data (p_ccb, (BT_HDR *)p_data);
  854. l2c_link_check_send_pkts (p_ccb->p_lcb, NULL, NULL);
  855. break;
  856. case L2CEVT_L2CA_CONFIG_REQ: /* Upper layer config req */
  857. p_ccb->chnl_state = CST_CONFIG;
  858. p_ccb->config_done &= ~CFG_DONE_MASK;
  859. l2cu_process_our_cfg_req (p_ccb, (tL2CAP_CFG_INFO *)p_data);
  860. l2cu_send_peer_config_req (p_ccb, (tL2CAP_CFG_INFO *)p_data);
  861. btu_start_timer (&p_ccb->timer_entry, BTU_TTYPE_L2CAP_CHNL, L2CAP_CHNL_CFG_TIMEOUT);
  862. break;
  863. case L2CEVT_TIMEOUT:
  864. /* Process the monitor/retransmission time-outs in flow control/retrans mode */
  865. if (p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_ERTM_MODE) {
  866. l2c_fcr_proc_tout (p_ccb);
  867. }
  868. break;
  869. case L2CEVT_ACK_TIMEOUT:
  870. l2c_fcr_proc_ack_tout (p_ccb);
  871. break;
  872. }
  873. }
  874. /*******************************************************************************
  875. **
  876. ** Function l2c_csm_w4_l2cap_disconnect_rsp
  877. **
  878. ** Description This function handles events when the channel is in
  879. ** CST_W4_L2CAP_DISCONNECT_RSP state.
  880. **
  881. ** Returns void
  882. **
  883. *******************************************************************************/
  884. static void l2c_csm_w4_l2cap_disconnect_rsp (tL2C_CCB *p_ccb, UINT16 event, void *p_data)
  885. {
  886. tL2CA_DISCONNECT_CFM_CB *disconnect_cfm = p_ccb->p_rcb->api.pL2CA_DisconnectCfm_Cb;
  887. UINT16 local_cid = p_ccb->local_cid;
  888. #if (BT_TRACE_VERBOSE == TRUE)
  889. L2CAP_TRACE_EVENT ("L2CAP - LCID: 0x%04x st: W4_L2CAP_DISC_RSP evt: %s", p_ccb->local_cid, l2c_csm_get_event_name (event));
  890. #else
  891. L2CAP_TRACE_EVENT ("L2CAP - st: W4_L2CAP_DISC_RSP evt: %d", event);
  892. #endif
  893. switch (event) {
  894. case L2CEVT_L2CAP_DISCONNECT_RSP: /* Peer disconnect response */
  895. l2cu_release_ccb (p_ccb);
  896. if (disconnect_cfm) {
  897. L2CAP_TRACE_API ("L2CAP - Calling DisconnectCfm_Cb(), CID: 0x%04x", local_cid);
  898. (*disconnect_cfm)(local_cid, L2CAP_DISC_OK);
  899. }
  900. break;
  901. case L2CEVT_L2CAP_DISCONNECT_REQ: /* Peer disconnect request */
  902. l2cu_send_peer_disc_rsp (p_ccb->p_lcb, p_ccb->remote_id, p_ccb->local_cid, p_ccb->remote_cid);
  903. l2cu_release_ccb (p_ccb);
  904. if (disconnect_cfm) {
  905. L2CAP_TRACE_API ("L2CAP - Calling DisconnectCfm_Cb(), CID: 0x%04x", local_cid);
  906. (*disconnect_cfm)(local_cid, L2CAP_DISC_OK);
  907. }
  908. break;
  909. case L2CEVT_LP_DISCONNECT_IND: /* Link was disconnected */
  910. case L2CEVT_TIMEOUT: /* Timeout */
  911. l2cu_release_ccb (p_ccb);
  912. if (disconnect_cfm) {
  913. L2CAP_TRACE_API ("L2CAP - Calling DisconnectCfm_Cb(), CID: 0x%04x", local_cid);
  914. (*disconnect_cfm)(local_cid, L2CAP_DISC_TIMEOUT);
  915. }
  916. break;
  917. case L2CEVT_L2CAP_DATA: /* Peer data packet rcvd */
  918. case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data to send */
  919. osi_free (p_data);
  920. break;
  921. }
  922. }
  923. /*******************************************************************************
  924. **
  925. ** Function l2c_csm_w4_l2ca_disconnect_rsp
  926. **
  927. ** Description This function handles events when the channel is in
  928. ** CST_W4_L2CA_DISCONNECT_RSP state.
  929. **
  930. ** Returns void
  931. **
  932. *******************************************************************************/
  933. static void l2c_csm_w4_l2ca_disconnect_rsp (tL2C_CCB *p_ccb, UINT16 event, void *p_data)
  934. {
  935. tL2CA_DISCONNECT_IND_CB *disconnect_ind = p_ccb->p_rcb->api.pL2CA_DisconnectInd_Cb;
  936. UINT16 local_cid = p_ccb->local_cid;
  937. #if (BT_TRACE_VERBOSE == TRUE)
  938. L2CAP_TRACE_EVENT ("L2CAP - LCID: 0x%04x st: W4_L2CA_DISC_RSP evt: %s", p_ccb->local_cid, l2c_csm_get_event_name (event));
  939. #else
  940. L2CAP_TRACE_EVENT ("L2CAP - st: W4_L2CA_DISC_RSP evt: %d", event);
  941. #endif
  942. switch (event) {
  943. case L2CEVT_LP_DISCONNECT_IND: /* Link was disconnected */
  944. L2CAP_TRACE_API ("L2CAP - Calling Disconnect_Ind_Cb(), CID: 0x%04x No Conf Needed", p_ccb->local_cid);
  945. l2cu_release_ccb (p_ccb);
  946. (*disconnect_ind)(local_cid, FALSE);
  947. break;
  948. case L2CEVT_TIMEOUT:
  949. l2cu_send_peer_disc_rsp (p_ccb->p_lcb, p_ccb->remote_id, p_ccb->local_cid, p_ccb->remote_cid);
  950. L2CAP_TRACE_API ("L2CAP - Calling Disconnect_Ind_Cb(), CID: 0x%04x No Conf Needed", p_ccb->local_cid);
  951. l2cu_release_ccb (p_ccb);
  952. (*disconnect_ind)(local_cid, FALSE);
  953. break;
  954. case L2CEVT_L2CA_DISCONNECT_REQ: /* Upper disconnect request */
  955. case L2CEVT_L2CA_DISCONNECT_RSP: /* Upper disconnect response */
  956. l2cu_send_peer_disc_rsp (p_ccb->p_lcb, p_ccb->remote_id, p_ccb->local_cid, p_ccb->remote_cid);
  957. l2cu_release_ccb (p_ccb);
  958. break;
  959. case L2CEVT_L2CAP_DATA: /* Peer data packet rcvd */
  960. case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data to send */
  961. osi_free (p_data);
  962. break;
  963. }
  964. }
  965. #endif /// (L2CAP_COC_INCLUDED == TRUE)
  966. #if (BT_TRACE_VERBOSE == TRUE)
  967. /*******************************************************************************
  968. **
  969. ** Function l2c_csm_get_event_name
  970. **
  971. ** Description This function returns the event name.
  972. **
  973. ** NOTE conditionally compiled to save memory.
  974. **
  975. ** Returns pointer to the name
  976. **
  977. *******************************************************************************/
  978. static char *l2c_csm_get_event_name (UINT16 event)
  979. {
  980. switch (event) {
  981. case L2CEVT_LP_CONNECT_CFM: /* Lower layer connect confirm */
  982. return ("LOWER_LAYER_CONNECT_CFM");
  983. case L2CEVT_LP_CONNECT_CFM_NEG: /* Lower layer connect confirm (failed) */
  984. return ("LOWER_LAYER_CONNECT_CFM_NEG");
  985. case L2CEVT_LP_CONNECT_IND: /* Lower layer connect indication */
  986. return ("LOWER_LAYER_CONNECT_IND");
  987. case L2CEVT_LP_DISCONNECT_IND: /* Lower layer disconnect indication */
  988. return ("LOWER_LAYER_DISCONNECT_IND");
  989. case L2CEVT_LP_QOS_CFM: /* Lower layer QOS confirmation */
  990. return ("LOWER_LAYER_QOS_CFM");
  991. case L2CEVT_LP_QOS_CFM_NEG: /* Lower layer QOS confirmation (failed)*/
  992. return ("LOWER_LAYER_QOS_CFM_NEG");
  993. case L2CEVT_LP_QOS_VIOLATION_IND: /* Lower layer QOS violation indication */
  994. return ("LOWER_LAYER_QOS_VIOLATION_IND");
  995. case L2CEVT_SEC_COMP: /* Security cleared successfully */
  996. return ("SECURITY_COMPLETE");
  997. case L2CEVT_SEC_COMP_NEG: /* Security procedure failed */
  998. return ("SECURITY_COMPLETE_NEG");
  999. case L2CEVT_L2CAP_CONNECT_REQ: /* Peer connection request */
  1000. return ("PEER_CONNECT_REQ");
  1001. case L2CEVT_L2CAP_CONNECT_RSP: /* Peer connection response */
  1002. return ("PEER_CONNECT_RSP");
  1003. case L2CEVT_L2CAP_CONNECT_RSP_PND: /* Peer connection response pending */
  1004. return ("PEER_CONNECT_RSP_PND");
  1005. case L2CEVT_L2CAP_CONNECT_RSP_NEG: /* Peer connection response (failed) */
  1006. return ("PEER_CONNECT_RSP_NEG");
  1007. case L2CEVT_L2CAP_CONFIG_REQ: /* Peer configuration request */
  1008. return ("PEER_CONFIG_REQ");
  1009. case L2CEVT_L2CAP_CONFIG_RSP: /* Peer configuration response */
  1010. return ("PEER_CONFIG_RSP");
  1011. case L2CEVT_L2CAP_CONFIG_RSP_NEG: /* Peer configuration response (failed) */
  1012. return ("PEER_CONFIG_RSP_NEG");
  1013. case L2CEVT_L2CAP_DISCONNECT_REQ: /* Peer disconnect request */
  1014. return ("PEER_DISCONNECT_REQ");
  1015. case L2CEVT_L2CAP_DISCONNECT_RSP: /* Peer disconnect response */
  1016. return ("PEER_DISCONNECT_RSP");
  1017. case L2CEVT_L2CAP_DATA: /* Peer data */
  1018. return ("PEER_DATA");
  1019. case L2CEVT_L2CA_CONNECT_REQ: /* Upper layer connect request */
  1020. return ("UPPER_LAYER_CONNECT_REQ");
  1021. case L2CEVT_L2CA_CONNECT_RSP: /* Upper layer connect response */
  1022. return ("UPPER_LAYER_CONNECT_RSP");
  1023. case L2CEVT_L2CA_CONNECT_RSP_NEG: /* Upper layer connect response (failed)*/
  1024. return ("UPPER_LAYER_CONNECT_RSP_NEG");
  1025. case L2CEVT_L2CA_CONFIG_REQ: /* Upper layer config request */
  1026. return ("UPPER_LAYER_CONFIG_REQ");
  1027. case L2CEVT_L2CA_CONFIG_RSP: /* Upper layer config response */
  1028. return ("UPPER_LAYER_CONFIG_RSP");
  1029. case L2CEVT_L2CA_CONFIG_RSP_NEG: /* Upper layer config response (failed) */
  1030. return ("UPPER_LAYER_CONFIG_RSP_NEG");
  1031. case L2CEVT_L2CA_DISCONNECT_REQ: /* Upper layer disconnect request */
  1032. return ("UPPER_LAYER_DISCONNECT_REQ");
  1033. case L2CEVT_L2CA_DISCONNECT_RSP: /* Upper layer disconnect response */
  1034. return ("UPPER_LAYER_DISCONNECT_RSP");
  1035. case L2CEVT_L2CA_DATA_READ: /* Upper layer data read */
  1036. return ("UPPER_LAYER_DATA_READ");
  1037. case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data write */
  1038. return ("UPPER_LAYER_DATA_WRITE");
  1039. case L2CEVT_TIMEOUT: /* Timeout */
  1040. return ("TIMEOUT");
  1041. case L2CEVT_SEC_RE_SEND_CMD:
  1042. return ("SEC_RE_SEND_CMD");
  1043. case L2CEVT_L2CAP_INFO_RSP: /* Peer information response */
  1044. return ("L2CEVT_L2CAP_INFO_RSP");
  1045. case L2CEVT_ACK_TIMEOUT:
  1046. return ("L2CEVT_ACK_TIMEOUT");
  1047. default:
  1048. return ("???? UNKNOWN EVENT");
  1049. }
  1050. }
  1051. #endif /* (BT_TRACE_VERBOSE == TRUE) */
  1052. /*******************************************************************************
  1053. **
  1054. ** Function l2c_enqueue_peer_data
  1055. **
  1056. ** Description Enqueues data destined for the peer in the ccb. Handles
  1057. ** FCR segmentation and checks for congestion.
  1058. **
  1059. ** Returns void
  1060. **
  1061. *******************************************************************************/
  1062. void l2c_enqueue_peer_data (tL2C_CCB *p_ccb, BT_HDR *p_buf)
  1063. {
  1064. UINT8 *p;
  1065. if (p_ccb->peer_cfg.fcr.mode != L2CAP_FCR_BASIC_MODE) {
  1066. p_buf->event = 0;
  1067. } else {
  1068. /* Save the channel ID for faster counting */
  1069. p_buf->event = p_ccb->local_cid;
  1070. /* Step back to add the L2CAP header */
  1071. p_buf->offset -= L2CAP_PKT_OVERHEAD;
  1072. p_buf->len += L2CAP_PKT_OVERHEAD;
  1073. /* Set the pointer to the beginning of the data */
  1074. p = (UINT8 *)(p_buf + 1) + p_buf->offset;
  1075. /* Now the L2CAP header */
  1076. UINT16_TO_STREAM (p, p_buf->len - L2CAP_PKT_OVERHEAD);
  1077. UINT16_TO_STREAM (p, p_ccb->remote_cid);
  1078. }
  1079. fixed_queue_enqueue(p_ccb->xmit_hold_q, p_buf, FIXED_QUEUE_MAX_TIMEOUT);
  1080. l2cu_check_channel_congestion (p_ccb);
  1081. #if (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE)
  1082. /* if new packet is higher priority than serving ccb and it is not overrun */
  1083. if (( p_ccb->p_lcb->rr_pri > p_ccb->ccb_priority )
  1084. && ( p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].quota > 0)) {
  1085. /* send out higher priority packet */
  1086. p_ccb->p_lcb->rr_pri = p_ccb->ccb_priority;
  1087. }
  1088. #endif
  1089. /* if we are doing a round robin scheduling, set the flag */
  1090. if (p_ccb->p_lcb->link_xmit_quota == 0) {
  1091. l2cb.check_round_robin = TRUE;
  1092. }
  1093. }