OSDN Git Service

DO NOT MERGE ANYWHERE HOGP mouse connect failed during OPP TX
authorYamei Du <yamei.du@mediatek.com>
Wed, 18 Nov 2015 09:28:07 +0000 (17:28 +0800)
committerZach Johnson <zachoverflow@google.com>
Thu, 1 Jun 2017 01:10:19 +0000 (18:10 -0700)
FW ACL buffer overflow.
One more ACL packet was sent to FW which is unexpected.

fix l2cap TX control defect.
Call fixed channel TX complete cb after packets is send to lower.

Bug: 26763700
Tested: manual
Change-Id: Iaba14a11c1583da2a72769ebd096e0baedf857c3
CR-Id: ALPS02404396

stack/l2cap/l2c_int.h
stack/l2cap/l2c_link.c
stack/l2cap/l2c_utils.c

index 0611ff8..0390be7 100644 (file)
@@ -683,7 +683,7 @@ extern BOOLEAN  l2cu_lcb_disconnecting (void);
 
 extern BOOLEAN l2cu_create_conn (tL2C_LCB *p_lcb, tBT_TRANSPORT transport);
 extern BOOLEAN l2cu_create_conn_after_switch (tL2C_LCB *p_lcb);
-extern BT_HDR *l2cu_get_next_buffer_to_send (tL2C_LCB *p_lcb);
+extern BT_HDR *l2cu_get_next_buffer_to_send (tL2C_LCB *p_lcb, UINT16 *fixed_cid);
 extern void    l2cu_resubmit_pending_sec_req (BD_ADDR p_bda);
 extern void    l2cu_initialize_amp_ccb (tL2C_LCB *p_lcb);
 extern void    l2cu_adjust_out_mps (tL2C_CCB *p_ccb);
index 16af049..7a50eb2 100644 (file)
@@ -45,7 +45,7 @@
 
 extern fixed_queue_t *btu_general_alarm_queue;
 
-static BOOLEAN l2c_link_send_to_lower (tL2C_LCB *p_lcb, BT_HDR *p_buf);
+static BOOLEAN l2c_link_send_to_lower (tL2C_LCB *p_lcb, BT_HDR *p_buf, UINT16 fixed_cid);
 
 /*******************************************************************************
 **
@@ -1065,6 +1065,7 @@ void l2c_link_check_send_pkts (tL2C_LCB *p_lcb, tL2C_CCB *p_ccb, BT_HDR *p_buf)
 {
     int         xx;
     BOOLEAN     single_write = FALSE;
+    UINT16    fixed_cid;
 
     /* Save the channel ID for faster counting */
     if (p_buf)
@@ -1110,6 +1111,10 @@ void l2c_link_check_send_pkts (tL2C_LCB *p_lcb, tL2C_CCB *p_ccb, BT_HDR *p_buf)
         /* Loop through, starting at the next */
         for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, p_lcb++)
         {
+            /* Check for wraparound */
+            if (p_lcb == &l2cb.lcb_pool[MAX_L2CAP_LINKS])
+                p_lcb = &l2cb.lcb_pool[0];
+
             /* If controller window is full, nothing to do */
             if (p_lcb->transport == BT_TRANSPORT_BR_EDR &&
                 (l2cb.controller_xmit_window == 0 ||
@@ -1132,10 +1137,6 @@ void l2c_link_check_send_pkts (tL2C_LCB *p_lcb, tL2C_CCB *p_ccb, BT_HDR *p_buf)
             }
 #endif
 
-            /* Check for wraparound */
-            if (p_lcb == &l2cb.lcb_pool[MAX_L2CAP_LINKS])
-                p_lcb = &l2cb.lcb_pool[0];
-
             if ( (!p_lcb->in_use)
                || (p_lcb->partial_segment_being_sent)
                || (p_lcb->link_state != LST_CONNECTED)
@@ -1147,7 +1148,7 @@ void l2c_link_check_send_pkts (tL2C_LCB *p_lcb, tL2C_CCB *p_ccb, BT_HDR *p_buf)
             if (!list_is_empty(p_lcb->link_xmit_data_q)) {
                 p_buf = (BT_HDR *)list_front(p_lcb->link_xmit_data_q);
                 list_remove(p_lcb->link_xmit_data_q, p_buf);
-                l2c_link_send_to_lower (p_lcb, p_buf);
+                l2c_link_send_to_lower (p_lcb, p_buf, 0);
             }
             else if (single_write)
             {
@@ -1155,9 +1156,9 @@ void l2c_link_check_send_pkts (tL2C_LCB *p_lcb, tL2C_CCB *p_ccb, BT_HDR *p_buf)
                 break;
             }
             /* If nothing on the link queue, check the channel queue */
-            else if ((p_buf = l2cu_get_next_buffer_to_send (p_lcb)) != NULL)
+            else if ((p_buf = l2cu_get_next_buffer_to_send (p_lcb, &fixed_cid)) != NULL)
             {
-                l2c_link_send_to_lower (p_lcb, p_buf);
+                l2c_link_send_to_lower (p_lcb, p_buf, fixed_cid);
             }
         }
 
@@ -1200,7 +1201,7 @@ void l2c_link_check_send_pkts (tL2C_LCB *p_lcb, tL2C_CCB *p_ccb, BT_HDR *p_buf)
 
             p_buf = (BT_HDR *)list_front(p_lcb->link_xmit_data_q);
             list_remove(p_lcb->link_xmit_data_q, p_buf);
-            if (!l2c_link_send_to_lower (p_lcb, p_buf))
+            if (!l2c_link_send_to_lower (p_lcb, p_buf, 0))
                 break;
         }
 
@@ -1215,10 +1216,10 @@ void l2c_link_check_send_pkts (tL2C_LCB *p_lcb, tL2C_CCB *p_ccb, BT_HDR *p_buf)
             while ((l2cb.controller_xmit_window != 0) && (p_lcb->sent_not_acked < p_lcb->link_xmit_quota))
 #endif
             {
-                if ((p_buf = l2cu_get_next_buffer_to_send (p_lcb)) == NULL)
+                if ((p_buf = l2cu_get_next_buffer_to_send (p_lcb, &fixed_cid)) == NULL)
                     break;
 
-                if (!l2c_link_send_to_lower (p_lcb, p_buf))
+                if (!l2c_link_send_to_lower (p_lcb, p_buf, fixed_cid))
                     break;
             }
         }
