/******************************************************************************* ** ** Function l2cble_advertiser_conn_comp ** ** Description This function is called when an HCI Connection Complete ** event is received while we are an advertiser (so we are slave). ** ** Returns void ** *******************************************************************************/ void l2cble_advertiser_conn_comp (UINT16 handle, BD_ADDR bda, tBLE_ADDR_TYPE type, UINT16 conn_interval, UINT16 conn_latency, UINT16 conn_timeout) { tL2C_LCB *p_lcb; tBTM_SEC_DEV_REC *p_dev_rec; /* See if we have a link control block for the remote device */ p_lcb = l2cu_find_lcb_by_bd_addr (bda); /* If we don't have one, create one and accept the connection. */ if (!p_lcb) { p_lcb = l2cu_allocate_lcb (bda, FALSE); if (!p_lcb) { btm_sec_disconnect (handle, HCI_ERR_NO_CONNECTION); L2CAP_TRACE_ERROR0 ("l2cble_advertiser_conn_comp - failed to allocate LCB"); return; } else { if (!l2cu_initialize_fixed_ccb (p_lcb, L2CAP_ATT_CID, &l2cb.fixed_reg[L2CAP_ATT_CID - L2CAP_FIRST_FIXED_CHNL].fixed_chnl_opts)) { btm_sec_disconnect (handle, HCI_ERR_NO_CONNECTION); L2CAP_TRACE_WARNING0 ("l2cble_scanner_conn_comp - LCB but no CCB"); return ; } } } /* Save the handle */ p_lcb->handle = handle; /* Connected OK. Change state to connected, we were advertising, so we are slave */ p_lcb->link_state = LST_CONNECTED; p_lcb->link_role = HCI_ROLE_SLAVE; p_lcb->is_ble_link = TRUE; /* Tell BTM Acl management about the link */ p_dev_rec = btm_find_or_alloc_dev (bda); btm_acl_created (bda, NULL, p_dev_rec->sec_bd_name, handle, p_lcb->link_role, TRUE); p_lcb->peer_chnl_mask[0] = L2CAP_FIXED_CHNL_ATT_BIT | L2CAP_FIXED_CHNL_BLE_SIG_BIT | L2CAP_FIXED_CHNL_SMP_BIT; l2cu_process_fixed_chnl_resp (p_lcb); }
/******************************************************************************* ** ** Function l2cble_scanner_conn_comp ** ** Description This function is called when an HCI Connection Complete ** event is received while we are a scanner (so we are master). ** ** Returns void ** *******************************************************************************/ void l2cble_scanner_conn_comp (UINT16 handle, BD_ADDR bda, tBLE_ADDR_TYPE type, UINT16 conn_interval, UINT16 conn_latency, UINT16 conn_timeout) { tL2C_LCB *p_lcb; tBTM_SEC_DEV_REC *p_dev_rec = btm_find_or_alloc_dev (bda); L2CAP_TRACE_DEBUG5 ("l2cble_scanner_conn_comp: HANDLE=%d addr_type=%d conn_interval=%d slave_latency=%d supervision_tout=%d", handle, type, conn_interval, conn_latency, conn_timeout); l2cb.is_ble_connecting = FALSE; /* See if we have a link control block for the remote device */ p_lcb = l2cu_find_lcb_by_bd_addr (bda); /* If we don't have one, create one. this is auto connection complete. */ if (!p_lcb) { p_lcb = l2cu_allocate_lcb (bda, FALSE); if (!p_lcb) { btm_sec_disconnect (handle, HCI_ERR_NO_CONNECTION); L2CAP_TRACE_ERROR0 ("l2cble_scanner_conn_comp - failed to allocate LCB"); return; } else { if (!l2cu_initialize_fixed_ccb (p_lcb, L2CAP_ATT_CID, &l2cb.fixed_reg[L2CAP_ATT_CID - L2CAP_FIRST_FIXED_CHNL].fixed_chnl_opts)) { btm_sec_disconnect (handle, HCI_ERR_NO_CONNECTION); L2CAP_TRACE_WARNING0 ("l2cble_scanner_conn_comp - LCB but no CCB"); return ; } } } else if (p_lcb->link_state != LST_CONNECTING) { L2CAP_TRACE_ERROR1 ("L2CAP got BLE scanner conn_comp in bad state: %d", p_lcb->link_state); return; } btu_stop_timer(&p_lcb->timer_entry); /* Save the handle */ p_lcb->handle = handle; /* Connected OK. Change state to connected, we were scanning so we are master */ p_lcb->link_state = LST_CONNECTED; p_lcb->link_role = HCI_ROLE_MASTER; p_lcb->is_ble_link = TRUE; /* If there are any preferred connection parameters, set them now */ if ( (p_dev_rec->conn_params.min_conn_int >= BTM_BLE_CONN_INT_MIN ) && (p_dev_rec->conn_params.min_conn_int <= BTM_BLE_CONN_INT_MAX ) && (p_dev_rec->conn_params.max_conn_int >= BTM_BLE_CONN_INT_MIN ) && (p_dev_rec->conn_params.max_conn_int <= BTM_BLE_CONN_INT_MAX ) && (p_dev_rec->conn_params.slave_latency <= BTM_BLE_CONN_LATENCY_MAX ) && (p_dev_rec->conn_params.supervision_tout >= BTM_BLE_CONN_SUP_TOUT_MIN) && (p_dev_rec->conn_params.supervision_tout <= BTM_BLE_CONN_SUP_TOUT_MAX) && ((conn_interval < p_dev_rec->conn_params.min_conn_int && p_dev_rec->conn_params.min_conn_int != BTM_BLE_CONN_PARAM_UNDEF) || (conn_interval > p_dev_rec->conn_params.max_conn_int) || (conn_latency > p_dev_rec->conn_params.slave_latency) || (conn_timeout > p_dev_rec->conn_params.supervision_tout))) { L2CAP_TRACE_ERROR5 ("upd_ll_conn_params: HANDLE=%d min_conn_int=%d max_conn_int=%d slave_latency=%d supervision_tout=%d", handle, p_dev_rec->conn_params.min_conn_int, p_dev_rec->conn_params.max_conn_int, p_dev_rec->conn_params.slave_latency, p_dev_rec->conn_params.supervision_tout); btsnd_hcic_ble_upd_ll_conn_params (handle, p_dev_rec->conn_params.min_conn_int, p_dev_rec->conn_params.max_conn_int, p_dev_rec->conn_params.slave_latency, p_dev_rec->conn_params.supervision_tout, 0, 0); } /* Tell BTM Acl management about the link */ btm_acl_created (bda, NULL, p_dev_rec->sec_bd_name, handle, p_lcb->link_role, TRUE); if (p_lcb->p_echo_rsp_cb) { L2CAP_TRACE_ERROR0 ("l2cu_send_peer_echo_req"); l2cu_send_peer_echo_req (p_lcb, NULL, 0); } p_lcb->peer_chnl_mask[0] = L2CAP_FIXED_CHNL_ATT_BIT | L2CAP_FIXED_CHNL_BLE_SIG_BIT | L2CAP_FIXED_CHNL_SMP_BIT; l2cu_process_fixed_chnl_resp (p_lcb); }
/******************************************************************************* ** ** Function l2c_rcv_acl_data ** ** Description This function is called from the HCI Interface when an ACL ** data packet is received. ** ** Returns void ** *******************************************************************************/ void l2c_rcv_acl_data (BT_HDR *p_msg) { UINT8 *p = (UINT8 *)(p_msg + 1) + p_msg->offset; UINT16 handle, hci_len; UINT8 pkt_type; tL2C_LCB *p_lcb; tL2C_CCB *p_ccb = NULL; UINT16 l2cap_len, rcv_cid, psm; /* Extract the handle */ STREAM_TO_UINT16 (handle, p); pkt_type = HCID_GET_EVENT (handle); handle = HCID_GET_HANDLE (handle); /* Since the HCI Transport is putting segmented packets back together, we */ /* should never get a valid packet with the type set to "continuation" */ if (pkt_type != L2CAP_PKT_CONTINUE) { /* Find the LCB based on the handle */ if ((p_lcb = l2cu_find_lcb_by_handle (handle)) == NULL) { UINT8 cmd_code; /* There is a slight possibility (specifically with USB) that we get an */ /* L2CAP connection request before we get the HCI connection complete. */ /* So for these types of messages, hold them for up to 2 seconds. */ STREAM_TO_UINT16 (hci_len, p); STREAM_TO_UINT16 (l2cap_len, p); STREAM_TO_UINT16 (rcv_cid, p); STREAM_TO_UINT8 (cmd_code, p); if ((p_msg->layer_specific == 0) && (rcv_cid == L2CAP_SIGNALLING_CID) && (cmd_code == L2CAP_CMD_INFO_REQ || cmd_code == L2CAP_CMD_CONN_REQ)) { L2CAP_TRACE_WARNING5 ("L2CAP - holding ACL for unknown handle:%d ls:%d cid:%d opcode:%d cur count:%d", handle, p_msg->layer_specific, rcv_cid, cmd_code, l2cb.rcv_hold_q.count); p_msg->layer_specific = 2; GKI_enqueue (&l2cb.rcv_hold_q, p_msg); if (l2cb.rcv_hold_q.count == 1) btu_start_timer (&l2cb.rcv_hold_tle, BTU_TTYPE_L2CAP_HOLD, BT_1SEC_TIMEOUT); return; } else { L2CAP_TRACE_ERROR5 ("L2CAP - rcvd ACL for unknown handle:%d ls:%d cid:%d opcode:%d cur count:%d", handle, p_msg->layer_specific, rcv_cid, cmd_code, l2cb.rcv_hold_q.count); } GKI_freebuf (p_msg); return; } } else { L2CAP_TRACE_WARNING1 ("L2CAP - expected pkt start or complete, got: %d", pkt_type); GKI_freebuf (p_msg); return; } /* Extract the length and update the buffer header */ STREAM_TO_UINT16 (hci_len, p); p_msg->offset += 4; #if (L2CAP_HOST_FLOW_CTRL == TRUE) /* Send ack if we hit the threshold */ if (++p_lcb->link_pkts_unacked >= p_lcb->link_ack_thresh) btu_hcif_send_host_rdy_for_data(); #endif /* Extract the length and CID */ STREAM_TO_UINT16 (l2cap_len, p); STREAM_TO_UINT16 (rcv_cid, p); /* Find the CCB for this CID */ if (rcv_cid >= L2CAP_BASE_APPL_CID) { if ((p_ccb = l2cu_find_ccb_by_cid (p_lcb, rcv_cid)) == NULL) { L2CAP_TRACE_WARNING1 ("L2CAP - unknown CID: 0x%04x", rcv_cid); GKI_freebuf (p_msg); return; } } if (hci_len >= L2CAP_PKT_OVERHEAD) /* Must receive at least the L2CAP length and CID.*/ { p_msg->len = hci_len - L2CAP_PKT_OVERHEAD; p_msg->offset += L2CAP_PKT_OVERHEAD; } else { L2CAP_TRACE_WARNING0 ("L2CAP - got incorrect hci header" ); GKI_freebuf (p_msg); return; } if (l2cap_len != p_msg->len) { L2CAP_TRACE_WARNING2 ("L2CAP - bad length in pkt. Exp: %d Act: %d", l2cap_len, p_msg->len); GKI_freebuf (p_msg); return; } /* Send the data through the channel state machine */ if (rcv_cid == L2CAP_SIGNALLING_CID) { process_l2cap_cmd (p_lcb, p, l2cap_len); GKI_freebuf (p_msg); } else if (rcv_cid == L2CAP_CONNECTIONLESS_CID) { /* process_connectionless_data (p_lcb); */ STREAM_TO_UINT16 (psm, p); L2CAP_TRACE_DEBUG1( "GOT CONNECTIONLESS DATA PSM:%d", psm ) ; #if (TCS_BCST_SETUP_INCLUDED == TRUE && TCS_INCLUDED == TRUE) if (psm == TCS_PSM_INTERCOM || psm == TCS_PSM_CORDLESS) { p_msg->offset += L2CAP_BCST_OVERHEAD; p_msg->len -= L2CAP_BCST_OVERHEAD; tcs_proc_bcst_msg( p_lcb->remote_bd_addr, p_msg ) ; GKI_freebuf (p_msg); } else #endif #if (L2CAP_UCD_INCLUDED == TRUE) /* if it is not broadcast, check UCD registration */ if ( l2c_ucd_check_rx_pkts( p_lcb, p_msg ) ) { /* nothing to do */ } else #endif GKI_freebuf (p_msg); } #if (BLE_INCLUDED == TRUE) else if (rcv_cid == L2CAP_BLE_SIGNALLING_CID) { l2cble_process_sig_cmd (p_lcb, p, l2cap_len); GKI_freebuf (p_msg); } #endif #if (L2CAP_NUM_FIXED_CHNLS > 0) else if ((rcv_cid >= L2CAP_FIRST_FIXED_CHNL) && (rcv_cid <= L2CAP_LAST_FIXED_CHNL) && (l2cb.fixed_reg[rcv_cid - L2CAP_FIRST_FIXED_CHNL].pL2CA_FixedData_Cb != NULL) ) { /* If no CCB for this channel, allocate one */ if (l2cu_initialize_fixed_ccb (p_lcb, rcv_cid, &l2cb.fixed_reg[rcv_cid - L2CAP_FIRST_FIXED_CHNL].fixed_chnl_opts)) { p_ccb = p_lcb->p_fixed_ccbs[rcv_cid - L2CAP_FIRST_FIXED_CHNL]; if (p_ccb->peer_cfg.fcr.mode != L2CAP_FCR_BASIC_MODE) l2c_fcr_proc_pdu (p_ccb, p_msg); else (*l2cb.fixed_reg[rcv_cid - L2CAP_FIRST_FIXED_CHNL].pL2CA_FixedData_Cb)(p_lcb->remote_bd_addr, p_msg); } else GKI_freebuf (p_msg); } #endif else { if (p_ccb == NULL) GKI_freebuf (p_msg); else { /* Basic mode packets go straight to the state machine */ if (p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_BASIC_MODE) l2c_csm_execute (p_ccb, L2CEVT_L2CAP_DATA, p_msg); else { /* eRTM or streaming mode, so we need to validate states first */ if ((p_ccb->chnl_state == CST_OPEN) || (p_ccb->chnl_state == CST_CONFIG)) l2c_fcr_proc_pdu (p_ccb, p_msg); else GKI_freebuf (p_msg); } } } }
/******************************************************************************* ** ** Function l2cble_advertiser_conn_comp ** ** Description This function is called when an HCI Connection Complete ** event is received while we are an advertiser (so we are slave). ** ** Returns void ** *******************************************************************************/ void l2cble_advertiser_conn_comp (UINT16 handle, BD_ADDR bda, tBLE_ADDR_TYPE type, UINT16 conn_interval, UINT16 conn_latency, UINT16 conn_timeout) { int i; tL2C_LCB *p_lcb; tBTM_SEC_DEV_REC *p_dev_rec; UNUSED(type); UNUSED(conn_interval); UNUSED(conn_latency); UNUSED(conn_timeout); /* See if we have a link control block for the remote device */ p_lcb = l2cu_find_lcb_by_bd_addr (bda, BT_TRANSPORT_LE); /* If we don't have one, create one and accept the connection. */ if (!p_lcb) { p_lcb = l2cu_allocate_lcb (bda, FALSE, BT_TRANSPORT_LE); if (!p_lcb) { btm_sec_disconnect (handle, HCI_ERR_NO_CONNECTION); L2CAP_TRACE_ERROR ("l2cble_advertiser_conn_comp - failed to allocate LCB"); return; } else { if (!l2cu_initialize_fixed_ccb (p_lcb, L2CAP_ATT_CID, &l2cb.fixed_reg[L2CAP_ATT_CID - L2CAP_FIRST_FIXED_CHNL].fixed_chnl_opts)) { btm_sec_disconnect (handle, HCI_ERR_NO_CONNECTION); L2CAP_TRACE_WARNING ("l2cble_scanner_conn_comp - LCB but no CCB"); return ; } } } /* Save the handle */ p_lcb->handle = handle; /* Connected OK. Change state to connected, we were advertising, so we are slave */ p_lcb->link_role = HCI_ROLE_SLAVE; p_lcb->transport = BT_TRANSPORT_LE; /* update link parameter, set slave link as non-spec default upon link up */ p_lcb->min_interval = p_lcb->max_interval = conn_interval; p_lcb->timeout = conn_timeout; p_lcb->latency = conn_latency; p_lcb->conn_update_mask = L2C_BLE_NOT_DEFAULT_PARAM; /* Tell BTM Acl management about the link */ p_dev_rec = btm_find_or_alloc_dev (bda); btm_acl_created (bda, NULL, p_dev_rec->sec_bd_name, handle, p_lcb->link_role, BT_TRANSPORT_LE); #if BLE_PRIVACY_SPT == TRUE btm_ble_disable_resolving_list(BTM_BLE_RL_ADV, TRUE); #endif p_lcb->peer_chnl_mask[0] = L2CAP_FIXED_CHNL_ATT_BIT | L2CAP_FIXED_CHNL_BLE_SIG_BIT | L2CAP_FIXED_CHNL_SMP_BIT; if (!HCI_LE_SLAVE_INIT_FEAT_EXC_SUPPORTED(controller_get_interface()->get_features_ble()->as_array)) { p_lcb->link_state = LST_CONNECTED; l2cu_process_fixed_chnl_resp (p_lcb); } /* when adv and initiating are both active, cancel the direct connection */ if (l2cb.is_ble_connecting && memcmp(bda, l2cb.ble_connecting_bda, BD_ADDR_LEN) == 0) { L2CA_CancelBleConnectReq(bda); } }
/******************************************************************************* ** ** Function l2c_rcv_acl_data ** ** Description This function is called from the HCI Interface when an ACL ** data packet is received. ** ** Returns void ** *******************************************************************************/ void l2c_rcv_acl_data (BT_HDR *p_msg) { UINT8 *p = (UINT8 *)(p_msg + 1) + p_msg->offset; UINT16 handle, hci_len; UINT8 pkt_type; tL2C_LCB *p_lcb; tL2C_CCB *p_ccb = NULL; UINT16 l2cap_len, rcv_cid, psm; /* Extract the handle */ STREAM_TO_UINT16 (handle, p); pkt_type = HCID_GET_EVENT (handle); handle = HCID_GET_HANDLE (handle); /* Since the HCI Transport is putting segmented packets back together, we */ /* should never get a valid packet with the type set to "continuation" */ if (pkt_type != L2CAP_PKT_CONTINUE) { /* Find the LCB based on the handle */ if ((p_lcb = l2cu_find_lcb_by_handle (handle)) == NULL) { UINT8 cmd_code; /* There is a slight possibility (specifically with USB) that we get an */ /* L2CAP connection request before we get the HCI connection complete. */ /* So for these types of messages, hold them for up to 2 seconds. */ STREAM_TO_UINT16 (hci_len, p); STREAM_TO_UINT16 (l2cap_len, p); STREAM_TO_UINT16 (rcv_cid, p); STREAM_TO_UINT8 (cmd_code, p); if ((p_msg->layer_specific == 0) && (rcv_cid == L2CAP_SIGNALLING_CID) && (cmd_code == L2CAP_CMD_INFO_REQ || cmd_code == L2CAP_CMD_CONN_REQ)) { L2CAP_TRACE_WARNING ("L2CAP - holding ACL for unknown handle:%d ls:%d" " cid:%d opcode:%d cur count:%d", handle, p_msg->layer_specific, rcv_cid, cmd_code, list_length(l2cb.rcv_pending_q)); p_msg->layer_specific = 2; list_append(l2cb.rcv_pending_q, p_msg); if (list_length(l2cb.rcv_pending_q) == 1) { btu_start_timer (&l2cb.rcv_hold_tle, BTU_TTYPE_L2CAP_HOLD, BT_1SEC_TIMEOUT); } return; } else { L2CAP_TRACE_ERROR ("L2CAP - rcvd ACL for unknown handle:%d ls:%d cid:%d" " opcode:%d cur count:%d", handle, p_msg->layer_specific, rcv_cid, cmd_code, list_length(l2cb.rcv_pending_q)); } GKI_freebuf (p_msg); return; } } else { L2CAP_TRACE_WARNING ("L2CAP - expected pkt start or complete, got: %d", pkt_type); GKI_freebuf (p_msg); return; } /* Extract the length and update the buffer header */ STREAM_TO_UINT16 (hci_len, p); p_msg->offset += 4; /* Extract the length and CID */ STREAM_TO_UINT16 (l2cap_len, p); STREAM_TO_UINT16 (rcv_cid, p); #if BLE_INCLUDED == TRUE /* for BLE channel, always notify connection when ACL data received on the link */ if (p_lcb && p_lcb->transport == BT_TRANSPORT_LE && p_lcb->link_state != LST_DISCONNECTING) /* only process fixed channel data as channel open indication when link is not in disconnecting mode */ { l2cble_notify_le_connection(p_lcb->remote_bd_addr); } #endif L2CAP_TRACE_DEBUG ("L2CAP - rcv_cid CID: 0x%04x\n", rcv_cid); /* Find the CCB for this CID */ if (rcv_cid >= L2CAP_BASE_APPL_CID) { if ((p_ccb = l2cu_find_ccb_by_cid (p_lcb, rcv_cid)) == NULL) { L2CAP_TRACE_WARNING ("L2CAP - unknown CID: 0x%04x", rcv_cid); GKI_freebuf (p_msg); return; } } if (hci_len >= L2CAP_PKT_OVERHEAD) { /* Must receive at least the L2CAP length and CID.*/ p_msg->len = hci_len - L2CAP_PKT_OVERHEAD; p_msg->offset += L2CAP_PKT_OVERHEAD; } else { L2CAP_TRACE_WARNING ("L2CAP - got incorrect hci header" ); GKI_freebuf (p_msg); return; } if (l2cap_len != p_msg->len) { L2CAP_TRACE_WARNING ("L2CAP - bad length in pkt. Exp: %d Act: %d", l2cap_len, p_msg->len); GKI_freebuf (p_msg); return; } /* Send the data through the channel state machine */ if (rcv_cid == L2CAP_SIGNALLING_CID) { //counter_add("l2cap.sig.rx.bytes", l2cap_len); //counter_add("l2cap.sig.rx.pkts", 1); #if (CLASSIC_BT_INCLUDED == TRUE) process_l2cap_cmd (p_lcb, p, l2cap_len); #endif ///CLASSIC_BT_INCLUDED == TRUE GKI_freebuf (p_msg); } else if (rcv_cid == L2CAP_CONNECTIONLESS_CID) { //counter_add("l2cap.ch2.rx.bytes", l2cap_len); //counter_add("l2cap.ch2.rx.pkts", 1); /* process_connectionless_data (p_lcb); */ STREAM_TO_UINT16 (psm, p); L2CAP_TRACE_DEBUG( "GOT CONNECTIONLESS DATA PSM:%d", psm ) ; #if (L2CAP_UCD_INCLUDED == TRUE) /* if it is not broadcast, check UCD registration */ if ( l2c_ucd_check_rx_pkts( p_lcb, p_msg ) ) { /* nothing to do */ } else #endif GKI_freebuf (p_msg); } #if (BLE_INCLUDED == TRUE) else if (rcv_cid == L2CAP_BLE_SIGNALLING_CID) { //counter_add("l2cap.ble.rx.bytes", l2cap_len); //counter_add("l2cap.ble.rx.pkts", 1); l2cble_process_sig_cmd (p_lcb, p, l2cap_len); GKI_freebuf (p_msg); } #endif #if (L2CAP_NUM_FIXED_CHNLS > 0) else if ((rcv_cid >= L2CAP_FIRST_FIXED_CHNL) && (rcv_cid <= L2CAP_LAST_FIXED_CHNL) && (l2cb.fixed_reg[rcv_cid - L2CAP_FIRST_FIXED_CHNL].pL2CA_FixedData_Cb != NULL) ) { //counter_add("l2cap.fix.rx.bytes", l2cap_len); //counter_add("l2cap.fix.rx.pkts", 1); /* If no CCB for this channel, allocate one */ if (p_lcb && /* only process fixed channel data when link is open or wait for data indication */ (p_lcb->link_state != LST_DISCONNECTING) && l2cu_initialize_fixed_ccb (p_lcb, rcv_cid, &l2cb.fixed_reg[rcv_cid - L2CAP_FIRST_FIXED_CHNL].fixed_chnl_opts)) { p_ccb = p_lcb->p_fixed_ccbs[rcv_cid - L2CAP_FIRST_FIXED_CHNL]; if (p_ccb->peer_cfg.fcr.mode != L2CAP_FCR_BASIC_MODE) { #if (CLASSIC_BT_INCLUDED == TRUE) l2c_fcr_proc_pdu (p_ccb, p_msg); #endif ///CLASSIC_BT_INCLUDED == TRUE } else (*l2cb.fixed_reg[rcv_cid - L2CAP_FIRST_FIXED_CHNL].pL2CA_FixedData_Cb) (rcv_cid, p_lcb->remote_bd_addr, p_msg); } else { GKI_freebuf (p_msg); } } #endif else { //counter_add("l2cap.dyn.rx.bytes", l2cap_len); //counter_add("l2cap.dyn.rx.pkts", 1); if (p_ccb == NULL) { GKI_freebuf (p_msg); } else { /* Basic mode packets go straight to the state machine */ if (p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_BASIC_MODE) { #if (CLASSIC_BT_INCLUDED == TRUE) l2c_csm_execute (p_ccb, L2CEVT_L2CAP_DATA, p_msg); #endif ///CLASSIC_BT_INCLUDED == TRUE } else { /* eRTM or streaming mode, so we need to validate states first */ if ((p_ccb->chnl_state == CST_OPEN) || (p_ccb->chnl_state == CST_CONFIG)) { #if (CLASSIC_BT_INCLUDED == TRUE) l2c_fcr_proc_pdu (p_ccb, p_msg); #endif ///CLASSIC_BT_INCLUDED == TRUE } else { GKI_freebuf (p_msg); } } } } }