OSDN Git Service

DO NOT MERGE process_l2cap_cmd: Fix OOB
[android-x86/system-bt.git] / stack / l2cap / l2c_main.c
index cc43666..6720814 100644 (file)
  *
  ******************************************************************************/
 
+#define LOG_TAG "bt_l2c_main"
+
+#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <stdio.h>
 
 #include <log/log.h>
 
-#include "device/include/controller.h"
-#include "btcore/include/counter.h"
 #include "bt_target.h"
 #include "btm_int.h"
 #include "btu.h"
-#include "gki.h"
+#include "device/include/controller.h"
+#include "bt_common.h"
 #include "hcimsgs.h"
 #include "l2c_api.h"
 #include "l2c_int.h"
 #include "l2cdefs.h"
 #include "osi/include/log.h"
 
+
+extern fixed_queue_t *btu_general_alarm_queue;
+
 /********************************************************************************/
 /*              L O C A L    F U N C T I O N     P R O T O T Y P E S            */
 /********************************************************************************/
@@ -54,65 +58,6 @@ tL2C_CB l2cb;
 
 /*******************************************************************************
 **
-** Function         l2c_bcst_msg
-**
-** Description
-**
-** Returns          void
-**
-*******************************************************************************/
-void l2c_bcst_msg( BT_HDR *p_buf, UINT16 psm )
-{
-    UINT8       *p;
-
-    /* Ensure we have enough space in the buffer for the L2CAP and HCI headers */
-    if (p_buf->offset < L2CAP_BCST_MIN_OFFSET)
-    {
-        L2CAP_TRACE_ERROR ("L2CAP - cannot send buffer, offset: %d", p_buf->offset);
-        GKI_freebuf (p_buf);
-        return;
-    }
-
-    /* Step back some bytes to add the headers */
-    p_buf->offset -= (HCI_DATA_PREAMBLE_SIZE + L2CAP_PKT_OVERHEAD + L2CAP_BCST_OVERHEAD);
-    p_buf->len    += L2CAP_PKT_OVERHEAD + L2CAP_BCST_OVERHEAD;
-
-    /* Set the pointer to the beginning of the data */
-    p = (UINT8 *)(p_buf + 1) + p_buf->offset;
-
-    /* First, the HCI transport header */
-    UINT16_TO_STREAM (p, 0x0050 | (L2CAP_PKT_START << 12) | (2 << 14));
-
-    uint16_t acl_data_size = controller_get_interface()->get_acl_data_size_classic();
-    /* The HCI transport will segment the buffers. */
-    if (p_buf->len > acl_data_size)
-    {
-        UINT16_TO_STREAM (p, acl_data_size);
-    }
-    else
-    {
-        UINT16_TO_STREAM (p, p_buf->len);
-    }
-
-    /* Now the L2CAP header */
-    UINT16_TO_STREAM (p, p_buf->len - L2CAP_PKT_OVERHEAD);
-    UINT16_TO_STREAM (p, L2CAP_CONNECTIONLESS_CID);
-    UINT16_TO_STREAM (p, psm);
-
-    p_buf->len += HCI_DATA_PREAMBLE_SIZE;
-
-    if (p_buf->len <= controller_get_interface()->get_acl_packet_size_classic())
-    {
-        counter_add("l2cap.ch2.tx.bytes", p_buf->len);
-        counter_add("l2cap.ch2.tx.pkts", 1);
-
-        bte_main_hci_send(p_buf, BT_EVT_TO_LM_HCI_ACL);
-    }
-}
-
-
-/*******************************************************************************
-**
 ** Function         l2c_rcv_acl_data
 **
 ** Description      This function is called from the HCI Interface when an ACL
@@ -129,6 +74,7 @@ void l2c_rcv_acl_data (BT_HDR *p_msg)
     tL2C_LCB    *p_lcb;
     tL2C_CCB    *p_ccb = NULL;
     UINT16      l2cap_len, rcv_cid;
+    UINT16      credit;
 
     /* Extract the handle */
     STREAM_TO_UINT16 (handle, p);
