Selaa lähdekoodia

Merge branch 'bugfix/fix_spp_read_flow_control' into 'master'

component_bt/fix spp flow control and vfs write

Closes BT-1011

See merge request espressif/esp-idf!10331
Jiang Jiang Jian 5 vuotta sitten
vanhempi
sitoutus
b3ce1db97a

+ 5 - 0
components/bt/common/btc/core/btc_task.c

@@ -415,3 +415,8 @@ bool btc_check_queue_is_congest(void)
     return false;
 }
 
+int get_btc_work_queue_size(void)
+{
+    return osi_thread_queue_wait_size(btc_thread, 0);
+}
+

+ 1 - 0
components/bt/common/btc/include/btc/btc_task.h

@@ -119,5 +119,6 @@ bt_status_t btc_inter_profile_call(btc_msg_t *msg, void *arg);
 bt_status_t btc_init(void);
 void btc_deinit(void);
 bool btc_check_queue_is_congest(void);
+int get_btc_work_queue_size(void);
 
 #endif /* __BTC_TASK_H__ */

+ 7 - 0
components/bt/common/osi/include/osi/list.h

@@ -22,6 +22,10 @@ list_t *list_new(list_free_cb callback);
 
 
 list_node_t *list_free_node(list_t *list, list_node_t *node);
+
+// similar with list_free_node, this function doesn't free the node data
+list_node_t *list_delete_node(list_t *list, list_node_t *node);
+
 // Frees the list. This function accepts NULL as an argument, in which case it
 // behaves like a no-op.
 void list_free(list_t *list);
@@ -79,6 +83,9 @@ bool list_append(list_t *list, void *data);
 
 bool list_remove(list_t *list, void *data);
 
+// similar with list_remove, but do not free the node data
+bool list_delete(list_t *list, void *data);
+
 // Removes all elements in the list. Calling this function will return the list to the
 // same state it was in after |list_new|. |list| may not be NULL.
 void list_clear(list_t *list);

+ 44 - 0
components/bt/common/osi/list.c

@@ -201,6 +201,36 @@ bool list_remove(list_t *list, void *data)
     return false;
 }
 
+bool list_delete(list_t *list, void *data)
+{
+    assert(list != NULL);
+    assert(data != NULL);
+
+    if (list_is_empty(list)) {
+        return false;
+    }
+
+    if (list->head->data == data) {
+        list_node_t *next = list_delete_node(list, list->head);
+        if (list->tail == list->head) {
+            list->tail = next;
+        }
+        list->head = next;
+        return true;
+    }
+
+    for (list_node_t *prev = list->head, *node = list->head->next; node; prev = node, node = node->next)
+        if (node->data == data) {
+            prev->next = list_delete_node(list, node);
+            if (list->tail == node) {
+                list->tail = prev;
+            }
+            return true;
+        }
+
+    return false;
+}
+
 void list_clear(list_t *list)
 {
     assert(list != NULL);
@@ -266,3 +296,17 @@ list_node_t *list_free_node(list_t *list, list_node_t *node)
 
     return next;
 }
+
+// remove the element from list but do not free the node data
+list_node_t *list_delete_node(list_t *list, list_node_t *node)
+{
+    assert(list != NULL);
+    assert(node != NULL);
+
+    list_node_t *next = node->next;
+
+    osi_free(node);
+    --list->length;
+
+    return next;
+}

+ 4 - 1
components/bt/host/bluedroid/api/include/api/esp_spp_api.h

@@ -27,7 +27,10 @@ typedef enum {
     ESP_SPP_FAILURE,                /*!< Generic failure. */
     ESP_SPP_BUSY,                   /*!< Temporarily can not handle this request. */
     ESP_SPP_NO_DATA,                /*!< no data. */
-    ESP_SPP_NO_RESOURCE             /*!< No more set pm control block */
+    ESP_SPP_NO_RESOURCE,            /*!< No more resource */
+    ESP_SPP_NEED_INIT,              /*!< SPP module shall init first */
+    ESP_SPP_NEED_DEINIT,            /*!< SPP module shall deinit first */
+    ESP_SPP_NO_CONNECTION,          /*!< connection may have been closed */
 } esp_spp_status_t;
 
 /* Security Setting Mask, Suggest to use ESP_SPP_SEC_NONE, ESP_SPP_SEC_AUTHORIZE or ESP_SPP_SEC_AUTHENTICATE only.*/

+ 2 - 2
components/bt/host/bluedroid/bta/dm/bta_dm_act.c

