mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-03-24 04:43:36 +00:00
moved l2cap_channel_t, l2cap_service_t, rfcomm_multiplexer_t, rfcomm_channel_t, rfcomm_service_t to header files
This commit is contained in:
parent
9574ad1db1
commit
73cf2b3d2a
117
src/l2cap.c
117
src/l2cap.c
@ -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;
|
||||
|
90
src/l2cap.h
90
src/l2cap.h
@ -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
|
||||
|
281
src/rfcomm.c
281
src/rfcomm.c
@ -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:
|
||||
|
197
src/rfcomm.h
197
src/rfcomm.h
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user