@@ -1244,7 +1245,7 @@ void l2c_link_check_send_pkts (tL2C_LCB *p_lcb, tL2C_CCB *p_ccb, BT_HDR *p_buf)
 ** Returns          TRUE for success, FALSE for fail
 **
 *******************************************************************************/
-static BOOLEAN l2c_link_send_to_lower (tL2C_LCB *p_lcb, BT_HDR *p_buf)
+static BOOLEAN l2c_link_send_to_lower (tL2C_LCB *p_lcb, BT_HDR *p_buf, UINT16 fixed_cid)
 {
     UINT16      num_segs;
     UINT16      xmit_window, acl_data_size;
@@ -1375,6 +1376,15 @@ static BOOLEAN l2c_link_send_to_lower (tL2C_LCB *p_lcb, BT_HDR *p_buf)
     }
 #endif
 
+    if (fixed_cid != 0)
+    {
+        L2CAP_TRACE_DEBUG("%s: fixed_cid = %d, send tx complete", __func__, fixed_cid);
+        /* send tx complete */
+        if (l2cb.fixed_reg[fixed_cid - L2CAP_FIRST_FIXED_CHNL].pL2CA_FixedTxComplete_Cb)
+        {
+            (*l2cb.fixed_reg[fixed_cid - L2CAP_FIRST_FIXED_CHNL].pL2CA_FixedTxComplete_Cb)(fixed_cid, 1);
+        }
+    }
     return TRUE;
 }
 
index 5796022..185aa76 100644 (file)
@@ -3538,7 +3538,7 @@ static tL2C_CCB *l2cu_get_next_channel(tL2C_LCB *p_lcb)
 ** Returns          pointer to buffer or NULL
 **
 *******************************************************************************/
-BT_HDR *l2cu_get_next_buffer_to_send (tL2C_LCB *p_lcb)
+BT_HDR *l2cu_get_next_buffer_to_send (tL2C_LCB *p_lcb, UINT16 *fixed_cid)
 {
     tL2C_CCB    *p_ccb;
     BT_HDR      *p_buf;
@@ -3547,6 +3547,7 @@ BT_HDR *l2cu_get_next_buffer_to_send (tL2C_LCB *p_lcb)
 #if (L2CAP_NUM_FIXED_CHNLS > 0)
     int         xx;
 
+    *fixed_cid = 0;
     for (xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++)
     {
         if ((p_ccb = p_lcb->p_fixed_ccbs[xx]) == NULL)
@@ -3586,9 +3587,11 @@ BT_HDR *l2cu_get_next_buffer_to_send (tL2C_LCB *p_lcb)
                     L2CAP_TRACE_ERROR("l2cu_get_buffer_to_send: No data to be sent");
                     return (NULL);
                 }
-                /* send tx complete */
-                if (l2cb.fixed_reg[xx].pL2CA_FixedTxComplete_Cb)
-                    (*l2cb.fixed_reg[xx].pL2CA_FixedTxComplete_Cb)(p_ccb->local_cid, 1);
+                if (fixed_cid != NULL)
+                {
+                    *fixed_cid = p_ccb->local_cid;
+                    L2CAP_TRACE_DEBUG("l2cu_get_buffer_to_send: fixed_cid = %d", *fixed_cid);
+                }
 
                 l2cu_check_channel_congestion (p_ccb);
                 l2cu_set_acl_hci_header (p_buf, p_ccb);