From 0b9d7e785bfe534b96e3bd7f7c6d1f0d64fbc623 Mon Sep 17 00:00:00 2001
From: Matthias Ringwald <matthias@ringwald.ch>
Date: Fri, 1 Apr 2016 14:15:39 +0200
Subject: [PATCH] don't emit X_EVENT_CAN_SEND_NOW if x_can_send_now returns
 false

---
 src/ble/att_dispatch.c | 34 ++++++++++++++++++++++++----------
 src/ble/att_dispatch.h | 15 +++++++++++++++
 src/ble/att_server.c   |  8 ++------
 src/classic/bnep.c     |  8 +-------
 src/classic/rfcomm.c   |  6 +-----
 src/classic/rfcomm.h   |  1 -
 src/l2cap.c            | 34 ++++++++++++++++------------------
 src/l2cap.h            |  1 +
 8 files changed, 60 insertions(+), 47 deletions(-)

diff --git a/src/ble/att_dispatch.c b/src/ble/att_dispatch.c
index ec89ceb27..8fe5a4e06 100644
--- a/src/ble/att_dispatch.c
+++ b/src/ble/att_dispatch.c
@@ -105,11 +105,7 @@ void att_dispatch_register_server(btstack_packet_handler_t packet_handler){
  * @param handle
  */
 int att_dispatch_client_can_send_now(hci_con_handle_t con_handle){
-	int res = l2cap_can_send_fixed_channel_packet_now(con_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL);
-	if (!res){
-		att_client_waiting_for_can_send =1;
-	}
-	return res;
+	return l2cap_can_send_fixed_channel_packet_now(con_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL);
 }
 
 /**
@@ -117,9 +113,27 @@ int att_dispatch_client_can_send_now(hci_con_handle_t con_handle){
  * @param handle
  */
 int att_dispatch_server_can_send_now(hci_con_handle_t con_handle){
-	int res = l2cap_can_send_fixed_channel_packet_now(con_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL);
-	if (!res){
-		att_server_waiting_for_can_send =1;
-	}
-	return res;
+	return l2cap_can_send_fixed_channel_packet_now(con_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL);
+}
+
+/** 
+ * @brief Request emission of L2CAP_EVENT_CAN_SEND_NOW as soon as possible for client
+ * @note L2CAP_EVENT_CAN_SEND_NOW might be emitted during call to this function
+ *       so packet handler should be ready to handle it
+ * @param con_handle
+ */
+void att_dispatch_client_request_can_send_now_event(hci_con_handle_t con_handle){
+	att_client_waiting_for_can_send = 1;
+	l2cap_request_can_send_fix_channel_now_event(con_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL);
+}
+
+/** 
+ * @brief Request emission of L2CAP_EVENT_CAN_SEND_NOW as soon as possible for server
+ * @note L2CAP_EVENT_CAN_SEND_NOW might be emitted during call to this function
+ *       so packet handler should be ready to handle it
+ * @param con_handle
+ */
+void att_dispatch_server_request_can_send_now_event(hci_con_handle_t con_handle){
+	att_server_waiting_for_can_send = 1;
+	l2cap_request_can_send_fix_channel_now_event(con_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL);
 }
diff --git a/src/ble/att_dispatch.h b/src/ble/att_dispatch.h
index eb09b0399..e19b5761a 100644
--- a/src/ble/att_dispatch.h
+++ b/src/ble/att_dispatch.h
@@ -73,6 +73,21 @@ int att_dispatch_client_can_send_now(hci_con_handle_t con_handle);
  */
 int att_dispatch_server_can_send_now(hci_con_handle_t con_handle);
 
+/** 
+ * @brief Request emission of L2CAP_EVENT_CAN_SEND_NOW as soon as possible for client
+ * @note L2CAP_EVENT_CAN_SEND_NOW might be emitted during call to this function
+ *       so packet handler should be ready to handle it
+ * @param con_handle
+ */
+void att_dispatch_client_request_can_send_now_event(hci_con_handle_t con_handle);
+
+/** 
+ * @brief Request emission of L2CAP_EVENT_CAN_SEND_NOW as soon as possible for server
+ * @note L2CAP_EVENT_CAN_SEND_NOW might be emitted during call to this function
+ *       so packet handler should be ready to handle it
+ * @param con_handle
+ */
+void att_dispatch_server_request_can_send_now_event(hci_con_handle_t con_handle);
 
 #if defined __cplusplus
 }
diff --git a/src/ble/att_server.c b/src/ble/att_server.c
index 41ede1b68..7051f6c1b 100644
--- a/src/ble/att_server.c
+++ b/src/ble/att_server.c
@@ -415,16 +415,12 @@ void att_server_register_packet_handler(btstack_packet_handler_t handler){
 
 int  att_server_can_send_packet_now(void){
 	if (att_connection.con_handle == 0) return 0;
-	int can_send = att_dispatch_server_can_send_now(att_connection.con_handle);
-    if (!can_send){
-        att_client_waiting_for_can_send = 1;
-    }
-    return can_send;
+	return att_dispatch_server_can_send_now(att_connection.con_handle);
 }
 
 void att_server_request_can_send_now_event(){
     att_client_waiting_for_can_send = 1;
-    att_server_notify_can_send();
+    att_dispatch_server_request_can_send_now_event(att_connection.con_handle);
 }
 
 int att_server_notify(uint16_t attribute_handle, uint8_t *value, uint16_t value_len){
diff --git a/src/classic/bnep.c b/src/classic/bnep.c
index 4a0059f4b..23c8742df 100644
--- a/src/classic/bnep.c
+++ b/src/classic/bnep.c
@@ -378,13 +378,7 @@ int bnep_can_send_packet_now(uint16_t bnep_cid)
         return 0;
     }
     
-    int can_send = l2cap_can_send_packet_now(channel->l2cap_cid);
-
-    if (!can_send){
-        channel->waiting_for_can_send_now = 1;
-    }
-
-    return can_send;
+    return l2cap_can_send_packet_now(channel->l2cap_cid);
 }
 
 void bnep_request_can_send_now_event(uint16_t bnep_cid)
