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