From 8d3b3b9f9095d05e8b29de6b97d49dbc705aabe4 Mon Sep 17 00:00:00 2001 From: "matthias.ringwald" Date: Sun, 11 Sep 2011 17:58:11 +0000 Subject: [PATCH] slowly work towards incoming rfcomm flow control --- src/rfcomm.c | 70 +++++++++++++++++++++++++++++----------------------- src/rfcomm.h | 14 ++++++++--- 2 files changed, 50 insertions(+), 34 deletions(-) diff --git a/src/rfcomm.c b/src/rfcomm.c index c763eb59e..44207557b 100644 --- a/src/rfcomm.c +++ b/src/rfcomm.c @@ -303,6 +303,10 @@ static void rfcomm_channel_initialize(rfcomm_channel_t *channel, rfcomm_multiple channel->credits_outgoing = 0; channel->packets_granted = 0; + // incoming flow control not active + channel->new_credits_incoming = 0x30; + channel->incoming_flow_control = 0; + if (service) { // incoming connection channel->outgoing = 0; @@ -903,23 +907,6 @@ static void rfcomm_channel_send_credits(rfcomm_channel_t *channel, uint8_t credi channel->credits_incoming += credits; } -static void rfcomm_channel_provide_credits(rfcomm_channel_t *channel){ - - if (!l2cap_can_send_packet_now(channel->multiplexer->l2cap_cid)) return; - - int credits = 0x30; - switch (channel->state) { - case RFCOMM_CHANNEL_DLC_SETUP: - case RFCOMM_CHANNEL_OPEN: - if (channel->credits_incoming < 5){ - rfcomm_channel_send_credits(channel, credits); - } - break; - default: - break; - } -} - static void rfcomm_channel_opened(rfcomm_channel_t *rfChannel){ log_info("rfcomm_channel_opened!\n"); @@ -947,32 +934,39 @@ static void rfcomm_channel_packet_handler_uih(rfcomm_multiplexer_t *multiplexer, const uint8_t credit_offset = ((packet[1] & BT_RFCOMM_UIH_PF) == BT_RFCOMM_UIH_PF) ? 1 : 0; // credits for uih_pf frames const uint8_t payload_offset = 3 + length_offset + credit_offset; - rfcomm_channel_t * rfChannel = rfcomm_channel_for_multiplexer_and_dlci(multiplexer, frame_dlci); - if (!rfChannel) return; + rfcomm_channel_t * channel = rfcomm_channel_for_multiplexer_and_dlci(multiplexer, frame_dlci); + if (!channel) return; - // handle credits + // handle new outgoing credits if (packet[1] == BT_RFCOMM_UIH_PF) { // add them uint16_t new_credits = packet[3+length_offset]; - rfChannel->credits_outgoing += new_credits; - log_info( "RFCOMM data UIH_PF, new credits: %u, now %u\n", new_credits, rfChannel->credits_outgoing); + channel->credits_outgoing += new_credits; + log_info( "RFCOMM data UIH_PF, new credits: %u, now %u\n", new_credits, channel->credits_outgoing); // notify channel statemachine rfcomm_channel_event_t channel_event = { CH_EVT_RCVD_CREDITS }; - rfcomm_channel_state_machine(rfChannel, &channel_event); + rfcomm_channel_state_machine(channel, &channel_event); } - if (rfChannel->credits_incoming > 0){ - rfChannel->credits_incoming--; + // decrease incoming credit counter + if (channel->credits_incoming > 0){ + channel->credits_incoming--; } - rfcomm_channel_provide_credits(rfChannel); + // deliver payload if (size - 1 > payload_offset){ // don't send empty frames, -1 for header checksum at end // log_info( "RFCOMM data UIH_PF, size %u, channel %x\n", size-payload_offset-1, (int) rfChannel->connection); - (*app_packet_handler)(rfChannel->connection, RFCOMM_DATA_PACKET, rfChannel->rfcomm_cid, + (*app_packet_handler)(channel->connection, RFCOMM_DATA_PACKET, channel->rfcomm_cid, &packet[payload_offset], size-payload_offset-1); } + + // provide new credits to remote device, if no incoming flow control + if (!channel->incoming_flow_control && channel->credits_incoming < 5){ + channel->new_credits_incoming = 0x30; + } + // we received new RFCOMM credits, hand them out if possible rfcomm_hand_out_credits(); } @@ -1222,6 +1216,7 @@ void rfcomm_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe if (frame_dlci && (packet[1] == BT_RFCOMM_UIH || packet[1] == BT_RFCOMM_UIH_PF)) { rfcomm_channel_packet_handler_uih(multiplexer, packet, size); + rfcomm_run(); return; } @@ -1455,10 +1450,10 @@ static void rfcomm_channel_state_machine(rfcomm_channel_t *channel, rfcomm_chann log_info("Providing credits for #%u\n", channel->dlci); channel->state_var &= ~RFCOMM_CHANNEL_STATE_VAR_SEND_CREDITS; channel->state_var |= RFCOMM_CHANNEL_STATE_VAR_SENT_CREDITS; - - // TODO: handle client controlled credits - rfcomm_channel_send_credits(channel, 0x30); - // old: rfcomm_channel_provide_credits(channel); + if (channel->new_credits_incoming) { + rfcomm_channel_send_credits(channel, channel->new_credits_incoming); + channel->new_credits_incoming = 0; + } break; } @@ -1485,6 +1480,11 @@ static void rfcomm_channel_state_machine(rfcomm_channel_t *channel, rfcomm_chann rfcomm_send_uih_msc_rsp(multiplexer, channel->dlci, 0x8d); // ea=1,fc=0,rtc=1,rtr=1,ic=0,dv=1 break; } + if (channel->new_credits_incoming) { + rfcomm_channel_send_credits(channel, channel->new_credits_incoming); + channel->new_credits_incoming = 0; + break; + } break; case CH_EVT_RCVD_CREDITS: { // notify daemon -> might trigger re-try of parked connections @@ -1769,6 +1769,14 @@ void rfcomm_decline_connection_internal(uint16_t rfcomm_cid){ rfcomm_run(); } +void rfcomm_grant_credits(uint16_t rfcomm_cid, uint8_t credits){ + rfcomm_channel_t * channel = rfcomm_channel_for_rfcomm_cid(rfcomm_cid); + if (!channel) return; + if (!channel->incoming_flow_control) return; + channel->new_credits_incoming += credits; + rfcomm_run(); +} + // void rfcomm_close_connection(void *connection){ linked_item_t *it; diff --git a/src/rfcomm.h b/src/rfcomm.h index 5cb8d0d98..3964cf36f 100644 --- a/src/rfcomm.h +++ b/src/rfcomm.h @@ -59,6 +59,7 @@ void rfcomm_decline_connection_internal(uint16_t rfcomm_cid); int rfcomm_send_internal(uint8_t rfcomm_cid, uint8_t *data, uint16_t len); void rfcomm_close_connection(void *connection); +#define UNLIMITED_INCOMING_CREDITS 0xff // private structs typedef enum { @@ -127,6 +128,7 @@ typedef enum { CH_EVT_RCVD_MSC_RSP, CH_EVT_RCVD_RPN_CMD, CH_EVT_RCVD_RPN_REQ, + CH_EVT_RCVD_CREDITS, CH_EVT_MULTIPLEXER_READY, CH_EVT_READY_TO_SEND, } RFCOMM_CHANNEL_EVENT; @@ -215,15 +217,21 @@ typedef struct { uint8_t outgoing; uint8_t dlci; + // number of packets granted to client + uint8_t packets_granted; + // credits for outgoing traffic uint8_t credits_outgoing; - // number of packets granted to client - uint8_t packets_granted; - + // number of packets remote will be granted + uint8_t new_credits_incoming; + // credits for incoming traffic uint8_t credits_incoming; + // use incoming flow control + uint8_t incoming_flow_control; + // channel state RFCOMM_CHANNEL_STATE state;