@@ -3827,9 +3827,9 @@ static void bta_dm_adjust_roles(BOOLEAN delay_role_switch)
                         BTM_SwitchRole (bta_dm_cb.device_list.peer_device[i].peer_bdaddr,
                                         HCI_ROLE_MASTER, NULL);
                     } else {
-                        bta_dm_cb.switch_delay_timer.p_cback =
+                        bta_dm_cb.switch_delay_timer[i].p_cback =
                             (TIMER_CBACK *)&bta_dm_delay_role_switch_cback;
-                        bta_sys_start_timer(&bta_dm_cb.switch_delay_timer, 0, 500);
+                        bta_sys_start_timer(&bta_dm_cb.switch_delay_timer[i], 0, 500);
                     }
                 }
 

+ 1 - 1
components/bt/host/bluedroid/bta/dm/include/bta_dm_int.h

@@ -1102,7 +1102,7 @@ typedef struct {
 
 
     tBTA_DM_ENCRYPT_CBACK      *p_encrypt_cback;
-    TIMER_LIST_ENT              switch_delay_timer;
+    TIMER_LIST_ENT              switch_delay_timer[BTA_DM_NUM_PEER_DEVICE];
 
 } tBTA_DM_CB;
 

+ 13 - 0
components/bt/host/bluedroid/bta/include/bta/bta_jv_api.h

@@ -346,6 +346,7 @@ typedef struct {
     UINT32          req_id;     /* The req_id in the associated BTA_JvRfcommWrite() */
     int             len;        /* The length of the data written. */
     BOOLEAN         cong;       /* congestion status */
+    BOOLEAN         old_cong;   /* congestion status */
 } tBTA_JV_RFCOMM_WRITE;
 
 /* data associated with BTA_JV_API_SET_PM_PROFILE_EVT */
@@ -894,6 +895,18 @@ extern tBTA_JV_STATUS BTA_JvRfcommReady(UINT32 handle, UINT32 *p_data_size);
 *******************************************************************************/
 extern tBTA_JV_STATUS BTA_JvRfcommWrite(UINT32 handle, UINT32 req_id, int len, UINT8 *p_data);
 
