slowly work towards incoming rfcomm flow control

This commit is contained in:
matthias.ringwald 2011-09-11 17:58:11 +00:00
parent 3789769fff
commit 8d3b3b9f90
2 changed files with 50 additions and 34 deletions

View File

@ -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;

View File

@ -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;