@@ -160,8 +106,12 @@ void l2c_rcv_acl_data (BT_HDR *p_msg)
                 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);
+                if (list_length(l2cb.rcv_pending_q) == 1) {
+                    alarm_set_on_queue(l2cb.receive_hold_timer,
+                                       BT_1SEC_TIMEOUT_MS,
+                                       l2c_receive_hold_timer_timeout, NULL,
+                                       btu_general_alarm_queue);
+                }
 
                 return;
             } else {
@@ -169,14 +119,14 @@ void l2c_rcv_acl_data (BT_HDR *p_msg)
                         " opcode:%d cur count:%d", handle, p_msg->layer_specific, rcv_cid,
                         cmd_code, list_length(l2cb.rcv_pending_q));
             }
-            GKI_freebuf (p_msg);
+            osi_free(p_msg);
             return;
         }
     }
     else
     {
         L2CAP_TRACE_WARNING ("L2CAP - expected pkt start or complete, got: %d", pkt_type);
-        GKI_freebuf (p_msg);
+        osi_free(p_msg);
         return;
     }
 
@@ -188,7 +138,7 @@ void l2c_rcv_acl_data (BT_HDR *p_msg)
         /* Must receive at least the L2CAP length and CID */
         L2CAP_TRACE_WARNING ("L2CAP - got incorrect hci header");
         android_errorWriteLog(0x534e4554, "34946955");
-        GKI_freebuf (p_msg);
+        osi_free(p_msg);
         return;
     }
 
@@ -209,7 +159,7 @@ void l2c_rcv_acl_data (BT_HDR *p_msg)
         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);
+            osi_free(p_msg);
             return;
         }
     }
@@ -222,22 +172,18 @@ void l2c_rcv_acl_data (BT_HDR *p_msg)
         L2CAP_TRACE_WARNING ("L2CAP - bad length in pkt. Exp: %d  Act: %d",
                               l2cap_len, p_msg->len);
 
-        GKI_freebuf (p_msg);
+        osi_free(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);
         process_l2cap_cmd (p_lcb, p, l2cap_len);
-        GKI_freebuf (p_msg);
+        osi_free(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); */
 
 #if (L2CAP_UCD_INCLUDED == TRUE)
@@ -248,23 +194,19 @@ void l2c_rcv_acl_data (BT_HDR *p_msg)
         }
         else
 #endif
-            GKI_freebuf (p_msg);
+            osi_free(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);
+        osi_free(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 */
@@ -280,28 +222,36 @@ void l2c_rcv_acl_data (BT_HDR *p_msg)
                     (rcv_cid, p_lcb->remote_bd_addr, p_msg);
         }
         else
-            GKI_freebuf (p_msg);
+            osi_free(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);
+            osi_free(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);
+            if (p_lcb->transport == BT_TRANSPORT_LE)
+            {
+               l2c_lcc_proc_pdu(p_ccb,p_msg);
+               // Got a pkt, valid send out credits to the peer device
+               credit = L2CAP_LE_DEFAULT_CREDIT;
+               l2c_csm_execute(p_ccb, L2CEVT_L2CA_SEND_FLOW_CONTROL_CREDIT, &credit);
+            }
             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);