diff --git a/src/classic/rfcomm.c b/src/classic/rfcomm.c
index 8d09415cd..6870f2cf6 100644
--- a/src/classic/rfcomm.c
+++ b/src/classic/rfcomm.c
@@ -1934,11 +1934,7 @@ int rfcomm_can_send_packet_now(uint16_t rfcomm_cid){
         log_error("rfcomm_send cid 0x%02x doesn't exist!", rfcomm_cid);
         return 0;
     }
-    int res = rfcomm_channel_can_send(channel);
-    if (!res){
-        channel->waiting_for_can_send_now = 1;
-    }
-    return res;
+    return rfcomm_channel_can_send(channel);
 }
 
 void rfcomm_request_can_send_now_event(uint16_t rfcomm_cid){
diff --git a/src/classic/rfcomm.h b/src/classic/rfcomm.h
index 467c15e76..6b725907a 100644
--- a/src/classic/rfcomm.h
+++ b/src/classic/rfcomm.h
@@ -320,7 +320,6 @@ void rfcomm_grant_credits(uint16_t rfcomm_cid, uint8_t credits);
 
 /** 
  * @brief Checks if RFCOMM can send packet. 
- * @note If packet cannot be sent now, a RFCOMM_EVENT_CAN_SEND_NOW will be emitted later
  * @param rfcomm_cid
  * @result != 0 if can send now
  */
diff --git a/src/l2cap.c b/src/l2cap.c
index 551799721..ddc4f9121 100644
--- a/src/l2cap.c
+++ b/src/l2cap.c
@@ -246,6 +246,8 @@ static l2cap_channel_t * l2cap_get_channel_for_local_cid(uint16_t local_cid){
     return NULL;
 }
 
+///
+
 void l2cap_request_can_send_now_event(uint16_t local_cid){
     l2cap_channel_t *channel = l2cap_get_channel_for_local_cid(local_cid);
     if (!channel) return;
@@ -253,37 +255,33 @@ void l2cap_request_can_send_now_event(uint16_t local_cid){
     l2cap_notify_channel_can_send();
 }
 
+void l2cap_request_can_send_fix_channel_now_event(hci_con_handle_t con_handle, uint16_t channel_id){
+    int index = l2cap_fixed_channel_table_index_for_channel_id(channel_id);
+    if (index < 0) return;
+    fixed_channels[index].waiting_for_can_send_now = 1;
+    l2cap_notify_channel_can_send();
+}
+
+///
+
 int  l2cap_can_send_packet_now(uint16_t local_cid){
     l2cap_channel_t *channel = l2cap_get_channel_for_local_cid(local_cid);
     if (!channel) return 0;
-    int can_send = hci_can_send_acl_packet_now(channel->con_handle);
-    if (!can_send){
-        channel->waiting_for_can_send_now = 1;
-    }
-    return can_send;
+    return hci_can_send_acl_packet_now(channel->con_handle);
 }
 
 int  l2cap_can_send_prepared_packet_now(uint16_t local_cid){
     l2cap_channel_t *channel = l2cap_get_channel_for_local_cid(local_cid);
     if (!channel) return 0;
-    int can_send = hci_can_send_prepared_acl_packet_now(channel->con_handle);
-    if (!can_send){
-        channel->waiting_for_can_send_now = 1;
-    }
-    return can_send;
+    return hci_can_send_prepared_acl_packet_now(channel->con_handle);
 }
 
 int  l2cap_can_send_fixed_channel_packet_now(hci_con_handle_t con_handle, uint16_t channel_id){
-    int can_send = hci_can_send_acl_packet_now(con_handle);
-    if (!can_send){
-        int index = l2cap_fixed_channel_table_index_for_channel_id(channel_id);
-        if (index >= 0){
-            fixed_channels[index].waiting_for_can_send_now = 1;
-        }
-    }
-    return can_send;
+    return hci_can_send_acl_packet_now(con_handle);
 }
 
+///
+
 uint16_t l2cap_get_remote_mtu_for_local_cid(uint16_t local_cid){
     l2cap_channel_t * channel = l2cap_get_channel_for_local_cid(local_cid);
     if (channel) {
diff --git a/src/l2cap.h b/src/l2cap.h
index 461a8a643..4010145c5 100644
--- a/src/l2cap.h
+++ b/src/l2cap.h
@@ -167,6 +167,7 @@ typedef struct l2cap_signaling_response {
 
 void l2cap_register_fixed_channel(btstack_packet_handler_t packet_handler, uint16_t channel_id);
 int  l2cap_can_send_fixed_channel_packet_now(hci_con_handle_t con_handle, uint16_t channel_id);
+void l2cap_request_can_send_fix_channel_now_event(hci_con_handle_t con_handle, uint16_t channel_id);
 int  l2cap_send_connectionless(hci_con_handle_t con_handle, uint16_t cid, uint8_t *data, uint16_t len);
 int  l2cap_send_prepared_connectionless(hci_con_handle_t con_handle, uint16_t cid, uint16_t len);