+/*******************************************************************************
+**
+** Function         BTA_JvRfcommFlowControl
+**
+** Description      This function gives the credit to the peer
+**
+** Returns          BTA_JV_SUCCESS, if the request is being processed.
+**                  BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+extern tBTA_JV_STATUS BTA_JvRfcommFlowControl(UINT32 handle, UINT16 credits_given);
+
 /*******************************************************************************
  **
  ** Function    BTA_JVSetPmProfile

+ 21 - 4
components/bt/host/bluedroid/bta/jv/bta_jv_act.c

@@ -2257,16 +2257,16 @@ void bta_jv_rfcomm_write(tBTA_JV_MSG *p_data)
     evt_data.status = BTA_JV_FAILURE;
     evt_data.handle = p_pcb->handle;
     evt_data.req_id = wc->req_id;
-    evt_data.cong   = p_pcb->cong;
+    evt_data.old_cong = p_pcb->cong;
     bta_jv_pm_conn_busy(p_pcb->p_pm_cb);
-    evt_data.len = wc->len;
-    if (!evt_data.cong &&
+    evt_data.len = -1;
+    if (!evt_data.old_cong &&
             PORT_WriteDataCO(p_pcb->port_handle, &evt_data.len, wc->len, wc->p_data) ==
             PORT_SUCCESS) {
         evt_data.status = BTA_JV_SUCCESS;
     }
     // update congestion flag
-    evt_data.cong   = p_pcb->cong;
+    evt_data.cong = p_pcb->cong;
     if (p_cb->p_cback) {
         p_cb->p_cback(BTA_JV_RFCOMM_WRITE_EVT, (tBTA_JV *)&evt_data, p_pcb->user_data);
     } else {
@@ -2275,6 +2275,23 @@ void bta_jv_rfcomm_write(tBTA_JV_MSG *p_data)
 
 }
 
+/*******************************************************************************
+**
+** Function     bta_jv_rfcomm_flow_control
+**
+** Description  give credits to the peer
+**
+** Returns      void
+**
+*******************************************************************************/
+void bta_jv_rfcomm_flow_control(tBTA_JV_MSG *p_data)
+{
+    tBTA_JV_API_RFCOMM_FLOW_CONTROL *fc = &(p_data->rfcomm_fc);
+
+    tBTA_JV_PCB *p_pcb = fc->p_pcb;
+    PORT_FlowControl_GiveCredit(p_pcb->port_handle, TRUE, fc->credits_given);
+}
+
 /*******************************************************************************
  **
  ** Function     bta_jv_set_pm_profile

+ 32 - 0
components/bt/host/bluedroid/bta/jv/bta_jv_api.c

@@ -1136,6 +1136,38 @@ tBTA_JV_STATUS BTA_JvRfcommWrite(UINT32 handle, UINT32 req_id, int len, UINT8 *p
     return (status);
 }
 
+/*******************************************************************************
+**
+** Function         BTA_JvRfcommFlowControl
+**
+** Description      This function gives credits to the peer
+**
+** Returns          BTA_JV_SUCCESS, if the request is being processed.
+**                  BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+tBTA_JV_STATUS BTA_JvRfcommFlowControl(UINT32 handle, UINT16 credits_given)
+{
+    tBTA_JV_STATUS status = BTA_JV_FAILURE;
+    tBTA_JV_API_RFCOMM_FLOW_CONTROL *p_msg;
+    UINT32  hi = ((handle & BTA_JV_RFC_HDL_MASK) & ~BTA_JV_RFCOMM_MASK) - 1;
+    UINT32  si = BTA_JV_RFC_HDL_TO_SIDX(handle);
+
+    APPL_TRACE_API( "BTA_JvRfcommFlowControl");
+    APPL_TRACE_DEBUG( "handle:0x%x, hi:%d, si:%d", handle, hi, si);
+    if (hi < BTA_JV_MAX_RFC_CONN && bta_jv_cb.rfc_cb[hi].p_cback &&
+            si < BTA_JV_MAX_RFC_SR_SESSION && bta_jv_cb.rfc_cb[hi].rfc_hdl[si] &&
+            (p_msg = (tBTA_JV_API_RFCOMM_FLOW_CONTROL *)osi_malloc(sizeof(tBTA_JV_API_RFCOMM_FLOW_CONTROL))) != NULL) {
+        p_msg->hdr.event = BTA_JV_API_RFCOMM_FLOW_CONTROL_EVT;
+        p_msg->p_cb = &bta_jv_cb.rfc_cb[hi];
+        p_msg->p_pcb = &bta_jv_cb.port_cb[p_msg->p_cb->rfc_hdl[si] - 1];
+        p_msg->credits_given = credits_given;
+        APPL_TRACE_API( "credits given %d", credits_given);
+        bta_sys_sendmsg(p_msg);
+        status = BTA_JV_SUCCESS;
+    }
+    return (status);
+}
 
 /*******************************************************************************
  **

+ 1 - 0
components/bt/host/bluedroid/bta/jv/bta_jv_main.c

@@ -68,6 +68,7 @@ const tBTA_JV_ACTION bta_jv_action[] = {
     bta_jv_rfcomm_stop_server,      /* BTA_JV_API_RFCOMM_STOP_SERVER_EVT */
     bta_jv_rfcomm_read,             /* BTA_JV_API_RFCOMM_READ_EVT */
     bta_jv_rfcomm_write,            /* BTA_JV_API_RFCOMM_WRITE_EVT */
+    bta_jv_rfcomm_flow_control,     /* BTA_JV_API_RFCOMM_FLOW_CONTROL_EVT */
     bta_jv_set_pm_profile,          /* BTA_JV_API_SET_PM_PROFILE_EVT */
     bta_jv_change_pm_state,         /* BTA_JV_API_PM_STATE_CHANGE_EVT */
 #if BTA_JV_L2CAP_INCLUDED

+ 11 - 0
components/bt/host/bluedroid/bta/jv/include/bta_jv_int.h