+                /* 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
-                    GKI_freebuf (p_msg);
+                {
+                    /* 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
+                        osi_free (p_msg);
+                }
             }
         }
     }
@@ -427,7 +377,7 @@ static void process_l2cap_cmd (tL2C_LCB *p_lcb, UINT8 *p, UINT16 pkt_len)
             /* SonyEricsson Info request Bug workaround (Continue connection) */
             else if (rej_reason == L2CAP_CMD_REJ_NOT_UNDERSTOOD && p_lcb->w4_info_rsp)
             {
-                btu_stop_timer (&p_lcb->info_timer_entry);
+                alarm_cancel(p_lcb->info_resp_timer);
 
                 p_lcb->w4_info_rsp = FALSE;
                 ci.status = HCI_SUCCESS;
@@ -538,7 +488,11 @@ static void process_l2cap_cmd (tL2C_LCB *p_lcb, UINT8 *p, UINT16 pkt_len)
                 {
                 case L2CAP_CFG_TYPE_MTU:
                     cfg_info.mtu_present = TRUE;
-                    if (p + 2 > p_next_cmd) {
+                    if (cfg_len != 2) {
+                        android_errorWriteLog(0x534e4554, "119870451");
+                        return;
+                    }
+                    if (p + cfg_len > p_next_cmd) {
                         android_errorWriteLog(0x534e4554, "74202041");
                         return;
                     }
@@ -547,7 +501,11 @@ static void process_l2cap_cmd (tL2C_LCB *p_lcb, UINT8 *p, UINT16 pkt_len)
 
                 case L2CAP_CFG_TYPE_FLUSH_TOUT:
                     cfg_info.flush_to_present = TRUE;
-                    if (p + 2 > p_next_cmd) {
+                    if (cfg_len != 2) {
+                        android_errorWriteLog(0x534e4554, "119870451");
+                        return;
+                    }
+                    if (p + cfg_len > p_next_cmd) {
                         android_errorWriteLog(0x534e4554, "74202041");
                         return;
                     }
@@ -556,7 +514,11 @@ static void process_l2cap_cmd (tL2C_LCB *p_lcb, UINT8 *p, UINT16 pkt_len)
 
                 case L2CAP_CFG_TYPE_QOS:
                     cfg_info.qos_present = TRUE;
-                    if (p + 2 + 5 * 4 > p_next_cmd) {
+                    if (cfg_len != 2 + 5 * 4) {
+                        android_errorWriteLog(0x534e4554, "119870451");
+                        return;
+                    }
+                    if (p + cfg_len > p_next_cmd) {
                         android_errorWriteLog(0x534e4554, "74202041");
                         return;
                     }
@@ -571,7 +533,11 @@ static void process_l2cap_cmd (tL2C_LCB *p_lcb, UINT8 *p, UINT16 pkt_len)
 
                 case L2CAP_CFG_TYPE_FCR:
                     cfg_info.fcr_present = TRUE;
-                    if (p + 3 + 3 * 2 > p_next_cmd) {
+                    if (cfg_len != 3 + 3 * 2) {
+                        android_errorWriteLog(0x534e4554, "119870451");
+                        return;
+                    }
+                    if (p + cfg_len > p_next_cmd) {
                         android_errorWriteLog(0x534e4554, "74202041");
                         return;
                     }
@@ -585,7 +551,11 @@ static void process_l2cap_cmd (tL2C_LCB *p_lcb, UINT8 *p, UINT16 pkt_len)
 
                 case L2CAP_CFG_TYPE_FCS:
                     cfg_info.fcs_present = TRUE;
-                    if (p + 1 > p_next_cmd) {
+                    if (cfg_len != 1) {
+                        android_errorWriteLog(0x534e4554, "119870451");
+                        return;
+                    }
+                    if (p + cfg_len > p_next_cmd) {
                         android_errorWriteLog(0x534e4554, "74202041");
                         return;
                     }
@@ -594,7 +564,11 @@ static void process_l2cap_cmd (tL2C_LCB *p_lcb, UINT8 *p, UINT16 pkt_len)
 
                 case L2CAP_CFG_TYPE_EXT_FLOW:
                     cfg_info.ext_flow_spec_present = TRUE;
-                    if (p + 2 + 2 + 3 * 4 > p_next_cmd) {
+                    if (cfg_len != 1 + 2 + 3 * 4) {
+                        android_errorWriteLog(0x534e4554, "119870451");
+                        return;
+                    }
+                    if (p + cfg_len > p_next_cmd) {
                         android_errorWriteLog(0x534e4554, "74202041");
                         return;
                     }
@@ -610,6 +584,10 @@ static void process_l2cap_cmd (tL2C_LCB *p_lcb, UINT8 *p, UINT16 pkt_len)
                     /* sanity check option length */
                     if ((cfg_len + L2CAP_CFG_OPTION_OVERHEAD) <= cmd_len)
                     {
+                        if (p + cfg_len > p_next_cmd) {
+                            android_errorWriteLog(0x534e4554, "79488381");
+                            return;
+                        }
                         p += cfg_len;
                         if ((cfg_code & 0x80) == 0)
                         {
@@ -761,7 +739,6 @@ static void process_l2cap_cmd (tL2C_LCB *p_lcb, UINT8 *p, UINT16 pkt_len)
             }
             break;
 
-
         case L2CAP_CMD_DISC_REQ:
             if (p + 4 > p_next_cmd) {
                 android_errorWriteLog(0x534e4554, "74202041");
@@ -829,7 +806,7 @@ static void process_l2cap_cmd (tL2C_LCB *p_lcb, UINT8 *p, UINT16 pkt_len)
             /* Stop the link connect timer if sent before L2CAP connection is up */
             if (p_lcb->w4_info_rsp)
             {
-                btu_stop_timer (&p_lcb->info_timer_entry);
+                alarm_cancel(p_lcb->info_resp_timer);
                 p_lcb->w4_info_rsp = FALSE;
             }
 
@@ -864,7 +841,6 @@ static void process_l2cap_cmd (tL2C_LCB *p_lcb, UINT8 *p, UINT16 pkt_len)
 #endif
             }
 
-
 #if (L2CAP_NUM_FIXED_CHNLS > 0)
             if (info_type == L2CAP_FIXED_CHANNELS_INFO_TYPE)
             {
@@ -922,7 +898,7 @@ void l2c_process_held_packets(BOOLEAN timed_out) {
         return;
 
     if (!timed_out) {
-        btu_stop_timer(&l2cb.rcv_hold_tle);
+        alarm_cancel(l2cb.receive_hold_timer);
         L2CAP_TRACE_WARNING("L2CAP HOLD CONTINUE");
     } else {
         L2CAP_TRACE_WARNING("L2CAP HOLD TIMEOUT");
@@ -940,11 +916,13 @@ void l2c_process_held_packets(BOOLEAN timed_out) {
     }
 
     /* If anyone still in the queue, restart the timeout */
-    if (!list_is_empty(l2cb.rcv_pending_q))
-        btu_start_timer (&l2cb.rcv_hold_tle, BTU_TTYPE_L2CAP_HOLD, BT_1SEC_TIMEOUT);
+    if (!list_is_empty(l2cb.rcv_pending_q)) {
+        alarm_set_on_queue(l2cb.receive_hold_timer, BT_1SEC_TIMEOUT_MS,
+                           l2c_receive_hold_timer_timeout, NULL,
+                           btu_general_alarm_queue);
+    }
 }
 
-
 /*******************************************************************************
 **
 ** Function         l2c_init
@@ -974,7 +952,6 @@ void l2c_init (void)
     l2cb.non_flushable_pbf = L2CAP_PKT_START << L2CAP_PKT_TYPE_SHIFT;
 #endif
 
-
     l2cb.p_free_ccb_first = &l2cb.ccb_pool[0];
     l2cb.p_free_ccb_last  = &l2cb.ccb_pool[MAX_L2CAP_CHANNELS - 1];
 
@@ -1010,48 +987,40 @@ 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__);
+        LOG_ERROR(LOG_TAG, "%s unable to allocate memory for link layer control block", __func__);
+    l2cb.receive_hold_timer = alarm_new("l2c.receive_hold_timer");
 }
 
 void l2c_free(void) {
     list_free(l2cb.rcv_pending_q);
+    l2cb.rcv_pending_q = NULL;
 }
 
-/*******************************************************************************
-**
-** Function         l2c_process_timeout
-**
-** Description      This function is called when an L2CAP-related timeout occurs
-**
-** Returns          void
-**
-*******************************************************************************/
-void l2c_process_timeout (TIMER_LIST_ENT *p_tle)
+void l2c_receive_hold_timer_timeout(UNUSED_ATTR void *data)
 {
-    /* What type of timeout ? */
-    switch (p_tle->event)
-    {
-    case BTU_TTYPE_L2CAP_LINK:
-        l2c_link_timeout ((tL2C_LCB *)p_tle->param);
-        break;
-
-    case BTU_TTYPE_L2CAP_CHNL:
-        l2c_csm_execute (((tL2C_CCB *)p_tle->param), L2CEVT_TIMEOUT, NULL);
-        break;
-
-    case BTU_TTYPE_L2CAP_FCR_ACK:
-        l2c_csm_execute (((tL2C_CCB *)p_tle->param), L2CEVT_ACK_TIMEOUT, NULL);
-        break;
-
-    case BTU_TTYPE_L2CAP_HOLD:
-        /* Update the timeouts in the hold queue */
-        l2c_process_held_packets(TRUE);
-        break;
-
-    case BTU_TTYPE_L2CAP_INFO:
-        l2c_info_timeout((tL2C_LCB *)p_tle->param);
-        break;
-    }
+    /* Update the timeouts in the hold queue */
+    l2c_process_held_packets(TRUE);
+}
+
+void l2c_ccb_timer_timeout(void *data)
+{
+    tL2C_CCB *p_ccb = (tL2C_CCB *)data;
+
+    l2c_csm_execute(p_ccb, L2CEVT_TIMEOUT, NULL);
+}
+
+void l2c_fcrb_ack_timer_timeout(void *data)
+{
+    tL2C_CCB *p_ccb = (tL2C_CCB *)data;
+
+    l2c_csm_execute(p_ccb, L2CEVT_ACK_TIMEOUT, NULL);
+}
+
+void l2c_lcb_timer_timeout(void *data)
+{
+    tL2C_LCB *p_lcb = (tL2C_LCB *)data;
+
+    l2c_link_timeout(p_lcb);
 }
 
 /*******************************************************************************
@@ -1073,16 +1042,23 @@ UINT8 l2c_data_write (UINT16 cid, BT_HDR *p_data, UINT16 flags)
     if ((p_ccb = l2cu_find_ccb_by_cid (NULL, cid)) == NULL)
     {
         L2CAP_TRACE_WARNING ("L2CAP - no CCB for L2CA_DataWrite, CID: %d", cid);
-        GKI_freebuf (p_data);
+        osi_free(p_data);
         return (L2CAP_DW_FAILED);
     }
 
 #ifndef TESTER /* Tester may send any amount of data. otherwise sending message
                   bigger than mtu size of peer is a violation of protocol */
-    if (p_data->len > p_ccb->peer_cfg.mtu)
+    UINT16 mtu;
+
+    if (p_ccb->p_lcb->transport == BT_TRANSPORT_LE)
+        mtu = p_ccb->peer_conn_cfg.mtu;
+    else
+        mtu = p_ccb->peer_cfg.mtu;
+
+    if (p_data->len > mtu)
     {
         L2CAP_TRACE_WARNING ("L2CAP - CID: 0x%04x  cannot send message bigger than peer's mtu size", cid);
-        GKI_freebuf (p_data);
+        osi_free(p_data);
         return (L2CAP_DW_FAILED);
     }
 #endif
@@ -1094,14 +1070,14 @@ UINT8 l2c_data_write (UINT16 cid, BT_HDR *p_data, UINT16 flags)
     if (p_ccb->cong_sent)
     {
         L2CAP_TRACE_ERROR ("L2CAP - CID: 0x%04x cannot send, already congested  xmit_hold_q.count: %u  buff_quota: %u",
-                            p_ccb->local_cid, GKI_queue_length(&p_ccb->xmit_hold_q), p_ccb->buff_quota);
+                           p_ccb->local_cid,
+                           fixed_queue_length(p_ccb->xmit_hold_q),
+                           p_ccb->buff_quota);
 
-        GKI_freebuf (p_data);
+        osi_free(p_data);
         return (L2CAP_DW_FAILED);
     }
 
-    counter_add("l2cap.dyn.tx.bytes", p_data->len);
-    counter_add("l2cap.dyn.tx.pkts", 1);
 
     l2c_csm_execute (p_ccb, L2CEVT_L2CA_DATA_WRITE, p_data);