diff options
author | Balraj Selvaraj <bselva@codeaurora.org> | 2015-07-21 20:50:27 +0530 |
---|---|---|
committer | Linux Build Service Account <lnxbuild@localhost> | 2015-10-06 03:21:48 -0600 |
commit | 273de486f3b1771be80b83ed30fa7df4449c7eab (patch) | |
tree | d6e6a7e862ff9c5c00794ac1248dfa469376670f /stack/l2cap/l2c_main.c | |
parent | fc0cea9ec50c0b35ddfc28b269980da2ca7dc109 (diff) | |
download | android_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.c | 68 |
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) |