15738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************
25738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
35738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  Copyright (C) 1999-2012 Broadcom Corporation
45738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
55738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  Licensed under the Apache License, Version 2.0 (the "License");
65738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  you may not use this file except in compliance with the License.
75738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  You may obtain a copy of the License at:
85738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
95738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  http://www.apache.org/licenses/LICENSE-2.0
105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  Unless required by applicable law or agreed to in writing, software
125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  distributed under the License is distributed on an "AS IS" BASIS,
135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  See the License for the specific language governing permissions and
155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  limitations under the License.
165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ******************************************************************************/
185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************
205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  This file contains L2CAP interface functions
225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ******************************************************************************/
245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
25933926c92e1378cc76bc9c149107e670c4872d4eScott James Remnant#include <stddef.h>
265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "bt_target.h"
271a3844f933bd63c8a381371dabfb35c6a0249e3ePavlin Radoslavov
28911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#include "bt_common.h"
29d7ffd64accbd50a27289a388856e56244ccbb5daMyles Watson#include "osi/include/osi.h"
301a3844f933bd63c8a381371dabfb35c6a0249e3ePavlin Radoslavov#include "osi/include/time.h"
315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
32911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#include "bt_utils.h"
335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "l2c_api.h"
345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "l2cdefs.h"
35911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#include "port_api.h"
36911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#include "port_int.h"
375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "rfc_int.h"
38911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#include "rfcdefs.h"
395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*
41ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Define Callback functions to be called by L2CAP
425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*/
439e030fde05352ec4385d7baf6cc2af89e95e039cJakub Pawlowskistatic void RFCOMM_ConnectInd(const RawAddress& bd_addr, uint16_t lcid,
44c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski                              uint16_t psm, uint8_t id);
45911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonstatic void RFCOMM_ConnectCnf(uint16_t lcid, uint16_t err);
46911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonstatic void RFCOMM_ConfigInd(uint16_t lcid, tL2CAP_CFG_INFO* p_cfg);
47911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonstatic void RFCOMM_ConfigCnf(uint16_t lcid, tL2CAP_CFG_INFO* p_cfg);
48911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonstatic void RFCOMM_DisconnectInd(uint16_t lcid, bool is_clear);
499e030fde05352ec4385d7baf6cc2af89e95e039cJakub Pawlowskistatic void RFCOMM_QoSViolationInd(UNUSED_ATTR const RawAddress& bd_addr);
50911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonstatic void RFCOMM_BufDataInd(uint16_t lcid, BT_HDR* p_buf);
51911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonstatic void RFCOMM_CongestionStatusInd(uint16_t lcid, bool is_congested);
525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
54ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
55ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         rfcomm_l2cap_if_init
56ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
57ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      This function is called during the RFCOMM task startup
58ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  to register interface functions with L2CAP.
59ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
60ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
61911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid rfcomm_l2cap_if_init(void) {
62911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2CAP_APPL_INFO* p_l2c = &rfc_cb.rfc.reg_info;
63911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
64911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_l2c->pL2CA_ConnectInd_Cb = RFCOMM_ConnectInd;
65911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_l2c->pL2CA_ConnectCfm_Cb = RFCOMM_ConnectCnf;
66911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_l2c->pL2CA_ConnectPnd_Cb = NULL;
67911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_l2c->pL2CA_ConfigInd_Cb = RFCOMM_ConfigInd;
68911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_l2c->pL2CA_ConfigCfm_Cb = RFCOMM_ConfigCnf;
69911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_l2c->pL2CA_DisconnectInd_Cb = RFCOMM_DisconnectInd;
70911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_l2c->pL2CA_DisconnectCfm_Cb = NULL;
71911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_l2c->pL2CA_QoSViolationInd_Cb = RFCOMM_QoSViolationInd;
72911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_l2c->pL2CA_DataInd_Cb = RFCOMM_BufDataInd;
73911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_l2c->pL2CA_CongestionStatus_Cb = RFCOMM_CongestionStatusInd;
74911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_l2c->pL2CA_TxComplete_Cb = NULL;
75911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
76911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  L2CA_Register(BT_PSM_RFCOMM, p_l2c);
775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
80ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
81ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         RFCOMM_ConnectInd
82ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
83ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      This is a callback function called by L2CAP when
849ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  L2CA_ConnectInd received.  Allocate multiplexer control
859ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  block and dispatch the event to it.
86ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
87ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
889e030fde05352ec4385d7baf6cc2af89e95e039cJakub Pawlowskivoid RFCOMM_ConnectInd(const RawAddress& bd_addr, uint16_t lcid,
89c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski                       UNUSED_ATTR uint16_t psm, uint8_t id) {
901979fa31d2e9aa7dfe7380327fbddebfffd0cda4Jakub Pawlowski  tRFC_MCB* p_mcb = rfc_alloc_multiplexer_channel(bd_addr, false);
91911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
92911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if ((p_mcb) && (p_mcb->state != RFC_MX_STATE_IDLE)) {
93911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* if this is collision case */
94911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if ((p_mcb->is_initiator) && (p_mcb->state == RFC_MX_STATE_WAIT_CONN_CNF)) {
95911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_mcb->pending_lcid = lcid;
96911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_mcb->pending_id = id;
97911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
98911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* wait random timeout (2 - 12) to resolve collision */
99911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* if peer gives up then local device rejects incoming connection and
100911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson       * continues as initiator */
101911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* if timeout, local device disconnects outgoing connection and continues
102911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson       * as acceptor */
103911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      RFCOMM_TRACE_DEBUG(
104911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          "RFCOMM_ConnectInd start timer for collision, initiator's "
105911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          "LCID(0x%x), acceptor's LCID(0x%x)",
106911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          p_mcb->lcid, p_mcb->pending_lcid);
107911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
108911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      rfc_timer_start(p_mcb, (uint16_t)(time_get_os_boottime_ms() % 10 + 2));
109911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      return;
110911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    } else {
111911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* we cannot accept connection request from peer at this state */
112911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* don't update lcid */
113911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_mcb = NULL;
1145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
115911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else {
116911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* store mcb even if null */
117911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    rfc_save_lcid_mcb(p_mcb, lcid);
118911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
119911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
120911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_mcb == NULL) {
121911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CA_ConnectRsp(bd_addr, id, lcid, L2CAP_CONN_NO_RESOURCES, 0);
122911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
123911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
124911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_mcb->lcid = lcid;
125911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
126911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  rfc_mx_sm_execute(p_mcb, RFC_MX_EVENT_CONN_IND, &id);
1275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
1285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
130ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
131ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         RFCOMM_ConnectCnf
132ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
133ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      This is a callback function called by L2CAP when
134ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  L2CA_ConnectCnf received.  Save L2CAP handle and dispatch
135ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  event to the FSM.
136ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
137ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
138911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid RFCOMM_ConnectCnf(uint16_t lcid, uint16_t result) {
139911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tRFC_MCB* p_mcb = rfc_find_lcid_mcb(lcid);
140911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
141911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (!p_mcb) {
142911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    RFCOMM_TRACE_ERROR("RFCOMM_ConnectCnf LCID:0x%x", lcid);
143911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
144911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
145911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
146911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_mcb->pending_lcid) {
147911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* if peer rejects our connect request but peer's connect request is pending
148911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson     */
149911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (result != L2CAP_CONN_OK) {
150911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      uint16_t i;
151911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      uint8_t idx;
152911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
153911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      RFCOMM_TRACE_DEBUG(
154911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          "RFCOMM_ConnectCnf retry as acceptor on pending LCID(0x%x)",
155911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          p_mcb->pending_lcid);
156911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
157911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* remove mcb from mapping table */
158911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      rfc_save_lcid_mcb(NULL, p_mcb->lcid);
159911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
160911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_mcb->lcid = p_mcb->pending_lcid;
161911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_mcb->is_initiator = false;
162911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_mcb->state = RFC_MX_STATE_IDLE;
163911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
164911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* store mcb into mapping table */
165911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      rfc_save_lcid_mcb(p_mcb, p_mcb->lcid);
166911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
167911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* update direction bit */
168911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      for (i = 0; i < RFCOMM_MAX_DLCI; i += 2) {
169911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        idx = p_mcb->port_inx[i];
170911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        if (idx != 0) {
171911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          p_mcb->port_inx[i] = 0;
172911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          p_mcb->port_inx[i + 1] = idx;
173911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          rfc_cb.port.port[idx - 1].dlci += 1;
174911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          RFCOMM_TRACE_DEBUG("RFCOMM MX - DLCI:%d -> %d", i,
175911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                             rfc_cb.port.port[idx - 1].dlci);
1765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
177911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
1785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
179911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      rfc_mx_sm_execute(p_mcb, RFC_MX_EVENT_CONN_IND, &(p_mcb->pending_id));
180911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      return;
181911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    } else {
182911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      RFCOMM_TRACE_DEBUG("RFCOMM_ConnectCnf peer gave up pending LCID(0x%x)",
183911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                         p_mcb->pending_lcid);
1845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
185911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* Peer gave up his connection request, make sure cleaning up L2CAP
186911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson       * channel */
1871979fa31d2e9aa7dfe7380327fbddebfffd0cda4Jakub Pawlowski      L2CA_ConnectRsp(p_mcb->bd_addr, p_mcb->pending_id, p_mcb->pending_lcid,
1881979fa31d2e9aa7dfe7380327fbddebfffd0cda4Jakub Pawlowski                      L2CAP_CONN_NO_RESOURCES, 0);
189911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
190911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_mcb->pending_lcid = 0;
1915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
192911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
1935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
194911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Save LCID to be used in all consecutive calls to L2CAP */
195911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_mcb->lcid = lcid;
1965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
197911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  rfc_mx_sm_execute(p_mcb, RFC_MX_EVENT_CONN_CNF, &result);
1985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
1995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
201ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
202ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         RFCOMM_ConfigInd
203ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
204ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      This is a callback function called by L2CAP when
205ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  L2CA_ConfigInd received.  Save parameters in the control
206ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  block and dispatch event to the FSM.
207ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
208ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
209911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid RFCOMM_ConfigInd(uint16_t lcid, tL2CAP_CFG_INFO* p_cfg) {
210911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tRFC_MCB* p_mcb = rfc_find_lcid_mcb(lcid);
2115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
212911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (!p_mcb) {
213911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    RFCOMM_TRACE_ERROR("RFCOMM_ConfigInd LCID:0x%x", lcid);
214911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
215911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
2165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
217911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  rfc_mx_sm_execute(p_mcb, RFC_MX_EVENT_CONF_IND, (void*)p_cfg);
218911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson}
2195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
221ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
222ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         RFCOMM_ConfigCnf
223ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
224ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      This is a callback function called by L2CAP when
225ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  L2CA_ConfigCnf received.  Save L2CAP handle and dispatch
226ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  event to the FSM.
227ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
228ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
229911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid RFCOMM_ConfigCnf(uint16_t lcid, tL2CAP_CFG_INFO* p_cfg) {
230911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tRFC_MCB* p_mcb = rfc_find_lcid_mcb(lcid);
2315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
232911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (!p_mcb) {
233911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    RFCOMM_TRACE_ERROR("RFCOMM_ConfigCnf no MCB LCID:0x%x", lcid);
234911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
235911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
2365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
237911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  rfc_mx_sm_execute(p_mcb, RFC_MX_EVENT_CONF_CNF, (void*)p_cfg);
238911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson}
2395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
241ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
242ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         RFCOMM_QoSViolationInd
243ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
244ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      This is a callback function called by L2CAP when
2459ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  L2CA_QoSViolationIndInd received.  Dispatch event to the
2469ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  FSM.
247ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
248ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
2499e030fde05352ec4385d7baf6cc2af89e95e039cJakub Pawlowskivoid RFCOMM_QoSViolationInd(UNUSED_ATTR const RawAddress& bd_addr) {}
2505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
252ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
253ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         RFCOMM_DisconnectInd
254ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
255ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      This is a callback function called by L2CAP when
256ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  L2CA_DisconnectInd received.  Dispatch event to the FSM.
257ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
258ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
259911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid RFCOMM_DisconnectInd(uint16_t lcid, bool is_conf_needed) {
260911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tRFC_MCB* p_mcb = rfc_find_lcid_mcb(lcid);
2615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
262911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (is_conf_needed) {
263911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CA_DisconnectRsp(lcid);
264911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
2655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
266911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (!p_mcb) {
267911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    RFCOMM_TRACE_WARNING("RFCOMM_DisconnectInd LCID:0x%x", lcid);
268911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
269911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
2705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
271911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  rfc_mx_sm_execute(p_mcb, RFC_MX_EVENT_DISC_IND, NULL);
2725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
2735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
275ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
276ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         RFCOMM_BufDataInd
277ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
278ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      This is a callback function called by L2CAP when
279ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  data RFCOMM frame is received.  Parse the frames, check
280ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  the checksum and dispatch event to multiplexer or port
281ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  state machine depending on the frame destination.
282ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
283ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
284911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid RFCOMM_BufDataInd(uint16_t lcid, BT_HDR* p_buf) {
285911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tRFC_MCB* p_mcb = rfc_find_lcid_mcb(lcid);
286911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tPORT* p_port;
287911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t event;
2885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
289911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (!p_mcb) {
290911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    RFCOMM_TRACE_WARNING("RFCOMM_BufDataInd LCID:0x%x", lcid);
291911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    osi_free(p_buf);
292911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
293911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
2945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
295911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  event = rfc_parse_data(p_mcb, &rfc_cb.rfc.rx_frame, p_buf);
2965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
297911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* If the frame did not pass validation just ignore it */
298911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (event == RFC_EVENT_BAD_FRAME) {
299911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    osi_free(p_buf);
300911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
301911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
302911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
303911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (rfc_cb.rfc.rx_frame.dlci == RFCOMM_MX_DLCI) {
304911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* Take special care of the Multiplexer Control Messages */
305911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (event == RFC_EVENT_UIH) {
306911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      rfc_process_mx_message(p_mcb, p_buf);
307911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      return;
3085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
3095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
310911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* Other multiplexer events go to state machine */
311911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    rfc_mx_sm_execute(p_mcb, event, NULL);
312911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    osi_free(p_buf);
313911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
314911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
315911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
316911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* The frame was received on the data channel DLCI, verify that DLC exists */
317911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (((p_port = port_find_mcb_dlci_port(p_mcb, rfc_cb.rfc.rx_frame.dlci)) ==
318911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson       NULL) ||
319911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      (!p_port->rfc.p_mcb)) {
320911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* If this is a SABME on the new port, check if any appl is waiting for it
321911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson     */
322911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (event != RFC_EVENT_SABME) {
323911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if ((p_mcb->is_initiator && !rfc_cb.rfc.rx_frame.cr) ||
324911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          (!p_mcb->is_initiator && rfc_cb.rfc.rx_frame.cr))
325911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        rfc_send_dm(p_mcb, rfc_cb.rfc.rx_frame.dlci, rfc_cb.rfc.rx_frame.pf);
326911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      osi_free(p_buf);
327911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      return;
3285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
3295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
330911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_port = port_find_dlci_port(rfc_cb.rfc.rx_frame.dlci);
331911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_port == NULL) {
332911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      rfc_send_dm(p_mcb, rfc_cb.rfc.rx_frame.dlci, true);
333911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      osi_free(p_buf);
334911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      return;
335911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    }
336911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_mcb->port_inx[rfc_cb.rfc.rx_frame.dlci] = p_port->inx;
337911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_port->rfc.p_mcb = p_mcb;
338911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
339cccf02fadb2dd4dceb22f2d58ed5840b0ef1860eChris Manton
340911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (event == RFC_EVENT_UIH) {
341911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_buf->len > 0)
342911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      rfc_port_sm_execute(p_port, event, p_buf);
343911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    else
344911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      osi_free(p_buf);
3455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
346911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (rfc_cb.rfc.rx_frame.credit != 0)
347911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      rfc_inc_credit(p_port, rfc_cb.rfc.rx_frame.credit);
3485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
349911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
350911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
351911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  rfc_port_sm_execute(p_port, event, NULL);
352911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  osi_free(p_buf);
3535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
3545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
356ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
357ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         RFCOMM_CongestionStatusInd
358ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
359ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      This is a callback function called by L2CAP when
360ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  data RFCOMM L2CAP congestion status changes
361ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
362ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
363911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid RFCOMM_CongestionStatusInd(uint16_t lcid, bool is_congested) {
364911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tRFC_MCB* p_mcb = rfc_find_lcid_mcb(lcid);
365911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
366911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (!p_mcb) {
367911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    RFCOMM_TRACE_ERROR("RFCOMM_CongestionStatusInd dropped LCID:0x%x", lcid);
368911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
369911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else {
370911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    RFCOMM_TRACE_EVENT("RFCOMM_CongestionStatusInd LCID:0x%x", lcid);
371911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
372911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  rfc_process_l2cap_congestion(p_mcb, is_congested);
3735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
3745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
376ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
377ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         rfc_find_lcid_mcb
378ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
379ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      This function returns MCB block supporting local cid
380ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
381ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
382911d1ae03efec2d54c3b1b605589d790d1745488Myles WatsontRFC_MCB* rfc_find_lcid_mcb(uint16_t lcid) {
383911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tRFC_MCB* p_mcb;
384911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
385911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (lcid - L2CAP_BASE_APPL_CID >= MAX_L2CAP_CHANNELS) {
386911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    RFCOMM_TRACE_ERROR("rfc_find_lcid_mcb LCID:0x%x", lcid);
387911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return (NULL);
388911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else {
389911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_mcb = rfc_cb.rfc.p_rfc_lcid_mcb[lcid - L2CAP_BASE_APPL_CID];
390911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_mcb != NULL) {
391911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (p_mcb->lcid != lcid) {
392911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        RFCOMM_TRACE_WARNING(
393911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            "rfc_find_lcid_mcb LCID reused LCID:0x%x current:0x%x", lcid,
394911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            p_mcb->lcid);
3955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        return (NULL);
396911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
3975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
398911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
399911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return (p_mcb);
4005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
4015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
403ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
404ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         rfc_save_lcid_mcb
405ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
406ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      This function returns MCB block supporting local cid
407ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
408ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
409911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid rfc_save_lcid_mcb(tRFC_MCB* p_mcb, uint16_t lcid) {
410911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (lcid < L2CAP_BASE_APPL_CID) return;
411911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  rfc_cb.rfc.p_rfc_lcid_mcb[lcid - L2CAP_BASE_APPL_CID] = p_mcb;
4125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
413