moved l2cap_channel_t, l2cap_service_t, rfcomm_multiplexer_t, rfcomm_channel_t, rfcomm_service_t to header files

This commit is contained in:
matthias.ringwald 2011-07-24 08:49:09 +00:00
parent 9574ad1db1
commit 73cf2b3d2a
4 changed files with 348 additions and 337 deletions

View File

@ -66,93 +66,6 @@
#define L2CAP_SIGNALING_COMMAND_LENGTH_OFFSET 2
#define L2CAP_SIGNALING_COMMAND_DATA_OFFSET 4
typedef enum {
L2CAP_STATE_CLOSED = 1, // no baseband
L2CAP_STATE_WILL_SEND_CREATE_CONNECTION,
L2CAP_STATE_WAIT_CONNECTION_COMPLETE,
L2CAP_STATE_WAIT_CLIENT_ACCEPT_OR_REJECT,
L2CAP_STATE_WAIT_CONNECT_RSP, // from peer
L2CAP_STATE_CONFIG,
L2CAP_STATE_OPEN,
L2CAP_STATE_WAIT_DISCONNECT, // from application
L2CAP_STATE_WILL_SEND_CONNECTION_REQUEST,
L2CAP_STATE_WILL_SEND_CONNECTION_RESPONSE_DECLINE,
L2CAP_STATE_WILL_SEND_CONNECTION_RESPONSE_ACCEPT,
L2CAP_STATE_WILL_SEND_DISCONNECT_REQUEST,
L2CAP_STATE_WILL_SEND_DISCONNECT_RESPONSE,
} L2CAP_STATE;
typedef enum {
STATE_VAR_NONE = 0,
STATE_VAR_RCVD_CONF_REQ = 1 << 0,
STATE_VAR_RCVD_CONF_RSP = 1 << 1,
STATE_VAR_SEND_CONF_REQ = 1 << 2,
STATE_VAR_SEND_CONF_RSP = 1 << 3,
STATE_VAR_SENT_CONF_REQ = 1 << 4,
STATE_VAR_SENT_CONF_RSP = 1 << 5,
} L2CAP_CHANNEL_STATE_VAR;
// info regarding an actual coneection
typedef struct {
// linked list - assert: first field
linked_item_t item;
L2CAP_STATE state;
L2CAP_CHANNEL_STATE_VAR state_var;
bd_addr_t address;
hci_con_handle_t handle;
uint8_t remote_sig_id; // used by other side, needed for delayed response
uint8_t local_sig_id; // own signaling identifier
uint16_t local_cid;
uint16_t remote_cid;
uint16_t local_mtu;
uint16_t remote_mtu;
uint16_t psm;
uint8_t packets_granted; // number of L2CAP/ACL packets client is allowed to send
uint8_t reason; // used in decline internal
// client connection
void * connection;
// internal connection
btstack_packet_handler_t packet_handler;
} l2cap_channel_t;
// info regarding potential connections
typedef struct {
// linked list - assert: first field
linked_item_t item;
// service id
uint16_t psm;
// incoming MTU
uint16_t mtu;
// client connection
void *connection;
// internal connection
btstack_packet_handler_t packet_handler;
} l2cap_service_t;
typedef struct l2cap_signaling_response {
hci_con_handle_t handle;
uint8_t sig_id;
uint8_t code;
uint16_t infoType;
} l2cap_signaling_response_t;
static void null_packet_handler(void * connection, uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
static void l2cap_packet_handler(uint8_t packet_type, uint8_t *packet, uint16_t size);
@ -423,7 +336,7 @@ void l2cap_run(void){
case L2CAP_STATE_WILL_SEND_CONNECTION_RESPONSE_ACCEPT:
channel->state = L2CAP_STATE_CONFIG;
channel->state_var |= STATE_VAR_SEND_CONF_REQ;
channel->state_var |= L2CAP_CHANNEL_STATE_VAR_SEND_CONF_REQ;
l2cap_send_signaling_packet(channel->handle, CONNECTION_RESPONSE, channel->remote_sig_id, channel->local_cid, channel->remote_cid, 0, 0);
break;
@ -435,14 +348,14 @@ void l2cap_run(void){
break;
case L2CAP_STATE_CONFIG:
if (channel->state_var & STATE_VAR_SEND_CONF_RSP){
channel->state_var &= ~STATE_VAR_SEND_CONF_RSP;
channel->state_var |= STATE_VAR_SENT_CONF_RSP;
if (channel->state_var & L2CAP_CHANNEL_STATE_VAR_SEND_CONF_RSP){
channel->state_var &= ~L2CAP_CHANNEL_STATE_VAR_SEND_CONF_RSP;
channel->state_var |= L2CAP_CHANNEL_STATE_VAR_SENT_CONF_RSP;
l2cap_send_signaling_packet(channel->handle, CONFIGURE_RESPONSE, channel->remote_sig_id, channel->remote_cid, 0, 0, 0, NULL);
}
else if (channel->state_var & STATE_VAR_SEND_CONF_REQ){
channel->state_var &= ~STATE_VAR_SEND_CONF_REQ;
channel->state_var |= STATE_VAR_SENT_CONF_REQ;
else if (channel->state_var & L2CAP_CHANNEL_STATE_VAR_SEND_CONF_REQ){
channel->state_var &= ~L2CAP_CHANNEL_STATE_VAR_SEND_CONF_REQ;
channel->state_var |= L2CAP_CHANNEL_STATE_VAR_SENT_CONF_REQ;
channel->local_sig_id = l2cap_next_sig_id();
config_options[0] = 1; // MTU
config_options[1] = 2; // len param
@ -502,7 +415,7 @@ void l2cap_create_channel_internal(void * connection, btstack_packet_handler_t p
// set initial state
chan->state = L2CAP_STATE_WILL_SEND_CREATE_CONNECTION;
chan->state_var = STATE_VAR_NONE;
chan->state_var = L2CAP_CHANNEL_STATE_VAR_NONE;
chan->remote_sig_id = L2CAP_SIG_ID_INVALID;
chan->local_sig_id = L2CAP_SIG_ID_INVALID;
@ -699,7 +612,7 @@ static void l2cap_handle_connection_request(hci_con_handle_t handle, uint8_t sig
// set initial state
channel->state = L2CAP_STATE_WAIT_CLIENT_ACCEPT_OR_REJECT;
channel->state_var = STATE_VAR_NONE;
channel->state_var = L2CAP_CHANNEL_STATE_VAR_NONE;
// add to connections list
linked_list_add(&l2cap_channels, (linked_item_t *) channel);
@ -753,8 +666,8 @@ void l2cap_signaling_handle_configure_request(l2cap_channel_t *channel, uint8_t
static int l2cap_channel_ready_for_open(l2cap_channel_t *channel){
// log_info("l2cap_channel_ready_for_open 0x%02x\n", channel->state_var);
if ((channel->state_var & STATE_VAR_RCVD_CONF_RSP) == 0) return 0;
if ((channel->state_var & STATE_VAR_SENT_CONF_RSP) == 0) return 0;
if ((channel->state_var & L2CAP_CHANNEL_STATE_VAR_RCVD_CONF_RSP) == 0) return 0;
if ((channel->state_var & L2CAP_CHANNEL_STATE_VAR_SENT_CONF_RSP) == 0) return 0;
return 1;
}
@ -795,7 +708,7 @@ void l2cap_signaling_handler_channel(l2cap_channel_t *channel, uint8_t *command)
// successful connection
channel->remote_cid = READ_BT_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET);
channel->state = L2CAP_STATE_CONFIG;
channel->state_var |= STATE_VAR_SEND_CONF_REQ;
channel->state_var |= L2CAP_CHANNEL_STATE_VAR_SEND_CONF_REQ;
break;
case 1:
// connection pending. get some coffee
@ -828,12 +741,12 @@ void l2cap_signaling_handler_channel(l2cap_channel_t *channel, uint8_t *command)
case L2CAP_STATE_CONFIG:
switch (code) {
case CONFIGURE_REQUEST:
channel->state_var |= STATE_VAR_RCVD_CONF_REQ;
channel->state_var |= STATE_VAR_SEND_CONF_RSP;
channel->state_var |= L2CAP_CHANNEL_STATE_VAR_RCVD_CONF_REQ;
channel->state_var |= L2CAP_CHANNEL_STATE_VAR_SEND_CONF_RSP;
l2cap_signaling_handle_configure_request(channel, command);
break;
case CONFIGURE_RESPONSE:
channel->state_var |= STATE_VAR_RCVD_CONF_RSP;
channel->state_var |= L2CAP_CHANNEL_STATE_VAR_RCVD_CONF_RSP;
break;
default:
break;

View File

@ -68,6 +68,96 @@ void l2cap_unregister_service_internal(void *connection, uint16_t psm);
void l2cap_accept_connection_internal(uint16_t local_cid);
void l2cap_decline_connection_internal(uint16_t local_cid, uint8_t reason);
// private structs
typedef enum {
L2CAP_STATE_CLOSED = 1, // no baseband
L2CAP_STATE_WILL_SEND_CREATE_CONNECTION,
L2CAP_STATE_WAIT_CONNECTION_COMPLETE,
L2CAP_STATE_WAIT_CLIENT_ACCEPT_OR_REJECT,
L2CAP_STATE_WAIT_CONNECT_RSP, // from peer
L2CAP_STATE_CONFIG,
L2CAP_STATE_OPEN,
L2CAP_STATE_WAIT_DISCONNECT, // from application
L2CAP_STATE_WILL_SEND_CONNECTION_REQUEST,
L2CAP_STATE_WILL_SEND_CONNECTION_RESPONSE_DECLINE,
L2CAP_STATE_WILL_SEND_CONNECTION_RESPONSE_ACCEPT,
L2CAP_STATE_WILL_SEND_DISCONNECT_REQUEST,
L2CAP_STATE_WILL_SEND_DISCONNECT_RESPONSE,
} L2CAP_STATE;
typedef enum {
L2CAP_CHANNEL_STATE_VAR_NONE = 0,
L2CAP_CHANNEL_STATE_VAR_RCVD_CONF_REQ = 1 << 0,
L2CAP_CHANNEL_STATE_VAR_RCVD_CONF_RSP = 1 << 1,
L2CAP_CHANNEL_STATE_VAR_SEND_CONF_REQ = 1 << 2,
L2CAP_CHANNEL_STATE_VAR_SEND_CONF_RSP = 1 << 3,
L2CAP_CHANNEL_STATE_VAR_SENT_CONF_REQ = 1 << 4,
L2CAP_CHANNEL_STATE_VAR_SENT_CONF_RSP = 1 << 5,
} L2CAP_CHANNEL_STATE_VAR;
// info regarding an actual coneection
typedef struct {
// linked list - assert: first field
linked_item_t item;
L2CAP_STATE state;
L2CAP_CHANNEL_STATE_VAR state_var;
bd_addr_t address;
hci_con_handle_t handle;
uint8_t remote_sig_id; // used by other side, needed for delayed response
uint8_t local_sig_id; // own signaling identifier
uint16_t local_cid;
uint16_t remote_cid;
uint16_t local_mtu;
uint16_t remote_mtu;
uint16_t psm;
uint8_t packets_granted; // number of L2CAP/ACL packets client is allowed to send
uint8_t reason; // used in decline internal
// client connection
void * connection;
// internal connection
btstack_packet_handler_t packet_handler;
} l2cap_channel_t;
// info regarding potential connections
typedef struct {
// linked list - assert: first field
linked_item_t item;
// service id
uint16_t psm;
// incoming MTU
uint16_t mtu;
// client connection
void *connection;
// internal connection
btstack_packet_handler_t packet_handler;
} l2cap_service_t;
typedef struct l2cap_signaling_response {
hci_con_handle_t handle;
uint8_t sig_id;
uint8_t code;
uint16_t infoType;
} l2cap_signaling_response_t;
#if defined __cplusplus
}
#endif

View File

@ -84,195 +84,6 @@
#include "l2cap.h"
// private structs
typedef enum {
RFCOMM_MULTIPLEXER_CLOSED = 1,
RFCOMM_MULTIPLEXER_W4_CONNECT, // outgoing
RFCOMM_MULTIPLEXER_SEND_SABM_0, // "
RFCOMM_MULTIPLEXER_W4_UA_0, // "
RFCOMM_MULTIPLEXER_W4_SABM_0, // incoming
RFCOMM_MULTIPLEXER_SEND_UA_0,
RFCOMM_MULTIPLEXER_OPEN,
RFCOMM_MULTIPLEXER_SEND_UA_0_AND_DISC
} RFCOMM_MULTIPLEXER_STATE;
typedef enum {
MULT_EV_READY_TO_SEND = 1,
} RFCOMM_MULTIPLEXER_EVENT;
typedef enum {
RFCOMM_CHANNEL_CLOSED = 1,
RFCOMM_CHANNEL_W4_MULTIPLEXER,
RFCOMM_CHANNEL_SEND_UIH_PN,
RFCOMM_CHANNEL_W4_PN_RSP,
RFCOMM_CHANNEL_SEND_SABM_W4_UA,
RFCOMM_CHANNEL_W4_UA,
RFCOMM_CHANNEL_INCOMING_SETUP,
RFCOMM_CHANNEL_DLC_SETUP,
RFCOMM_CHANNEL_OPEN,
RFCOMM_CHANNEL_SEND_UA_AFTER_DISC,
RFCOMM_CHANNEL_SEND_DISC,
RFCOMM_CHANNEL_SEND_DM,
} RFCOMM_CHANNEL_STATE;
typedef enum {
STATE_VAR_NONE = 0,
STATE_VAR_CLIENT_ACCEPTED = 1 << 0,
STATE_VAR_RCVD_PN = 1 << 1,
STATE_VAR_RCVD_RPN = 1 << 2,
STATE_VAR_RCVD_SABM = 1 << 3,
STATE_VAR_RCVD_MSC_CMD = 1 << 4,
STATE_VAR_RCVD_MSC_RSP = 1 << 5,
STATE_VAR_SEND_PN_RSP = 1 << 6,
STATE_VAR_SEND_RPN_INFO = 1 << 7,
STATE_VAR_SEND_RPN_RSP = 1 << 8,
STATE_VAR_SEND_UA = 1 << 9,
STATE_VAR_SEND_MSC_CMD = 1 << 10,
STATE_VAR_SEND_MSC_RSP = 1 << 11,
STATE_VAR_SEND_CREDITS = 1 << 12,
STATE_VAR_SENT_MSC_CMD = 1 << 13,
STATE_VAR_SENT_MSC_RSP = 1 << 14,
STATE_VAR_SENT_CREDITS = 1 << 15,
} RFCOMM_CHANNEL_STATE_VAR;
typedef enum {
CH_EVT_RCVD_SABM = 1,
CH_EVT_RCVD_UA,
CH_EVT_RCVD_PN,
CH_EVT_RCVD_PN_RSP,
CH_EVT_RCVD_DISC,
CH_EVT_RCVD_DM,
CH_EVT_RCVD_MSC_CMD,
CH_EVT_RCVD_MSC_RSP,
CH_EVT_RCVD_RPN_CMD,
CH_EVT_RCVD_RPN_REQ,
CH_EVT_MULTIPLEXER_READY,
CH_EVT_READY_TO_SEND,
} RFCOMM_CHANNEL_EVENT;
typedef struct rfcomm_channel_event {
RFCOMM_CHANNEL_EVENT type;
} rfcomm_channel_event_t;
typedef struct rfcomm_channel_event_pn {
rfcomm_channel_event_t super;
uint16_t max_frame_size;
uint8_t priority;
uint8_t credits_outgoing;
} rfcomm_channel_event_pn_t;
typedef struct rfcomm_rpn_data {
uint8_t baud_rate;
uint8_t flags;
uint8_t flow_control;
uint8_t xon;
uint8_t xoff;
uint8_t parameter_mask_0; // first byte
uint8_t parameter_mask_1; // second byte
} rfcomm_rpn_data_t;
typedef struct rfcomm_channel_event_rpn {
rfcomm_channel_event_t super;
rfcomm_rpn_data_t data;
} rfcomm_channel_event_rpn_t;
// info regarding potential connections
typedef struct {
// linked list - assert: first field
linked_item_t item;
// server channel
uint8_t server_channel;
// incoming max frame size
uint16_t max_frame_size;
// client connection
void *connection;
// internal connection
btstack_packet_handler_t packet_handler;
} rfcomm_service_t;
// info regarding multiplexer
// note: spec mandates single multplexer per device combination
typedef struct {
// linked list - assert: first field
linked_item_t item;
timer_source_t timer;
int timer_active;
RFCOMM_MULTIPLEXER_STATE state;
uint16_t l2cap_cid;
uint8_t l2cap_credits;
bd_addr_t remote_addr;
hci_con_handle_t con_handle;
uint8_t outgoing;
// hack to deal with authentication failure only observed by remote side
uint8_t at_least_one_connection;
uint16_t max_frame_size;
// send DM for DLCI != 0
uint8_t send_dm_for_dlci;
} rfcomm_multiplexer_t;
// info regarding an actual coneection
typedef struct {
// linked list - assert: first field
linked_item_t item;
rfcomm_multiplexer_t *multiplexer;
uint16_t rfcomm_cid;
uint8_t outgoing;
uint8_t dlci;
// credits for outgoing traffic
uint8_t credits_outgoing;
// number of packets granted to client
uint8_t packets_granted;
// credits for incoming traffic
uint8_t credits_incoming;
// channel state
RFCOMM_CHANNEL_STATE state;
// state variables used in RFCOMM_CHANNEL_INCOMING
RFCOMM_CHANNEL_STATE_VAR state_var;
// priority set by incoming side in PN
uint8_t pn_priority;
// negotiated frame size
uint16_t max_frame_size;
// rpn data
rfcomm_rpn_data_t rpn_data;
// server channel (see rfcomm_service_t) - NULL => outgoing channel
rfcomm_service_t * service;
// internal connection
btstack_packet_handler_t packet_handler;
// client connection
void * connection;
} rfcomm_channel_t;
// global rfcomm data
static uint16_t rfcomm_client_cid_generator; // used for client channel IDs
@ -444,7 +255,7 @@ static void rfcomm_channel_initialize(rfcomm_channel_t *channel, rfcomm_multiple
bzero(channel, sizeof(rfcomm_channel_t));
channel->state = RFCOMM_CHANNEL_CLOSED;
channel->state_var = STATE_VAR_NONE;
channel->state_var = RFCOMM_CHANNEL_STATE_VAR_NONE;
channel->multiplexer = multiplexer;
channel->service = service;
@ -1361,10 +1172,10 @@ void rfcomm_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe
}
static int rfcomm_channel_ready_for_open(rfcomm_channel_t *channel){
// log_info("rfcomm_channel_ready_for_open state %u, flags needed %04x, current %04x, rf credits %u, l2cap credits %u \n", channel->state, STATE_VAR_RCVD_MSC_RSP|STATE_VAR_SENT_MSC_RSP|STATE_VAR_SENT_CREDITS, channel->state_var, channel->credits_outgoing, channel->multiplexer->l2cap_credits);
if ((channel->state_var & STATE_VAR_RCVD_MSC_RSP) == 0) return 0;
if ((channel->state_var & STATE_VAR_SENT_MSC_RSP) == 0) return 0;
if ((channel->state_var & STATE_VAR_SENT_CREDITS) == 0) return 0;
// log_info("rfcomm_channel_ready_for_open state %u, flags needed %04x, current %04x, rf credits %u, l2cap credits %u \n", channel->state, RFCOMM_CHANNEL_STATE_VAR_RCVD_MSC_RSP|RFCOMM_CHANNEL_STATE_VAR_SENT_MSC_RSP|RFCOMM_CHANNEL_STATE_VAR_SENT_CREDITS, channel->state_var, channel->credits_outgoing, channel->multiplexer->l2cap_credits);
if ((channel->state_var & RFCOMM_CHANNEL_STATE_VAR_RCVD_MSC_RSP) == 0) return 0;
if ((channel->state_var & RFCOMM_CHANNEL_STATE_VAR_SENT_MSC_RSP) == 0) return 0;
if ((channel->state_var & RFCOMM_CHANNEL_STATE_VAR_SENT_CREDITS) == 0) return 0;
if (channel->credits_outgoing == 0) return 0;
return 1;
@ -1404,7 +1215,7 @@ static void rfcomm_channel_state_machine(rfcomm_channel_t *channel, rfcomm_chann
// control port parameters
rfcomm_channel_event_rpn_t *event_rpn = (rfcomm_channel_event_rpn_t*) event;
memcpy(&channel->rpn_data, &event_rpn->data, sizeof(rfcomm_rpn_data_t));
channel->state_var |= STATE_VAR_SEND_RPN_RSP;
channel->state_var |= RFCOMM_CHANNEL_STATE_VAR_SEND_RPN_RSP;
return;
}
@ -1420,15 +1231,15 @@ static void rfcomm_channel_state_machine(rfcomm_channel_t *channel, rfcomm_chann
rpn_data.parameter_mask_0 = 0x7f; /* parameter mask, all values set */
rpn_data.parameter_mask_1 = 0x3f; /* parameter mask, all values set */
memcpy(&channel->rpn_data, &rpn_data, sizeof(rfcomm_rpn_data_t));
channel->state_var |= STATE_VAR_SEND_RPN_RSP;
channel->state_var |= RFCOMM_CHANNEL_STATE_VAR_SEND_RPN_RSP;
return;
}
// TODO: integrate in common swich
if (event->type == CH_EVT_READY_TO_SEND){
if (channel->state_var & STATE_VAR_SEND_RPN_RSP){
if (channel->state_var & RFCOMM_CHANNEL_STATE_VAR_SEND_RPN_RSP){
log_info("Sending Remote Port Negotiation RSP for #%u\n", channel->dlci);
channel->state_var &= ~STATE_VAR_SEND_RPN_RSP;
channel->state_var &= ~RFCOMM_CHANNEL_STATE_VAR_SEND_RPN_RSP;
rfcomm_send_uih_rpn_rsp(multiplexer, channel->dlci, &channel->rpn_data);
return;
}
@ -1441,14 +1252,14 @@ static void rfcomm_channel_state_machine(rfcomm_channel_t *channel, rfcomm_chann
switch (event->type){
case CH_EVT_RCVD_SABM:
log_info("-> Inform app\n");
channel->state_var |= STATE_VAR_RCVD_SABM;
channel->state_var |= RFCOMM_CHANNEL_STATE_VAR_RCVD_SABM;
channel->state = RFCOMM_CHANNEL_INCOMING_SETUP;
rfcomm_emit_connection_request(channel);
break;
case CH_EVT_RCVD_PN:
rfcomm_channel_accept_pn(channel, event_pn);
log_info("-> Inform app\n");
channel->state_var |= STATE_VAR_RCVD_PN;
channel->state_var |= RFCOMM_CHANNEL_STATE_VAR_RCVD_PN;
channel->state = RFCOMM_CHANNEL_INCOMING_SETUP;
rfcomm_emit_connection_request(channel);
break;
@ -1460,32 +1271,32 @@ static void rfcomm_channel_state_machine(rfcomm_channel_t *channel, rfcomm_chann
case RFCOMM_CHANNEL_INCOMING_SETUP:
switch (event->type){
case CH_EVT_RCVD_SABM:
channel->state_var |= STATE_VAR_RCVD_SABM;
if (channel->state_var & STATE_VAR_CLIENT_ACCEPTED) {
channel->state_var |= STATE_VAR_SEND_UA;
channel->state_var |= RFCOMM_CHANNEL_STATE_VAR_RCVD_SABM;
if (channel->state_var & RFCOMM_CHANNEL_STATE_VAR_CLIENT_ACCEPTED) {
channel->state_var |= RFCOMM_CHANNEL_STATE_VAR_SEND_UA;
}
break;
case CH_EVT_RCVD_PN:
rfcomm_channel_accept_pn(channel, event_pn);
channel->state_var |= STATE_VAR_RCVD_PN;
if (channel->state_var & STATE_VAR_CLIENT_ACCEPTED) {
channel->state_var |= STATE_VAR_SEND_PN_RSP;
channel->state_var |= RFCOMM_CHANNEL_STATE_VAR_RCVD_PN;
if (channel->state_var & RFCOMM_CHANNEL_STATE_VAR_CLIENT_ACCEPTED) {
channel->state_var |= RFCOMM_CHANNEL_STATE_VAR_SEND_PN_RSP;
}
break;
case CH_EVT_READY_TO_SEND:
if (channel->state_var & STATE_VAR_SEND_PN_RSP){
if (channel->state_var & RFCOMM_CHANNEL_STATE_VAR_SEND_PN_RSP){
log_info("Sending UIH Parameter Negotiation Respond for #%u\n", channel->dlci);
channel->state_var &= ~STATE_VAR_SEND_PN_RSP;
channel->state_var &= ~RFCOMM_CHANNEL_STATE_VAR_SEND_PN_RSP;
rfcomm_send_uih_pn_response(multiplexer, channel->dlci, channel->pn_priority, channel->max_frame_size);
}
else if (channel->state_var & STATE_VAR_SEND_UA){
else if (channel->state_var & RFCOMM_CHANNEL_STATE_VAR_SEND_UA){
log_info("Sending UA #%u\n", channel->dlci);
channel->state_var &= ~STATE_VAR_SEND_UA;
channel->state_var &= ~RFCOMM_CHANNEL_STATE_VAR_SEND_UA;
rfcomm_send_ua(multiplexer, channel->dlci);
}
if ((channel->state_var & STATE_VAR_CLIENT_ACCEPTED) && (channel->state_var & STATE_VAR_RCVD_SABM)) {
channel->state_var |= STATE_VAR_SEND_MSC_CMD;
channel->state_var |= STATE_VAR_SEND_CREDITS;
if ((channel->state_var & RFCOMM_CHANNEL_STATE_VAR_CLIENT_ACCEPTED) && (channel->state_var & RFCOMM_CHANNEL_STATE_VAR_RCVD_SABM)) {
channel->state_var |= RFCOMM_CHANNEL_STATE_VAR_SEND_MSC_CMD;
channel->state_var |= RFCOMM_CHANNEL_STATE_VAR_SEND_CREDITS;
channel->state = RFCOMM_CHANNEL_DLC_SETUP;
}
break;
@ -1550,8 +1361,8 @@ static void rfcomm_channel_state_machine(rfcomm_channel_t *channel, rfcomm_chann
switch (event->type){
case CH_EVT_RCVD_UA:
channel->state = RFCOMM_CHANNEL_DLC_SETUP;
channel->state_var |= STATE_VAR_SEND_MSC_CMD;
channel->state_var |= STATE_VAR_SEND_CREDITS;
channel->state_var |= RFCOMM_CHANNEL_STATE_VAR_SEND_MSC_CMD;
channel->state_var |= RFCOMM_CHANNEL_STATE_VAR_SEND_CREDITS;
break;
default:
break;
@ -1561,32 +1372,32 @@ static void rfcomm_channel_state_machine(rfcomm_channel_t *channel, rfcomm_chann
case RFCOMM_CHANNEL_DLC_SETUP:
switch (event->type){
case CH_EVT_RCVD_MSC_CMD:
channel->state_var |= STATE_VAR_RCVD_MSC_CMD;
channel->state_var |= STATE_VAR_SEND_MSC_RSP;
channel->state_var |= RFCOMM_CHANNEL_STATE_VAR_RCVD_MSC_CMD;
channel->state_var |= RFCOMM_CHANNEL_STATE_VAR_SEND_MSC_RSP;
break;
case CH_EVT_RCVD_MSC_RSP:
channel->state_var |= STATE_VAR_RCVD_MSC_RSP;
channel->state_var |= RFCOMM_CHANNEL_STATE_VAR_RCVD_MSC_RSP;
break;
case CH_EVT_READY_TO_SEND:
if (channel->state_var & STATE_VAR_SEND_MSC_CMD){
if (channel->state_var & RFCOMM_CHANNEL_STATE_VAR_SEND_MSC_CMD){
log_info("Sending MSC CMD for #%u\n", channel->dlci);
channel->state_var &= ~STATE_VAR_SEND_MSC_CMD;
channel->state_var |= STATE_VAR_SENT_MSC_CMD;
channel->state_var &= ~RFCOMM_CHANNEL_STATE_VAR_SEND_MSC_CMD;
channel->state_var |= RFCOMM_CHANNEL_STATE_VAR_SENT_MSC_CMD;
rfcomm_send_uih_msc_cmd(multiplexer, channel->dlci , 0x8d); // ea=1,fc=0,rtc=1,rtr=1,ic=0,dv=1
break;
}
if (channel->state_var & STATE_VAR_SEND_MSC_RSP){
if (channel->state_var & RFCOMM_CHANNEL_STATE_VAR_SEND_MSC_RSP){
log_info("Sending MSC RSP for #%u\n", channel->dlci);
channel->state_var &= ~STATE_VAR_SEND_MSC_RSP;
channel->state_var |= STATE_VAR_SENT_MSC_RSP;
channel->state_var &= ~RFCOMM_CHANNEL_STATE_VAR_SEND_MSC_RSP;
channel->state_var |= RFCOMM_CHANNEL_STATE_VAR_SENT_MSC_RSP;
rfcomm_send_uih_msc_rsp(multiplexer, channel->dlci, 0x8d); // ea=1,fc=0,rtc=1,rtr=1,ic=0,dv=1
break;
}
if (channel->state_var & STATE_VAR_SEND_CREDITS){
if (channel->state_var & RFCOMM_CHANNEL_STATE_VAR_SEND_CREDITS){
log_info("Providing credits for #%u\n", channel->dlci);
channel->state_var &= ~STATE_VAR_SEND_CREDITS;
channel->state_var |= STATE_VAR_SENT_CREDITS;
channel->state_var &= ~RFCOMM_CHANNEL_STATE_VAR_SEND_CREDITS;
channel->state_var |= RFCOMM_CHANNEL_STATE_VAR_SENT_CREDITS;
rfcomm_channel_provide_credits(channel);
break;
@ -1605,12 +1416,12 @@ static void rfcomm_channel_state_machine(rfcomm_channel_t *channel, rfcomm_chann
case RFCOMM_CHANNEL_OPEN:
switch (event->type){
case CH_EVT_RCVD_MSC_CMD:
channel->state_var |= STATE_VAR_SEND_MSC_RSP;
channel->state_var |= RFCOMM_CHANNEL_STATE_VAR_SEND_MSC_RSP;
break;
case CH_EVT_READY_TO_SEND:
if (channel->state_var & STATE_VAR_SEND_MSC_RSP){
if (channel->state_var & RFCOMM_CHANNEL_STATE_VAR_SEND_MSC_RSP){
log_info("Sending MSC RSP for #%u\n", channel->dlci);
channel->state_var &= ~STATE_VAR_SEND_MSC_RSP;
channel->state_var &= ~RFCOMM_CHANNEL_STATE_VAR_SEND_MSC_RSP;
rfcomm_send_uih_msc_rsp(multiplexer, channel->dlci, 0x8d); // ea=1,fc=0,rtc=1,rtr=1,ic=0,dv=1
break;
}
@ -1860,12 +1671,12 @@ void rfcomm_accept_connection_internal(uint16_t rfcomm_cid){
if (!channel) return;
switch (channel->state) {
case RFCOMM_CHANNEL_INCOMING_SETUP:
channel->state_var |= STATE_VAR_CLIENT_ACCEPTED;
if (channel->state_var & STATE_VAR_RCVD_PN){
channel->state_var |= STATE_VAR_SEND_PN_RSP;
channel->state_var |= RFCOMM_CHANNEL_STATE_VAR_CLIENT_ACCEPTED;
if (channel->state_var & RFCOMM_CHANNEL_STATE_VAR_RCVD_PN){
channel->state_var |= RFCOMM_CHANNEL_STATE_VAR_SEND_PN_RSP;
}
if (channel->state_var & STATE_VAR_RCVD_SABM){
channel->state_var |= STATE_VAR_SEND_UA;
if (channel->state_var & RFCOMM_CHANNEL_STATE_VAR_RCVD_SABM){
channel->state_var |= RFCOMM_CHANNEL_STATE_VAR_SEND_UA;
}
break;
default:

View File

@ -38,6 +38,10 @@
#include <stdint.h>
#if defined __cplusplus
extern "C" {
#endif
void rfcomm_init(void);
// register packet handler
@ -56,4 +60,197 @@ int rfcomm_send_internal(uint8_t rfcomm_cid, uint8_t *data, uint16_t len);
void rfcomm_close_connection(void *connection);
// private structs
typedef enum {
RFCOMM_MULTIPLEXER_CLOSED = 1,
RFCOMM_MULTIPLEXER_W4_CONNECT, // outgoing
RFCOMM_MULTIPLEXER_SEND_SABM_0, // "
RFCOMM_MULTIPLEXER_W4_UA_0, // "
RFCOMM_MULTIPLEXER_W4_SABM_0, // incoming
RFCOMM_MULTIPLEXER_SEND_UA_0,
RFCOMM_MULTIPLEXER_OPEN,
RFCOMM_MULTIPLEXER_SEND_UA_0_AND_DISC
} RFCOMM_MULTIPLEXER_STATE;
typedef enum {
MULT_EV_READY_TO_SEND = 1,
} RFCOMM_MULTIPLEXER_EVENT;
typedef enum {
RFCOMM_CHANNEL_CLOSED = 1,
RFCOMM_CHANNEL_W4_MULTIPLEXER,
RFCOMM_CHANNEL_SEND_UIH_PN,
RFCOMM_CHANNEL_W4_PN_RSP,
RFCOMM_CHANNEL_SEND_SABM_W4_UA,
RFCOMM_CHANNEL_W4_UA,
RFCOMM_CHANNEL_INCOMING_SETUP,
RFCOMM_CHANNEL_DLC_SETUP,
RFCOMM_CHANNEL_OPEN,
RFCOMM_CHANNEL_SEND_UA_AFTER_DISC,
RFCOMM_CHANNEL_SEND_DISC,
RFCOMM_CHANNEL_SEND_DM,
} RFCOMM_CHANNEL_STATE;
typedef enum {
RFCOMM_CHANNEL_STATE_VAR_NONE = 0,
RFCOMM_CHANNEL_STATE_VAR_CLIENT_ACCEPTED = 1 << 0,
RFCOMM_CHANNEL_STATE_VAR_RCVD_PN = 1 << 1,
RFCOMM_CHANNEL_STATE_VAR_RCVD_RPN = 1 << 2,
RFCOMM_CHANNEL_STATE_VAR_RCVD_SABM = 1 << 3,
RFCOMM_CHANNEL_STATE_VAR_RCVD_MSC_CMD = 1 << 4,
RFCOMM_CHANNEL_STATE_VAR_RCVD_MSC_RSP = 1 << 5,
RFCOMM_CHANNEL_STATE_VAR_SEND_PN_RSP = 1 << 6,
RFCOMM_CHANNEL_STATE_VAR_SEND_RPN_INFO = 1 << 7,
RFCOMM_CHANNEL_STATE_VAR_SEND_RPN_RSP = 1 << 8,
RFCOMM_CHANNEL_STATE_VAR_SEND_UA = 1 << 9,
RFCOMM_CHANNEL_STATE_VAR_SEND_MSC_CMD = 1 << 10,
RFCOMM_CHANNEL_STATE_VAR_SEND_MSC_RSP = 1 << 11,
RFCOMM_CHANNEL_STATE_VAR_SEND_CREDITS = 1 << 12,
RFCOMM_CHANNEL_STATE_VAR_SENT_MSC_CMD = 1 << 13,
RFCOMM_CHANNEL_STATE_VAR_SENT_MSC_RSP = 1 << 14,
RFCOMM_CHANNEL_STATE_VAR_SENT_CREDITS = 1 << 15,
} RFCOMM_CHANNEL_STATE_VAR;
typedef enum {
CH_EVT_RCVD_SABM = 1,
CH_EVT_RCVD_UA,
CH_EVT_RCVD_PN,
CH_EVT_RCVD_PN_RSP,
CH_EVT_RCVD_DISC,
CH_EVT_RCVD_DM,
CH_EVT_RCVD_MSC_CMD,
CH_EVT_RCVD_MSC_RSP,
CH_EVT_RCVD_RPN_CMD,
CH_EVT_RCVD_RPN_REQ,
CH_EVT_MULTIPLEXER_READY,
CH_EVT_READY_TO_SEND,
} RFCOMM_CHANNEL_EVENT;
typedef struct rfcomm_channel_event {
RFCOMM_CHANNEL_EVENT type;
} rfcomm_channel_event_t;
typedef struct rfcomm_channel_event_pn {
rfcomm_channel_event_t super;
uint16_t max_frame_size;
uint8_t priority;
uint8_t credits_outgoing;
} rfcomm_channel_event_pn_t;
typedef struct rfcomm_rpn_data {
uint8_t baud_rate;
uint8_t flags;
uint8_t flow_control;
uint8_t xon;
uint8_t xoff;
uint8_t parameter_mask_0; // first byte
uint8_t parameter_mask_1; // second byte
} rfcomm_rpn_data_t;
typedef struct rfcomm_channel_event_rpn {
rfcomm_channel_event_t super;
rfcomm_rpn_data_t data;
} rfcomm_channel_event_rpn_t;
// info regarding potential connections
typedef struct {
// linked list - assert: first field
linked_item_t item;
// server channel
uint8_t server_channel;
// incoming max frame size
uint16_t max_frame_size;
// client connection
void *connection;
// internal connection
btstack_packet_handler_t packet_handler;
} rfcomm_service_t;
// info regarding multiplexer
// note: spec mandates single multplexer per device combination
typedef struct {
// linked list - assert: first field
linked_item_t item;
timer_source_t timer;
int timer_active;
RFCOMM_MULTIPLEXER_STATE state;
uint16_t l2cap_cid;
uint8_t l2cap_credits;
bd_addr_t remote_addr;
hci_con_handle_t con_handle;
uint8_t outgoing;
// hack to deal with authentication failure only observed by remote side
uint8_t at_least_one_connection;
uint16_t max_frame_size;
// send DM for DLCI != 0
uint8_t send_dm_for_dlci;
} rfcomm_multiplexer_t;
// info regarding an actual coneection
typedef struct {
// linked list - assert: first field
linked_item_t item;
rfcomm_multiplexer_t *multiplexer;
uint16_t rfcomm_cid;
uint8_t outgoing;
uint8_t dlci;
// credits for outgoing traffic
uint8_t credits_outgoing;
// number of packets granted to client
uint8_t packets_granted;
// credits for incoming traffic
uint8_t credits_incoming;
// channel state
RFCOMM_CHANNEL_STATE state;
// state variables used in RFCOMM_CHANNEL_INCOMING
RFCOMM_CHANNEL_STATE_VAR state_var;
// priority set by incoming side in PN
uint8_t pn_priority;
// negotiated frame size
uint16_t max_frame_size;
// rpn data
rfcomm_rpn_data_t rpn_data;
// server channel (see rfcomm_service_t) - NULL => outgoing channel
rfcomm_service_t * service;
// internal connection
btstack_packet_handler_t packet_handler;
// client connection
void * connection;
} rfcomm_channel_t;
#if defined __cplusplus
}
#endif