1 /******************************************************************************
2 *
3 * Copyright 1999-2012 Broadcom Corporation
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 ******************************************************************************/
18
19 /******************************************************************************
20 *
21 * This file contains the L2CAP channel state machine
22 *
23 ******************************************************************************/
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28
29 #include "bt_common.h"
30 #include "bt_target.h"
31 #include "btm_int.h"
32 #include "btu.h"
33 #include "common/time_util.h"
34 #include "hcidefs.h"
35 #include "hcimsgs.h"
36 #include "l2c_int.h"
37 #include "l2cdefs.h"
38
39 /******************************************************************************/
40 /* L O C A L F U N C T I O N P R O T O T Y P E S */
41 /******************************************************************************/
42 static void l2c_csm_closed(tL2C_CCB* p_ccb, uint16_t event, void* p_data);
43 static void l2c_csm_orig_w4_sec_comp(tL2C_CCB* p_ccb, uint16_t event,
44 void* p_data);
45 static void l2c_csm_term_w4_sec_comp(tL2C_CCB* p_ccb, uint16_t event,
46 void* p_data);
47 static void l2c_csm_w4_l2cap_connect_rsp(tL2C_CCB* p_ccb, uint16_t event,
48 void* p_data);
49 static void l2c_csm_w4_l2ca_connect_rsp(tL2C_CCB* p_ccb, uint16_t event,
50 void* p_data);
51 static void l2c_csm_config(tL2C_CCB* p_ccb, uint16_t event, void* p_data);
52 static void l2c_csm_open(tL2C_CCB* p_ccb, uint16_t event, void* p_data);
53 static void l2c_csm_w4_l2cap_disconnect_rsp(tL2C_CCB* p_ccb, uint16_t event,
54 void* p_data);
55 static void l2c_csm_w4_l2ca_disconnect_rsp(tL2C_CCB* p_ccb, uint16_t event,
56 void* p_data);
57
58 static const char* l2c_csm_get_event_name(uint16_t event);
59
60 /*******************************************************************************
61 *
62 * Function l2c_csm_execute
63 *
64 * Description This function executes the state machine.
65 *
66 * Returns void
67 *
68 ******************************************************************************/
l2c_csm_execute(tL2C_CCB * p_ccb,uint16_t event,void * p_data)69 void l2c_csm_execute(tL2C_CCB* p_ccb, uint16_t event, void* p_data) {
70 if (!l2cu_is_ccb_active(p_ccb)) {
71 L2CAP_TRACE_WARNING("%s CCB not in use, event (%d) cannot be processed",
72 __func__, event);
73 return;
74 }
75
76 switch (p_ccb->chnl_state) {
77 case CST_CLOSED:
78 l2c_csm_closed(p_ccb, event, p_data);
79 break;
80
81 case CST_ORIG_W4_SEC_COMP:
82 l2c_csm_orig_w4_sec_comp(p_ccb, event, p_data);
83 break;
84
85 case CST_TERM_W4_SEC_COMP:
86 l2c_csm_term_w4_sec_comp(p_ccb, event, p_data);
87 break;
88
89 case CST_W4_L2CAP_CONNECT_RSP:
90 l2c_csm_w4_l2cap_connect_rsp(p_ccb, event, p_data);
91 break;
92
93 case CST_W4_L2CA_CONNECT_RSP:
94 l2c_csm_w4_l2ca_connect_rsp(p_ccb, event, p_data);
95 break;
96
97 case CST_CONFIG:
98 l2c_csm_config(p_ccb, event, p_data);
99 break;
100
101 case CST_OPEN:
102 l2c_csm_open(p_ccb, event, p_data);
103 break;
104
105 case CST_W4_L2CAP_DISCONNECT_RSP:
106 l2c_csm_w4_l2cap_disconnect_rsp(p_ccb, event, p_data);
107 break;
108
109 case CST_W4_L2CA_DISCONNECT_RSP:
110 l2c_csm_w4_l2ca_disconnect_rsp(p_ccb, event, p_data);
111 break;
112
113 default:
114 L2CAP_TRACE_DEBUG("Unhandled event! event = %d", event);
115 break;
116 }
117 }
118
119 /*******************************************************************************
120 *
121 * Function l2c_csm_closed
122 *
123 * Description This function handles events when the channel is in
124 * CLOSED state. This state exists only when the link is
125 * being initially established.
126 *
127 * Returns void
128 *
129 ******************************************************************************/
l2c_csm_closed(tL2C_CCB * p_ccb,uint16_t event,void * p_data)130 static void l2c_csm_closed(tL2C_CCB* p_ccb, uint16_t event, void* p_data) {
131 tL2C_CONN_INFO* p_ci = (tL2C_CONN_INFO*)p_data;
132 uint16_t local_cid = p_ccb->local_cid;
133 tL2CA_DISCONNECT_IND_CB* disconnect_ind;
134 tL2CA_CONNECT_CFM_CB* connect_cfm;
135
136 if (p_ccb->p_rcb == NULL) {
137 L2CAP_TRACE_ERROR("L2CAP - LCID: 0x%04x st: CLOSED evt: %s p_rcb == NULL",
138 p_ccb->local_cid, l2c_csm_get_event_name(event));
139 return;
140 }
141
142 disconnect_ind = p_ccb->p_rcb->api.pL2CA_DisconnectInd_Cb;
143 connect_cfm = p_ccb->p_rcb->api.pL2CA_ConnectCfm_Cb;
144
145 L2CAP_TRACE_EVENT("L2CAP - LCID: 0x%04x st: CLOSED evt: %s",
146 p_ccb->local_cid, l2c_csm_get_event_name(event));
147
148 switch (event) {
149 case L2CEVT_LP_DISCONNECT_IND: /* Link was disconnected */
150 L2CAP_TRACE_API(
151 "L2CAP - Calling Disconnect_Ind_Cb(), CID: 0x%04x No Conf Needed",
152 p_ccb->local_cid);
153 l2cu_release_ccb(p_ccb);
154 (*disconnect_ind)(local_cid, false);
155 break;
156
157 case L2CEVT_LP_CONNECT_CFM: /* Link came up */
158 if (p_ccb->p_lcb->transport == BT_TRANSPORT_LE) {
159 p_ccb->chnl_state = CST_ORIG_W4_SEC_COMP;
160 l2ble_sec_access_req(p_ccb->p_lcb->remote_bd_addr, p_ccb->p_rcb->psm,
161 true, &l2c_link_sec_comp2, p_ccb);
162 } else {
163 p_ccb->chnl_state = CST_ORIG_W4_SEC_COMP;
164 btm_sec_l2cap_access_req(p_ccb->p_lcb->remote_bd_addr,
165 p_ccb->p_rcb->psm, p_ccb->p_lcb->handle, true,
166 &l2c_link_sec_comp, p_ccb);
167 }
168 break;
169
170 case L2CEVT_LP_CONNECT_CFM_NEG: /* Link failed */
171 /* Disconnect unless ACL collision and upper layer wants to handle it */
172 if (p_ci->status != HCI_ERR_CONNECTION_EXISTS ||
173 !btm_acl_notif_conn_collision(p_ccb->p_lcb->remote_bd_addr)) {
174 L2CAP_TRACE_API(
175 "L2CAP - Calling ConnectCfm_Cb(), CID: 0x%04x Status: %d",
176 p_ccb->local_cid, p_ci->status);
177 l2cu_release_ccb(p_ccb);
178 (*connect_cfm)(local_cid, p_ci->status);
179 }
180 break;
181
182 case L2CEVT_L2CA_CONNECT_REQ: /* API connect request */
183 if (p_ccb->p_lcb->transport == BT_TRANSPORT_LE) {
184 p_ccb->chnl_state = CST_ORIG_W4_SEC_COMP;
185 l2ble_sec_access_req(p_ccb->p_lcb->remote_bd_addr, p_ccb->p_rcb->psm,
186 true, &l2c_link_sec_comp2, p_ccb);
187 } else {
188 /* Cancel sniff mode if needed */
189 tBTM_PM_PWR_MD settings;
190 memset((void*)&settings, 0, sizeof(settings));
191 settings.mode = BTM_PM_MD_ACTIVE;
192
193 BTM_SetPowerMode(BTM_PM_SET_ONLY_ID, p_ccb->p_lcb->remote_bd_addr,
194 &settings);
195
196 /* If sec access does not result in started SEC_COM or COMP_NEG are
197 * already processed */
198 if (btm_sec_l2cap_access_req(p_ccb->p_lcb->remote_bd_addr,
199 p_ccb->p_rcb->psm, p_ccb->p_lcb->handle,
200 true, &l2c_link_sec_comp,
201 p_ccb) == BTM_CMD_STARTED) {
202 p_ccb->chnl_state = CST_ORIG_W4_SEC_COMP;
203 }
204 }
205 break;
206
207 case L2CEVT_SEC_COMP:
208 p_ccb->chnl_state = CST_W4_L2CAP_CONNECT_RSP;
209
210 /* Wait for the info resp in this state before sending connect req (if
211 * needed) */
212 if (!p_ccb->p_lcb->w4_info_rsp) {
213 /* Need to have at least one compatible channel to continue */
214 if (!l2c_fcr_chk_chan_modes(p_ccb)) {
215 l2cu_release_ccb(p_ccb);
216 (*p_ccb->p_rcb->api.pL2CA_ConnectCfm_Cb)(local_cid,
217 L2CAP_CONN_NO_LINK);
218 } else {
219 l2cu_send_peer_connect_req(p_ccb);
220 alarm_set_on_mloop(p_ccb->l2c_ccb_timer,
221 L2CAP_CHNL_CONNECT_TIMEOUT_MS,
222 l2c_ccb_timer_timeout, p_ccb);
223 }
224 }
225 break;
226
227 case L2CEVT_SEC_COMP_NEG: /* something is really bad with security */
228 L2CAP_TRACE_API(
229 "L2CAP - Calling ConnectCfm_Cb(), CID: 0x%04x Status: %d",
230 p_ccb->local_cid, L2CAP_CONN_TIMEOUT);
231 l2cu_release_ccb(p_ccb);
232 (*connect_cfm)(local_cid, L2CAP_CONN_SECURITY_BLOCK);
233 break;
234
235 case L2CEVT_L2CAP_CONNECT_REQ: /* Peer connect request */
236 /* stop link timer to avoid race condition between A2MP, Security, and
237 * L2CAP */
238 alarm_cancel(p_ccb->p_lcb->l2c_lcb_timer);
239
240 if (p_ccb->p_lcb->transport == BT_TRANSPORT_LE) {
241 p_ccb->chnl_state = CST_TERM_W4_SEC_COMP;
242 tL2CAP_LE_RESULT_CODE result = l2ble_sec_access_req(
243 p_ccb->p_lcb->remote_bd_addr, p_ccb->p_rcb->psm, false,
244 &l2c_link_sec_comp2, p_ccb);
245
246 switch (result) {
247 case L2CAP_LE_RESULT_INSUFFICIENT_AUTHENTICATION:
248 case L2CAP_LE_RESULT_INSUFFICIENT_ENCRYP_KEY_SIZE:
249 case L2CAP_LE_RESULT_INSUFFICIENT_ENCRYP:
250 l2cu_reject_ble_connection(p_ccb->p_lcb, p_ccb->remote_id, result);
251 l2cu_release_ccb(p_ccb);
252 break;
253 // TODO: Handle the other return codes
254 }
255 } else {
256 /* Cancel sniff mode if needed */
257 {
258 tBTM_PM_PWR_MD settings;
259 memset((void*)&settings, 0, sizeof(settings));
260 settings.mode = BTM_PM_MD_ACTIVE;
261
262 BTM_SetPowerMode(BTM_PM_SET_ONLY_ID, p_ccb->p_lcb->remote_bd_addr,
263 &settings);
264 }
265
266 p_ccb->chnl_state = CST_TERM_W4_SEC_COMP;
267 if (btm_sec_l2cap_access_req(p_ccb->p_lcb->remote_bd_addr,
268 p_ccb->p_rcb->psm, p_ccb->p_lcb->handle,
269 false, &l2c_link_sec_comp,
270 p_ccb) == BTM_CMD_STARTED) {
271 /* started the security process, tell the peer to set a longer timer
272 */
273 l2cu_send_peer_connect_rsp(p_ccb, L2CAP_CONN_PENDING, 0);
274 }
275 }
276 break;
277
278 case L2CEVT_TIMEOUT:
279 L2CAP_TRACE_API(
280 "L2CAP - Calling ConnectCfm_Cb(), CID: 0x%04x Status: %d",
281 p_ccb->local_cid, L2CAP_CONN_TIMEOUT);
282 l2cu_release_ccb(p_ccb);
283 (*connect_cfm)(local_cid, L2CAP_CONN_TIMEOUT);
284 break;
285
286 case L2CEVT_L2CAP_DATA: /* Peer data packet rcvd */
287 case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data to send */
288 osi_free(p_data);
289 break;
290
291 case L2CEVT_L2CA_DISCONNECT_REQ: /* Upper wants to disconnect */
292 l2cu_release_ccb(p_ccb);
293 break;
294 }
295 }
296
297 /*******************************************************************************
298 *
299 * Function l2c_csm_orig_w4_sec_comp
300 *
301 * Description This function handles events when the channel is in
302 * CST_ORIG_W4_SEC_COMP state.
303 *
304 * Returns void
305 *
306 ******************************************************************************/
l2c_csm_orig_w4_sec_comp(tL2C_CCB * p_ccb,uint16_t event,void * p_data)307 static void l2c_csm_orig_w4_sec_comp(tL2C_CCB* p_ccb, uint16_t event,
308 void* p_data) {
309 tL2CA_DISCONNECT_IND_CB* disconnect_ind =
310 p_ccb->p_rcb->api.pL2CA_DisconnectInd_Cb;
311 tL2CA_CONNECT_CFM_CB* connect_cfm = p_ccb->p_rcb->api.pL2CA_ConnectCfm_Cb;
312 uint16_t local_cid = p_ccb->local_cid;
313
314 L2CAP_TRACE_EVENT(
315 "%s: %sL2CAP - LCID: 0x%04x st: ORIG_W4_SEC_COMP evt: %s", __func__,
316 ((p_ccb->p_lcb) && (p_ccb->p_lcb->transport == BT_TRANSPORT_LE)) ? "LE "
317 : "",
318 p_ccb->local_cid, l2c_csm_get_event_name(event));
319
320 switch (event) {
321 case L2CEVT_LP_DISCONNECT_IND: /* Link was disconnected */
322 L2CAP_TRACE_API(
323 "L2CAP - Calling Disconnect_Ind_Cb(), CID: 0x%04x No Conf Needed",
324 p_ccb->local_cid);
325 l2cu_release_ccb(p_ccb);
326 (*disconnect_ind)(local_cid, false);
327 break;
328
329 case L2CEVT_SEC_RE_SEND_CMD: /* BTM has enough info to proceed */
330 case L2CEVT_LP_CONNECT_CFM: /* Link came up */
331 if (p_ccb->p_lcb->transport == BT_TRANSPORT_LE) {
332 l2ble_sec_access_req(p_ccb->p_lcb->remote_bd_addr, p_ccb->p_rcb->psm,
333 false, &l2c_link_sec_comp2, p_ccb);
334 } else {
335 btm_sec_l2cap_access_req(p_ccb->p_lcb->remote_bd_addr,
336 p_ccb->p_rcb->psm, p_ccb->p_lcb->handle, true,
337 &l2c_link_sec_comp, p_ccb);
338 }
339 break;
340
341 case L2CEVT_SEC_COMP: /* Security completed success */
342 /* Wait for the info resp in this state before sending connect req (if
343 * needed) */
344 p_ccb->chnl_state = CST_W4_L2CAP_CONNECT_RSP;
345 if (p_ccb->p_lcb->transport == BT_TRANSPORT_LE) {
346 alarm_set_on_mloop(p_ccb->l2c_ccb_timer, L2CAP_CHNL_CONNECT_TIMEOUT_MS,
347 l2c_ccb_timer_timeout, p_ccb);
348 l2cble_credit_based_conn_req(p_ccb); /* Start Connection */
349 } else {
350 if (!p_ccb->p_lcb->w4_info_rsp) {
351 /* Need to have at least one compatible channel to continue */
352 if (!l2c_fcr_chk_chan_modes(p_ccb)) {
353 l2cu_release_ccb(p_ccb);
354 (*connect_cfm)(local_cid, L2CAP_CONN_NO_LINK);
355 } else {
356 alarm_set_on_mloop(p_ccb->l2c_ccb_timer,
357 L2CAP_CHNL_CONNECT_TIMEOUT_MS,
358 l2c_ccb_timer_timeout, p_ccb);
359 l2cu_send_peer_connect_req(p_ccb); /* Start Connection */
360 }
361 }
362 }
363 break;
364
365 case L2CEVT_SEC_COMP_NEG:
366 L2CAP_TRACE_API(
367 "L2CAP - Calling ConnectCfm_Cb(), CID: 0x%04x Status: %d",
368 p_ccb->local_cid, HCI_ERR_AUTH_FAILURE);
369
370 /* If last channel immediately disconnect the ACL for better security.
371 Also prevents a race condition between BTM and L2CAP */
372 if ((p_ccb == p_ccb->p_lcb->ccb_queue.p_first_ccb) &&
373 (p_ccb == p_ccb->p_lcb->ccb_queue.p_last_ccb)) {
374 p_ccb->p_lcb->idle_timeout = 0;
375 }
376
377 l2cu_release_ccb(p_ccb);
378 (*connect_cfm)(local_cid, HCI_ERR_AUTH_FAILURE);
379 break;
380
381 case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data to send */
382 case L2CEVT_L2CAP_DATA: /* Peer data packet rcvd */
383 osi_free(p_data);
384 break;
385
386 case L2CEVT_L2CA_DISCONNECT_REQ: /* Upper wants to disconnect */
387 /* Tell security manager to abort */
388 btm_sec_abort_access_req(p_ccb->p_lcb->remote_bd_addr);
389
390 l2cu_release_ccb(p_ccb);
391 break;
392 }
393 }
394
395 /*******************************************************************************
396 *
397 * Function l2c_csm_term_w4_sec_comp
398 *
399 * Description This function handles events when the channel is in
400 * CST_TERM_W4_SEC_COMP state.
401 *
402 * Returns void
403 *
404 ******************************************************************************/
l2c_csm_term_w4_sec_comp(tL2C_CCB * p_ccb,uint16_t event,void * p_data)405 static void l2c_csm_term_w4_sec_comp(tL2C_CCB* p_ccb, uint16_t event,
406 void* p_data) {
407 L2CAP_TRACE_EVENT("L2CAP - LCID: 0x%04x st: TERM_W4_SEC_COMP evt: %s",
408 p_ccb->local_cid, l2c_csm_get_event_name(event));
409
410 switch (event) {
411 case L2CEVT_LP_DISCONNECT_IND: /* Link was disconnected */
412 /* Tell security manager to abort */
413 btm_sec_abort_access_req(p_ccb->p_lcb->remote_bd_addr);
414
415 l2cu_release_ccb(p_ccb);
416 break;
417
418 case L2CEVT_SEC_COMP:
419 p_ccb->chnl_state = CST_W4_L2CA_CONNECT_RSP;
420
421 /* Wait for the info resp in next state before sending connect ind (if
422 * needed) */
423 if (!p_ccb->p_lcb->w4_info_rsp) {
424 /* Don't need to get info from peer or already retrieved so continue */
425 alarm_set_on_mloop(p_ccb->l2c_ccb_timer, L2CAP_CHNL_CONNECT_TIMEOUT_MS,
426 l2c_ccb_timer_timeout, p_ccb);
427 L2CAP_TRACE_API("L2CAP - Calling Connect_Ind_Cb(), CID: 0x%04x",
428 p_ccb->local_cid);
429
430 (*p_ccb->p_rcb->api.pL2CA_ConnectInd_Cb)(
431 p_ccb->p_lcb->remote_bd_addr, p_ccb->local_cid, p_ccb->p_rcb->psm,
432 p_ccb->remote_id);
433 } else {
434 /*
435 ** L2CAP Connect Response will be sent out by 3 sec timer expiration
436 ** because Bluesoleil doesn't respond to L2CAP Information Request.
437 ** Bluesoleil seems to disconnect ACL link as failure case, because
438 ** it takes too long (4~7secs) to get response.
439 ** product version : Bluesoleil 2.1.1.0 EDR Release 060123
440 ** stack version : 05.04.11.20060119
441 */
442
443 /* Waiting for the info resp, tell the peer to set a longer timer */
444 l2cu_send_peer_connect_rsp(p_ccb, L2CAP_CONN_PENDING, 0);
445 }
446 break;
447
448 case L2CEVT_SEC_COMP_NEG:
449 if (((tL2C_CONN_INFO*)p_data)->status == BTM_DELAY_CHECK) {
450 /* start a timer - encryption change not received before L2CAP connect
451 * req */
452 alarm_set_on_mloop(p_ccb->l2c_ccb_timer,
453 L2CAP_DELAY_CHECK_SM4_TIMEOUT_MS,
454 l2c_ccb_timer_timeout, p_ccb);
455 } else {
456 if (p_ccb->p_lcb->transport == BT_TRANSPORT_LE)
457 l2cu_reject_ble_connection(
458 p_ccb->p_lcb, p_ccb->remote_id,
459 L2CAP_LE_RESULT_INSUFFICIENT_AUTHENTICATION);
460 else
461 l2cu_send_peer_connect_rsp(p_ccb, L2CAP_CONN_SECURITY_BLOCK, 0);
462 l2cu_release_ccb(p_ccb);
463 }
464 break;
465
466 case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data to send */
467 case L2CEVT_L2CAP_DATA: /* Peer data packet rcvd */
468 osi_free(p_data);
469 break;
470
471 case L2CEVT_L2CA_DISCONNECT_REQ: /* Upper wants to disconnect */
472 l2cu_release_ccb(p_ccb);
473 break;
474
475 case L2CEVT_L2CAP_DISCONNECT_REQ: /* Peer disconnected request */
476 l2cu_send_peer_disc_rsp(p_ccb->p_lcb, p_ccb->remote_id, p_ccb->local_cid,
477 p_ccb->remote_cid);
478
479 /* Tell security manager to abort */
480 btm_sec_abort_access_req(p_ccb->p_lcb->remote_bd_addr);
481
482 l2cu_release_ccb(p_ccb);
483 break;
484
485 case L2CEVT_TIMEOUT:
486 /* SM4 related. */
487 btsnd_hcic_disconnect(p_ccb->p_lcb->handle, HCI_ERR_AUTH_FAILURE);
488 break;
489
490 case L2CEVT_SEC_RE_SEND_CMD: /* BTM has enough info to proceed */
491 btm_sec_l2cap_access_req(p_ccb->p_lcb->remote_bd_addr, p_ccb->p_rcb->psm,
492 p_ccb->p_lcb->handle, false, &l2c_link_sec_comp,
493 p_ccb);
494 break;
495 }
496 }
497
498 /*******************************************************************************
499 *
500 * Function l2c_csm_w4_l2cap_connect_rsp
501 *
502 * Description This function handles events when the channel is in
503 * CST_W4_L2CAP_CONNECT_RSP state.
504 *
505 * Returns void
506 *
507 ******************************************************************************/
l2c_csm_w4_l2cap_connect_rsp(tL2C_CCB * p_ccb,uint16_t event,void * p_data)508 static void l2c_csm_w4_l2cap_connect_rsp(tL2C_CCB* p_ccb, uint16_t event,
509 void* p_data) {
510 tL2C_CONN_INFO* p_ci = (tL2C_CONN_INFO*)p_data;
511 tL2CA_DISCONNECT_IND_CB* disconnect_ind =
512 p_ccb->p_rcb->api.pL2CA_DisconnectInd_Cb;
513 tL2CA_CONNECT_CFM_CB* connect_cfm = p_ccb->p_rcb->api.pL2CA_ConnectCfm_Cb;
514 uint16_t local_cid = p_ccb->local_cid;
515
516 L2CAP_TRACE_EVENT("L2CAP - LCID: 0x%04x st: W4_L2CAP_CON_RSP evt: %s",
517 p_ccb->local_cid, l2c_csm_get_event_name(event));
518
519 switch (event) {
520 case L2CEVT_LP_DISCONNECT_IND: /* Link was disconnected */
521 /* Send disc indication unless peer to peer race condition AND normal
522 * disconnect */
523 /* *((uint8_t *)p_data) != HCI_ERR_PEER_USER happens when peer device try
524 * to disconnect for normal reason */
525 p_ccb->chnl_state = CST_CLOSED;
526 if ((p_ccb->flags & CCB_FLAG_NO_RETRY) || !p_data ||
527 (*((uint8_t*)p_data) != HCI_ERR_PEER_USER)) {
528 L2CAP_TRACE_API(
529 "L2CAP - Calling Disconnect_Ind_Cb(), CID: 0x%04x No Conf Needed",
530 p_ccb->local_cid);
531 l2cu_release_ccb(p_ccb);
532 (*disconnect_ind)(local_cid, false);
533 }
534 p_ccb->flags |= CCB_FLAG_NO_RETRY;
535 break;
536
537 case L2CEVT_L2CAP_CONNECT_RSP: /* Got peer connect confirm */
538 p_ccb->remote_cid = p_ci->remote_cid;
539 if (p_ccb->p_lcb->transport == BT_TRANSPORT_LE) {
540 /* Connection is completed */
541 alarm_cancel(p_ccb->l2c_ccb_timer);
542 p_ccb->chnl_state = CST_OPEN;
543 } else {
544 p_ccb->chnl_state = CST_CONFIG;
545 alarm_set_on_mloop(p_ccb->l2c_ccb_timer, L2CAP_CHNL_CFG_TIMEOUT_MS,
546 l2c_ccb_timer_timeout, p_ccb);
547 }
548 L2CAP_TRACE_API("L2CAP - Calling Connect_Cfm_Cb(), CID: 0x%04x, Success",
549 p_ccb->local_cid);
550
551 (*p_ccb->p_rcb->api.pL2CA_ConnectCfm_Cb)(local_cid, L2CAP_CONN_OK);
552 break;
553
554 case L2CEVT_L2CAP_CONNECT_RSP_PND: /* Got peer connect pending */
555 p_ccb->remote_cid = p_ci->remote_cid;
556 alarm_set_on_mloop(p_ccb->l2c_ccb_timer,
557 L2CAP_CHNL_CONNECT_EXT_TIMEOUT_MS,
558 l2c_ccb_timer_timeout, p_ccb);
559 if (p_ccb->p_rcb->api.pL2CA_ConnectPnd_Cb) {
560 L2CAP_TRACE_API("L2CAP - Calling Connect_Pnd_Cb(), CID: 0x%04x",
561 p_ccb->local_cid);
562 (*p_ccb->p_rcb->api.pL2CA_ConnectPnd_Cb)(p_ccb->local_cid);
563 }
564 break;
565
566 case L2CEVT_L2CAP_CONNECT_RSP_NEG: /* Peer rejected connection */
567 LOG(WARNING) << __func__ << ": L2CAP connection rejected, lcid="
568 << loghex(p_ccb->local_cid)
569 << ", reason=" << loghex(p_ci->l2cap_result);
570 l2cu_release_ccb(p_ccb);
571 (*connect_cfm)(local_cid, p_ci->l2cap_result);
572 break;
573
574 case L2CEVT_TIMEOUT:
575 LOG(WARNING) << __func__ << ": L2CAP connection timeout, lcid="
576 << loghex(p_ccb->local_cid);
577 l2cu_release_ccb(p_ccb);
578 (*connect_cfm)(local_cid, L2CAP_CONN_TIMEOUT);
579 break;
580
581 case L2CEVT_L2CA_DISCONNECT_REQ: /* Upper wants to disconnect */
582 /* If we know peer CID from connect pending, we can send disconnect */
583 if (p_ccb->remote_cid != 0) {
584 l2cu_send_peer_disc_req(p_ccb);
585 p_ccb->chnl_state = CST_W4_L2CAP_DISCONNECT_RSP;
586 alarm_set_on_mloop(p_ccb->l2c_ccb_timer,
587 L2CAP_CHNL_DISCONNECT_TIMEOUT_MS,
588 l2c_ccb_timer_timeout, p_ccb);
589 } else {
590 tL2CA_DISCONNECT_CFM_CB* disconnect_cfm =
591 p_ccb->p_rcb->api.pL2CA_DisconnectCfm_Cb;
592 l2cu_release_ccb(p_ccb);
593 if (disconnect_cfm) {
594 L2CAP_TRACE_API("%s: L2CAP - Calling DisconnectCfm_Cb(), CID: 0x%04x",
595 __func__, local_cid);
596 (*disconnect_cfm)(local_cid, L2CAP_CONN_NO_LINK);
597 }
598 }
599 break;
600
601 case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data to send */
602 case L2CEVT_L2CAP_DATA: /* Peer data packet rcvd */
603 osi_free(p_data);
604 break;
605
606 case L2CEVT_L2CAP_INFO_RSP:
607 /* Need to have at least one compatible channel to continue */
608 if (!l2c_fcr_chk_chan_modes(p_ccb)) {
609 l2cu_release_ccb(p_ccb);
610 (*connect_cfm)(local_cid, L2CAP_CONN_NO_LINK);
611 } else {
612 /* We have feature info, so now send peer connect request */
613 alarm_set_on_mloop(p_ccb->l2c_ccb_timer, L2CAP_CHNL_CONNECT_TIMEOUT_MS,
614 l2c_ccb_timer_timeout, p_ccb);
615 l2cu_send_peer_connect_req(p_ccb); /* Start Connection */
616 }
617 break;
618 }
619 }
620
621 /*******************************************************************************
622 *
623 * Function l2c_csm_w4_l2ca_connect_rsp
624 *
625 * Description This function handles events when the channel is in
626 * CST_W4_L2CA_CONNECT_RSP state.
627 *
628 * Returns void
629 *
630 ******************************************************************************/
l2c_csm_w4_l2ca_connect_rsp(tL2C_CCB * p_ccb,uint16_t event,void * p_data)631 static void l2c_csm_w4_l2ca_connect_rsp(tL2C_CCB* p_ccb, uint16_t event,
632 void* p_data) {
633 tL2C_CONN_INFO* p_ci;
634 tL2CA_DISCONNECT_IND_CB* disconnect_ind =
635 p_ccb->p_rcb->api.pL2CA_DisconnectInd_Cb;
636 uint16_t local_cid = p_ccb->local_cid;
637
638 L2CAP_TRACE_EVENT("L2CAP - LCID: 0x%04x st: W4_L2CA_CON_RSP evt: %s",
639 p_ccb->local_cid, l2c_csm_get_event_name(event));
640
641 switch (event) {
642 case L2CEVT_LP_DISCONNECT_IND: /* Link was disconnected */
643 L2CAP_TRACE_API(
644 "L2CAP - Calling Disconnect_Ind_Cb(), CID: 0x%04x No Conf Needed",
645 p_ccb->local_cid);
646 l2cu_release_ccb(p_ccb);
647 (*disconnect_ind)(local_cid, false);
648 break;
649
650 case L2CEVT_L2CA_CONNECT_RSP:
651 p_ci = (tL2C_CONN_INFO*)p_data;
652 if (p_ccb->p_lcb->transport == BT_TRANSPORT_LE) {
653 /* Result should be OK or Reject */
654 if ((!p_ci) || (p_ci->l2cap_result == L2CAP_CONN_OK)) {
655 l2cble_credit_based_conn_res(p_ccb, L2CAP_CONN_OK);
656 p_ccb->chnl_state = CST_OPEN;
657 alarm_cancel(p_ccb->l2c_ccb_timer);
658 } else {
659 l2cble_credit_based_conn_res(p_ccb, p_ci->l2cap_result);
660 l2cu_release_ccb(p_ccb);
661 }
662 } else {
663 /* Result should be OK or PENDING */
664 if ((!p_ci) || (p_ci->l2cap_result == L2CAP_CONN_OK)) {
665 l2cu_send_peer_connect_rsp(p_ccb, L2CAP_CONN_OK, 0);
666 p_ccb->chnl_state = CST_CONFIG;
667 alarm_set_on_mloop(p_ccb->l2c_ccb_timer, L2CAP_CHNL_CFG_TIMEOUT_MS,
668 l2c_ccb_timer_timeout, p_ccb);
669 } else {
670 /* If pending, stay in same state and start extended timer */
671 l2cu_send_peer_connect_rsp(p_ccb, p_ci->l2cap_result,
672 p_ci->l2cap_status);
673 alarm_set_on_mloop(p_ccb->l2c_ccb_timer,
674 L2CAP_CHNL_CONNECT_EXT_TIMEOUT_MS,
675 l2c_ccb_timer_timeout, p_ccb);
676 }
677 }
678 break;
679
680 case L2CEVT_L2CA_CONNECT_RSP_NEG:
681 p_ci = (tL2C_CONN_INFO*)p_data;
682 if (p_ccb->p_lcb->transport == BT_TRANSPORT_LE)
683 l2cble_credit_based_conn_res(p_ccb, p_ci->l2cap_result);
684 else
685 l2cu_send_peer_connect_rsp(p_ccb, p_ci->l2cap_result,
686 p_ci->l2cap_status);
687 l2cu_release_ccb(p_ccb);
688 break;
689
690 case L2CEVT_TIMEOUT:
691 l2cu_send_peer_connect_rsp(p_ccb, L2CAP_CONN_NO_PSM, 0);
692 L2CAP_TRACE_API(
693 "L2CAP - Calling Disconnect_Ind_Cb(), CID: 0x%04x No Conf Needed",
694 p_ccb->local_cid);
695 l2cu_release_ccb(p_ccb);
696 (*disconnect_ind)(local_cid, false);
697 break;
698
699 case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data to send */
700 case L2CEVT_L2CAP_DATA: /* Peer data packet rcvd */
701 osi_free(p_data);
702 break;
703
704 case L2CEVT_L2CA_DISCONNECT_REQ: /* Upper wants to disconnect */
705 l2cu_send_peer_disc_req(p_ccb);
706 p_ccb->chnl_state = CST_W4_L2CAP_DISCONNECT_RSP;
707 alarm_set_on_mloop(p_ccb->l2c_ccb_timer, L2CAP_CHNL_DISCONNECT_TIMEOUT_MS,
708 l2c_ccb_timer_timeout, p_ccb);
709 break;
710
711 case L2CEVT_L2CAP_INFO_RSP:
712 /* We have feature info, so now give the upper layer connect IND */
713 alarm_set_on_mloop(p_ccb->l2c_ccb_timer, L2CAP_CHNL_CONNECT_TIMEOUT_MS,
714 l2c_ccb_timer_timeout, p_ccb);
715 L2CAP_TRACE_API("L2CAP - Calling Connect_Ind_Cb(), CID: 0x%04x",
716 p_ccb->local_cid);
717
718 (*p_ccb->p_rcb->api.pL2CA_ConnectInd_Cb)(
719 p_ccb->p_lcb->remote_bd_addr, p_ccb->local_cid, p_ccb->p_rcb->psm,
720 p_ccb->remote_id);
721 break;
722 }
723 }
724
725 /*******************************************************************************
726 *
727 * Function l2c_csm_config
728 *
729 * Description This function handles events when the channel is in
730 * CONFIG state.
731 *
732 * Returns void
733 *
734 ******************************************************************************/
l2c_csm_config(tL2C_CCB * p_ccb,uint16_t event,void * p_data)735 static void l2c_csm_config(tL2C_CCB* p_ccb, uint16_t event, void* p_data) {
736 tL2CAP_CFG_INFO* p_cfg = (tL2CAP_CFG_INFO*)p_data;
737 tL2CA_DISCONNECT_IND_CB* disconnect_ind =
738 p_ccb->p_rcb->api.pL2CA_DisconnectInd_Cb;
739 uint16_t local_cid = p_ccb->local_cid;
740 uint8_t cfg_result;
741
742 L2CAP_TRACE_EVENT("L2CAP - LCID: 0x%04x st: CONFIG evt: %s",
743 p_ccb->local_cid, l2c_csm_get_event_name(event));
744
745 switch (event) {
746 case L2CEVT_LP_DISCONNECT_IND: /* Link was disconnected */
747 L2CAP_TRACE_API(
748 "L2CAP - Calling Disconnect_Ind_Cb(), CID: 0x%04x No Conf Needed",
749 p_ccb->local_cid);
750 l2cu_release_ccb(p_ccb);
751 (*disconnect_ind)(local_cid, false);
752 break;
753
754 case L2CEVT_L2CAP_CONFIG_REQ: /* Peer config request */
755
756 cfg_result = l2cu_process_peer_cfg_req(p_ccb, p_cfg);
757 if (cfg_result == L2CAP_PEER_CFG_OK) {
758 L2CAP_TRACE_EVENT(
759 "L2CAP - Calling Config_Req_Cb(), CID: 0x%04x, C-bit %d",
760 p_ccb->local_cid, (p_cfg->flags & L2CAP_CFG_FLAGS_MASK_CONT));
761 (*p_ccb->p_rcb->api.pL2CA_ConfigInd_Cb)(p_ccb->local_cid, p_cfg);
762 } else if (cfg_result == L2CAP_PEER_CFG_DISCONNECT) {
763 /* Disconnect if channels are incompatible */
764 L2CAP_TRACE_EVENT("L2CAP - incompatible configurations disconnect");
765 l2cu_disconnect_chnl(p_ccb);
766 } else /* Return error to peer so he can renegotiate if possible */
767 {
768 L2CAP_TRACE_EVENT(
769 "L2CAP - incompatible configurations trying reconfig");
770 l2cu_send_peer_config_rsp(p_ccb, p_cfg);
771 }
772 break;
773
774 case L2CEVT_L2CAP_CONFIG_RSP: /* Peer config response */
775 l2cu_process_peer_cfg_rsp(p_ccb, p_cfg);
776
777 if (p_cfg->result != L2CAP_CFG_PENDING) {
778 /* TBD: When config options grow beyong minimum MTU (48 bytes)
779 * logic needs to be added to handle responses with
780 * continuation bit set in flags field.
781 * 1. Send additional config request out until C-bit is cleared in
782 * response
783 */
784 p_ccb->config_done |= OB_CFG_DONE;
785
786 if (p_ccb->config_done & IB_CFG_DONE) {
787 /* Verify two sides are in compatible modes before continuing */
788 if (p_ccb->our_cfg.fcr.mode != p_ccb->peer_cfg.fcr.mode) {
789 l2cu_send_peer_disc_req(p_ccb);
790 L2CAP_TRACE_WARNING(
791 "L2CAP - Calling Disconnect_Ind_Cb(Incompatible CFG), CID: "
792 "0x%04x No Conf Needed",
793 p_ccb->local_cid);
794 l2cu_release_ccb(p_ccb);
795 (*disconnect_ind)(local_cid, false);
796 break;
797 }
798
799 p_ccb->config_done |= RECONFIG_FLAG;
800 p_ccb->chnl_state = CST_OPEN;
801 l2c_link_adjust_chnl_allocation();
802 alarm_cancel(p_ccb->l2c_ccb_timer);
803
804 /* If using eRTM and waiting for an ACK, restart the ACK timer */
805 if (p_ccb->fcrb.wait_ack) l2c_fcr_start_timer(p_ccb);
806
807 /*
808 ** check p_ccb->our_cfg.fcr.mon_tout and
809 *p_ccb->our_cfg.fcr.rtrans_tout
810 ** we may set them to zero when sending config request during
811 *renegotiation
812 */
813 if ((p_ccb->our_cfg.fcr.mode == L2CAP_FCR_ERTM_MODE) &&
814 ((p_ccb->our_cfg.fcr.mon_tout == 0) ||
815 (p_ccb->our_cfg.fcr.rtrans_tout))) {
816 l2c_fcr_adj_monitor_retran_timeout(p_ccb);
817 }
818
819 #if (L2CAP_ERTM_STATS == TRUE)
820 p_ccb->fcrb.connect_tick_count =
821 bluetooth::common::time_get_os_boottime_ms();
822 #endif
823 /* See if we can forward anything on the hold queue */
824 if (!fixed_queue_is_empty(p_ccb->xmit_hold_q)) {
825 l2c_link_check_send_pkts(p_ccb->p_lcb, NULL, NULL);
826 }
827 }
828 }
829
830 L2CAP_TRACE_API("L2CAP - Calling Config_Rsp_Cb(), CID: 0x%04x",
831 p_ccb->local_cid);
832 (*p_ccb->p_rcb->api.pL2CA_ConfigCfm_Cb)(p_ccb->local_cid, p_cfg);
833 break;
834
835 case L2CEVT_L2CAP_CONFIG_RSP_NEG: /* Peer config error rsp */
836 /* Disable the Timer */
837 alarm_cancel(p_ccb->l2c_ccb_timer);
838
839 /* If failure was channel mode try to renegotiate */
840 if (!l2c_fcr_renegotiate_chan(p_ccb, p_cfg)) {
841 L2CAP_TRACE_API(
842 "L2CAP - Calling Config_Rsp_Cb(), CID: 0x%04x, Failure: %d",
843 p_ccb->local_cid, p_cfg->result);
844 (*p_ccb->p_rcb->api.pL2CA_ConfigCfm_Cb)(p_ccb->local_cid, p_cfg);
845 }
846 break;
847
848 case L2CEVT_L2CAP_DISCONNECT_REQ: /* Peer disconnected request */
849 alarm_set_on_mloop(p_ccb->l2c_ccb_timer, L2CAP_CHNL_DISCONNECT_TIMEOUT_MS,
850 l2c_ccb_timer_timeout, p_ccb);
851 p_ccb->chnl_state = CST_W4_L2CA_DISCONNECT_RSP;
852 L2CAP_TRACE_API(
853 "L2CAP - Calling Disconnect_Ind_Cb(), CID: 0x%04x Conf Needed",
854 p_ccb->local_cid);
855 (*p_ccb->p_rcb->api.pL2CA_DisconnectInd_Cb)(p_ccb->local_cid, true);
856 break;
857
858 case L2CEVT_L2CA_CONFIG_REQ: /* Upper layer config req */
859 l2cu_process_our_cfg_req(p_ccb, p_cfg);
860 l2cu_send_peer_config_req(p_ccb, p_cfg);
861 alarm_set_on_mloop(p_ccb->l2c_ccb_timer, L2CAP_CHNL_CFG_TIMEOUT_MS,
862 l2c_ccb_timer_timeout, p_ccb);
863 break;
864
865 case L2CEVT_L2CA_CONFIG_RSP: /* Upper layer config rsp */
866 l2cu_process_our_cfg_rsp(p_ccb, p_cfg);
867
868 /* Not finished if continuation flag is set */
869 if ((p_cfg->flags & L2CAP_CFG_FLAGS_MASK_CONT) ||
870 (p_cfg->result == L2CAP_CFG_PENDING)) {
871 /* Send intermediate response; remain in cfg state */
872 l2cu_send_peer_config_rsp(p_ccb, p_cfg);
873 break;
874 }
875
876 /* Local config done; clear cached configuration in case reconfig takes
877 * place later */
878 p_ccb->peer_cfg.mtu_present = false;
879 p_ccb->peer_cfg.flush_to_present = false;
880 p_ccb->peer_cfg.qos_present = false;
881
882 p_ccb->config_done |= IB_CFG_DONE;
883
884 if (p_ccb->config_done & OB_CFG_DONE) {
885 /* Verify two sides are in compatible modes before continuing */
886 if (p_ccb->our_cfg.fcr.mode != p_ccb->peer_cfg.fcr.mode) {
887 l2cu_send_peer_disc_req(p_ccb);
888 L2CAP_TRACE_WARNING(
889 "L2CAP - Calling Disconnect_Ind_Cb(Incompatible CFG), CID: "
890 "0x%04x No Conf Needed",
891 p_ccb->local_cid);
892 l2cu_release_ccb(p_ccb);
893 (*disconnect_ind)(local_cid, false);
894 break;
895 }
896
897 p_ccb->config_done |= RECONFIG_FLAG;
898 p_ccb->chnl_state = CST_OPEN;
899 l2c_link_adjust_chnl_allocation();
900 alarm_cancel(p_ccb->l2c_ccb_timer);
901 }
902
903 l2cu_send_peer_config_rsp(p_ccb, p_cfg);
904
905 /* If using eRTM and waiting for an ACK, restart the ACK timer */
906 if (p_ccb->fcrb.wait_ack) l2c_fcr_start_timer(p_ccb);
907
908 #if (L2CAP_ERTM_STATS == TRUE)
909 p_ccb->fcrb.connect_tick_count =
910 bluetooth::common::time_get_os_boottime_ms();
911 #endif
912
913 /* See if we can forward anything on the hold queue */
914 if ((p_ccb->chnl_state == CST_OPEN) &&
915 (!fixed_queue_is_empty(p_ccb->xmit_hold_q))) {
916 l2c_link_check_send_pkts(p_ccb->p_lcb, NULL, NULL);
917 }
918 break;
919
920 case L2CEVT_L2CA_CONFIG_RSP_NEG: /* Upper layer config reject */
921 l2cu_send_peer_config_rsp(p_ccb, p_cfg);
922 alarm_set_on_mloop(p_ccb->l2c_ccb_timer, L2CAP_CHNL_CFG_TIMEOUT_MS,
923 l2c_ccb_timer_timeout, p_ccb);
924 break;
925
926 case L2CEVT_L2CA_DISCONNECT_REQ: /* Upper wants to disconnect */
927 l2cu_send_peer_disc_req(p_ccb);
928 p_ccb->chnl_state = CST_W4_L2CAP_DISCONNECT_RSP;
929 alarm_set_on_mloop(p_ccb->l2c_ccb_timer, L2CAP_CHNL_DISCONNECT_TIMEOUT_MS,
930 l2c_ccb_timer_timeout, p_ccb);
931 break;
932
933 case L2CEVT_L2CAP_DATA: /* Peer data packet rcvd */
934 L2CAP_TRACE_API("L2CAP - Calling DataInd_Cb(), CID: 0x%04x",
935 p_ccb->local_cid);
936 #if (L2CAP_NUM_FIXED_CHNLS > 0)
937 if (p_ccb->local_cid >= L2CAP_FIRST_FIXED_CHNL &&
938 p_ccb->local_cid <= L2CAP_LAST_FIXED_CHNL) {
939 if (p_ccb->local_cid < L2CAP_BASE_APPL_CID) {
940 if (l2cb.fixed_reg[p_ccb->local_cid - L2CAP_FIRST_FIXED_CHNL]
941 .pL2CA_FixedData_Cb)
942 (*l2cb.fixed_reg[p_ccb->local_cid - L2CAP_FIRST_FIXED_CHNL]
943 .pL2CA_FixedData_Cb)(p_ccb->local_cid,
944 p_ccb->p_lcb->remote_bd_addr,
945 (BT_HDR*)p_data);
946 else
947 osi_free(p_data);
948 break;
949 }
950 }
951 #endif
952 (*p_ccb->p_rcb->api.pL2CA_DataInd_Cb)(p_ccb->local_cid, (BT_HDR*)p_data);
953 break;
954
955 case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data to send */
956 if (p_ccb->config_done & OB_CFG_DONE)
957 l2c_enqueue_peer_data(p_ccb, (BT_HDR*)p_data);
958 else
959 osi_free(p_data);
960 break;
961
962 case L2CEVT_TIMEOUT:
963 l2cu_send_peer_disc_req(p_ccb);
964 L2CAP_TRACE_API(
965 "L2CAP - Calling Disconnect_Ind_Cb(), CID: 0x%04x No Conf Needed",
966 p_ccb->local_cid);
967 l2cu_release_ccb(p_ccb);
968 (*disconnect_ind)(local_cid, false);
969 break;
970 }
971 }
972
973 /*******************************************************************************
974 *
975 * Function l2c_csm_open
976 *
977 * Description This function handles events when the channel is in
978 * OPEN state.
979 *
980 * Returns void
981 *
982 ******************************************************************************/
l2c_csm_open(tL2C_CCB * p_ccb,uint16_t event,void * p_data)983 static void l2c_csm_open(tL2C_CCB* p_ccb, uint16_t event, void* p_data) {
984 uint16_t local_cid = p_ccb->local_cid;
985 tL2CAP_CFG_INFO* p_cfg;
986 tL2C_CHNL_STATE tempstate;
987 uint8_t tempcfgdone;
988 uint8_t cfg_result;
989 uint16_t* credit;
990
991 L2CAP_TRACE_EVENT("L2CAP - LCID: 0x%04x st: OPEN evt: %s", p_ccb->local_cid,
992 l2c_csm_get_event_name(event));
993
994 switch (event) {
995 case L2CEVT_LP_DISCONNECT_IND: /* Link was disconnected */
996 L2CAP_TRACE_API(
997 "L2CAP - Calling Disconnect_Ind_Cb(), CID: 0x%04x No Conf Needed",
998 p_ccb->local_cid);
999 l2cu_release_ccb(p_ccb);
1000 if (p_ccb->p_rcb)
1001 (*p_ccb->p_rcb->api.pL2CA_DisconnectInd_Cb)(local_cid, false);
1002 break;
1003
1004 case L2CEVT_LP_QOS_VIOLATION_IND: /* QOS violation */
1005 /* Tell upper layer. If service guaranteed, then clear the channel */
1006 if (p_ccb->p_rcb->api.pL2CA_QoSViolationInd_Cb)
1007 (*p_ccb->p_rcb->api.pL2CA_QoSViolationInd_Cb)(
1008 p_ccb->p_lcb->remote_bd_addr);
1009 break;
1010
1011 case L2CEVT_L2CAP_CONFIG_REQ: /* Peer config request */
1012 p_cfg = (tL2CAP_CFG_INFO*)p_data;
1013
1014 tempstate = p_ccb->chnl_state;
1015 tempcfgdone = p_ccb->config_done;
1016 p_ccb->chnl_state = CST_CONFIG;
1017 p_ccb->config_done &= ~IB_CFG_DONE;
1018
1019 alarm_set_on_mloop(p_ccb->l2c_ccb_timer, L2CAP_CHNL_CFG_TIMEOUT_MS,
1020 l2c_ccb_timer_timeout, p_ccb);
1021
1022 cfg_result = l2cu_process_peer_cfg_req(p_ccb, p_cfg);
1023 if (cfg_result == L2CAP_PEER_CFG_OK) {
1024 (*p_ccb->p_rcb->api.pL2CA_ConfigInd_Cb)(p_ccb->local_cid, p_cfg);
1025 }
1026
1027 /* Error in config parameters: reset state and config flag */
1028 else if (cfg_result == L2CAP_PEER_CFG_UNACCEPTABLE) {
1029 alarm_cancel(p_ccb->l2c_ccb_timer);
1030 p_ccb->chnl_state = tempstate;
1031 p_ccb->config_done = tempcfgdone;
1032 l2cu_send_peer_config_rsp(p_ccb, p_cfg);
1033 } else /* L2CAP_PEER_CFG_DISCONNECT */
1034 {
1035 /* Disconnect if channels are incompatible
1036 * Note this should not occur if reconfigure
1037 * since this should have never passed original config.
1038 */
1039 l2cu_disconnect_chnl(p_ccb);
1040 }
1041 break;
1042
1043 case L2CEVT_L2CAP_DISCONNECT_REQ: /* Peer disconnected request */
1044 if (p_ccb->p_lcb->transport != BT_TRANSPORT_LE) {
1045 /* Make sure we are not in sniff mode */
1046 {
1047 tBTM_PM_PWR_MD settings;
1048 memset((void*)&settings, 0, sizeof(settings));
1049 settings.mode = BTM_PM_MD_ACTIVE;
1050 BTM_SetPowerMode(BTM_PM_SET_ONLY_ID, p_ccb->p_lcb->remote_bd_addr,
1051 &settings);
1052 }
1053 }
1054
1055 p_ccb->chnl_state = CST_W4_L2CA_DISCONNECT_RSP;
1056 alarm_set_on_mloop(p_ccb->l2c_ccb_timer, L2CAP_CHNL_DISCONNECT_TIMEOUT_MS,
1057 l2c_ccb_timer_timeout, p_ccb);
1058 L2CAP_TRACE_API(
1059 "L2CAP - Calling Disconnect_Ind_Cb(), CID: 0x%04x Conf Needed",
1060 p_ccb->local_cid);
1061 (*p_ccb->p_rcb->api.pL2CA_DisconnectInd_Cb)(p_ccb->local_cid, true);
1062 break;
1063
1064 case L2CEVT_L2CAP_DATA: /* Peer data packet rcvd */
1065 if ((p_ccb->p_rcb) && (p_ccb->p_rcb->api.pL2CA_DataInd_Cb))
1066 (*p_ccb->p_rcb->api.pL2CA_DataInd_Cb)(p_ccb->local_cid,
1067 (BT_HDR*)p_data);
1068 break;
1069
1070 case L2CEVT_L2CA_DISCONNECT_REQ: /* Upper wants to disconnect */
1071 if (p_ccb->p_lcb->transport != BT_TRANSPORT_LE) {
1072 /* Make sure we are not in sniff mode */
1073 {
1074 tBTM_PM_PWR_MD settings;
1075 memset((void*)&settings, 0, sizeof(settings));
1076 settings.mode = BTM_PM_MD_ACTIVE;
1077 BTM_SetPowerMode(BTM_PM_SET_ONLY_ID, p_ccb->p_lcb->remote_bd_addr,
1078 &settings);
1079 }
1080 }
1081
1082 if (p_ccb->p_lcb->transport == BT_TRANSPORT_LE)
1083 l2cble_send_peer_disc_req(p_ccb);
1084 else
1085 l2cu_send_peer_disc_req(p_ccb);
1086
1087 p_ccb->chnl_state = CST_W4_L2CAP_DISCONNECT_RSP;
1088 alarm_set_on_mloop(p_ccb->l2c_ccb_timer, L2CAP_CHNL_DISCONNECT_TIMEOUT_MS,
1089 l2c_ccb_timer_timeout, p_ccb);
1090 break;
1091
1092 case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data to send */
1093 l2c_enqueue_peer_data(p_ccb, (BT_HDR*)p_data);
1094 l2c_link_check_send_pkts(p_ccb->p_lcb, NULL, NULL);
1095 break;
1096
1097 case L2CEVT_L2CA_CONFIG_REQ: /* Upper layer config req */
1098 p_ccb->chnl_state = CST_CONFIG;
1099 p_ccb->config_done &= ~CFG_DONE_MASK;
1100 l2cu_process_our_cfg_req(p_ccb, (tL2CAP_CFG_INFO*)p_data);
1101 l2cu_send_peer_config_req(p_ccb, (tL2CAP_CFG_INFO*)p_data);
1102 alarm_set_on_mloop(p_ccb->l2c_ccb_timer, L2CAP_CHNL_CFG_TIMEOUT_MS,
1103 l2c_ccb_timer_timeout, p_ccb);
1104 break;
1105
1106 case L2CEVT_TIMEOUT:
1107 /* Process the monitor/retransmission time-outs in flow control/retrans
1108 * mode */
1109 if (p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_ERTM_MODE)
1110 l2c_fcr_proc_tout(p_ccb);
1111 break;
1112
1113 case L2CEVT_ACK_TIMEOUT:
1114 l2c_fcr_proc_ack_tout(p_ccb);
1115 break;
1116
1117 case L2CEVT_L2CA_SEND_FLOW_CONTROL_CREDIT:
1118 L2CAP_TRACE_DEBUG("%s Sending credit", __func__);
1119 credit = (uint16_t*)p_data;
1120 l2cble_send_flow_control_credit(p_ccb, *credit);
1121 break;
1122
1123 case L2CEVT_L2CAP_RECV_FLOW_CONTROL_CREDIT:
1124 credit = (uint16_t*)p_data;
1125 L2CAP_TRACE_DEBUG("%s Credits received %d", __func__, *credit);
1126 if ((p_ccb->peer_conn_cfg.credits + *credit) > L2CAP_LE_CREDIT_MAX) {
1127 /* we have received credits more than max coc credits,
1128 * so disconnecting the Le Coc Channel
1129 */
1130 l2cble_send_peer_disc_req(p_ccb);
1131 } else {
1132 p_ccb->peer_conn_cfg.credits += *credit;
1133
1134 tL2CA_CREDITS_RECEIVED_CB* cr_cb =
1135 p_ccb->p_rcb->api.pL2CA_CreditsReceived_Cb;
1136 if (p_ccb->p_lcb->transport == BT_TRANSPORT_LE && (cr_cb)) {
1137 (*cr_cb)(p_ccb->local_cid, *credit, p_ccb->peer_conn_cfg.credits);
1138 }
1139 l2c_link_check_send_pkts(p_ccb->p_lcb, NULL, NULL);
1140 }
1141 break;
1142 }
1143 }
1144
1145 /*******************************************************************************
1146 *
1147 * Function l2c_csm_w4_l2cap_disconnect_rsp
1148 *
1149 * Description This function handles events when the channel is in
1150 * CST_W4_L2CAP_DISCONNECT_RSP state.
1151 *
1152 * Returns void
1153 *
1154 ******************************************************************************/
l2c_csm_w4_l2cap_disconnect_rsp(tL2C_CCB * p_ccb,uint16_t event,void * p_data)1155 static void l2c_csm_w4_l2cap_disconnect_rsp(tL2C_CCB* p_ccb, uint16_t event,
1156 void* p_data) {
1157 tL2CA_DISCONNECT_CFM_CB* disconnect_cfm =
1158 p_ccb->p_rcb->api.pL2CA_DisconnectCfm_Cb;
1159 uint16_t local_cid = p_ccb->local_cid;
1160
1161 L2CAP_TRACE_EVENT("L2CAP - LCID: 0x%04x st: W4_L2CAP_DISC_RSP evt: %s",
1162 p_ccb->local_cid, l2c_csm_get_event_name(event));
1163
1164 switch (event) {
1165 case L2CEVT_L2CAP_DISCONNECT_RSP: /* Peer disconnect response */
1166 l2cu_release_ccb(p_ccb);
1167 if (disconnect_cfm) {
1168 L2CAP_TRACE_API("L2CAP - Calling DisconnectCfm_Cb(), CID: 0x%04x",
1169 local_cid);
1170 (*disconnect_cfm)(local_cid, L2CAP_DISC_OK);
1171 }
1172 break;
1173
1174 case L2CEVT_L2CAP_DISCONNECT_REQ: /* Peer disconnect request */
1175 l2cu_send_peer_disc_rsp(p_ccb->p_lcb, p_ccb->remote_id, p_ccb->local_cid,
1176 p_ccb->remote_cid);
1177 l2cu_release_ccb(p_ccb);
1178 if (disconnect_cfm) {
1179 L2CAP_TRACE_API("L2CAP - Calling DisconnectCfm_Cb(), CID: 0x%04x",
1180 local_cid);
1181 (*disconnect_cfm)(local_cid, L2CAP_DISC_OK);
1182 }
1183 break;
1184
1185 case L2CEVT_LP_DISCONNECT_IND: /* Link was disconnected */
1186 case L2CEVT_TIMEOUT: /* Timeout */
1187 l2cu_release_ccb(p_ccb);
1188 if (disconnect_cfm) {
1189 L2CAP_TRACE_API("L2CAP - Calling DisconnectCfm_Cb(), CID: 0x%04x",
1190 local_cid);
1191 (*disconnect_cfm)(local_cid, L2CAP_DISC_TIMEOUT);
1192 }
1193 break;
1194
1195 case L2CEVT_L2CAP_DATA: /* Peer data packet rcvd */
1196 case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data to send */
1197 osi_free(p_data);
1198 break;
1199 }
1200 }
1201
1202 /*******************************************************************************
1203 *
1204 * Function l2c_csm_w4_l2ca_disconnect_rsp
1205 *
1206 * Description This function handles events when the channel is in
1207 * CST_W4_L2CA_DISCONNECT_RSP state.
1208 *
1209 * Returns void
1210 *
1211 ******************************************************************************/
l2c_csm_w4_l2ca_disconnect_rsp(tL2C_CCB * p_ccb,uint16_t event,void * p_data)1212 static void l2c_csm_w4_l2ca_disconnect_rsp(tL2C_CCB* p_ccb, uint16_t event,
1213 void* p_data) {
1214 tL2CA_DISCONNECT_IND_CB* disconnect_ind =
1215 p_ccb->p_rcb->api.pL2CA_DisconnectInd_Cb;
1216 uint16_t local_cid = p_ccb->local_cid;
1217
1218 L2CAP_TRACE_EVENT("L2CAP - LCID: 0x%04x st: W4_L2CA_DISC_RSP evt: %s",
1219 p_ccb->local_cid, l2c_csm_get_event_name(event));
1220
1221 switch (event) {
1222 case L2CEVT_LP_DISCONNECT_IND: /* Link was disconnected */
1223 L2CAP_TRACE_API(
1224 "L2CAP - Calling Disconnect_Ind_Cb(), CID: 0x%04x No Conf Needed",
1225 p_ccb->local_cid);
1226 l2cu_release_ccb(p_ccb);
1227 (*disconnect_ind)(local_cid, false);
1228 break;
1229
1230 case L2CEVT_TIMEOUT:
1231 l2cu_send_peer_disc_rsp(p_ccb->p_lcb, p_ccb->remote_id, p_ccb->local_cid,
1232 p_ccb->remote_cid);
1233 L2CAP_TRACE_API(
1234 "L2CAP - Calling Disconnect_Ind_Cb(), CID: 0x%04x No Conf Needed",
1235 p_ccb->local_cid);
1236 l2cu_release_ccb(p_ccb);
1237 (*disconnect_ind)(local_cid, false);
1238 break;
1239
1240 case L2CEVT_L2CA_DISCONNECT_REQ: /* Upper disconnect request */
1241 case L2CEVT_L2CA_DISCONNECT_RSP: /* Upper disconnect response */
1242 l2cu_send_peer_disc_rsp(p_ccb->p_lcb, p_ccb->remote_id, p_ccb->local_cid,
1243 p_ccb->remote_cid);
1244 l2cu_release_ccb(p_ccb);
1245 break;
1246
1247 case L2CEVT_L2CAP_DATA: /* Peer data packet rcvd */
1248 case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data to send */
1249 osi_free(p_data);
1250 break;
1251 }
1252 }
1253
1254 /*******************************************************************************
1255 *
1256 * Function l2c_csm_get_event_name
1257 *
1258 * Description This function returns the event name.
1259 *
1260 * NOTE conditionally compiled to save memory.
1261 *
1262 * Returns pointer to the name
1263 *
1264 ******************************************************************************/
l2c_csm_get_event_name(uint16_t event)1265 static const char* l2c_csm_get_event_name(uint16_t event) {
1266 switch (event) {
1267 case L2CEVT_LP_CONNECT_CFM: /* Lower layer connect confirm */
1268 return ("LOWER_LAYER_CONNECT_CFM");
1269 case L2CEVT_LP_CONNECT_CFM_NEG: /* Lower layer connect confirm (failed) */
1270 return ("LOWER_LAYER_CONNECT_CFM_NEG");
1271 case L2CEVT_LP_CONNECT_IND: /* Lower layer connect indication */
1272 return ("LOWER_LAYER_CONNECT_IND");
1273 case L2CEVT_LP_DISCONNECT_IND: /* Lower layer disconnect indication */
1274 return ("LOWER_LAYER_DISCONNECT_IND");
1275 case L2CEVT_LP_QOS_CFM: /* Lower layer QOS confirmation */
1276 return ("LOWER_LAYER_QOS_CFM");
1277 case L2CEVT_LP_QOS_CFM_NEG: /* Lower layer QOS confirmation (failed)*/
1278 return ("LOWER_LAYER_QOS_CFM_NEG");
1279 case L2CEVT_LP_QOS_VIOLATION_IND: /* Lower layer QOS violation indication */
1280 return ("LOWER_LAYER_QOS_VIOLATION_IND");
1281
1282 case L2CEVT_SEC_COMP: /* Security cleared successfully */
1283 return ("SECURITY_COMPLETE");
1284 case L2CEVT_SEC_COMP_NEG: /* Security procedure failed */
1285 return ("SECURITY_COMPLETE_NEG");
1286
1287 case L2CEVT_L2CAP_CONNECT_REQ: /* Peer connection request */
1288 return ("PEER_CONNECT_REQ");
1289 case L2CEVT_L2CAP_CONNECT_RSP: /* Peer connection response */
1290 return ("PEER_CONNECT_RSP");
1291 case L2CEVT_L2CAP_CONNECT_RSP_PND: /* Peer connection response pending */
1292 return ("PEER_CONNECT_RSP_PND");
1293 case L2CEVT_L2CAP_CONNECT_RSP_NEG: /* Peer connection response (failed) */
1294 return ("PEER_CONNECT_RSP_NEG");
1295 case L2CEVT_L2CAP_CONFIG_REQ: /* Peer configuration request */
1296 return ("PEER_CONFIG_REQ");
1297 case L2CEVT_L2CAP_CONFIG_RSP: /* Peer configuration response */
1298 return ("PEER_CONFIG_RSP");
1299 case L2CEVT_L2CAP_CONFIG_RSP_NEG: /* Peer configuration response (failed) */
1300 return ("PEER_CONFIG_RSP_NEG");
1301 case L2CEVT_L2CAP_DISCONNECT_REQ: /* Peer disconnect request */
1302 return ("PEER_DISCONNECT_REQ");
1303 case L2CEVT_L2CAP_DISCONNECT_RSP: /* Peer disconnect response */
1304 return ("PEER_DISCONNECT_RSP");
1305 case L2CEVT_L2CAP_DATA: /* Peer data */
1306 return ("PEER_DATA");
1307
1308 case L2CEVT_L2CA_CONNECT_REQ: /* Upper layer connect request */
1309 return ("UPPER_LAYER_CONNECT_REQ");
1310 case L2CEVT_L2CA_CONNECT_RSP: /* Upper layer connect response */
1311 return ("UPPER_LAYER_CONNECT_RSP");
1312 case L2CEVT_L2CA_CONNECT_RSP_NEG: /* Upper layer connect response (failed)*/
1313 return ("UPPER_LAYER_CONNECT_RSP_NEG");
1314 case L2CEVT_L2CA_CONFIG_REQ: /* Upper layer config request */
1315 return ("UPPER_LAYER_CONFIG_REQ");
1316 case L2CEVT_L2CA_CONFIG_RSP: /* Upper layer config response */
1317 return ("UPPER_LAYER_CONFIG_RSP");
1318 case L2CEVT_L2CA_CONFIG_RSP_NEG: /* Upper layer config response (failed) */
1319 return ("UPPER_LAYER_CONFIG_RSP_NEG");
1320 case L2CEVT_L2CA_DISCONNECT_REQ: /* Upper layer disconnect request */
1321 return ("UPPER_LAYER_DISCONNECT_REQ");
1322 case L2CEVT_L2CA_DISCONNECT_RSP: /* Upper layer disconnect response */
1323 return ("UPPER_LAYER_DISCONNECT_RSP");
1324 case L2CEVT_L2CA_DATA_READ: /* Upper layer data read */
1325 return ("UPPER_LAYER_DATA_READ");
1326 case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data write */
1327 return ("UPPER_LAYER_DATA_WRITE");
1328 case L2CEVT_TIMEOUT: /* Timeout */
1329 return ("TIMEOUT");
1330 case L2CEVT_SEC_RE_SEND_CMD:
1331 return ("SEC_RE_SEND_CMD");
1332 case L2CEVT_L2CAP_INFO_RSP: /* Peer information response */
1333 return ("L2CEVT_L2CAP_INFO_RSP");
1334 case L2CEVT_ACK_TIMEOUT:
1335 return ("L2CEVT_ACK_TIMEOUT");
1336 case L2CEVT_L2CA_SEND_FLOW_CONTROL_CREDIT: /* Upper layer send credit packet
1337 */
1338 return ("SEND_FLOW_CONTROL_CREDIT");
1339 case L2CEVT_L2CAP_RECV_FLOW_CONTROL_CREDIT: /* Peer send credit packet */
1340 return ("RECV_FLOW_CONTROL_CREDIT");
1341
1342 default:
1343 return ("???? UNKNOWN EVENT");
1344 }
1345 }
1346
1347 /*******************************************************************************
1348 *
1349 * Function l2c_enqueue_peer_data
1350 *
1351 * Description Enqueues data destined for the peer in the ccb. Handles
1352 * FCR segmentation and checks for congestion.
1353 *
1354 * Returns void
1355 *
1356 ******************************************************************************/
l2c_enqueue_peer_data(tL2C_CCB * p_ccb,BT_HDR * p_buf)1357 void l2c_enqueue_peer_data(tL2C_CCB* p_ccb, BT_HDR* p_buf) {
1358 uint8_t* p;
1359
1360 if (p_ccb->peer_cfg.fcr.mode != L2CAP_FCR_BASIC_MODE) {
1361 p_buf->event = 0;
1362 } else {
1363 /* Save the channel ID for faster counting */
1364 p_buf->event = p_ccb->local_cid;
1365
1366 /* Step back to add the L2CAP header */
1367 p_buf->offset -= L2CAP_PKT_OVERHEAD;
1368 p_buf->len += L2CAP_PKT_OVERHEAD;
1369
1370 /* Set the pointer to the beginning of the data */
1371 p = (uint8_t*)(p_buf + 1) + p_buf->offset;
1372
1373 /* Now the L2CAP header */
1374 UINT16_TO_STREAM(p, p_buf->len - L2CAP_PKT_OVERHEAD);
1375 UINT16_TO_STREAM(p, p_ccb->remote_cid);
1376 }
1377
1378 if (p_ccb->xmit_hold_q == NULL) {
1379 L2CAP_TRACE_ERROR(
1380 "%s: empty queue: p_ccb = %p p_ccb->in_use = %d p_ccb->chnl_state = %d "
1381 "p_ccb->local_cid = %u p_ccb->remote_cid = %u",
1382 __func__, p_ccb, p_ccb->in_use, p_ccb->chnl_state, p_ccb->local_cid,
1383 p_ccb->remote_cid);
1384 }
1385 fixed_queue_enqueue(p_ccb->xmit_hold_q, p_buf);
1386
1387 l2cu_check_channel_congestion(p_ccb);
1388
1389 #if (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE)
1390 /* if new packet is higher priority than serving ccb and it is not overrun */
1391 if ((p_ccb->p_lcb->rr_pri > p_ccb->ccb_priority) &&
1392 (p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].quota > 0)) {
1393 /* send out higher priority packet */
1394 p_ccb->p_lcb->rr_pri = p_ccb->ccb_priority;
1395 }
1396 #endif
1397
1398 /* if we are doing a round robin scheduling, set the flag */
1399 if (p_ccb->p_lcb->link_xmit_quota == 0) l2cb.check_round_robin = true;
1400 }
1401