diff --git a/src/l2cap.c b/src/l2cap.c index a8f1a8d76..da89af3c8 100644 --- a/src/l2cap.c +++ b/src/l2cap.c @@ -57,23 +57,102 @@ // nr of buffered acl packets in outgoing queue to get max performance #define NR_BUFFERED_ACL_PACKETS 3 +// used to cache l2cap rejects, echo, and informational requests +#define NR_PENDING_SIGNALING_RESPONSES 10 + // offsets for L2CAP SIGNALING COMMANDS #define L2CAP_SIGNALING_COMMAND_CODE_OFFSET 0 #define L2CAP_SIGNALING_COMMAND_SIGID_OFFSET 1 #define L2CAP_SIGNALING_COMMAND_LENGTH_OFFSET 2 #define L2CAP_SIGNALING_COMMAND_DATA_OFFSET 4 -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); +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_WAIT_CONFIG_REQ_OR_SEND_CONFIG_REQ, + L2CAP_STATE_WAIT_CONFIG_REQ_RSP_OR_CONFIG_REQ, + L2CAP_STATE_WAIT_CONFIG_REQ_RSP_OR_WILL_SEND_CONFIG_REQ_RSP, + L2CAP_STATE_WAIT_CONFIG_REQ_RSP, + L2CAP_STATE_WAIT_CONFIG_REQ, + 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_CONFIG_REQ, + L2CAP_STATE_WILL_SEND_CONFIG_REQ_RSP, + L2CAP_STATE_WILL_SEND_CONFIG_REQ_AND_CONFIG_REQ_RSP, + L2CAP_STATE_WILL_SEND_DISCONNECT_REQUEST, + L2CAP_STATE_WILL_SEND_DISCONNECT_RESPONSE, +} L2CAP_STATE; + +// info regarding an actual coneection +typedef struct { + // linked list - assert: first field + linked_item_t item; + + L2CAP_STATE state; + + 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; + -// used to cache l2cap rejects, echo, and informational requests -#define NR_PENDING_SIGNALING_RESPONSES 10 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); + +// used to cache l2cap rejects, echo, and informational requests static l2cap_signaling_response_t signaling_responses[NR_PENDING_SIGNALING_RESPONSES]; static int signaling_responses_pending; @@ -84,6 +163,15 @@ static uint8_t * acl_buffer = NULL; static void (*packet_handler) (void * connection, uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) = null_packet_handler; static int new_credits_blocked = 0; + +// prototypes +void l2cap_finialize_channel_close(l2cap_channel_t *channel); +l2cap_service_t * l2cap_get_service(uint16_t psm); +void l2cap_emit_channel_opened(l2cap_channel_t *channel, uint8_t status); +void l2cap_emit_channel_closed(l2cap_channel_t *channel); +void l2cap_emit_connection_request(l2cap_channel_t *channel); + + void l2cap_init(){ sig_buffer = malloc( L2CAP_MINIMAL_MTU ); acl_buffer = malloc( HCI_ACL_3DH5_SIZE); diff --git a/src/l2cap.h b/src/l2cap.h index d69b41f67..e2d3d95f2 100644 --- a/src/l2cap.h +++ b/src/l2cap.h @@ -50,84 +50,6 @@ extern "C" { #define L2CAP_SIG_ID_INVALID 0 -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_WAIT_CONFIG_REQ_OR_SEND_CONFIG_REQ, - L2CAP_STATE_WAIT_CONFIG_REQ_RSP_OR_CONFIG_REQ, - L2CAP_STATE_WAIT_CONFIG_REQ_RSP_OR_WILL_SEND_CONFIG_REQ_RSP, - L2CAP_STATE_WAIT_CONFIG_REQ_RSP, - L2CAP_STATE_WAIT_CONFIG_REQ, - 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_CONFIG_REQ, - L2CAP_STATE_WILL_SEND_CONFIG_REQ_RSP, - L2CAP_STATE_WILL_SEND_CONFIG_REQ_AND_CONFIG_REQ_RSP, - L2CAP_STATE_WILL_SEND_DISCONNECT_REQUEST, - L2CAP_STATE_WILL_SEND_DISCONNECT_RESPONSE, -} L2CAP_STATE; - -// info regarding an actual coneection -typedef struct { - // linked list - assert: first field - linked_item_t item; - - L2CAP_STATE state; - - 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 - - // uint16_t flush_timeout_incoming; - // uint16_t flush_timeout_outgoing; - - // 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; - void l2cap_init(void); void l2cap_register_packet_handler(void (*handler)(void * connection, uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size)); void l2cap_create_channel_internal(void * connection, btstack_packet_handler_t packet_handler, bd_addr_t address, uint16_t psm, uint16_t mtu); @@ -138,20 +60,14 @@ uint16_t l2cap_get_remote_mtu_for_local_cid(uint16_t local_cid); void l2cap_block_new_credits(uint8_t blocked); int l2cap_can_send_packet_now(uint16_t local_cid); // non-blocking UART write -void l2cap_finialize_channel_close(l2cap_channel_t *channel); void l2cap_close_connection(void *connection); -l2cap_service_t * l2cap_get_service(uint16_t psm); void l2cap_register_service_internal(void *connection, btstack_packet_handler_t packet_handler, uint16_t psm, uint16_t mtu); 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); -void l2cap_emit_channel_opened(l2cap_channel_t *channel, uint8_t status); -void l2cap_emit_channel_closed(l2cap_channel_t *channel); -void l2cap_emit_connection_request(l2cap_channel_t *channel); - #if defined __cplusplus } #endif