@@ -62,6 +62,7 @@ enum {
     BTA_JV_API_RFCOMM_STOP_SERVER_EVT,
     BTA_JV_API_RFCOMM_READ_EVT,
     BTA_JV_API_RFCOMM_WRITE_EVT,
+    BTA_JV_API_RFCOMM_FLOW_CONTROL_EVT,
     BTA_JV_API_SET_PM_PROFILE_EVT,
     BTA_JV_API_PM_STATE_CHANGE_EVT,
 #if BTA_JV_L2CAP_INCLUDED
@@ -309,6 +310,14 @@ typedef struct {
     tBTA_JV_PCB     *p_pcb;
 } tBTA_JV_API_RFCOMM_WRITE;
 
+/* data type for BTA_JV_API_RFCOMM_FLOW_CONTROL_EVT */
+typedef struct {
+    BT_HDR      hdr;
+    tBTA_JV_RFC_CB  *p_cb;
+    tBTA_JV_PCB     *p_pcb;
+    UINT16      credits_given;
+} tBTA_JV_API_RFCOMM_FLOW_CONTROL;
+
 /* data type for BTA_JV_API_RFCOMM_CLOSE_EVT */
 typedef struct {
     BT_HDR          hdr;
@@ -375,6 +384,7 @@ typedef union {
     tBTA_JV_API_RFCOMM_CONNECT      rfcomm_connect;
     tBTA_JV_API_RFCOMM_READ         rfcomm_read;
     tBTA_JV_API_RFCOMM_WRITE        rfcomm_write;
+    tBTA_JV_API_RFCOMM_FLOW_CONTROL rfcomm_fc;
     tBTA_JV_API_SET_PM_PROFILE      set_pm;
     tBTA_JV_API_PM_STATE_CHANGE     change_pm_state;
     tBTA_JV_API_RFCOMM_CLOSE        rfcomm_close;
@@ -444,6 +454,7 @@ extern void bta_jv_rfcomm_start_server (tBTA_JV_MSG *p_data);
 extern void bta_jv_rfcomm_stop_server (tBTA_JV_MSG *p_data);
 extern void bta_jv_rfcomm_read (tBTA_JV_MSG *p_data);
 extern void bta_jv_rfcomm_write (tBTA_JV_MSG *p_data);
+extern void bta_jv_rfcomm_flow_control(tBTA_JV_MSG *p_data);
 extern void bta_jv_set_pm_profile (tBTA_JV_MSG *p_data);
 extern void bta_jv_change_pm_state(tBTA_JV_MSG *p_data);
 #if BTA_JV_L2CAP_INCLUDED

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 521 - 235
components/bt/host/bluedroid/btc/profile/std/spp/btc_spp.c


+ 5 - 0
components/bt/host/bluedroid/stack/btu/btu_init.c

@@ -260,3 +260,8 @@ bool BTU_check_queue_is_congest(void)
     return false;
 }
 #endif
+
+int get_btu_work_queue_size(void)
+{
+    return osi_thread_queue_wait_size(btu_thread, 0);
+}

+ 2 - 0
components/bt/host/bluedroid/stack/include/stack/btu.h

@@ -290,6 +290,8 @@ UINT16 BTU_BleAclPktSize(void);
 
 bool btu_task_post(uint32_t sig, void *param, uint32_t timeout);
 
+int get_btu_work_queue_size(void);
+
 /*
 #ifdef __cplusplus
 }

+ 12 - 1
components/bt/host/bluedroid/stack/include/stack/port_api.h

@@ -409,7 +409,18 @@ extern int PORT_Control (UINT16 handle, UINT8 signal);
 *******************************************************************************/
 extern int PORT_FlowControl (UINT16 handle, BOOLEAN enable);
 
-
+/*******************************************************************************
+**
+** Function         PORT_FlowControl_GiveCredit
+**
+** Description      This function gives specified credits to the peer
+**
+** Parameters:      handle        - Handle returned in the RFCOMM_CreateConnection
+**                  enable        - enables data flow
+**                  credits_given - credits to give
+**
+*******************************************************************************/
+extern int PORT_FlowControl_GiveCredit (UINT16 handle, BOOLEAN enable, UINT16 credits_given);
 /*******************************************************************************
 **
 ** Function         PORT_GetModemStatus

+ 71 - 0
components/bt/host/bluedroid/stack/rfcomm/port_api.c

@@ -899,6 +899,77 @@ int PORT_FlowControl_MaxCredit (UINT16 handle, BOOLEAN enable)
 }
 #endif
 
+/*******************************************************************************
+**
+** Function         PORT_FlowControl_GiveCredit
+**
+** Description      This function gives specified credits to the peer
+**
+** Parameters:      handle        - Handle returned in the RFCOMM_CreateConnection
+**                  enable        - enables data flow
+**                  credits_given - credits to give
+**
+*******************************************************************************/
+int PORT_FlowControl_GiveCredit (UINT16 handle, BOOLEAN enable, UINT16 credits_given)
+{
+    tPORT      *p_port;
+    BOOLEAN    old_fc;
+    UINT32     events;
+
+    RFCOMM_TRACE_DEBUG("%s handle:%d enable: %d, cred %d", __func__, handle, enable, credits_given);
+
+    /* Check if handle is valid to avoid crashing */
+    if ((handle == 0) || (handle > MAX_RFC_PORTS)) {
+        return (PORT_BAD_HANDLE);
+    }
+
+    p_port = &rfc_cb.port.port[handle - 1];
+
+    if (!p_port->in_use || (p_port->state == PORT_STATE_CLOSED)) {
+        return (PORT_NOT_OPENED);
+    }
+
+    if (!p_port->rfc.p_mcb) {
+        return (PORT_NOT_OPENED);
+    }
+
+    p_port->rx.user_fc = !enable;
+
+    if (p_port->rfc.p_mcb->flow == PORT_FC_CREDIT) {
+        if (!p_port->rx.user_fc) {
+            port_flow_control_peer(p_port, TRUE, credits_given);
+        }
+    } else {
+        assert(0); // karl: temporarily not allowed
+        old_fc = p_port->local_ctrl.fc;
+
+        /* FC is set if user is set or peer is set */
+        p_port->local_ctrl.fc = (p_port->rx.user_fc | p_port->rx.peer_fc);
+
+        if (p_port->local_ctrl.fc != old_fc) {
+            port_start_control (p_port);
+        }
+    }
+
+    /* Need to take care of the case when we could not deliver events */
+    /* to the application because we were flow controlled */
+    if (enable && (p_port->rx.queue_size != 0)) {
+        assert(0); // karl: temporarily not allowed
+        events = PORT_EV_RXCHAR;
+        if (p_port->rx_flag_ev_pending) {
+            p_port->rx_flag_ev_pending = FALSE;
+            events |= PORT_EV_RXFLAG;
+        }
+
+        events &= p_port->ev_mask;
+        if (p_port->p_callback && events) {
+            p_port->p_callback (events, p_port->inx);
+        }
+    }
+    return (PORT_SUCCESS);
+}
+
+
 /*******************************************************************************
 **
 ** Function         PORT_GetModemStatus

+ 2 - 1
components/bt/host/bluedroid/stack/rfcomm/port_rfc.c

@@ -826,7 +826,8 @@ void PORT_DataInd (tRFC_MCB *p_mcb, UINT8 dlci, BT_HDR *p_buf)
         /* Another packet is delivered to user.  Send credits to peer if required */
 
         if (p_port->p_data_co_callback(p_port->inx, (UINT8 *)p_buf, -1, DATA_CO_CALLBACK_TYPE_INCOMING)) {
-            port_flow_control_peer(p_port, TRUE, 1);
+            // do nothing, flow control credits will be given upon upper-layer request;
+            // port_flow_control_peer(p_port, TRUE, 1);
         } else {
             port_flow_control_peer(p_port, FALSE, 0);
         }

+ 8 - 6
components/bt/host/bluedroid/stack/rfcomm/port_utils.c

@@ -210,17 +210,17 @@ void port_release_port (tPORT *p_port)
 
     osi_mutex_global_lock();
     RFCOMM_TRACE_DEBUG("port_release_port, p_port:%p", p_port);
-    if (p_port->rx.queue) {
+    if (p_port->rx.queue != NULL) {
         while ((p_buf = (BT_HDR *)fixed_queue_dequeue(p_port->rx.queue, 0)) != NULL) {
-            osi_free (p_buf);
+            osi_free(p_buf);
         }
     }
     p_port->rx.queue_size = 0;
 
-    if (p_port->tx.queue) {
+    if (p_port->tx.queue != NULL) {
         while ((p_buf = (BT_HDR *)fixed_queue_dequeue(p_port->tx.queue, 0)) != NULL) {
-            osi_free (p_buf);
-        }   
+            osi_free(p_buf);
+        }
     }
     p_port->tx.queue_size = 0;
 
@@ -514,10 +514,12 @@ void port_flow_control_peer(tPORT *p_port, BOOLEAN enable, UINT16 count)
                     && (p_port->credit_rx_max > p_port->credit_rx)) {
                 rfc_send_credit(p_port->rfc.p_mcb, p_port->dlci,
                                 (UINT8) (p_port->credit_rx_max - p_port->credit_rx));
-
+                RFCOMM_TRACE_DEBUG("send credit: max %d, rx %d, count %d", p_port->credit_rx_max, p_port->credit_rx, count);
                 p_port->credit_rx = p_port->credit_rx_max;
 
                 p_port->rx.peer_fc = FALSE;
+            } else {
+                RFCOMM_TRACE_DEBUG("credit: max %d, rx %d, low %d", p_port->credit_rx_max, p_port->credit_rx, p_port->credit_rx_low);
             }
         }
         /* else want to disable flow from peer */

Kaikkia tiedostoja ei voida näyttää, sillä liian monta tiedostoa muuttui tässä diffissä