OSDN Git Service

DO NOT MERGE
[android-x86/system-bt.git] / stack / l2cap / l2c_main.c
index f8b7991..3c48d69 100644 (file)
@@ -28,8 +28,9 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include <log/log.h>
+
 #include "bt_target.h"
-#include "btcore/include/counter.h"
 #include "btm_int.h"
 #include "btu.h"
 #include "device/include/controller.h"
@@ -40,6 +41,9 @@
 #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,64 +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);
-        osi_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
@@ -128,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, psm;
+    UINT16      credit;
 
     /* Extract the handle */
     STREAM_TO_UINT16 (handle, p);
@@ -159,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_te, 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 {
@@ -168,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));
             }
-            osi_freebuf (p_msg);
+            osi_free(p_msg);
             return;
         }
     }
     else
     {
         L2CAP_TRACE_WARNING ("L2CAP - expected pkt start or complete, got: %d", pkt_type);
-        osi_freebuf (p_msg);
+        osi_free(p_msg);
         return;
     }
 
@@ -183,6 +134,14 @@ void l2c_rcv_acl_data (BT_HDR *p_msg)
     STREAM_TO_UINT16 (hci_len, p);
     p_msg->offset += 4;
 
+    if (hci_len < L2CAP_PKT_OVERHEAD) {
+        /* Must receive at least the L2CAP length and CID */
+        L2CAP_TRACE_WARNING ("L2CAP - got incorrect hci header");
+        android_errorWriteLog(0x534e4554, "34946955");
+        osi_free(p_msg);
+        return;
+    }
+
     /* Extract the length and CID */
     STREAM_TO_UINT16 (l2cap_len, p);
     STREAM_TO_UINT16 (rcv_cid, p);
@@ -200,44 +159,31 @@ 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);
-            osi_freebuf (p_msg);
+            osi_free(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" );
-        osi_freebuf (p_msg);
-        return;
-    }
+    p_msg->len    = hci_len - L2CAP_PKT_OVERHEAD;
+    p_msg->offset += L2CAP_PKT_OVERHEAD;
 
     if (l2cap_len != p_msg->len)
     {
         L2CAP_TRACE_WARNING ("L2CAP - bad length in pkt. Exp: %d  Act: %d",
                               l2cap_len, p_msg->len);
 
-        osi_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);
-        osi_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); */
         STREAM_TO_UINT16 (psm, p);
         L2CAP_TRACE_DEBUG( "GOT CONNECTIONLESS DATA PSM:%d", psm ) ;
@@ -250,23 +196,19 @@ void l2c_rcv_acl_data (BT_HDR *p_msg)
         }
         else
 #endif
-            osi_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);
-        osi_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 */
@@ -282,28 +224,36 @@ void l2c_rcv_acl_data (BT_HDR *p_msg)
                     (rcv_cid, p_lcb->remote_bd_addr, p_msg);
         }
         else
-            osi_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)
-            osi_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
-                    osi_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);
+                }
             }
         }
     }
@@ -417,7 +367,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;
@@ -734,7 +684,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;
             }
 
@@ -814,7 +764,7 @@ void l2c_process_held_packets(BOOLEAN timed_out) {
         return;
 
     if (!timed_out) {
-        btu_stop_timer(&l2cb.rcv_hold_te);
+        alarm_cancel(l2cb.receive_hold_timer);
         L2CAP_TRACE_WARNING("L2CAP HOLD CONTINUE");
     } else {
         L2CAP_TRACE_WARNING("L2CAP HOLD TIMEOUT");
@@ -832,8 +782,11 @@ 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_te, 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);
+    }
 }
 
 /*******************************************************************************
@@ -901,47 +854,39 @@ void l2c_init (void)
     l2cb.rcv_pending_q = list_new(NULL);
     if (l2cb.rcv_pending_q == NULL)
         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_entry_t *p_te)
+void l2c_receive_hold_timer_timeout(UNUSED_ATTR void *data)
 {
-    /* What type of timeout ? */
-    switch (p_te->event)
-    {
-    case BTU_TTYPE_L2CAP_LINK:
-        l2c_link_timeout ((tL2C_LCB *)p_te->param);
-        break;
-
-    case BTU_TTYPE_L2CAP_CHNL:
-        l2c_csm_execute (((tL2C_CCB *)p_te->param), L2CEVT_TIMEOUT, NULL);
-        break;
-
-    case BTU_TTYPE_L2CAP_FCR_ACK:
-        l2c_csm_execute (((tL2C_CCB *)p_te->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_te->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);
 }
 
 /*******************************************************************************
@@ -963,16 +908,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);
-        osi_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);
-        osi_freebuf (p_data);
+        osi_free(p_data);
         return (L2CAP_DW_FAILED);
     }
 #endif
@@ -988,12 +940,10 @@ UINT8 l2c_data_write (UINT16 cid, BT_HDR *p_data, UINT16 flags)
                            fixed_queue_length(p_ccb->xmit_hold_q),
                            p_ccb->buff_quota);
 
-        osi_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);