summaryrefslogtreecommitdiffstats
path: root/stack/l2cap/l2c_main.c
diff options
context:
space:
mode:
authorBalraj Selvaraj <bselva@codeaurora.org>2015-07-21 20:50:27 +0530
committerLinux Build Service Account <lnxbuild@localhost>2015-10-06 03:21:48 -0600
commit273de486f3b1771be80b83ed30fa7df4449c7eab (patch)
treed6e6a7e862ff9c5c00794ac1248dfa469376670f /stack/l2cap/l2c_main.c
parentfc0cea9ec50c0b35ddfc28b269980da2ca7dc109 (diff)
downloadandroid_system_bt-273de486f3b1771be80b83ed30fa7df4449c7eab.tar.gz
android_system_bt-273de486f3b1771be80b83ed30fa7df4449c7eab.tar.bz2
android_system_bt-273de486f3b1771be80b83ed30fa7df4449c7eab.zip
Bluetooth: LE-L2CAP-COC on M.
LE L2CAP Connection Oriented Channel implementation for credit based flow control on LE L2CAP. - This feature is enabled only when BLE feature is enabled. - Handled signalling commands on channel id 5 to establish the connection of LE COC. - Implemented the SM for LE L2CAP channel to handle events from App layer and hci layer. - Introduced security levels for LE L2CAP channels. - Introduced tranport variable for major functions where BREDR and LE shares common data structures. - Implemented segmentation and reassembly of LE L2CAP SDU. - Introduced congestion mechanism for LE L2CAP channel - As the new LE L2CAP callbacks not required for existing BREDR services, made it as null for newly introduced LE L2CAP callbacks. - New APIs introduced for LE L2CAP connection establishment. - New APIs provided for LE L2CAP security procedure. - Relevent L2cap APIs from Test app interface exposed to the test tool. - New macros, definitions, structures introduced for LE L2CAP channel establishment/data tranfer. CRs-Fixed: 776657 Change-Id: I50a24374659f9802cbc92421db139f75f2790f2e
Diffstat (limited to 'stack/l2cap/l2c_main.c')
-rw-r--r--stack/l2cap/l2c_main.c68
1 files changed, 68 insertions, 0 deletions
diff --git a/stack/l2cap/l2c_main.c b/stack/l2cap/l2c_main.c
index bbadbea98..18889d47e 100644
--- a/stack/l2cap/l2c_main.c
+++ b/stack/l2cap/l2c_main.c
@@ -38,6 +38,9 @@
#include "l2cdefs.h"
#include "osi/include/log.h"
+#if (defined(LE_L2CAP_CFC_INCLUDED) && (LE_L2CAP_CFC_INCLUDED == TRUE))
+#include <pthread.h>
+#endif
/********************************************************************************/
/* L O C A L F U N C T I O N P R O T O T Y P E S */
/********************************************************************************/
@@ -50,6 +53,10 @@ static void process_l2cap_cmd (tL2C_LCB *p_lcb, UINT8 *p, UINT16 pkt_len);
tL2C_CB l2cb;
#endif
+#if (defined(LE_L2CAP_CFC_INCLUDED) && (LE_L2CAP_CFC_INCLUDED == TRUE))
+pthread_mutex_t lock_mutex_le_credits;
+#endif
+
/*******************************************************************************
**
** Function l2c_bcst_msg
@@ -294,6 +301,23 @@ void l2c_rcv_acl_data (BT_HDR *p_msg)
GKI_freebuf (p_msg);
else
{
+#if (defined(LE_L2CAP_CFC_INCLUDED) && (LE_L2CAP_CFC_INCLUDED == TRUE))
+ if (p_lcb->transport == BT_TRANSPORT_LE)
+ {
+ if ( (p_ccb->is_le_coc == TRUE) && (p_ccb->chnl_state == CST_OPEN))
+ {
+ if(!l2c_le_proc_pdu(p_ccb, p_msg))
+ GKI_freebuf (p_msg);
+ }
+ else
+ {
+ L2CAP_TRACE_ERROR("L2CAP-LE: Error: Not a LE COC chnl or state is not open" \
+ "state %d is_le_coc", p_ccb->chnl_state, p_ccb->is_le_coc);
+ GKI_freebuf (p_msg);
+ }
+ }
+ else
+#endif /* LE_L2CAP_CFC_INCLUDED */
/* 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);
@@ -440,7 +464,11 @@ static void process_l2cap_cmd (tL2C_LCB *p_lcb, UINT8 *p, UINT16 pkt_len)
case L2CAP_CMD_CONN_REQ:
STREAM_TO_UINT16 (con_info.psm, p);
STREAM_TO_UINT16 (rcid, p);
+#if (defined(LE_L2CAP_CFC_INCLUDED) && (LE_L2CAP_CFC_INCLUDED == TRUE))
+ if ((p_rcb = l2cu_find_rcb_by_psm (con_info.psm, BT_TRANSPORT_BR_EDR)) == NULL)
+#else
if ((p_rcb = l2cu_find_rcb_by_psm (con_info.psm)) == NULL)
+#endif
{
L2CAP_TRACE_WARNING ("L2CAP - rcvd conn req for unknown PSM: %d", con_info.psm);
l2cu_reject_connection (p_lcb, rcid, id, L2CAP_CONN_NO_PSM);
@@ -911,12 +939,23 @@ void l2c_init (void)
l2cb.rcv_pending_q = list_new(NULL);
if (l2cb.rcv_pending_q == NULL)
LOG_ERROR("%s unable to allocate memory for link layer control block", __func__);
+
+#if (defined(LE_L2CAP_CFC_INCLUDED) && (LE_L2CAP_CFC_INCLUDED == TRUE))
+ pthread_mutex_init(&lock_mutex_le_credits, NULL);
+#endif
}
void l2c_free(void) {
list_free(l2cb.rcv_pending_q);
}
+#if (defined(LE_L2CAP_CFC_INCLUDED) && (LE_L2CAP_CFC_INCLUDED == TRUE))
+void l2c_cleanup (void)
+{
+ pthread_mutex_destroy(&lock_mutex_le_credits);
+}
+#endif
+
/*******************************************************************************
**
** Function l2c_process_timeout
@@ -936,6 +975,14 @@ void l2c_process_timeout (TIMER_LIST_ENT *p_tle)
break;
case BTU_TTYPE_L2CAP_CHNL:
+#if (defined(LE_L2CAP_CFC_INCLUDED) && (LE_L2CAP_CFC_INCLUDED == TRUE))
+ if((BT_TRANSPORT_LE == l2cu_get_chnl_transport((tL2C_CCB *)p_tle->param))
+ && (((tL2C_CCB *)p_tle->param)->is_le_coc == TRUE))
+ {
+ l2c_le_csm_execute (((tL2C_CCB *)p_tle->param), L2CEVT_TIMEOUT, NULL);
+ }
+ else
+#endif
l2c_csm_execute (((tL2C_CCB *)p_tle->param), L2CEVT_TIMEOUT, NULL);
break;
@@ -979,6 +1026,19 @@ UINT8 l2c_data_write (UINT16 cid, BT_HDR *p_data, UINT16 flags)
#ifndef TESTER /* Tester may send any amount of data. otherwise sending message
bigger than mtu size of peer is a violation of protocol */
+#if (defined(LE_L2CAP_CFC_INCLUDED) && (LE_L2CAP_CFC_INCLUDED == TRUE))
+ if((BT_TRANSPORT_LE == l2cu_get_chnl_transport(p_ccb)) &&
+ (p_ccb->is_le_coc == TRUE))
+ {
+ if (p_data->len > p_ccb->le_rmt_conn_info.le_mtu)
+ {
+ L2CAP_TRACE_WARNING ("LE-L2CAP: CID: 0x%04x Send msg bigger than peer's mtu", cid);
+ GKI_freebuf (p_data);
+ return (L2CAP_DW_FAILED);
+ }
+ }
+ else
+#endif
if (p_data->len > p_ccb->peer_cfg.mtu)
{
L2CAP_TRACE_WARNING ("L2CAP - CID: 0x%04x cannot send message bigger than peer's mtu size", cid);
@@ -1003,6 +1063,14 @@ UINT8 l2c_data_write (UINT16 cid, BT_HDR *p_data, UINT16 flags)
counter_add("l2cap.dyn.tx.bytes", p_data->len);
counter_add("l2cap.dyn.tx.pkts", 1);
+#if (defined(LE_L2CAP_CFC_INCLUDED) && (LE_L2CAP_CFC_INCLUDED == TRUE))
+ if((BT_TRANSPORT_LE == l2cu_get_chnl_transport(p_ccb)) &&
+ (p_ccb->is_le_coc == TRUE))
+ {
+ l2c_le_csm_execute (p_ccb, L2CEVT_L2CA_DATA_WRITE, p_data);
+ }
+ else
+#endif
l2c_csm_execute (p_ccb, L2CEVT_L2CA_DATA_WRITE, p_data);
if (p_ccb->cong_sent)