143625864Smatthias.ringwald /* 2a0c35809S[email protected] * Copyright (C) 2014 BlueKitchen GmbH 31713bceaSmatthias.ringwald * 41713bceaSmatthias.ringwald * Redistribution and use in source and binary forms, with or without 51713bceaSmatthias.ringwald * modification, are permitted provided that the following conditions 61713bceaSmatthias.ringwald * are met: 71713bceaSmatthias.ringwald * 81713bceaSmatthias.ringwald * 1. Redistributions of source code must retain the above copyright 91713bceaSmatthias.ringwald * notice, this list of conditions and the following disclaimer. 101713bceaSmatthias.ringwald * 2. Redistributions in binary form must reproduce the above copyright 111713bceaSmatthias.ringwald * notice, this list of conditions and the following disclaimer in the 121713bceaSmatthias.ringwald * documentation and/or other materials provided with the distribution. 131713bceaSmatthias.ringwald * 3. Neither the name of the copyright holders nor the names of 141713bceaSmatthias.ringwald * contributors may be used to endorse or promote products derived 151713bceaSmatthias.ringwald * from this software without specific prior written permission. 166b64433eSmatthias.ringwald * 4. Any redistribution, use, or modification is done solely for 176b64433eSmatthias.ringwald * personal benefit and not for any commercial purpose or for 186b64433eSmatthias.ringwald * monetary gain. 191713bceaSmatthias.ringwald * 20a0c35809S[email protected] * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS 211713bceaSmatthias.ringwald * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 221713bceaSmatthias.ringwald * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 232fca4dadSMilanka Ringwald * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN 242fca4dadSMilanka Ringwald * GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 251713bceaSmatthias.ringwald * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 261713bceaSmatthias.ringwald * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 271713bceaSmatthias.ringwald * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 281713bceaSmatthias.ringwald * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 291713bceaSmatthias.ringwald * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 301713bceaSmatthias.ringwald * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 311713bceaSmatthias.ringwald * SUCH DAMAGE. 321713bceaSmatthias.ringwald * 33a0c35809S[email protected] * Please inquire about commercial licensing options at 34a0c35809S[email protected] * [email protected] 356b64433eSmatthias.ringwald * 361713bceaSmatthias.ringwald */ 371713bceaSmatthias.ringwald 38e501bae0SMatthias Ringwald #define BTSTACK_FILE__ "l2cap.c" 39ab2c6ae4SMatthias Ringwald 401713bceaSmatthias.ringwald /* 4143625864Smatthias.ringwald * l2cap.c 425cc4b885SMatthias Ringwald * Logical Link Control and Adaption Protocol (L2CAP) 4343625864Smatthias.ringwald */ 4443625864Smatthias.ringwald 4543625864Smatthias.ringwald #include "l2cap.h" 46645658c9Smatthias.ringwald #include "hci.h" 472b3c6c9bSmatthias.ringwald #include "hci_dump.h" 48235946f1SMatthias Ringwald #include "bluetooth_sdp.h" 4984e3541eSMilanka Ringwald #include "bluetooth_psm.h" 50ea6a43faSMatthias Ringwald #include "btstack_bool.h" 5116ece135SMatthias Ringwald #include "btstack_debug.h" 520e2df43fSMatthias Ringwald #include "btstack_event.h" 53d3a9df87Smatthias.ringwald #include "btstack_memory.h" 5443625864Smatthias.ringwald 555cc4b885SMatthias Ringwald #ifdef ENABLE_LE_DATA_CHANNELS 565cc4b885SMatthias Ringwald // TODO avoid dependency on higher layer: used to trigger pairing for outgoing connections 575cc4b885SMatthias Ringwald #include "ble/sm.h" 585cc4b885SMatthias Ringwald #endif 595cc4b885SMatthias Ringwald 6043625864Smatthias.ringwald #include <stdarg.h> 6143625864Smatthias.ringwald #include <string.h> 6243625864Smatthias.ringwald 63a6e314f1SMatthias Ringwald /* 64a6e314f1SMatthias Ringwald * @brief L2CAP Supervisory function in S-Frames 65a6e314f1SMatthias Ringwald */ 66a6e314f1SMatthias Ringwald typedef enum { 67a6e314f1SMatthias Ringwald L2CAP_SUPERVISORY_FUNCTION_RR_RECEIVER_READY = 0, 68a6e314f1SMatthias Ringwald L2CAP_SUPERVISORY_FUNCTION_REJ_REJECT, 69a6e314f1SMatthias Ringwald L2CAP_SUPERVISORY_FUNCTION_RNR_RECEIVER_NOT_READY, 70a6e314f1SMatthias Ringwald L2CAP_SUPERVISORY_FUNCTION_SREJ_SELECTIVE_REJECT 71a6e314f1SMatthias Ringwald } l2cap_supervisory_function_t; 72a6e314f1SMatthias Ringwald 73a6e314f1SMatthias Ringwald /** 74a6e314f1SMatthias Ringwald * @brief L2CAP Information Types used in Information Request & Response 75a6e314f1SMatthias Ringwald */ 76a6e314f1SMatthias Ringwald typedef enum { 77a6e314f1SMatthias Ringwald L2CAP_INFO_TYPE_CONNECTIONLESS_MTU = 1, 78a6e314f1SMatthias Ringwald L2CAP_INFO_TYPE_EXTENDED_FEATURES_SUPPORTED, 79a6e314f1SMatthias Ringwald L2CAP_INFO_TYPE_FIXED_CHANNELS_SUPPORTED, 80a6e314f1SMatthias Ringwald } l2cap_info_type_t; 81a6e314f1SMatthias Ringwald 82a6e314f1SMatthias Ringwald /** 83a6e314f1SMatthias Ringwald * @brief L2CAP Configuration Option Types used in Configurateion Request & Response 84a6e314f1SMatthias Ringwald */ 85a6e314f1SMatthias Ringwald typedef enum { 86a6e314f1SMatthias Ringwald L2CAP_CONFIG_OPTION_TYPE_MAX_TRANSMISSION_UNIT = 1, 87a6e314f1SMatthias Ringwald L2CAP_CONFIG_OPTION_TYPE_FLUSH_TIMEOUT, 88a6e314f1SMatthias Ringwald L2CAP_CONFIG_OPTION_TYPE_QUALITY_OF_SERVICE, 89a6e314f1SMatthias Ringwald L2CAP_CONFIG_OPTION_TYPE_RETRANSMISSION_AND_FLOW_CONTROL, 90a6e314f1SMatthias Ringwald L2CAP_CONFIG_OPTION_TYPE_FRAME_CHECK_SEQUENCE, 91a6e314f1SMatthias Ringwald L2CAP_CONFIG_OPTION_TYPE_EXTENDED_FLOW_SPECIFICATION, 92a6e314f1SMatthias Ringwald L2CAP_CONFIG_OPTION_TYPE_EXTENDED_WINDOW_SIZE, 93a6e314f1SMatthias Ringwald } l2cap_config_option_type_t; 94a6e314f1SMatthias Ringwald 95a6e314f1SMatthias Ringwald 96a6e314f1SMatthias Ringwald #define L2CAP_SIG_ID_INVALID 0 97a6e314f1SMatthias Ringwald 98a6e314f1SMatthias Ringwald // size of HCI ACL + L2CAP Header for regular data packets (8) 99a6e314f1SMatthias Ringwald #define COMPLETE_L2CAP_HEADER (HCI_ACL_HEADER_SIZE + L2CAP_HEADER_SIZE) 100a6e314f1SMatthias Ringwald 101a6e314f1SMatthias Ringwald // L2CAP Configuration Result Codes 102a6e314f1SMatthias Ringwald #define L2CAP_CONF_RESULT_SUCCESS 0x0000 103a6e314f1SMatthias Ringwald #define L2CAP_CONF_RESULT_UNACCEPTABLE_PARAMETERS 0x0001 104a6e314f1SMatthias Ringwald #define L2CAP_CONF_RESULT_REJECT 0x0002 105a6e314f1SMatthias Ringwald #define L2CAP_CONF_RESULT_UNKNOWN_OPTIONS 0x0003 106a6e314f1SMatthias Ringwald #define L2CAP_CONF_RESULT_PENDING 0x0004 107a6e314f1SMatthias Ringwald #define L2CAP_CONF_RESULT_FLOW_SPEC_REJECTED 0x0005 108a6e314f1SMatthias Ringwald 109a6e314f1SMatthias Ringwald // L2CAP Reject Result Codes 110a6e314f1SMatthias Ringwald #define L2CAP_REJ_CMD_UNKNOWN 0x0000 111a6e314f1SMatthias Ringwald 112a6e314f1SMatthias Ringwald // Response Timeout eXpired 113a6e314f1SMatthias Ringwald #define L2CAP_RTX_TIMEOUT_MS 10000 114a6e314f1SMatthias Ringwald 115a6e314f1SMatthias Ringwald // Extended Response Timeout eXpired 116a6e314f1SMatthias Ringwald #define L2CAP_ERTX_TIMEOUT_MS 120000 117a6e314f1SMatthias Ringwald 1184c744e21Smatthias.ringwald // nr of buffered acl packets in outgoing queue to get max performance 1194c744e21Smatthias.ringwald #define NR_BUFFERED_ACL_PACKETS 3 1204c744e21Smatthias.ringwald 12139bda6d5Smatthias.ringwald // used to cache l2cap rejects, echo, and informational requests 122e16a9cacSmatthias.ringwald #define NR_PENDING_SIGNALING_RESPONSES 3 12339bda6d5Smatthias.ringwald 12485aeef60SMatthias Ringwald // nr of credits provided to remote if credits fall below watermark 12585aeef60SMatthias Ringwald #define L2CAP_LE_DATA_CHANNELS_AUTOMATIC_CREDITS_WATERMARK 5 12685aeef60SMatthias Ringwald #define L2CAP_LE_DATA_CHANNELS_AUTOMATIC_CREDITS_INCREMENT 5 12785aeef60SMatthias Ringwald 12800d93d79Smatthias.ringwald // offsets for L2CAP SIGNALING COMMANDS 12900d93d79Smatthias.ringwald #define L2CAP_SIGNALING_COMMAND_CODE_OFFSET 0 13000d93d79Smatthias.ringwald #define L2CAP_SIGNALING_COMMAND_SIGID_OFFSET 1 13100d93d79Smatthias.ringwald #define L2CAP_SIGNALING_COMMAND_LENGTH_OFFSET 2 13200d93d79Smatthias.ringwald #define L2CAP_SIGNALING_COMMAND_DATA_OFFSET 4 13300d93d79Smatthias.ringwald 134*a254c508SMatthias Ringwald #if defined(ENABLE_LE_DATA_CHANNELS) || defined(ENABLE_L2CAP_ENHANCED_DATA_CHANNELS) 135*a254c508SMatthias Ringwald #define ENABLE_L2CAP_CREDIT_BASED_CHANNELS 136*a254c508SMatthias Ringwald #endif 137*a254c508SMatthias Ringwald 138*a254c508SMatthias Ringwald #if defined(ENABLE_L2CAP_CREDIT_BASED_CHANNELS) || defined(ENABLE_CLASSIC) 13909e9d05bSMatthias Ringwald #define L2CAP_USES_CHANNELS 14009e9d05bSMatthias Ringwald #endif 14109e9d05bSMatthias Ringwald 14233c40538SMatthias Ringwald // prototypes 143675e6881SMatthias Ringwald static void l2cap_run(void); 14433c40538SMatthias Ringwald static void l2cap_hci_event_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size); 1453d50b4baSMatthias Ringwald static void l2cap_acl_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size ); 14630725612SMatthias Ringwald static void l2cap_notify_channel_can_send(void); 14709e9d05bSMatthias Ringwald static void l2cap_emit_can_send_now(btstack_packet_handler_t packet_handler, uint16_t channel); 1486ddef68dSMilanka Ringwald static uint8_t l2cap_next_sig_id(void); 1497740e150SMatthias Ringwald static l2cap_fixed_channel_t * l2cap_fixed_channel_for_channel_id(uint16_t local_cid); 15009e9d05bSMatthias Ringwald #ifdef ENABLE_CLASSIC 151b2e1493cSMatthias Ringwald static void l2cap_handle_security_level_incoming_sufficient(l2cap_channel_t * channel); 152a400e4c3SMatthias Ringwald static int l2cap_security_level_0_allowed_for_PSM(uint16_t psm); 153474f5c3fSMatthias Ringwald static void l2cap_handle_remote_supported_features_received(l2cap_channel_t * channel); 154474f5c3fSMatthias Ringwald static void l2cap_handle_connection_complete(hci_con_handle_t con_handle, l2cap_channel_t * channel); 155*a254c508SMatthias Ringwald static void l2cap_finalize_channel_close(l2cap_channel_t *channel); 156*a254c508SMatthias Ringwald static void l2cap_handle_information_request_complete(hci_connection_t * connection); 15709e9d05bSMatthias Ringwald static inline l2cap_service_t * l2cap_get_service(uint16_t psm); 15809e9d05bSMatthias Ringwald static void l2cap_emit_channel_opened(l2cap_channel_t *channel, uint8_t status); 15909e9d05bSMatthias Ringwald static void l2cap_emit_channel_closed(l2cap_channel_t *channel); 16009e9d05bSMatthias Ringwald static void l2cap_emit_incoming_connection(l2cap_channel_t *channel); 16109e9d05bSMatthias Ringwald static int l2cap_channel_ready_for_open(l2cap_channel_t *channel); 16209e9d05bSMatthias Ringwald #endif 163cab29d48SMatthias Ringwald #ifdef ENABLE_LE_DATA_CHANNELS 16457be49d6SMatthias Ringwald static void l2cap_emit_le_channel_opened(l2cap_channel_t *channel, uint8_t status); 16587050a0bSMatthias Ringwald static void l2cap_emit_le_channel_closed(l2cap_channel_t * channel); 16657be49d6SMatthias Ringwald static void l2cap_emit_le_incoming_connection(l2cap_channel_t *channel); 16744276248SMatthias Ringwald static void l2cap_le_notify_channel_can_send(l2cap_channel_t *channel); 168828a7f7aSMatthias Ringwald static void l2cap_le_finialize_channel_close(l2cap_channel_t *channel); 169e7d0c9aaSMatthias Ringwald static inline l2cap_service_t * l2cap_le_get_service(uint16_t psm); 170e7d0c9aaSMatthias Ringwald #endif 171*a254c508SMatthias Ringwald #ifdef ENABLE_L2CAP_CREDIT_BASED_CHANNELS 172*a254c508SMatthias Ringwald static void l2cap_credit_based_send_pdu(l2cap_channel_t *channel); 173*a254c508SMatthias Ringwald static void l2cap_credit_based_send_credits(l2cap_channel_t *channel); 174*a254c508SMatthias Ringwald static bool l2cap_credit_based_handle_credit_indication(hci_con_handle_t handle, const uint8_t * command, uint16_t len); 175*a254c508SMatthias Ringwald static void l2cap_credit_based_handle_pdu(l2cap_channel_t * l2cap_channel, const uint8_t * packet, uint16_t size); 176*a254c508SMatthias Ringwald #endif 177474f5c3fSMatthias Ringwald #ifdef L2CAP_USES_CHANNELS 1786a5ffed8SMatthias Ringwald static uint16_t l2cap_next_local_cid(void); 1796a5ffed8SMatthias Ringwald static l2cap_channel_t * l2cap_get_channel_for_local_cid(uint16_t local_cid); 180836ae835SMatthias Ringwald static void l2cap_emit_simple_event_with_cid(l2cap_channel_t * channel, uint8_t event_code); 181474f5c3fSMatthias Ringwald static void l2cap_dispatch_to_channel(l2cap_channel_t *channel, uint8_t type, uint8_t * data, uint16_t size); 1825d18f623SMatthias Ringwald static l2cap_channel_t * l2cap_create_channel_entry(btstack_packet_handler_t packet_handler, l2cap_channel_type_t channel_type, bd_addr_t address, bd_addr_type_t address_type, 183474f5c3fSMatthias Ringwald uint16_t psm, uint16_t local_mtu, gap_security_level_t security_level); 184c45d6b2cSMatthias Ringwald static void l2cap_free_channel_entry(l2cap_channel_t * channel); 185474f5c3fSMatthias Ringwald #endif 186212b6be2SMatthias Ringwald #ifdef ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE 18796646001SMatthias Ringwald static void l2cap_ertm_notify_channel_can_send(l2cap_channel_t * channel); 188c9300dcaSMatthias Ringwald static void l2cap_ertm_monitor_timeout_callback(btstack_timer_source_t * ts); 1898a700052SMatthias Ringwald static void l2cap_ertm_retransmission_timeout_callback(btstack_timer_source_t * ts); 190212b6be2SMatthias Ringwald #endif 191*a254c508SMatthias Ringwald #ifdef ENABLE_L2CAP_ENHANCED_DATA_CHANNELS 192*a254c508SMatthias Ringwald static int l2cap_enhanced_signaling_handler_dispatch(hci_con_handle_t handle, uint16_t signaling_cid, uint8_t * command, uint8_t sig_id); 193*a254c508SMatthias Ringwald #endif 19433c40538SMatthias Ringwald 195fad84cafSMatthias Ringwald // l2cap_fixed_channel_t entries 19624eb964eSMatthias Ringwald #ifdef ENABLE_BLE 197fad84cafSMatthias Ringwald static l2cap_fixed_channel_t l2cap_fixed_channel_att; 198fad84cafSMatthias Ringwald static l2cap_fixed_channel_t l2cap_fixed_channel_sm; 19924eb964eSMatthias Ringwald #endif 20024eb964eSMatthias Ringwald #ifdef ENABLE_CLASSIC 201fad84cafSMatthias Ringwald static l2cap_fixed_channel_t l2cap_fixed_channel_connectionless; 20224eb964eSMatthias Ringwald #endif 2035628cf69SMatthias Ringwald 20409e9d05bSMatthias Ringwald #ifdef ENABLE_CLASSIC 2055628cf69SMatthias Ringwald static btstack_linked_list_t l2cap_services; 20691c8d67dSMatthias Ringwald static uint8_t l2cap_require_security_level2_for_outgoing_sdp; 207ece97caeSMatthias Ringwald static bd_addr_t l2cap_outgoing_classic_addr; 20809e9d05bSMatthias Ringwald #endif 20957be49d6SMatthias Ringwald 21057be49d6SMatthias Ringwald #ifdef ENABLE_LE_DATA_CHANNELS 2115628cf69SMatthias Ringwald static btstack_linked_list_t l2cap_le_services; 21257be49d6SMatthias Ringwald #endif 21339bda6d5Smatthias.ringwald 214*a254c508SMatthias Ringwald #ifdef ENABLE_L2CAP_ENHANCED_DATA_CHANNELS 215*a254c508SMatthias Ringwald static btstack_linked_list_t l2cap_enhanced_services; 216*a254c508SMatthias Ringwald static uint16_t l2cap_enhanced_mps_min; 217*a254c508SMatthias Ringwald static uint16_t l2cap_enhanced_mps_max; 218*a254c508SMatthias Ringwald #endif 219*a254c508SMatthias Ringwald 220fad84cafSMatthias Ringwald // single list of channels for Classic Channels, LE Data Channels, Classic Connectionless, ATT, and SM 221421cb104SMatthias Ringwald static btstack_linked_list_t l2cap_channels; 2226a5ffed8SMatthias Ringwald #ifdef L2CAP_USES_CHANNELS 2236ddef68dSMilanka Ringwald // next channel id for new connections 22491c8d67dSMatthias Ringwald static uint16_t l2cap_local_source_cid; 2256a5ffed8SMatthias Ringwald #endif 2266ddef68dSMilanka Ringwald // next signaling sequence number 22791c8d67dSMatthias Ringwald static uint8_t l2cap_sig_seq_nr; 228421cb104SMatthias Ringwald 22939bda6d5Smatthias.ringwald // used to cache l2cap rejects, echo, and informational requests 23091c8d67dSMatthias Ringwald static l2cap_signaling_response_t l2cap_signaling_responses[NR_PENDING_SIGNALING_RESPONSES]; 23191c8d67dSMatthias Ringwald static int l2cap_signaling_responses_pending; 23291c8d67dSMatthias Ringwald static btstack_packet_callback_registration_t l2cap_hci_event_callback_registration; 23339bda6d5Smatthias.ringwald 234*a254c508SMatthias Ringwald static bool l2cap_call_notify_channel_in_run; 235*a254c508SMatthias Ringwald 236d6ed9f9cSMatthias Ringwald #ifdef ENABLE_BLE 237d6ed9f9cSMatthias Ringwald // only used for connection parameter update events 23825818320SMatthias Ringwald static uint16_t l2cap_le_custom_max_mtu; 239d6ed9f9cSMatthias Ringwald #endif 240d6ed9f9cSMatthias Ringwald 2410b81d2a5SMatthias Ringwald /* callbacks for events */ 2420b81d2a5SMatthias Ringwald static btstack_linked_list_t l2cap_event_handlers; 2430b81d2a5SMatthias Ringwald 24485ddcd84SMatthias Ringwald #ifdef ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE 24585ddcd84SMatthias Ringwald 246e288be62SMatthias Ringwald // enable for testing 247e288be62SMatthias Ringwald // #define L2CAP_ERTM_SIMULATE_FCS_ERROR_INTERVAL 16 248e288be62SMatthias Ringwald 24985ddcd84SMatthias Ringwald /* 25085ddcd84SMatthias Ringwald * CRC lookup table for generator polynom D^16 + D^15 + D^2 + 1 25185ddcd84SMatthias Ringwald */ 25285ddcd84SMatthias Ringwald static const uint16_t crc16_table[256] = { 25385ddcd84SMatthias Ringwald 0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, 0xc241, 0xc601, 0x06c0, 0x0780, 0xc741, 0x0500, 0xc5c1, 0xc481, 0x0440, 25485ddcd84SMatthias Ringwald 0xcc01, 0x0cc0, 0x0d80, 0xcd41, 0x0f00, 0xcfc1, 0xce81, 0x0e40, 0x0a00, 0xcac1, 0xcb81, 0x0b40, 0xc901, 0x09c0, 0x0880, 0xc841, 25585ddcd84SMatthias Ringwald 0xd801, 0x18c0, 0x1980, 0xd941, 0x1b00, 0xdbc1, 0xda81, 0x1a40, 0x1e00, 0xdec1, 0xdf81, 0x1f40, 0xdd01, 0x1dc0, 0x1c80, 0xdc41, 25685ddcd84SMatthias Ringwald 0x1400, 0xd4c1, 0xd581, 0x1540, 0xd701, 0x17c0, 0x1680, 0xd641, 0xd201, 0x12c0, 0x1380, 0xd341, 0x1100, 0xd1c1, 0xd081, 0x1040, 25785ddcd84SMatthias Ringwald 0xf001, 0x30c0, 0x3180, 0xf141, 0x3300, 0xf3c1, 0xf281, 0x3240, 0x3600, 0xf6c1, 0xf781, 0x3740, 0xf501, 0x35c0, 0x3480, 0xf441, 25885ddcd84SMatthias Ringwald 0x3c00, 0xfcc1, 0xfd81, 0x3d40, 0xff01, 0x3fc0, 0x3e80, 0xfe41, 0xfa01, 0x3ac0, 0x3b80, 0xfb41, 0x3900, 0xf9c1, 0xf881, 0x3840, 25985ddcd84SMatthias Ringwald 0x2800, 0xe8c1, 0xe981, 0x2940, 0xeb01, 0x2bc0, 0x2a80, 0xea41, 0xee01, 0x2ec0, 0x2f80, 0xef41, 0x2d00, 0xedc1, 0xec81, 0x2c40, 26085ddcd84SMatthias Ringwald 0xe401, 0x24c0, 0x2580, 0xe541, 0x2700, 0xe7c1, 0xe681, 0x2640, 0x2200, 0xe2c1, 0xe381, 0x2340, 0xe101, 0x21c0, 0x2080, 0xe041, 26185ddcd84SMatthias Ringwald 0xa001, 0x60c0, 0x6180, 0xa141, 0x6300, 0xa3c1, 0xa281, 0x6240, 0x6600, 0xa6c1, 0xa781, 0x6740, 0xa501, 0x65c0, 0x6480, 0xa441, 26285ddcd84SMatthias Ringwald 0x6c00, 0xacc1, 0xad81, 0x6d40, 0xaf01, 0x6fc0, 0x6e80, 0xae41, 0xaa01, 0x6ac0, 0x6b80, 0xab41, 0x6900, 0xa9c1, 0xa881, 0x6840, 26385ddcd84SMatthias Ringwald 0x7800, 0xb8c1, 0xb981, 0x7940, 0xbb01, 0x7bc0, 0x7a80, 0xba41, 0xbe01, 0x7ec0, 0x7f80, 0xbf41, 0x7d00, 0xbdc1, 0xbc81, 0x7c40, 26485ddcd84SMatthias Ringwald 0xb401, 0x74c0, 0x7580, 0xb541, 0x7700, 0xb7c1, 0xb681, 0x7640, 0x7200, 0xb2c1, 0xb381, 0x7340, 0xb101, 0x71c0, 0x7080, 0xb041, 26585ddcd84SMatthias Ringwald 0x5000, 0x90c1, 0x9181, 0x5140, 0x9301, 0x53c0, 0x5280, 0x9241, 0x9601, 0x56c0, 0x5780, 0x9741, 0x5500, 0x95c1, 0x9481, 0x5440, 26685ddcd84SMatthias Ringwald 0x9c01, 0x5cc0, 0x5d80, 0x9d41, 0x5f00, 0x9fc1, 0x9e81, 0x5e40, 0x5a00, 0x9ac1, 0x9b81, 0x5b40, 0x9901, 0x59c0, 0x5880, 0x9841, 26785ddcd84SMatthias Ringwald 0x8801, 0x48c0, 0x4980, 0x8941, 0x4b00, 0x8bc1, 0x8a81, 0x4a40, 0x4e00, 0x8ec1, 0x8f81, 0x4f40, 0x8d01, 0x4dc0, 0x4c80, 0x8c41, 26885ddcd84SMatthias Ringwald 0x4400, 0x84c1, 0x8581, 0x4540, 0x8701, 0x47c0, 0x4680, 0x8641, 0x8201, 0x42c0, 0x4380, 0x8341, 0x4100, 0x81c1, 0x8081, 0x4040, 26985ddcd84SMatthias Ringwald }; 27085ddcd84SMatthias Ringwald 27185ddcd84SMatthias Ringwald static uint16_t crc16_calc(uint8_t * data, uint16_t len){ 27285ddcd84SMatthias Ringwald uint16_t crc = 0; // initial value = 0 27385ddcd84SMatthias Ringwald while (len--){ 27485ddcd84SMatthias Ringwald crc = (crc >> 8) ^ crc16_table[ (crc ^ ((uint16_t) *data++)) & 0x00FF ]; 27585ddcd84SMatthias Ringwald } 27685ddcd84SMatthias Ringwald return crc; 27785ddcd84SMatthias Ringwald } 27885ddcd84SMatthias Ringwald 279474f5c3fSMatthias Ringwald static inline uint16_t l2cap_encanced_control_field_for_information_frame(uint8_t tx_seq, int final, uint8_t req_seq, l2cap_segmentation_and_reassembly_t sar){ 280474f5c3fSMatthias Ringwald return (((uint16_t) sar) << 14) | (req_seq << 8) | (final << 7) | (tx_seq << 1) | 0; 281474f5c3fSMatthias Ringwald } 282474f5c3fSMatthias Ringwald 283474f5c3fSMatthias Ringwald static inline uint16_t l2cap_encanced_control_field_for_supevisor_frame(l2cap_supervisory_function_t supervisory_function, int poll, int final, uint8_t req_seq){ 284474f5c3fSMatthias Ringwald return (req_seq << 8) | (final << 7) | (poll << 4) | (((int) supervisory_function) << 2) | 1; 285474f5c3fSMatthias Ringwald } 286474f5c3fSMatthias Ringwald 287474f5c3fSMatthias Ringwald static int l2cap_next_ertm_seq_nr(int seq_nr){ 288474f5c3fSMatthias Ringwald return (seq_nr + 1) & 0x3f; 289474f5c3fSMatthias Ringwald } 290474f5c3fSMatthias Ringwald 2916106bf3fSMatthias Ringwald static bool l2cap_ertm_can_store_packet_now(l2cap_channel_t * channel){ 292474f5c3fSMatthias Ringwald // get num free tx buffers 293a8409e80SMatthias Ringwald int num_free_tx_buffers = channel->num_tx_buffers - channel->num_stored_tx_frames; 294474f5c3fSMatthias Ringwald // calculate num tx buffers for remote MTU 295474f5c3fSMatthias Ringwald int num_tx_buffers_for_max_remote_mtu; 296b90eac91SMatthias Ringwald uint16_t effective_mps = btstack_min(channel->remote_mps, channel->local_mps); 297b90eac91SMatthias Ringwald if (channel->remote_mtu <= effective_mps){ 298474f5c3fSMatthias Ringwald // MTU fits into single packet 299474f5c3fSMatthias Ringwald num_tx_buffers_for_max_remote_mtu = 1; 300474f5c3fSMatthias Ringwald } else { 301474f5c3fSMatthias Ringwald // include SDU Length 302b90eac91SMatthias Ringwald num_tx_buffers_for_max_remote_mtu = (channel->remote_mtu + 2 + (effective_mps - 1)) / effective_mps; 303474f5c3fSMatthias Ringwald } 304a8409e80SMatthias Ringwald log_debug("num_free_tx_buffers %u, num_tx_buffers_for_max_remote_mtu %u", num_free_tx_buffers, num_tx_buffers_for_max_remote_mtu); 305474f5c3fSMatthias Ringwald return num_tx_buffers_for_max_remote_mtu <= num_free_tx_buffers; 306474f5c3fSMatthias Ringwald } 307474f5c3fSMatthias Ringwald 308ef2faf56SMatthias Ringwald static void l2cap_ertm_retransmit_unacknowleded_frames(l2cap_channel_t * l2cap_channel){ 309ef2faf56SMatthias Ringwald log_info("Retransmit unacknowleged frames"); 310ef2faf56SMatthias Ringwald l2cap_channel->unacked_frames = 0;; 311ef2faf56SMatthias Ringwald l2cap_channel->tx_send_index = l2cap_channel->tx_read_index; 312ef2faf56SMatthias Ringwald } 313ef2faf56SMatthias Ringwald 314474f5c3fSMatthias Ringwald static void l2cap_ertm_next_tx_write_index(l2cap_channel_t * channel){ 315474f5c3fSMatthias Ringwald channel->tx_write_index++; 316474f5c3fSMatthias Ringwald if (channel->tx_write_index < channel->num_tx_buffers) return; 317474f5c3fSMatthias Ringwald channel->tx_write_index = 0; 318474f5c3fSMatthias Ringwald } 319474f5c3fSMatthias Ringwald 320474f5c3fSMatthias Ringwald static void l2cap_ertm_start_monitor_timer(l2cap_channel_t * channel){ 321550189ffSMatthias Ringwald log_info("Start Monitor timer"); 322474f5c3fSMatthias Ringwald btstack_run_loop_remove_timer(&channel->monitor_timer); 323474f5c3fSMatthias Ringwald btstack_run_loop_set_timer_handler(&channel->monitor_timer, &l2cap_ertm_monitor_timeout_callback); 324474f5c3fSMatthias Ringwald btstack_run_loop_set_timer_context(&channel->monitor_timer, channel); 325474f5c3fSMatthias Ringwald btstack_run_loop_set_timer(&channel->monitor_timer, channel->local_monitor_timeout_ms); 326474f5c3fSMatthias Ringwald btstack_run_loop_add_timer(&channel->monitor_timer); 327474f5c3fSMatthias Ringwald } 328474f5c3fSMatthias Ringwald 329550189ffSMatthias Ringwald static void l2cap_ertm_stop_monitor_timer(l2cap_channel_t * channel){ 330550189ffSMatthias Ringwald log_info("Stop Monitor timer"); 331550189ffSMatthias Ringwald btstack_run_loop_remove_timer(&channel->monitor_timer); 332550189ffSMatthias Ringwald } 333474f5c3fSMatthias Ringwald 334474f5c3fSMatthias Ringwald static void l2cap_ertm_start_retransmission_timer(l2cap_channel_t * channel){ 335550189ffSMatthias Ringwald log_info("Start Retransmission timer"); 336474f5c3fSMatthias Ringwald btstack_run_loop_remove_timer(&channel->retransmission_timer); 337474f5c3fSMatthias Ringwald btstack_run_loop_set_timer_handler(&channel->retransmission_timer, &l2cap_ertm_retransmission_timeout_callback); 338474f5c3fSMatthias Ringwald btstack_run_loop_set_timer_context(&channel->retransmission_timer, channel); 339474f5c3fSMatthias Ringwald btstack_run_loop_set_timer(&channel->retransmission_timer, channel->local_retransmission_timeout_ms); 340474f5c3fSMatthias Ringwald btstack_run_loop_add_timer(&channel->retransmission_timer); 341474f5c3fSMatthias Ringwald } 342474f5c3fSMatthias Ringwald 343474f5c3fSMatthias Ringwald static void l2cap_ertm_stop_retransmission_timer(l2cap_channel_t * l2cap_channel){ 344550189ffSMatthias Ringwald log_info("Stop Retransmission timer"); 345474f5c3fSMatthias Ringwald btstack_run_loop_remove_timer(&l2cap_channel->retransmission_timer); 346474f5c3fSMatthias Ringwald } 347474f5c3fSMatthias Ringwald 348474f5c3fSMatthias Ringwald static void l2cap_ertm_monitor_timeout_callback(btstack_timer_source_t * ts){ 349550189ffSMatthias Ringwald log_info("Monitor timeout"); 350474f5c3fSMatthias Ringwald l2cap_channel_t * l2cap_channel = (l2cap_channel_t *) btstack_run_loop_get_timer_context(ts); 351474f5c3fSMatthias Ringwald 352474f5c3fSMatthias Ringwald // TODO: we assume that it's the oldest packet 353474f5c3fSMatthias Ringwald l2cap_ertm_tx_packet_state_t * tx_state; 354474f5c3fSMatthias Ringwald tx_state = &l2cap_channel->tx_packets_state[l2cap_channel->tx_read_index]; 355474f5c3fSMatthias Ringwald 356474f5c3fSMatthias Ringwald // check retry count 357474f5c3fSMatthias Ringwald if (tx_state->retry_count < l2cap_channel->remote_max_transmit){ 358474f5c3fSMatthias Ringwald // increment retry count 359474f5c3fSMatthias Ringwald tx_state->retry_count++; 360474f5c3fSMatthias Ringwald 361ef2faf56SMatthias Ringwald // start retransmit 362ef2faf56SMatthias Ringwald l2cap_ertm_retransmit_unacknowleded_frames(l2cap_channel); 363ef2faf56SMatthias Ringwald 364ef2faf56SMatthias Ringwald // start monitor timer 365474f5c3fSMatthias Ringwald l2cap_ertm_start_monitor_timer(l2cap_channel); 366474f5c3fSMatthias Ringwald 367474f5c3fSMatthias Ringwald // send RR/P=1 368474f5c3fSMatthias Ringwald l2cap_channel->send_supervisor_frame_receiver_ready_poll = 1; 369474f5c3fSMatthias Ringwald } else { 370474f5c3fSMatthias Ringwald log_info("Monitor timer expired & retry count >= max transmit -> disconnect"); 371474f5c3fSMatthias Ringwald l2cap_channel->state = L2CAP_STATE_WILL_SEND_DISCONNECT_REQUEST; 372474f5c3fSMatthias Ringwald } 373474f5c3fSMatthias Ringwald l2cap_run(); 374474f5c3fSMatthias Ringwald } 375474f5c3fSMatthias Ringwald 376474f5c3fSMatthias Ringwald static void l2cap_ertm_retransmission_timeout_callback(btstack_timer_source_t * ts){ 377550189ffSMatthias Ringwald log_info("Retransmission timeout"); 378474f5c3fSMatthias Ringwald l2cap_channel_t * l2cap_channel = (l2cap_channel_t *) btstack_run_loop_get_timer_context(ts); 379474f5c3fSMatthias Ringwald 380474f5c3fSMatthias Ringwald // TODO: we assume that it's the oldest packet 381474f5c3fSMatthias Ringwald l2cap_ertm_tx_packet_state_t * tx_state; 382474f5c3fSMatthias Ringwald tx_state = &l2cap_channel->tx_packets_state[l2cap_channel->tx_read_index]; 383474f5c3fSMatthias Ringwald 384474f5c3fSMatthias Ringwald // set retry count = 1 385474f5c3fSMatthias Ringwald tx_state->retry_count = 1; 386474f5c3fSMatthias Ringwald 387ef2faf56SMatthias Ringwald // start retransmit 388ef2faf56SMatthias Ringwald l2cap_ertm_retransmit_unacknowleded_frames(l2cap_channel); 389ef2faf56SMatthias Ringwald 390474f5c3fSMatthias Ringwald // start monitor timer 391474f5c3fSMatthias Ringwald l2cap_ertm_start_monitor_timer(l2cap_channel); 392474f5c3fSMatthias Ringwald 393474f5c3fSMatthias Ringwald // send RR/P=1 394474f5c3fSMatthias Ringwald l2cap_channel->send_supervisor_frame_receiver_ready_poll = 1; 395474f5c3fSMatthias Ringwald l2cap_run(); 396474f5c3fSMatthias Ringwald } 397474f5c3fSMatthias Ringwald 398474f5c3fSMatthias Ringwald static int l2cap_ertm_send_information_frame(l2cap_channel_t * channel, int index, int final){ 399474f5c3fSMatthias Ringwald l2cap_ertm_tx_packet_state_t * tx_state = &channel->tx_packets_state[index]; 400474f5c3fSMatthias Ringwald hci_reserve_packet_buffer(); 401474f5c3fSMatthias Ringwald uint8_t *acl_buffer = hci_get_outgoing_packet_buffer(); 402474f5c3fSMatthias Ringwald uint16_t control = l2cap_encanced_control_field_for_information_frame(tx_state->tx_seq, final, channel->req_seq, tx_state->sar); 403474f5c3fSMatthias Ringwald log_info("I-Frame: control 0x%04x", control); 404474f5c3fSMatthias Ringwald little_endian_store_16(acl_buffer, 8, control); 4056535961aSMatthias Ringwald (void)memcpy(&acl_buffer[8 + 2], 4066535961aSMatthias Ringwald &channel->tx_packets_data[index * channel->local_mps], 4076535961aSMatthias Ringwald tx_state->len); 4081e1a46bbSMatthias Ringwald // (re-)start retransmission timer on 4091e1a46bbSMatthias Ringwald l2cap_ertm_start_retransmission_timer(channel); 410474f5c3fSMatthias Ringwald // send 411474f5c3fSMatthias Ringwald return l2cap_send_prepared(channel->local_cid, 2 + tx_state->len); 412474f5c3fSMatthias Ringwald } 413474f5c3fSMatthias Ringwald 414474f5c3fSMatthias Ringwald static void l2cap_ertm_store_fragment(l2cap_channel_t * channel, l2cap_segmentation_and_reassembly_t sar, uint16_t sdu_length, uint8_t * data, uint16_t len){ 415474f5c3fSMatthias Ringwald // get next index for storing packets 416474f5c3fSMatthias Ringwald int index = channel->tx_write_index; 417474f5c3fSMatthias Ringwald 418474f5c3fSMatthias Ringwald l2cap_ertm_tx_packet_state_t * tx_state = &channel->tx_packets_state[index]; 419474f5c3fSMatthias Ringwald tx_state->tx_seq = channel->next_tx_seq; 420474f5c3fSMatthias Ringwald tx_state->sar = sar; 421474f5c3fSMatthias Ringwald tx_state->retry_count = 0; 422474f5c3fSMatthias Ringwald 4233b81f0d3SMatthias Ringwald uint8_t * tx_packet = &channel->tx_packets_data[index * channel->local_mps]; 424b90eac91SMatthias Ringwald log_debug("index %u, local mps %u, remote mps %u, packet tx %p, len %u", index, channel->local_mps, channel->remote_mps, tx_packet, len); 425474f5c3fSMatthias Ringwald int pos = 0; 426474f5c3fSMatthias Ringwald if (sar == L2CAP_SEGMENTATION_AND_REASSEMBLY_START_OF_L2CAP_SDU){ 427474f5c3fSMatthias Ringwald little_endian_store_16(tx_packet, 0, sdu_length); 428474f5c3fSMatthias Ringwald pos += 2; 429474f5c3fSMatthias Ringwald } 4306535961aSMatthias Ringwald (void)memcpy(&tx_packet[pos], data, len); 431b90eac91SMatthias Ringwald tx_state->len = pos + len; 432474f5c3fSMatthias Ringwald 433474f5c3fSMatthias Ringwald // update 434a8409e80SMatthias Ringwald channel->num_stored_tx_frames++; 435474f5c3fSMatthias Ringwald channel->next_tx_seq = l2cap_next_ertm_seq_nr(channel->next_tx_seq); 436474f5c3fSMatthias Ringwald l2cap_ertm_next_tx_write_index(channel); 43794301352SMatthias Ringwald 438a8409e80SMatthias Ringwald log_info("l2cap_ertm_store_fragment: tx_read_index %u, tx_write_index %u, num stored %u", channel->tx_read_index, channel->tx_write_index, channel->num_stored_tx_frames); 43994301352SMatthias Ringwald 440474f5c3fSMatthias Ringwald } 441474f5c3fSMatthias Ringwald 442dccc4e95SMatthias Ringwald static uint8_t l2cap_ertm_send(l2cap_channel_t * channel, uint8_t * data, uint16_t len){ 443474f5c3fSMatthias Ringwald if (len > channel->remote_mtu){ 444a8409e80SMatthias Ringwald log_error("l2cap_ertm_send cid 0x%02x, data length exceeds remote MTU.", channel->local_cid); 445474f5c3fSMatthias Ringwald return L2CAP_DATA_LEN_EXCEEDS_REMOTE_MTU; 446474f5c3fSMatthias Ringwald } 447474f5c3fSMatthias Ringwald 448a8409e80SMatthias Ringwald if (!l2cap_ertm_can_store_packet_now(channel)){ 449a8409e80SMatthias Ringwald log_error("l2cap_ertm_send cid 0x%02x, fragment store full", channel->local_cid); 450a8409e80SMatthias Ringwald return BTSTACK_ACL_BUFFERS_FULL; 451a8409e80SMatthias Ringwald } 452a8409e80SMatthias Ringwald 453474f5c3fSMatthias Ringwald // check if it needs to get fragmented 454b90eac91SMatthias Ringwald uint16_t effective_mps = btstack_min(channel->remote_mps, channel->local_mps); 455b90eac91SMatthias Ringwald if (len > effective_mps){ 456474f5c3fSMatthias Ringwald // fragmentation needed. 457474f5c3fSMatthias Ringwald l2cap_segmentation_and_reassembly_t sar = L2CAP_SEGMENTATION_AND_REASSEMBLY_START_OF_L2CAP_SDU; 458474f5c3fSMatthias Ringwald int chunk_len; 459474f5c3fSMatthias Ringwald while (len){ 460474f5c3fSMatthias Ringwald switch (sar){ 461474f5c3fSMatthias Ringwald case L2CAP_SEGMENTATION_AND_REASSEMBLY_START_OF_L2CAP_SDU: 462b90eac91SMatthias Ringwald chunk_len = effective_mps - 2; // sdu_length 463474f5c3fSMatthias Ringwald l2cap_ertm_store_fragment(channel, sar, len, data, chunk_len); 464474f5c3fSMatthias Ringwald len -= chunk_len; 465474f5c3fSMatthias Ringwald sar = L2CAP_SEGMENTATION_AND_REASSEMBLY_CONTINUATION_OF_L2CAP_SDU; 466474f5c3fSMatthias Ringwald break; 467474f5c3fSMatthias Ringwald case L2CAP_SEGMENTATION_AND_REASSEMBLY_CONTINUATION_OF_L2CAP_SDU: 468b90eac91SMatthias Ringwald chunk_len = effective_mps; 469474f5c3fSMatthias Ringwald if (chunk_len >= len){ 470474f5c3fSMatthias Ringwald sar = L2CAP_SEGMENTATION_AND_REASSEMBLY_END_OF_L2CAP_SDU; 471474f5c3fSMatthias Ringwald chunk_len = len; 472474f5c3fSMatthias Ringwald } 473474f5c3fSMatthias Ringwald l2cap_ertm_store_fragment(channel, sar, len, data, chunk_len); 474474f5c3fSMatthias Ringwald len -= chunk_len; 475474f5c3fSMatthias Ringwald break; 476474f5c3fSMatthias Ringwald default: 477474f5c3fSMatthias Ringwald break; 478474f5c3fSMatthias Ringwald } 479474f5c3fSMatthias Ringwald } 480474f5c3fSMatthias Ringwald 481474f5c3fSMatthias Ringwald } else { 482474f5c3fSMatthias Ringwald l2cap_ertm_store_fragment(channel, L2CAP_SEGMENTATION_AND_REASSEMBLY_UNSEGMENTED_L2CAP_SDU, 0, data, len); 483474f5c3fSMatthias Ringwald } 484474f5c3fSMatthias Ringwald 485474f5c3fSMatthias Ringwald // try to send 486d89ab698SMatthias Ringwald l2cap_notify_channel_can_send(); 487dccc4e95SMatthias Ringwald return ERROR_CODE_SUCCESS; 488474f5c3fSMatthias Ringwald } 489474f5c3fSMatthias Ringwald 4907cbe539fSMatthias Ringwald static uint16_t l2cap_setup_options_ertm_request(l2cap_channel_t * channel, uint8_t * config_options){ 491fcb125edSMatthias Ringwald int pos = 0; 492fcb125edSMatthias Ringwald config_options[pos++] = L2CAP_CONFIG_OPTION_TYPE_RETRANSMISSION_AND_FLOW_CONTROL; 493fcb125edSMatthias Ringwald config_options[pos++] = 9; // length 494fcb125edSMatthias Ringwald config_options[pos++] = (uint8_t) channel->mode; 495fcb125edSMatthias Ringwald config_options[pos++] = channel->num_rx_buffers; // == TxWindows size 496fcb125edSMatthias Ringwald config_options[pos++] = channel->local_max_transmit; 497fcb125edSMatthias Ringwald little_endian_store_16( config_options, pos, channel->local_retransmission_timeout_ms); 498fcb125edSMatthias Ringwald pos += 2; 499fcb125edSMatthias Ringwald little_endian_store_16( config_options, pos, channel->local_monitor_timeout_ms); 500fcb125edSMatthias Ringwald pos += 2; 501fcb125edSMatthias Ringwald little_endian_store_16( config_options, pos, channel->local_mps); 502fcb125edSMatthias Ringwald pos += 2; 5036574158aSMatthias Ringwald // 504fcb125edSMatthias Ringwald config_options[pos++] = L2CAP_CONFIG_OPTION_TYPE_MAX_TRANSMISSION_UNIT; 505fcb125edSMatthias Ringwald config_options[pos++] = 2; // length 506fcb125edSMatthias Ringwald little_endian_store_16(config_options, pos, channel->local_mtu); 507fcb125edSMatthias Ringwald pos += 2; 508c425ea4aSMatthias Ringwald 509c425ea4aSMatthias Ringwald // Issue: iOS (e.g. 10.2) uses "No FCS" as default while Core 5.0 specifies "FCS" as default 510c425ea4aSMatthias Ringwald // Workaround: try to actively negotiate FCS option 511fcb125edSMatthias Ringwald config_options[pos++] = L2CAP_CONFIG_OPTION_TYPE_FRAME_CHECK_SEQUENCE; 512fcb125edSMatthias Ringwald config_options[pos++] = 1; // length 513fcb125edSMatthias Ringwald config_options[pos++] = channel->fcs_option; 514f2c70799Sandryblack return pos; // 11+4+3=18 515474f5c3fSMatthias Ringwald } 516474f5c3fSMatthias Ringwald 5177cbe539fSMatthias Ringwald static uint16_t l2cap_setup_options_ertm_response(l2cap_channel_t * channel, uint8_t * config_options){ 518fcb125edSMatthias Ringwald int pos = 0; 519fcb125edSMatthias Ringwald config_options[pos++] = L2CAP_CONFIG_OPTION_TYPE_RETRANSMISSION_AND_FLOW_CONTROL; 520fcb125edSMatthias Ringwald config_options[pos++] = 9; // length 521fcb125edSMatthias Ringwald config_options[pos++] = (uint8_t) channel->mode; 5227cbe539fSMatthias Ringwald // less or equal to remote tx window size 523fcb125edSMatthias Ringwald config_options[pos++] = btstack_min(channel->num_tx_buffers, channel->remote_tx_window_size); 5247cbe539fSMatthias Ringwald // max transmit in response shall be ignored -> use sender values 525fcb125edSMatthias Ringwald config_options[pos++] = channel->remote_max_transmit; 5267cbe539fSMatthias Ringwald // A value for the Retransmission time-out shall be sent in a positive Configuration Response 5277cbe539fSMatthias Ringwald // and indicates the value that will be used by the sender of the Configuration Response -> use our value 528fcb125edSMatthias Ringwald little_endian_store_16( config_options, pos, channel->local_retransmission_timeout_ms); 529fcb125edSMatthias Ringwald pos += 2; 5307cbe539fSMatthias Ringwald // A value for the Monitor time-out shall be sent in a positive Configuration Response 5317cbe539fSMatthias Ringwald // and indicates the value that will be used by the sender of the Configuration Response -> use our value 532fcb125edSMatthias Ringwald little_endian_store_16( config_options, pos, channel->local_monitor_timeout_ms); 533fcb125edSMatthias Ringwald pos += 2; 5347cbe539fSMatthias Ringwald // less or equal to remote mps 535b90eac91SMatthias Ringwald uint16_t effective_mps = btstack_min(channel->remote_mps, channel->local_mps); 536b90eac91SMatthias Ringwald little_endian_store_16( config_options, pos, effective_mps); 537fcb125edSMatthias Ringwald pos += 2; 5386574158aSMatthias Ringwald // 539fcb125edSMatthias Ringwald config_options[pos++] = L2CAP_CONFIG_OPTION_TYPE_MAX_TRANSMISSION_UNIT; // MTU 540fcb125edSMatthias Ringwald config_options[pos++] = 2; // length 541fcb125edSMatthias Ringwald little_endian_store_16(config_options, pos, channel->remote_mtu); 542fcb125edSMatthias Ringwald pos += 2; 543fcb125edSMatthias Ringwald #if 0 544d64e9771SMatthias Ringwald // 545fcb125edSMatthias Ringwald config_options[pos++] = L2CAP_CONFIG_OPTION_TYPE_FRAME_CHECK_SEQUENCE; 546fcb125edSMatthias Ringwald config_options[pos++] = 1; // length 547fcb125edSMatthias Ringwald config_options[pos++] = channel->fcs_option; 548fcb125edSMatthias Ringwald #endif 549f2c70799Sandryblack return pos; // 11+4=15 5507cbe539fSMatthias Ringwald } 5517cbe539fSMatthias Ringwald 552474f5c3fSMatthias Ringwald static int l2cap_ertm_send_supervisor_frame(l2cap_channel_t * channel, uint16_t control){ 553474f5c3fSMatthias Ringwald hci_reserve_packet_buffer(); 554474f5c3fSMatthias Ringwald uint8_t *acl_buffer = hci_get_outgoing_packet_buffer(); 555474f5c3fSMatthias Ringwald log_info("S-Frame: control 0x%04x", control); 556474f5c3fSMatthias Ringwald little_endian_store_16(acl_buffer, 8, control); 557474f5c3fSMatthias Ringwald return l2cap_send_prepared(channel->local_cid, 2); 558474f5c3fSMatthias Ringwald } 559474f5c3fSMatthias Ringwald 5605774a392SMatthias Ringwald static uint8_t l2cap_ertm_validate_local_config(l2cap_ertm_config_t * ertm_config){ 561474f5c3fSMatthias Ringwald 562474f5c3fSMatthias Ringwald uint8_t result = ERROR_CODE_SUCCESS; 5639c0e62d3SMatthias Ringwald if (ertm_config->max_transmit < 1){ 564474f5c3fSMatthias Ringwald log_error("max_transmit must be >= 1"); 565474f5c3fSMatthias Ringwald result = ERROR_CODE_INVALID_HCI_COMMAND_PARAMETERS; 566474f5c3fSMatthias Ringwald } 5679c0e62d3SMatthias Ringwald if (ertm_config->retransmission_timeout_ms < 2000){ 568474f5c3fSMatthias Ringwald log_error("retransmission_timeout_ms must be >= 2000 ms"); 569474f5c3fSMatthias Ringwald result = ERROR_CODE_INVALID_HCI_COMMAND_PARAMETERS; 570474f5c3fSMatthias Ringwald } 5719c0e62d3SMatthias Ringwald if (ertm_config->monitor_timeout_ms < 12000){ 572474f5c3fSMatthias Ringwald log_error("monitor_timeout_ms must be >= 12000 ms"); 573474f5c3fSMatthias Ringwald result = ERROR_CODE_INVALID_HCI_COMMAND_PARAMETERS; 574474f5c3fSMatthias Ringwald } 5759c0e62d3SMatthias Ringwald if (ertm_config->local_mtu < 48){ 576474f5c3fSMatthias Ringwald log_error("local_mtu must be >= 48"); 577474f5c3fSMatthias Ringwald result = ERROR_CODE_INVALID_HCI_COMMAND_PARAMETERS; 578474f5c3fSMatthias Ringwald } 5799c0e62d3SMatthias Ringwald if (ertm_config->num_rx_buffers < 1){ 580474f5c3fSMatthias Ringwald log_error("num_rx_buffers must be >= 1"); 581474f5c3fSMatthias Ringwald result = ERROR_CODE_INVALID_HCI_COMMAND_PARAMETERS; 582474f5c3fSMatthias Ringwald } 5839c0e62d3SMatthias Ringwald if (ertm_config->num_tx_buffers < 1){ 584474f5c3fSMatthias Ringwald log_error("num_rx_buffers must be >= 1"); 585474f5c3fSMatthias Ringwald result = ERROR_CODE_INVALID_HCI_COMMAND_PARAMETERS; 586474f5c3fSMatthias Ringwald } 587474f5c3fSMatthias Ringwald return result; 588474f5c3fSMatthias Ringwald } 589474f5c3fSMatthias Ringwald 5909c0e62d3SMatthias Ringwald static void l2cap_ertm_configure_channel(l2cap_channel_t * channel, l2cap_ertm_config_t * ertm_config, uint8_t * buffer, uint32_t size){ 591474f5c3fSMatthias Ringwald 592474f5c3fSMatthias Ringwald channel->mode = L2CAP_CHANNEL_MODE_ENHANCED_RETRANSMISSION; 5939c0e62d3SMatthias Ringwald channel->ertm_mandatory = ertm_config->ertm_mandatory; 5949c0e62d3SMatthias Ringwald channel->local_max_transmit = ertm_config->max_transmit; 5959c0e62d3SMatthias Ringwald channel->local_retransmission_timeout_ms = ertm_config->retransmission_timeout_ms; 5969c0e62d3SMatthias Ringwald channel->local_monitor_timeout_ms = ertm_config->monitor_timeout_ms; 5979c0e62d3SMatthias Ringwald channel->local_mtu = ertm_config->local_mtu; 5989c0e62d3SMatthias Ringwald channel->num_rx_buffers = ertm_config->num_rx_buffers; 5999c0e62d3SMatthias Ringwald channel->num_tx_buffers = ertm_config->num_tx_buffers; 600474f5c3fSMatthias Ringwald 601c342091bSMatthias Ringwald // align buffer to 16-byte boundary to assert l2cap_ertm_rx_packet_state_t is aligned 602474f5c3fSMatthias Ringwald int bytes_till_alignment = 16 - (((uintptr_t) buffer) & 0x0f); 603474f5c3fSMatthias Ringwald buffer += bytes_till_alignment; 604474f5c3fSMatthias Ringwald size -= bytes_till_alignment; 605474f5c3fSMatthias Ringwald 606c342091bSMatthias Ringwald // setup state buffers - use void cast to avoid -Wcast-align warning 607474f5c3fSMatthias Ringwald uint32_t pos = 0; 608c342091bSMatthias Ringwald channel->rx_packets_state = (l2cap_ertm_rx_packet_state_t *) (void *) &buffer[pos]; 6099c0e62d3SMatthias Ringwald pos += ertm_config->num_rx_buffers * sizeof(l2cap_ertm_rx_packet_state_t); 610c342091bSMatthias Ringwald channel->tx_packets_state = (l2cap_ertm_tx_packet_state_t *) (void *) &buffer[pos]; 6119c0e62d3SMatthias Ringwald pos += ertm_config->num_tx_buffers * sizeof(l2cap_ertm_tx_packet_state_t); 612474f5c3fSMatthias Ringwald 613474f5c3fSMatthias Ringwald // setup reassembly buffer 614474f5c3fSMatthias Ringwald channel->reassembly_buffer = &buffer[pos]; 6159c0e62d3SMatthias Ringwald pos += ertm_config->local_mtu; 616474f5c3fSMatthias Ringwald 617474f5c3fSMatthias Ringwald // divide rest of data equally 6189c0e62d3SMatthias Ringwald channel->local_mps = (size - pos) / (ertm_config->num_rx_buffers + ertm_config->num_tx_buffers); 6190d3ee2efSMatthias Ringwald log_info("Local MPS: %u", channel->local_mps); 620474f5c3fSMatthias Ringwald channel->rx_packets_data = &buffer[pos]; 6210d3ee2efSMatthias Ringwald pos += ertm_config->num_rx_buffers * channel->local_mps; 622474f5c3fSMatthias Ringwald channel->tx_packets_data = &buffer[pos]; 6236574158aSMatthias Ringwald 624c425ea4aSMatthias Ringwald channel->fcs_option = ertm_config->fcs_option; 625474f5c3fSMatthias Ringwald } 626474f5c3fSMatthias Ringwald 627474f5c3fSMatthias Ringwald uint8_t l2cap_create_ertm_channel(btstack_packet_handler_t packet_handler, bd_addr_t address, uint16_t psm, 6289c0e62d3SMatthias Ringwald l2cap_ertm_config_t * ertm_config, uint8_t * buffer, uint32_t size, uint16_t * out_local_cid){ 629474f5c3fSMatthias Ringwald 6309c0e62d3SMatthias Ringwald log_info("L2CAP_CREATE_ERTM_CHANNEL addr %s, psm 0x%x, local mtu %u", bd_addr_to_str(address), psm, ertm_config->local_mtu); 631474f5c3fSMatthias Ringwald 632474f5c3fSMatthias Ringwald // validate local config 6335774a392SMatthias Ringwald uint8_t result = l2cap_ertm_validate_local_config(ertm_config); 634474f5c3fSMatthias Ringwald if (result) return result; 635474f5c3fSMatthias Ringwald 636a400e4c3SMatthias Ringwald // determine security level based on psm 637a400e4c3SMatthias Ringwald const gap_security_level_t security_level = l2cap_security_level_0_allowed_for_PSM(psm) ? LEVEL_0 : gap_get_security_level(); 638a400e4c3SMatthias Ringwald 639a400e4c3SMatthias Ringwald l2cap_channel_t * channel = l2cap_create_channel_entry(packet_handler, L2CAP_CHANNEL_TYPE_CLASSIC, address, BD_ADDR_TYPE_ACL, psm, ertm_config->local_mtu, security_level); 640474f5c3fSMatthias Ringwald if (!channel) { 641474f5c3fSMatthias Ringwald return BTSTACK_MEMORY_ALLOC_FAILED; 642474f5c3fSMatthias Ringwald } 643474f5c3fSMatthias Ringwald 644474f5c3fSMatthias Ringwald // configure ERTM 6459c0e62d3SMatthias Ringwald l2cap_ertm_configure_channel(channel, ertm_config, buffer, size); 646474f5c3fSMatthias Ringwald 647474f5c3fSMatthias Ringwald // add to connections list 648da4c2b27SMatthias Ringwald btstack_linked_list_add_tail(&l2cap_channels, (btstack_linked_item_t *) channel); 649474f5c3fSMatthias Ringwald 650474f5c3fSMatthias Ringwald // store local_cid 651474f5c3fSMatthias Ringwald if (out_local_cid){ 652474f5c3fSMatthias Ringwald *out_local_cid = channel->local_cid; 653474f5c3fSMatthias Ringwald } 654474f5c3fSMatthias Ringwald 655474f5c3fSMatthias Ringwald // check if hci connection is already usable 656f16129ceSMatthias Ringwald hci_connection_t * conn = hci_connection_for_bd_addr_and_type(address, BD_ADDR_TYPE_ACL); 657474f5c3fSMatthias Ringwald if (conn){ 658474f5c3fSMatthias Ringwald log_info("l2cap_create_channel, hci connection already exists"); 659474f5c3fSMatthias Ringwald l2cap_handle_connection_complete(conn->con_handle, channel); 660474f5c3fSMatthias Ringwald // check if remote supported fearures are already received 6616ffc78ceSMatthias Ringwald if (hci_remote_features_available(conn->con_handle)) { 662474f5c3fSMatthias Ringwald l2cap_handle_remote_supported_features_received(channel); 663d6596031SMatthias Ringwald } else { 664d6596031SMatthias Ringwald hci_remote_features_query(conn->con_handle); 665d6596031SMatthias Ringwald }; 666474f5c3fSMatthias Ringwald } 667474f5c3fSMatthias Ringwald 668474f5c3fSMatthias Ringwald l2cap_run(); 669474f5c3fSMatthias Ringwald 670474f5c3fSMatthias Ringwald return 0; 671474f5c3fSMatthias Ringwald } 672474f5c3fSMatthias Ringwald 673474f5c3fSMatthias Ringwald static void l2cap_ertm_notify_channel_can_send(l2cap_channel_t * channel){ 674474f5c3fSMatthias Ringwald if (l2cap_ertm_can_store_packet_now(channel)){ 675474f5c3fSMatthias Ringwald channel->waiting_for_can_send_now = 0; 676474f5c3fSMatthias Ringwald l2cap_emit_can_send_now(channel->packet_handler, channel->local_cid); 677474f5c3fSMatthias Ringwald } 678474f5c3fSMatthias Ringwald } 679474f5c3fSMatthias Ringwald 6809c0e62d3SMatthias Ringwald uint8_t l2cap_accept_ertm_connection(uint16_t local_cid, l2cap_ertm_config_t * ertm_config, uint8_t * buffer, uint32_t size){ 681474f5c3fSMatthias Ringwald 682474f5c3fSMatthias Ringwald log_info("L2CAP_ACCEPT_ERTM_CONNECTION local_cid 0x%x", local_cid); 683f68b21d7SMatthias Ringwald l2cap_channel_t * channel = l2cap_get_channel_for_local_cid(local_cid); 684474f5c3fSMatthias Ringwald if (!channel) { 685474f5c3fSMatthias Ringwald log_error("l2cap_accept_connection called but local_cid 0x%x not found", local_cid); 686474f5c3fSMatthias Ringwald return L2CAP_LOCAL_CID_DOES_NOT_EXIST; 687474f5c3fSMatthias Ringwald } 688474f5c3fSMatthias Ringwald 689474f5c3fSMatthias Ringwald // validate local config 6905774a392SMatthias Ringwald uint8_t result = l2cap_ertm_validate_local_config(ertm_config); 691474f5c3fSMatthias Ringwald if (result) return result; 692474f5c3fSMatthias Ringwald 693474f5c3fSMatthias Ringwald // configure L2CAP ERTM 6949c0e62d3SMatthias Ringwald l2cap_ertm_configure_channel(channel, ertm_config, buffer, size); 695474f5c3fSMatthias Ringwald 69663d7a647SMatthias Ringwald // already available? 697836ae835SMatthias Ringwald hci_connection_t * connection = hci_connection_for_handle(channel->con_handle); 69863d7a647SMatthias Ringwald btstack_assert(connection != NULL); 699836ae835SMatthias Ringwald 70063d7a647SMatthias Ringwald // we need to know if ERTM is supported before sending a config response 70163d7a647SMatthias Ringwald switch (connection->l2cap_state.information_state){ 70263d7a647SMatthias Ringwald case L2CAP_INFORMATION_STATE_DONE: 70363d7a647SMatthias Ringwald l2cap_handle_information_request_complete(connection); 70463d7a647SMatthias Ringwald break; 70563d7a647SMatthias Ringwald case L2CAP_INFORMATION_STATE_IDLE: 70663d7a647SMatthias Ringwald connection->l2cap_state.information_state = L2CAP_INFORMATION_STATE_W2_SEND_EXTENDED_FEATURE_REQUEST; 70763d7a647SMatthias Ringwald /* fall through */ 70863d7a647SMatthias Ringwald default: 70963d7a647SMatthias Ringwald channel->state = L2CAP_STATE_WAIT_INCOMING_EXTENDED_FEATURES; 71063d7a647SMatthias Ringwald break; 711836ae835SMatthias Ringwald } 712836ae835SMatthias Ringwald 713474f5c3fSMatthias Ringwald l2cap_run(); 714474f5c3fSMatthias Ringwald 715474f5c3fSMatthias Ringwald return ERROR_CODE_SUCCESS; 716474f5c3fSMatthias Ringwald } 717474f5c3fSMatthias Ringwald 718474f5c3fSMatthias Ringwald uint8_t l2cap_ertm_set_busy(uint16_t local_cid){ 719f68b21d7SMatthias Ringwald l2cap_channel_t * channel = l2cap_get_channel_for_local_cid( local_cid); 720474f5c3fSMatthias Ringwald if (!channel) { 721474f5c3fSMatthias Ringwald log_error( "l2cap_decline_connection called but local_cid 0x%x not found", local_cid); 722474f5c3fSMatthias Ringwald return L2CAP_LOCAL_CID_DOES_NOT_EXIST; 723474f5c3fSMatthias Ringwald } 724474f5c3fSMatthias Ringwald if (!channel->local_busy){ 725474f5c3fSMatthias Ringwald channel->local_busy = 1; 726474f5c3fSMatthias Ringwald channel->send_supervisor_frame_receiver_not_ready = 1; 727474f5c3fSMatthias Ringwald l2cap_run(); 728474f5c3fSMatthias Ringwald } 729474f5c3fSMatthias Ringwald return ERROR_CODE_SUCCESS; 730474f5c3fSMatthias Ringwald } 731474f5c3fSMatthias Ringwald 732474f5c3fSMatthias Ringwald uint8_t l2cap_ertm_set_ready(uint16_t local_cid){ 733f68b21d7SMatthias Ringwald l2cap_channel_t * channel = l2cap_get_channel_for_local_cid( local_cid); 734474f5c3fSMatthias Ringwald if (!channel) { 735474f5c3fSMatthias Ringwald log_error( "l2cap_decline_connection called but local_cid 0x%x not found", local_cid); 736474f5c3fSMatthias Ringwald return L2CAP_LOCAL_CID_DOES_NOT_EXIST; 737474f5c3fSMatthias Ringwald } 738474f5c3fSMatthias Ringwald if (channel->local_busy){ 739474f5c3fSMatthias Ringwald channel->local_busy = 0; 740474f5c3fSMatthias Ringwald channel->send_supervisor_frame_receiver_ready_poll = 1; 741474f5c3fSMatthias Ringwald l2cap_run(); 742474f5c3fSMatthias Ringwald } 743474f5c3fSMatthias Ringwald return ERROR_CODE_SUCCESS; 744474f5c3fSMatthias Ringwald } 745474f5c3fSMatthias Ringwald 7461e1a46bbSMatthias Ringwald // Process-ReqSeq 7471e1a46bbSMatthias Ringwald static void l2cap_ertm_process_req_seq(l2cap_channel_t * l2cap_channel, uint8_t req_seq){ 748474f5c3fSMatthias Ringwald int num_buffers_acked = 0; 749474f5c3fSMatthias Ringwald l2cap_ertm_tx_packet_state_t * tx_state; 75094301352SMatthias Ringwald log_info("l2cap_ertm_process_req_seq: tx_read_index %u, tx_write_index %u, req_seq %u", l2cap_channel->tx_read_index, l2cap_channel->tx_write_index, req_seq); 751ff3cc4a5SMatthias Ringwald while (true){ 7521e1a46bbSMatthias Ringwald 75394301352SMatthias Ringwald // no unack packets left 75494301352SMatthias Ringwald if (l2cap_channel->unacked_frames == 0) { 7551e1a46bbSMatthias Ringwald // stop retransmission timer 7561e1a46bbSMatthias Ringwald l2cap_ertm_stop_retransmission_timer(l2cap_channel); 7571e1a46bbSMatthias Ringwald break; 7581e1a46bbSMatthias Ringwald } 7591e1a46bbSMatthias Ringwald 760474f5c3fSMatthias Ringwald tx_state = &l2cap_channel->tx_packets_state[l2cap_channel->tx_read_index]; 761474f5c3fSMatthias Ringwald // calc delta 762474f5c3fSMatthias Ringwald int delta = (req_seq - tx_state->tx_seq) & 0x03f; 763474f5c3fSMatthias Ringwald if (delta == 0) break; // all packets acknowledged 764474f5c3fSMatthias Ringwald if (delta > l2cap_channel->remote_tx_window_size) break; 765474f5c3fSMatthias Ringwald 766474f5c3fSMatthias Ringwald num_buffers_acked++; 767a8409e80SMatthias Ringwald l2cap_channel->num_stored_tx_frames--; 76894301352SMatthias Ringwald l2cap_channel->unacked_frames--; 769474f5c3fSMatthias Ringwald log_info("RR seq %u => packet with tx_seq %u done", req_seq, tx_state->tx_seq); 770474f5c3fSMatthias Ringwald 771474f5c3fSMatthias Ringwald l2cap_channel->tx_read_index++; 772474f5c3fSMatthias Ringwald if (l2cap_channel->tx_read_index >= l2cap_channel->num_rx_buffers){ 773474f5c3fSMatthias Ringwald l2cap_channel->tx_read_index = 0; 774474f5c3fSMatthias Ringwald } 775474f5c3fSMatthias Ringwald } 776474f5c3fSMatthias Ringwald if (num_buffers_acked){ 777a8409e80SMatthias Ringwald log_info("num_buffers_acked %u", num_buffers_acked); 778474f5c3fSMatthias Ringwald l2cap_ertm_notify_channel_can_send(l2cap_channel); 779474f5c3fSMatthias Ringwald } 780474f5c3fSMatthias Ringwald } 781474f5c3fSMatthias Ringwald 782474f5c3fSMatthias Ringwald static l2cap_ertm_tx_packet_state_t * l2cap_ertm_get_tx_state(l2cap_channel_t * l2cap_channel, uint8_t tx_seq){ 783474f5c3fSMatthias Ringwald int i; 784474f5c3fSMatthias Ringwald for (i=0;i<l2cap_channel->num_tx_buffers;i++){ 785474f5c3fSMatthias Ringwald l2cap_ertm_tx_packet_state_t * tx_state = &l2cap_channel->tx_packets_state[i]; 786474f5c3fSMatthias Ringwald if (tx_state->tx_seq == tx_seq) return tx_state; 787474f5c3fSMatthias Ringwald } 788474f5c3fSMatthias Ringwald return NULL; 789474f5c3fSMatthias Ringwald } 790474f5c3fSMatthias Ringwald 791474f5c3fSMatthias Ringwald // @param delta number of frames in the future, >= 1 792122c2b05SMatthias Ringwald // @assumption size <= l2cap_channel->local_mps (checked in l2cap_acl_classic_handler) 7933d244bfaSMatthias Ringwald static void l2cap_ertm_handle_out_of_sequence_sdu(l2cap_channel_t * l2cap_channel, l2cap_segmentation_and_reassembly_t sar, int delta, const uint8_t * payload, uint16_t size){ 794474f5c3fSMatthias Ringwald log_info("Store SDU with delta %u", delta); 795474f5c3fSMatthias Ringwald // get rx state for packet to store 796474f5c3fSMatthias Ringwald int index = l2cap_channel->rx_store_index + delta - 1; 797474f5c3fSMatthias Ringwald if (index > l2cap_channel->num_rx_buffers){ 798474f5c3fSMatthias Ringwald index -= l2cap_channel->num_rx_buffers; 799474f5c3fSMatthias Ringwald } 800474f5c3fSMatthias Ringwald log_info("Index of packet to store %u", index); 801474f5c3fSMatthias Ringwald l2cap_ertm_rx_packet_state_t * rx_state = &l2cap_channel->rx_packets_state[index]; 802474f5c3fSMatthias Ringwald // check if buffer is free 803474f5c3fSMatthias Ringwald if (rx_state->valid){ 804474f5c3fSMatthias Ringwald log_error("Packet buffer already used"); 805474f5c3fSMatthias Ringwald return; 806474f5c3fSMatthias Ringwald } 807474f5c3fSMatthias Ringwald rx_state->valid = 1; 808474f5c3fSMatthias Ringwald rx_state->sar = sar; 809474f5c3fSMatthias Ringwald rx_state->len = size; 810474f5c3fSMatthias Ringwald uint8_t * rx_buffer = &l2cap_channel->rx_packets_data[index]; 8116535961aSMatthias Ringwald (void)memcpy(rx_buffer, payload, size); 812474f5c3fSMatthias Ringwald } 813474f5c3fSMatthias Ringwald 814122c2b05SMatthias Ringwald // @assumption size <= l2cap_channel->local_mps (checked in l2cap_acl_classic_handler) 8153d244bfaSMatthias Ringwald static void l2cap_ertm_handle_in_sequence_sdu(l2cap_channel_t * l2cap_channel, l2cap_segmentation_and_reassembly_t sar, const uint8_t * payload, uint16_t size){ 816122c2b05SMatthias Ringwald uint16_t reassembly_sdu_length; 817474f5c3fSMatthias Ringwald switch (sar){ 818474f5c3fSMatthias Ringwald case L2CAP_SEGMENTATION_AND_REASSEMBLY_UNSEGMENTED_L2CAP_SDU: 819122c2b05SMatthias Ringwald // assert total packet size <= our mtu 820122c2b05SMatthias Ringwald if (size > l2cap_channel->local_mtu) break; 821474f5c3fSMatthias Ringwald // packet complete -> disapatch 8223d244bfaSMatthias Ringwald l2cap_dispatch_to_channel(l2cap_channel, L2CAP_DATA_PACKET, (uint8_t*) payload, size); 823474f5c3fSMatthias Ringwald break; 824474f5c3fSMatthias Ringwald case L2CAP_SEGMENTATION_AND_REASSEMBLY_START_OF_L2CAP_SDU: 825122c2b05SMatthias Ringwald // read SDU len 826122c2b05SMatthias Ringwald reassembly_sdu_length = little_endian_read_16(payload, 0); 827474f5c3fSMatthias Ringwald payload += 2; 828474f5c3fSMatthias Ringwald size -= 2; 829122c2b05SMatthias Ringwald // assert reassembled size <= our mtu 830122c2b05SMatthias Ringwald if (reassembly_sdu_length > l2cap_channel->local_mtu) break; 831122c2b05SMatthias Ringwald // store start segment 832122c2b05SMatthias Ringwald l2cap_channel->reassembly_sdu_length = reassembly_sdu_length; 8336535961aSMatthias Ringwald (void)memcpy(&l2cap_channel->reassembly_buffer[0], payload, size); 834474f5c3fSMatthias Ringwald l2cap_channel->reassembly_pos = size; 835474f5c3fSMatthias Ringwald break; 836474f5c3fSMatthias Ringwald case L2CAP_SEGMENTATION_AND_REASSEMBLY_CONTINUATION_OF_L2CAP_SDU: 837122c2b05SMatthias Ringwald // assert size of reassembled data <= our mtu 838122c2b05SMatthias Ringwald if (l2cap_channel->reassembly_pos + size > l2cap_channel->local_mtu) break; 839122c2b05SMatthias Ringwald // store continuation segment 8406535961aSMatthias Ringwald (void)memcpy(&l2cap_channel->reassembly_buffer[l2cap_channel->reassembly_pos], 8416535961aSMatthias Ringwald payload, size); 842474f5c3fSMatthias Ringwald l2cap_channel->reassembly_pos += size; 843474f5c3fSMatthias Ringwald break; 844474f5c3fSMatthias Ringwald case L2CAP_SEGMENTATION_AND_REASSEMBLY_END_OF_L2CAP_SDU: 845122c2b05SMatthias Ringwald // assert size of reassembled data <= our mtu 846122c2b05SMatthias Ringwald if (l2cap_channel->reassembly_pos + size > l2cap_channel->local_mtu) break; 847122c2b05SMatthias Ringwald // store continuation segment 8486535961aSMatthias Ringwald (void)memcpy(&l2cap_channel->reassembly_buffer[l2cap_channel->reassembly_pos], 8496535961aSMatthias Ringwald payload, size); 850474f5c3fSMatthias Ringwald l2cap_channel->reassembly_pos += size; 851122c2b05SMatthias Ringwald // assert size of reassembled data matches announced sdu length 852122c2b05SMatthias Ringwald if (l2cap_channel->reassembly_pos != l2cap_channel->reassembly_sdu_length) break; 853474f5c3fSMatthias Ringwald // packet complete -> disapatch 854474f5c3fSMatthias Ringwald l2cap_dispatch_to_channel(l2cap_channel, L2CAP_DATA_PACKET, l2cap_channel->reassembly_buffer, l2cap_channel->reassembly_pos); 855474f5c3fSMatthias Ringwald l2cap_channel->reassembly_pos = 0; 856474f5c3fSMatthias Ringwald break; 8577bbeb3adSMilanka Ringwald default: 8587bbeb3adSMilanka Ringwald btstack_assert(false); 8597bbeb3adSMilanka Ringwald break; 860474f5c3fSMatthias Ringwald } 861474f5c3fSMatthias Ringwald } 862474f5c3fSMatthias Ringwald 863d89ab698SMatthias Ringwald static void l2cap_ertm_channel_send_information_frame(l2cap_channel_t * channel){ 864d89ab698SMatthias Ringwald channel->unacked_frames++; 865d89ab698SMatthias Ringwald int index = channel->tx_send_index; 866d89ab698SMatthias Ringwald channel->tx_send_index++; 867d89ab698SMatthias Ringwald if (channel->tx_send_index >= channel->num_tx_buffers){ 868d89ab698SMatthias Ringwald channel->tx_send_index = 0; 869d89ab698SMatthias Ringwald } 870d89ab698SMatthias Ringwald l2cap_ertm_send_information_frame(channel, index, 0); // final = 0 871d89ab698SMatthias Ringwald } 872d89ab698SMatthias Ringwald 87385ddcd84SMatthias Ringwald #endif 87485ddcd84SMatthias Ringwald 8756a5ffed8SMatthias Ringwald #ifdef L2CAP_USES_CHANNELS 8766ddef68dSMilanka Ringwald static uint16_t l2cap_next_local_cid(void){ 8776268fbfeSMilanka Ringwald do { 8782017c6d2SMatthias Ringwald if (l2cap_local_source_cid == 0xfffeu) { 87991c8d67dSMatthias Ringwald l2cap_local_source_cid = 0x40; 8806268fbfeSMilanka Ringwald } else { 88191c8d67dSMatthias Ringwald l2cap_local_source_cid++; 8826268fbfeSMilanka Ringwald } 88391c8d67dSMatthias Ringwald } while (l2cap_get_channel_for_local_cid(l2cap_local_source_cid) != NULL); 88491c8d67dSMatthias Ringwald return l2cap_local_source_cid; 8856ddef68dSMilanka Ringwald } 8866a5ffed8SMatthias Ringwald #endif 8876ddef68dSMilanka Ringwald 8886ddef68dSMilanka Ringwald static uint8_t l2cap_next_sig_id(void){ 88991c8d67dSMatthias Ringwald if (l2cap_sig_seq_nr == 0xffu) { 89091c8d67dSMatthias Ringwald l2cap_sig_seq_nr = 1; 8916ddef68dSMilanka Ringwald } else { 89291c8d67dSMatthias Ringwald l2cap_sig_seq_nr++; 8936ddef68dSMilanka Ringwald } 89491c8d67dSMatthias Ringwald return l2cap_sig_seq_nr; 8956ddef68dSMilanka Ringwald } 8966ddef68dSMilanka Ringwald 89771de195eSMatthias Ringwald void l2cap_init(void){ 898b5bbcbf4SMatthias Ringwald #ifdef L2CAP_USES_CHANNELS 89991c8d67dSMatthias Ringwald l2cap_local_source_cid = 0x40; 900b5bbcbf4SMatthias Ringwald #endif 90191c8d67dSMatthias Ringwald l2cap_sig_seq_nr = 0xff; 902fad84cafSMatthias Ringwald 903fad84cafSMatthias Ringwald #ifdef ENABLE_CLASSIC 904fad84cafSMatthias Ringwald // Setup Connectionless Channel 905fad84cafSMatthias Ringwald l2cap_fixed_channel_connectionless.local_cid = L2CAP_CID_CONNECTIONLESS_CHANNEL; 9067740e150SMatthias Ringwald l2cap_fixed_channel_connectionless.channel_type = L2CAP_CHANNEL_TYPE_CONNECTIONLESS; 907fad84cafSMatthias Ringwald btstack_linked_list_add(&l2cap_channels, (btstack_linked_item_t *) &l2cap_fixed_channel_connectionless); 90809e9d05bSMatthias Ringwald #endif 909a3dc965aSMatthias Ringwald 910d6ed9f9cSMatthias Ringwald #ifdef ENABLE_BLE 911fad84cafSMatthias Ringwald // Setup fixed ATT Channel 912fad84cafSMatthias Ringwald l2cap_fixed_channel_att.local_cid = L2CAP_CID_ATTRIBUTE_PROTOCOL; 913904f1e16SMatthias Ringwald l2cap_fixed_channel_att.channel_type = L2CAP_CHANNEL_TYPE_FIXED; 914fad84cafSMatthias Ringwald btstack_linked_list_add(&l2cap_channels, (btstack_linked_item_t *) &l2cap_fixed_channel_att); 915fad84cafSMatthias Ringwald 916fad84cafSMatthias Ringwald // Setup fixed SM Channel 917fad84cafSMatthias Ringwald l2cap_fixed_channel_sm.local_cid = L2CAP_CID_SECURITY_MANAGER_PROTOCOL; 918904f1e16SMatthias Ringwald l2cap_fixed_channel_sm.channel_type = L2CAP_CHANNEL_TYPE_FIXED; 919fad84cafSMatthias Ringwald btstack_linked_list_add(&l2cap_channels, (btstack_linked_item_t *) &l2cap_fixed_channel_sm); 920d6ed9f9cSMatthias Ringwald #endif 921f5454fc6Smatthias.ringwald 922*a254c508SMatthias Ringwald #ifdef ENABLE_L2CAP_ENHANCED_DATA_CHANNELS 923*a254c508SMatthias Ringwald l2cap_enhanced_mps_min = 0x0001; 924*a254c508SMatthias Ringwald l2cap_enhanced_mps_max = 0xffff; 925*a254c508SMatthias Ringwald #endif 926*a254c508SMatthias Ringwald 927fcadd0caSmatthias.ringwald // 9282718e2e7Smatthias.ringwald // register callback with HCI 929fcadd0caSmatthias.ringwald // 93091c8d67dSMatthias Ringwald l2cap_hci_event_callback_registration.callback = &l2cap_hci_event_handler; 93191c8d67dSMatthias Ringwald hci_add_event_handler(&l2cap_hci_event_callback_registration); 932fb37a842SMatthias Ringwald 933d9a7306aSMatthias Ringwald hci_register_acl_packet_handler(&l2cap_acl_handler); 934fb37a842SMatthias Ringwald 93547a15588SMatthias Ringwald #ifndef ENABLE_EXPLICIT_CONNECTABLE_MODE_CONTROL 936be005ed6SMatthias Ringwald #ifdef ENABLE_CLASSIC 93715a95bd5SMatthias Ringwald gap_connectable_control(0); // no services yet 938be005ed6SMatthias Ringwald #endif 93947a15588SMatthias Ringwald #endif 940fcadd0caSmatthias.ringwald } 941fcadd0caSmatthias.ringwald 942a0549bf1SMatthias Ringwald /** 943a0549bf1SMatthias Ringwald * @brief De-Init L2CAP 944a0549bf1SMatthias Ringwald */ 945a0549bf1SMatthias Ringwald void l2cap_deinit(void){ 94691c8d67dSMatthias Ringwald l2cap_channels = NULL; 94791c8d67dSMatthias Ringwald l2cap_signaling_responses_pending = 0; 948b5bbcbf4SMatthias Ringwald #ifdef ENABLE_CLASSIC 94991c8d67dSMatthias Ringwald l2cap_require_security_level2_for_outgoing_sdp = 0; 95091c8d67dSMatthias Ringwald (void)memset(&l2cap_fixed_channel_connectionless, 0, sizeof(l2cap_fixed_channel_connectionless)); 95191c8d67dSMatthias Ringwald l2cap_services = NULL; 95291c8d67dSMatthias Ringwald (void)memset(l2cap_outgoing_classic_addr, 0, 6); 953b5bbcbf4SMatthias Ringwald #endif 95491c8d67dSMatthias Ringwald #ifdef ENABLE_BLE 95591c8d67dSMatthias Ringwald l2cap_le_custom_max_mtu = 0; 95691c8d67dSMatthias Ringwald (void)memset(&l2cap_fixed_channel_att, 0, sizeof(l2cap_fixed_channel_att)); 95791c8d67dSMatthias Ringwald (void)memset(&l2cap_fixed_channel_sm, 0, sizeof(l2cap_fixed_channel_sm)); 95891c8d67dSMatthias Ringwald #endif 95991c8d67dSMatthias Ringwald #ifdef ENABLE_LE_DATA_CHANNELS 96091c8d67dSMatthias Ringwald l2cap_le_services = NULL; 96191c8d67dSMatthias Ringwald #endif 962*a254c508SMatthias Ringwald #ifdef ENABLE_L2CAP_ENHANCED_DATA_CHANNELS 963*a254c508SMatthias Ringwald l2cap_enhanced_services = NULL; 964*a254c508SMatthias Ringwald #endif 9650b81d2a5SMatthias Ringwald l2cap_event_handlers = NULL; 966a0549bf1SMatthias Ringwald } 967a0549bf1SMatthias Ringwald 9680b81d2a5SMatthias Ringwald void l2cap_add_event_handler(btstack_packet_callback_registration_t * callback_handler){ 9690b81d2a5SMatthias Ringwald btstack_linked_list_add_tail(&l2cap_event_handlers, (btstack_linked_item_t*) callback_handler); 9700b81d2a5SMatthias Ringwald } 9710b81d2a5SMatthias Ringwald 9720b81d2a5SMatthias Ringwald void l2cap_remove_event_handler(btstack_packet_callback_registration_t * callback_handler){ 9730b81d2a5SMatthias Ringwald btstack_linked_list_remove(&l2cap_event_handlers, (btstack_linked_item_t*) callback_handler); 9740b81d2a5SMatthias Ringwald } 9750b81d2a5SMatthias Ringwald 9760b81d2a5SMatthias Ringwald static void l2cap_emit_event(uint8_t *event, uint16_t size) { 9770b81d2a5SMatthias Ringwald hci_dump_packet( HCI_EVENT_PACKET, 0, event, size); 9780b81d2a5SMatthias Ringwald // dispatch to all event handlers 9790b81d2a5SMatthias Ringwald btstack_linked_list_iterator_t it; 9800b81d2a5SMatthias Ringwald btstack_linked_list_iterator_init(&it, &l2cap_event_handlers); 9810b81d2a5SMatthias Ringwald while (btstack_linked_list_iterator_has_next(&it)){ 9820b81d2a5SMatthias Ringwald btstack_packet_callback_registration_t * entry = (btstack_packet_callback_registration_t*) btstack_linked_list_iterator_next(&it); 9830b81d2a5SMatthias Ringwald entry->callback(HCI_EVENT_PACKET, 0, event, size); 9840b81d2a5SMatthias Ringwald } 9851e6aba47Smatthias.ringwald } 9861e6aba47Smatthias.ringwald 98709e9d05bSMatthias Ringwald void l2cap_request_can_send_fix_channel_now_event(hci_con_handle_t con_handle, uint16_t channel_id){ 988fad84cafSMatthias Ringwald UNUSED(con_handle); // ok: there is no con handle 9899ec2630cSMatthias Ringwald 990f68b21d7SMatthias Ringwald l2cap_fixed_channel_t * channel = l2cap_fixed_channel_for_channel_id(channel_id); 991fad84cafSMatthias Ringwald if (!channel) return; 992fad84cafSMatthias Ringwald channel->waiting_for_can_send_now = 1; 99309e9d05bSMatthias Ringwald l2cap_notify_channel_can_send(); 99409e9d05bSMatthias Ringwald } 99509e9d05bSMatthias Ringwald 9966106bf3fSMatthias Ringwald bool l2cap_can_send_fixed_channel_packet_now(hci_con_handle_t con_handle, uint16_t channel_id){ 9975774a392SMatthias Ringwald UNUSED(channel_id); // ok: only depends on Controller LE buffers 9989ec2630cSMatthias Ringwald 99909e9d05bSMatthias Ringwald return hci_can_send_acl_packet_now(con_handle); 100009e9d05bSMatthias Ringwald } 100109e9d05bSMatthias Ringwald 100209e9d05bSMatthias Ringwald uint8_t *l2cap_get_outgoing_buffer(void){ 100309e9d05bSMatthias Ringwald return hci_get_outgoing_packet_buffer() + COMPLETE_L2CAP_HEADER; // 8 bytes 100409e9d05bSMatthias Ringwald } 100509e9d05bSMatthias Ringwald 10064e6fa3a2SMatthias Ringwald // only for L2CAP Basic Channels 1007a2fc0023SMatthias Ringwald bool l2cap_reserve_packet_buffer(void){ 100809e9d05bSMatthias Ringwald return hci_reserve_packet_buffer(); 100909e9d05bSMatthias Ringwald } 101009e9d05bSMatthias Ringwald 10114e6fa3a2SMatthias Ringwald // only for L2CAP Basic Channels 101209e9d05bSMatthias Ringwald void l2cap_release_packet_buffer(void){ 101309e9d05bSMatthias Ringwald hci_release_packet_buffer(); 101409e9d05bSMatthias Ringwald } 101509e9d05bSMatthias Ringwald 1016f511cefaSMatthias Ringwald static void l2cap_setup_header(uint8_t * acl_buffer, hci_con_handle_t con_handle, uint8_t packet_boundary, uint16_t remote_cid, uint16_t len){ 101709e9d05bSMatthias Ringwald // 0 - Connection handle : PB=pb : BC=00 10184ea43905SMatthias Ringwald little_endian_store_16(acl_buffer, 0u, con_handle | (packet_boundary << 12u) | (0u << 14u)); 101909e9d05bSMatthias Ringwald // 2 - ACL length 10204ea43905SMatthias Ringwald little_endian_store_16(acl_buffer, 2u, len + 4u); 102109e9d05bSMatthias Ringwald // 4 - L2CAP packet length 10224ea43905SMatthias Ringwald little_endian_store_16(acl_buffer, 4u, len + 0u); 102309e9d05bSMatthias Ringwald // 6 - L2CAP channel DEST 102409e9d05bSMatthias Ringwald little_endian_store_16(acl_buffer, 6, remote_cid); 102509e9d05bSMatthias Ringwald } 102609e9d05bSMatthias Ringwald 1027f511cefaSMatthias Ringwald // assumption - only on LE connections 1028dccc4e95SMatthias Ringwald uint8_t l2cap_send_prepared_connectionless(hci_con_handle_t con_handle, uint16_t cid, uint16_t len){ 102909e9d05bSMatthias Ringwald 103009e9d05bSMatthias Ringwald if (!hci_is_packet_buffer_reserved()){ 103109e9d05bSMatthias Ringwald log_error("l2cap_send_prepared_connectionless called without reserving packet first"); 103209e9d05bSMatthias Ringwald return BTSTACK_ACL_BUFFERS_FULL; 103309e9d05bSMatthias Ringwald } 103409e9d05bSMatthias Ringwald 103509e9d05bSMatthias Ringwald if (!hci_can_send_prepared_acl_packet_now(con_handle)){ 103609e9d05bSMatthias Ringwald log_info("l2cap_send_prepared_connectionless handle 0x%02x, cid 0x%02x, cannot send", con_handle, cid); 103709e9d05bSMatthias Ringwald return BTSTACK_ACL_BUFFERS_FULL; 103809e9d05bSMatthias Ringwald } 103909e9d05bSMatthias Ringwald 104009e9d05bSMatthias Ringwald log_debug("l2cap_send_prepared_connectionless handle %u, cid 0x%02x", con_handle, cid); 104109e9d05bSMatthias Ringwald 104209e9d05bSMatthias Ringwald uint8_t *acl_buffer = hci_get_outgoing_packet_buffer(); 1043f511cefaSMatthias Ringwald l2cap_setup_header(acl_buffer, con_handle, 0, cid, len); 104409e9d05bSMatthias Ringwald // send 10454ea43905SMatthias Ringwald return hci_send_acl_packet_buffer(len+8u); 104609e9d05bSMatthias Ringwald } 104709e9d05bSMatthias Ringwald 1048f511cefaSMatthias Ringwald // assumption - only on LE connections 1049dccc4e95SMatthias Ringwald uint8_t l2cap_send_connectionless(hci_con_handle_t con_handle, uint16_t cid, uint8_t *data, uint16_t len){ 105009e9d05bSMatthias Ringwald 105109e9d05bSMatthias Ringwald if (!hci_can_send_acl_packet_now(con_handle)){ 105209e9d05bSMatthias Ringwald log_info("l2cap_send cid 0x%02x, cannot send", cid); 105309e9d05bSMatthias Ringwald return BTSTACK_ACL_BUFFERS_FULL; 105409e9d05bSMatthias Ringwald } 105509e9d05bSMatthias Ringwald 105609e9d05bSMatthias Ringwald hci_reserve_packet_buffer(); 105709e9d05bSMatthias Ringwald uint8_t *acl_buffer = hci_get_outgoing_packet_buffer(); 105809e9d05bSMatthias Ringwald 10596535961aSMatthias Ringwald (void)memcpy(&acl_buffer[8], data, len); 106009e9d05bSMatthias Ringwald 106109e9d05bSMatthias Ringwald return l2cap_send_prepared_connectionless(con_handle, cid, len); 106209e9d05bSMatthias Ringwald } 106309e9d05bSMatthias Ringwald 106409e9d05bSMatthias Ringwald static void l2cap_emit_can_send_now(btstack_packet_handler_t packet_handler, uint16_t channel) { 1065d9d23054SMatthias Ringwald log_debug("L2CAP_EVENT_CHANNEL_CAN_SEND_NOW local_cid 0x%x", channel); 106609e9d05bSMatthias Ringwald uint8_t event[4]; 106709e9d05bSMatthias Ringwald event[0] = L2CAP_EVENT_CAN_SEND_NOW; 10684ea43905SMatthias Ringwald event[1] = sizeof(event) - 2u; 106909e9d05bSMatthias Ringwald little_endian_store_16(event, 2, channel); 107009e9d05bSMatthias Ringwald hci_dump_packet( HCI_EVENT_PACKET, 0, event, sizeof(event)); 107109e9d05bSMatthias Ringwald packet_handler(HCI_EVENT_PACKET, channel, event, sizeof(event)); 107209e9d05bSMatthias Ringwald } 107309e9d05bSMatthias Ringwald 107409e9d05bSMatthias Ringwald #ifdef L2CAP_USES_CHANNELS 107517a9b554SMatthias Ringwald static void l2cap_dispatch_to_channel(l2cap_channel_t *channel, uint8_t type, uint8_t * data, uint16_t size){ 107658de5610Smatthias.ringwald (* (channel->packet_handler))(type, channel->local_cid, data, size); 107758de5610Smatthias.ringwald } 107858de5610Smatthias.ringwald 107944276248SMatthias Ringwald static void l2cap_emit_simple_event_with_cid(l2cap_channel_t * channel, uint8_t event_code){ 108044276248SMatthias Ringwald uint8_t event[4]; 108144276248SMatthias Ringwald event[0] = event_code; 10824ea43905SMatthias Ringwald event[1] = sizeof(event) - 2u; 108344276248SMatthias Ringwald little_endian_store_16(event, 2, channel->local_cid); 108444276248SMatthias Ringwald hci_dump_packet( HCI_EVENT_PACKET, 0, event, sizeof(event)); 108544276248SMatthias Ringwald l2cap_dispatch_to_channel(channel, HCI_EVENT_PACKET, event, sizeof(event)); 108644276248SMatthias Ringwald } 108709e9d05bSMatthias Ringwald #endif 108844276248SMatthias Ringwald 108909e9d05bSMatthias Ringwald #ifdef ENABLE_CLASSIC 109058de5610Smatthias.ringwald void l2cap_emit_channel_opened(l2cap_channel_t *channel, uint8_t status) { 1091c9dc710bS[email protected] log_info("L2CAP_EVENT_CHANNEL_OPENED status 0x%x addr %s handle 0x%x psm 0x%x local_cid 0x%x remote_cid 0x%x local_mtu %u, remote_mtu %u, flush_timeout %u", 1092fc64f94aSMatthias Ringwald status, bd_addr_to_str(channel->address), channel->con_handle, channel->psm, 1093c9dc710bS[email protected] channel->local_cid, channel->remote_cid, channel->local_mtu, channel->remote_mtu, channel->flush_timeout); 10947f1690cfSMatthias Ringwald uint8_t event[26]; 109558de5610Smatthias.ringwald event[0] = L2CAP_EVENT_CHANNEL_OPENED; 109658de5610Smatthias.ringwald event[1] = sizeof(event) - 2; 109758de5610Smatthias.ringwald event[2] = status; 1098724d70a2SMatthias Ringwald reverse_bd_addr(channel->address, &event[3]); 1099fc64f94aSMatthias Ringwald little_endian_store_16(event, 9, channel->con_handle); 1100f8fbdce0SMatthias Ringwald little_endian_store_16(event, 11, channel->psm); 1101f8fbdce0SMatthias Ringwald little_endian_store_16(event, 13, channel->local_cid); 1102f8fbdce0SMatthias Ringwald little_endian_store_16(event, 15, channel->remote_cid); 1103f8fbdce0SMatthias Ringwald little_endian_store_16(event, 17, channel->local_mtu); 1104f8fbdce0SMatthias Ringwald little_endian_store_16(event, 19, channel->remote_mtu); 1105f8fbdce0SMatthias Ringwald little_endian_store_16(event, 21, channel->flush_timeout); 1106c1ab6cc1SMatthias Ringwald event[23] = (channel->state_var & L2CAP_CHANNEL_STATE_VAR_INCOMING) ? 1 : 0; 11077f1690cfSMatthias Ringwald #ifdef ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE 11087f1690cfSMatthias Ringwald log_info("ERTM mode %u, fcs enabled %u", channel->mode, channel->fcs_option); 11097f1690cfSMatthias Ringwald event[24] = channel->mode; 11107f1690cfSMatthias Ringwald event[25] = channel->fcs_option; 11117f1690cfSMatthias Ringwald 11127f1690cfSMatthias Ringwald #else 11137f1690cfSMatthias Ringwald event[24] = L2CAP_CHANNEL_MODE_BASIC; 11147f1690cfSMatthias Ringwald event[25] = 0; 11157f1690cfSMatthias Ringwald #endif 111658de5610Smatthias.ringwald hci_dump_packet( HCI_EVENT_PACKET, 0, event, sizeof(event)); 111717a9b554SMatthias Ringwald l2cap_dispatch_to_channel(channel, HCI_EVENT_PACKET, event, sizeof(event)); 111858de5610Smatthias.ringwald } 111958de5610Smatthias.ringwald 112044276248SMatthias Ringwald static void l2cap_emit_channel_closed(l2cap_channel_t *channel) { 1121e0abb8e7S[email protected] log_info("L2CAP_EVENT_CHANNEL_CLOSED local_cid 0x%x", channel->local_cid); 112244276248SMatthias Ringwald l2cap_emit_simple_event_with_cid(channel, L2CAP_EVENT_CHANNEL_CLOSED); 112358de5610Smatthias.ringwald } 112458de5610Smatthias.ringwald 112544276248SMatthias Ringwald static void l2cap_emit_incoming_connection(l2cap_channel_t *channel) { 1126e0abb8e7S[email protected] log_info("L2CAP_EVENT_INCOMING_CONNECTION addr %s handle 0x%x psm 0x%x local_cid 0x%x remote_cid 0x%x", 1127fc64f94aSMatthias Ringwald bd_addr_to_str(channel->address), channel->con_handle, channel->psm, channel->local_cid, channel->remote_cid); 112858de5610Smatthias.ringwald uint8_t event[16]; 112958de5610Smatthias.ringwald event[0] = L2CAP_EVENT_INCOMING_CONNECTION; 113058de5610Smatthias.ringwald event[1] = sizeof(event) - 2; 1131724d70a2SMatthias Ringwald reverse_bd_addr(channel->address, &event[2]); 1132fc64f94aSMatthias Ringwald little_endian_store_16(event, 8, channel->con_handle); 1133f8fbdce0SMatthias Ringwald little_endian_store_16(event, 10, channel->psm); 1134f8fbdce0SMatthias Ringwald little_endian_store_16(event, 12, channel->local_cid); 1135f8fbdce0SMatthias Ringwald little_endian_store_16(event, 14, channel->remote_cid); 113658de5610Smatthias.ringwald hci_dump_packet( HCI_EVENT_PACKET, 0, event, sizeof(event)); 113717a9b554SMatthias Ringwald l2cap_dispatch_to_channel(channel, HCI_EVENT_PACKET, event, sizeof(event)); 11380af41d30Smatthias.ringwald } 1139f62db1e3Smatthias.ringwald 114066a72640SMatthias Ringwald static void l2cap_handle_channel_open_failed(l2cap_channel_t * channel, uint8_t status){ 114166a72640SMatthias Ringwald #ifdef ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE 114266a72640SMatthias Ringwald // emit ertm buffer released, as it's not needed. if in basic mode, it was either not allocated or already released 114366a72640SMatthias Ringwald if (channel->mode == L2CAP_CHANNEL_MODE_ENHANCED_RETRANSMISSION){ 114466a72640SMatthias Ringwald l2cap_emit_simple_event_with_cid(channel, L2CAP_EVENT_ERTM_BUFFER_RELEASED); 114566a72640SMatthias Ringwald } 114666a72640SMatthias Ringwald #endif 1147624873c3SMatthias Ringwald l2cap_emit_channel_opened(channel, status); 1148624873c3SMatthias Ringwald } 1149624873c3SMatthias Ringwald 115066a72640SMatthias Ringwald static void l2cap_handle_channel_closed(l2cap_channel_t * channel){ 115166a72640SMatthias Ringwald #ifdef ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE 115266a72640SMatthias Ringwald // emit ertm buffer released, as it's not needed anymore. if in basic mode, it was either not allocated or already released 115366a72640SMatthias Ringwald if (channel->mode == L2CAP_CHANNEL_MODE_ENHANCED_RETRANSMISSION){ 115466a72640SMatthias Ringwald l2cap_emit_simple_event_with_cid(channel, L2CAP_EVENT_ERTM_BUFFER_RELEASED); 115566a72640SMatthias Ringwald } 115666a72640SMatthias Ringwald #endif 115766a72640SMatthias Ringwald l2cap_emit_channel_closed(channel); 115866a72640SMatthias Ringwald } 1159dd3bf36fSMatthias Ringwald #endif 1160dd3bf36fSMatthias Ringwald 1161dd3bf36fSMatthias Ringwald static l2cap_fixed_channel_t * l2cap_channel_item_by_cid(uint16_t cid){ 1162dd3bf36fSMatthias Ringwald btstack_linked_list_iterator_t it; 1163dd3bf36fSMatthias Ringwald btstack_linked_list_iterator_init(&it, &l2cap_channels); 1164dd3bf36fSMatthias Ringwald while (btstack_linked_list_iterator_has_next(&it)){ 1165dd3bf36fSMatthias Ringwald l2cap_fixed_channel_t * channel = (l2cap_fixed_channel_t*) btstack_linked_list_iterator_next(&it); 1166dd3bf36fSMatthias Ringwald if (channel->local_cid == cid) { 1167dd3bf36fSMatthias Ringwald return channel; 1168dd3bf36fSMatthias Ringwald } 1169dd3bf36fSMatthias Ringwald } 1170dd3bf36fSMatthias Ringwald return NULL; 1171dd3bf36fSMatthias Ringwald } 117266a72640SMatthias Ringwald 1173fad84cafSMatthias Ringwald // used for fixed channels in LE (ATT/SM) and Classic (Connectionless Channel). CID < 0x04 1174fad84cafSMatthias Ringwald static l2cap_fixed_channel_t * l2cap_fixed_channel_for_channel_id(uint16_t local_cid){ 11754ea43905SMatthias Ringwald if (local_cid >= 0x40u) return NULL; 1176fad84cafSMatthias Ringwald return (l2cap_fixed_channel_t*) l2cap_channel_item_by_cid(local_cid); 1177fad84cafSMatthias Ringwald } 117824eb964eSMatthias Ringwald 117924eb964eSMatthias Ringwald #ifdef L2CAP_USES_CHANNELS 1180*a254c508SMatthias Ringwald 1181*a254c508SMatthias Ringwald static int l2cap_is_dynamic_channel_type(l2cap_channel_type_t channel_type) { 1182*a254c508SMatthias Ringwald switch (channel_type) { 1183*a254c508SMatthias Ringwald case L2CAP_CHANNEL_TYPE_CLASSIC: 1184*a254c508SMatthias Ringwald case L2CAP_CHANNEL_TYPE_LE_DATA_CHANNEL: 1185*a254c508SMatthias Ringwald case L2CAP_CHANNEL_TYPE_ENHANCED_DATA_CHANNEL: 1186*a254c508SMatthias Ringwald return 1; 1187*a254c508SMatthias Ringwald default: 1188*a254c508SMatthias Ringwald return 0; 1189*a254c508SMatthias Ringwald } 1190*a254c508SMatthias Ringwald } 1191*a254c508SMatthias Ringwald 119224eb964eSMatthias Ringwald static l2cap_channel_t * l2cap_get_channel_for_local_cid(uint16_t local_cid){ 11934ea43905SMatthias Ringwald if (local_cid < 0x40u) return NULL; 119424eb964eSMatthias Ringwald return (l2cap_channel_t*) l2cap_channel_item_by_cid(local_cid); 119524eb964eSMatthias Ringwald } 11960b9d7e78SMatthias Ringwald 11977d5c2f20SMatthias Ringwald static l2cap_channel_t * l2cap_get_channel_for_local_cid_and_handle(uint16_t local_cid, hci_con_handle_t con_handle){ 11987d5c2f20SMatthias Ringwald if (local_cid < 0x40u) return NULL; 11997d5c2f20SMatthias Ringwald l2cap_channel_t * l2cap_channel = (l2cap_channel_t*) l2cap_channel_item_by_cid(local_cid); 12007d5c2f20SMatthias Ringwald if (l2cap_channel == NULL) return NULL; 12017d5c2f20SMatthias Ringwald if (l2cap_channel->con_handle != con_handle) return NULL; 12027d5c2f20SMatthias Ringwald return l2cap_channel; 12037d5c2f20SMatthias Ringwald } 120469246fa3SMatthias Ringwald #endif 12057d5c2f20SMatthias Ringwald 1206*a254c508SMatthias Ringwald #ifdef ENABLE_L2CAP_CREDIT_BASED_CHANNELS 1207*a254c508SMatthias Ringwald static l2cap_channel_t * l2cap_get_channel_for_remote_handle_and_cid(hci_con_handle_t con_handle, uint16_t remote_cid){ 1208*a254c508SMatthias Ringwald btstack_linked_list_iterator_t it; 1209*a254c508SMatthias Ringwald btstack_linked_list_iterator_init(&it, &l2cap_channels); 1210*a254c508SMatthias Ringwald while (btstack_linked_list_iterator_has_next(&it)){ 1211*a254c508SMatthias Ringwald l2cap_fixed_channel_t * channel = (l2cap_fixed_channel_t*) btstack_linked_list_iterator_next(&it); 1212*a254c508SMatthias Ringwald if (!l2cap_is_dynamic_channel_type(channel->channel_type)) continue; 1213*a254c508SMatthias Ringwald l2cap_channel_t * dynamic_channel = (l2cap_channel_t *) channel; 1214*a254c508SMatthias Ringwald if (dynamic_channel->con_handle != con_handle) continue; 1215*a254c508SMatthias Ringwald if (dynamic_channel->remote_cid != remote_cid) continue; 1216*a254c508SMatthias Ringwald return dynamic_channel; 1217*a254c508SMatthias Ringwald } 1218*a254c508SMatthias Ringwald return NULL; 1219*a254c508SMatthias Ringwald } 1220*a254c508SMatthias Ringwald #endif 1221*a254c508SMatthias Ringwald 122269246fa3SMatthias Ringwald #ifdef ENABLE_CLASSIC 122330725612SMatthias Ringwald void l2cap_request_can_send_now_event(uint16_t local_cid){ 122430725612SMatthias Ringwald l2cap_channel_t *channel = l2cap_get_channel_for_local_cid(local_cid); 122530725612SMatthias Ringwald if (!channel) return; 122630725612SMatthias Ringwald channel->waiting_for_can_send_now = 1; 122796646001SMatthias Ringwald #ifdef ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE 122896646001SMatthias Ringwald if (channel->mode == L2CAP_CHANNEL_MODE_ENHANCED_RETRANSMISSION){ 122996646001SMatthias Ringwald l2cap_ertm_notify_channel_can_send(channel); 123096646001SMatthias Ringwald return; 123196646001SMatthias Ringwald } 123296646001SMatthias Ringwald #endif 123330725612SMatthias Ringwald l2cap_notify_channel_can_send(); 123430725612SMatthias Ringwald } 123530725612SMatthias Ringwald 12366106bf3fSMatthias Ringwald bool l2cap_can_send_packet_now(uint16_t local_cid){ 123796646001SMatthias Ringwald l2cap_channel_t *channel = l2cap_get_channel_for_local_cid(local_cid); 12386106bf3fSMatthias Ringwald if (!channel) return false; 123996646001SMatthias Ringwald #ifdef ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE 124096646001SMatthias Ringwald if (channel->mode == L2CAP_CHANNEL_MODE_ENHANCED_RETRANSMISSION){ 124196646001SMatthias Ringwald return l2cap_ertm_can_store_packet_now(channel); 124296646001SMatthias Ringwald } 124396646001SMatthias Ringwald #endif 12440b9d7e78SMatthias Ringwald return hci_can_send_acl_packet_now(channel->con_handle); 12457856fb31S[email protected] } 12467856fb31S[email protected] 12476106bf3fSMatthias Ringwald bool l2cap_can_send_prepared_packet_now(uint16_t local_cid){ 124883e7cdd9SMatthias Ringwald l2cap_channel_t *channel = l2cap_get_channel_for_local_cid(local_cid); 12496106bf3fSMatthias Ringwald if (!channel) return false; 12500b20b13bSMatthias Ringwald #ifdef ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE 12510b20b13bSMatthias Ringwald if (channel->mode == L2CAP_CHANNEL_MODE_ENHANCED_RETRANSMISSION){ 12526106bf3fSMatthias Ringwald return false; 12530b20b13bSMatthias Ringwald } 12540b20b13bSMatthias Ringwald #endif 12550b9d7e78SMatthias Ringwald return hci_can_send_prepared_acl_packet_now(channel->con_handle); 125683e7cdd9SMatthias Ringwald } 12570b20b13bSMatthias Ringwald 125896cbd662Smatthias.ringwald uint16_t l2cap_get_remote_mtu_for_local_cid(uint16_t local_cid){ 125996cbd662Smatthias.ringwald l2cap_channel_t * channel = l2cap_get_channel_for_local_cid(local_cid); 126096cbd662Smatthias.ringwald if (channel) { 126196cbd662Smatthias.ringwald return channel->remote_mtu; 126296cbd662Smatthias.ringwald } 126396cbd662Smatthias.ringwald return 0; 126496cbd662Smatthias.ringwald } 126524eb964eSMatthias Ringwald #endif 126696cbd662Smatthias.ringwald 126724eb964eSMatthias Ringwald #ifdef ENABLE_CLASSIC 1268fad84cafSMatthias Ringwald // RTX Timer only exist for dynamic channels 1269ec820d77SMatthias Ringwald static l2cap_channel_t * l2cap_channel_for_rtx_timer(btstack_timer_source_t * ts){ 1270665d90f2SMatthias Ringwald btstack_linked_list_iterator_t it; 1271665d90f2SMatthias Ringwald btstack_linked_list_iterator_init(&it, &l2cap_channels); 1272665d90f2SMatthias Ringwald while (btstack_linked_list_iterator_has_next(&it)){ 1273665d90f2SMatthias Ringwald l2cap_channel_t * channel = (l2cap_channel_t *) btstack_linked_list_iterator_next(&it); 1274fad84cafSMatthias Ringwald if (!l2cap_is_dynamic_channel_type(channel->channel_type)) continue; 12755932bd7cS[email protected] if (&channel->rtx == ts) { 12765932bd7cS[email protected] return channel; 12775932bd7cS[email protected] } 12785932bd7cS[email protected] } 12795932bd7cS[email protected] return NULL; 12805932bd7cS[email protected] } 12815932bd7cS[email protected] 1282ec820d77SMatthias Ringwald static void l2cap_rtx_timeout(btstack_timer_source_t * ts){ 12835932bd7cS[email protected] l2cap_channel_t * channel = l2cap_channel_for_rtx_timer(ts); 128495d2c8f4SMatthias Ringwald if (!channel) return; 12855932bd7cS[email protected] 12865932bd7cS[email protected] log_info("l2cap_rtx_timeout for local cid 0x%02x", channel->local_cid); 12875932bd7cS[email protected] 12885932bd7cS[email protected] // "When terminating the channel, it is not necessary to send a L2CAP_DisconnectReq 12895932bd7cS[email protected] // and enter WAIT_DISCONNECT state. Channels can be transitioned directly to the CLOSED state." 12905932bd7cS[email protected] // notify client 129166a72640SMatthias Ringwald l2cap_handle_channel_open_failed(channel, L2CAP_CONNECTION_RESPONSE_RESULT_RTX_TIMEOUT); 12925932bd7cS[email protected] 12935932bd7cS[email protected] // discard channel 1294665d90f2SMatthias Ringwald btstack_linked_list_remove(&l2cap_channels, (btstack_linked_item_t *) channel); 1295c45d6b2cSMatthias Ringwald l2cap_free_channel_entry(channel); 12965932bd7cS[email protected] } 12975932bd7cS[email protected] 129813aa3e4bSMatthias Ringwald #endif 129913aa3e4bSMatthias Ringwald 130013aa3e4bSMatthias Ringwald #ifdef L2CAP_USES_CHANNELS 13015932bd7cS[email protected] static void l2cap_stop_rtx(l2cap_channel_t * channel){ 13025932bd7cS[email protected] log_info("l2cap_stop_rtx for local cid 0x%02x", channel->local_cid); 1303528a4a3bSMatthias Ringwald btstack_run_loop_remove_timer(&channel->rtx); 13045932bd7cS[email protected] } 130513aa3e4bSMatthias Ringwald #endif 130613aa3e4bSMatthias Ringwald 130751b2c70eSMatthias Ringwald static uint8_t l2cap_send_signaling_packet(hci_con_handle_t handle, uint8_t pb_flags, uint16_t cid, L2CAP_SIGNALING_COMMANDS cmd, int identifier, va_list argptr){ 130851b2c70eSMatthias Ringwald if (!hci_can_send_acl_packet_now(handle)){ 130951b2c70eSMatthias Ringwald log_info("l2cap_send_classic_signaling_packet, cannot send"); 131051b2c70eSMatthias Ringwald return BTSTACK_ACL_BUFFERS_FULL; 131151b2c70eSMatthias Ringwald } 131251b2c70eSMatthias Ringwald hci_reserve_packet_buffer(); 131351b2c70eSMatthias Ringwald uint8_t *acl_buffer = hci_get_outgoing_packet_buffer(); 131451b2c70eSMatthias Ringwald uint16_t len = l2cap_create_signaling_packet(acl_buffer, handle, pb_flags, cid, cmd, identifier, argptr); 131551b2c70eSMatthias Ringwald va_end(argptr); 131651b2c70eSMatthias Ringwald return hci_send_acl_packet_buffer(len); 131751b2c70eSMatthias Ringwald } 131851b2c70eSMatthias Ringwald 1319*a254c508SMatthias Ringwald #ifdef ENABLE_L2CAP_CREDIT_BASED_CHANNELS 1320*a254c508SMatthias Ringwald static int l2cap_send_general_signaling_packet(hci_con_handle_t handle, uint16_t signaling_cid, L2CAP_SIGNALING_COMMANDS cmd, int identifier, ...){ 1321*a254c508SMatthias Ringwald va_list argptr; 1322*a254c508SMatthias Ringwald va_start(argptr, identifier); 1323*a254c508SMatthias Ringwald uint8_t pb_flags = 0x00; 1324*a254c508SMatthias Ringwald #ifdef ENABLE_CLASSIC 1325*a254c508SMatthias Ringwald if ((signaling_cid == L2CAP_CID_SIGNALING) && (!hci_non_flushable_packet_boundary_flag_supported())){ 1326*a254c508SMatthias Ringwald pb_flags = 0x02; 1327*a254c508SMatthias Ringwald } 1328*a254c508SMatthias Ringwald #endif 1329*a254c508SMatthias Ringwald uint8_t result = l2cap_send_signaling_packet(handle, pb_flags, signaling_cid, cmd, identifier, argptr); 1330*a254c508SMatthias Ringwald va_end(argptr); 1331*a254c508SMatthias Ringwald return result; 1332*a254c508SMatthias Ringwald } 1333*a254c508SMatthias Ringwald #endif 1334*a254c508SMatthias Ringwald 133513aa3e4bSMatthias Ringwald #ifdef ENABLE_CLASSIC 13365932bd7cS[email protected] 13375932bd7cS[email protected] static void l2cap_start_rtx(l2cap_channel_t * channel){ 13385932bd7cS[email protected] l2cap_stop_rtx(channel); 1339cb0ff06bS[email protected] log_info("l2cap_start_rtx for local cid 0x%02x", channel->local_cid); 1340528a4a3bSMatthias Ringwald btstack_run_loop_set_timer_handler(&channel->rtx, l2cap_rtx_timeout); 1341528a4a3bSMatthias Ringwald btstack_run_loop_set_timer(&channel->rtx, L2CAP_RTX_TIMEOUT_MS); 1342528a4a3bSMatthias Ringwald btstack_run_loop_add_timer(&channel->rtx); 13435932bd7cS[email protected] } 13445932bd7cS[email protected] 13455932bd7cS[email protected] static void l2cap_start_ertx(l2cap_channel_t * channel){ 13465932bd7cS[email protected] log_info("l2cap_start_ertx for local cid 0x%02x", channel->local_cid); 13475932bd7cS[email protected] l2cap_stop_rtx(channel); 1348528a4a3bSMatthias Ringwald btstack_run_loop_set_timer_handler(&channel->rtx, l2cap_rtx_timeout); 1349528a4a3bSMatthias Ringwald btstack_run_loop_set_timer(&channel->rtx, L2CAP_ERTX_TIMEOUT_MS); 1350528a4a3bSMatthias Ringwald btstack_run_loop_add_timer(&channel->rtx); 13515932bd7cS[email protected] } 13525932bd7cS[email protected] 135371de195eSMatthias Ringwald void l2cap_require_security_level_2_for_outgoing_sdp(void){ 135491c8d67dSMatthias Ringwald l2cap_require_security_level2_for_outgoing_sdp = 1; 1355ac301f95S[email protected] } 1356ac301f95S[email protected] 1357df3354fcS[email protected] static int l2cap_security_level_0_allowed_for_PSM(uint16_t psm){ 135891c8d67dSMatthias Ringwald return (psm == BLUETOOTH_PSM_SDP) && (!l2cap_require_security_level2_for_outgoing_sdp); 1359df3354fcS[email protected] } 13605932bd7cS[email protected] 13614dc99b9dSMatthias Ringwald static int l2cap_send_classic_signaling_packet(hci_con_handle_t handle, L2CAP_SIGNALING_COMMANDS cmd, int identifier, ...){ 136258de5610Smatthias.ringwald va_list argptr; 136358de5610Smatthias.ringwald va_start(argptr, identifier); 1364d5a98629SMatthias Ringwald uint8_t pb_flags = hci_non_flushable_packet_boundary_flag_supported() ? 0x00 : 0x02; 136551b2c70eSMatthias Ringwald uint8_t result = l2cap_send_signaling_packet(handle, pb_flags, L2CAP_CID_SIGNALING, cmd, identifier, argptr); 136658de5610Smatthias.ringwald va_end(argptr); 136751b2c70eSMatthias Ringwald return result; 136858de5610Smatthias.ringwald } 136958de5610Smatthias.ringwald 1370f511cefaSMatthias Ringwald // assumption - only on Classic connections 13714e6fa3a2SMatthias Ringwald // cannot be used for L2CAP ERTM 1372dccc4e95SMatthias Ringwald uint8_t l2cap_send_prepared(uint16_t local_cid, uint16_t len){ 1373b1d43497Smatthias.ringwald 1374c8b9416aS[email protected] if (!hci_is_packet_buffer_reserved()){ 1375c8b9416aS[email protected] log_error("l2cap_send_prepared called without reserving packet first"); 1376c8b9416aS[email protected] return BTSTACK_ACL_BUFFERS_FULL; 1377c8b9416aS[email protected] } 1378c8b9416aS[email protected] 137958de5610Smatthias.ringwald l2cap_channel_t * channel = l2cap_get_channel_for_local_cid(local_cid); 1380b1d43497Smatthias.ringwald if (!channel) { 13819da54300S[email protected] log_error("l2cap_send_prepared no channel for cid 0x%02x", local_cid); 1382dccc4e95SMatthias Ringwald return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 13836218e6f1Smatthias.ringwald } 13846218e6f1Smatthias.ringwald 1385fc64f94aSMatthias Ringwald if (!hci_can_send_prepared_acl_packet_now(channel->con_handle)){ 13869da54300S[email protected] log_info("l2cap_send_prepared cid 0x%02x, cannot send", local_cid); 1387a35252c8S[email protected] return BTSTACK_ACL_BUFFERS_FULL; 1388a35252c8S[email protected] } 1389a35252c8S[email protected] 1390fc64f94aSMatthias Ringwald log_debug("l2cap_send_prepared cid 0x%02x, handle %u, 1 credit used", local_cid, channel->con_handle); 1391b1d43497Smatthias.ringwald 139285ddcd84SMatthias Ringwald int fcs_size = 0; 139385ddcd84SMatthias Ringwald 139485ddcd84SMatthias Ringwald #ifdef ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE 13956574158aSMatthias Ringwald if (channel->mode == L2CAP_CHANNEL_MODE_ENHANCED_RETRANSMISSION && channel->fcs_option){ 139685ddcd84SMatthias Ringwald fcs_size = 2; 139785ddcd84SMatthias Ringwald } 139885ddcd84SMatthias Ringwald #endif 139985ddcd84SMatthias Ringwald 1400f511cefaSMatthias Ringwald // set non-flushable packet boundary flag if supported on Controller 1401facf93fdS[email protected] uint8_t *acl_buffer = hci_get_outgoing_packet_buffer(); 1402f511cefaSMatthias Ringwald uint8_t packet_boundary_flag = hci_non_flushable_packet_boundary_flag_supported() ? 0x00 : 0x02; 140385ddcd84SMatthias Ringwald l2cap_setup_header(acl_buffer, channel->con_handle, packet_boundary_flag, channel->remote_cid, len + fcs_size); 140485ddcd84SMatthias Ringwald 140585ddcd84SMatthias Ringwald #ifdef ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE 1406b72f6906SMatthias Ringwald if (fcs_size){ 140785ddcd84SMatthias Ringwald // calculate FCS over l2cap data 140885ddcd84SMatthias Ringwald uint16_t fcs = crc16_calc(acl_buffer + 4, 4 + len); 140985ddcd84SMatthias Ringwald log_info("I-Frame: fcs 0x%04x", fcs); 141085ddcd84SMatthias Ringwald little_endian_store_16(acl_buffer, 8 + len, fcs); 141158de5610Smatthias.ringwald } 141285ddcd84SMatthias Ringwald #endif 141385ddcd84SMatthias Ringwald 141485ddcd84SMatthias Ringwald // send 141585ddcd84SMatthias Ringwald return hci_send_acl_packet_buffer(len+8+fcs_size); 141685ddcd84SMatthias Ringwald } 141785ddcd84SMatthias Ringwald 1418f511cefaSMatthias Ringwald // assumption - only on Classic connections 1419dccc4e95SMatthias Ringwald uint8_t l2cap_send(uint16_t local_cid, uint8_t *data, uint16_t len){ 1420a35252c8S[email protected] l2cap_channel_t * channel = l2cap_get_channel_for_local_cid(local_cid); 1421a35252c8S[email protected] if (!channel) { 1422ce8f182eSMatthias Ringwald log_error("l2cap_send no channel for cid 0x%02x", local_cid); 1423dccc4e95SMatthias Ringwald return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 1424a35252c8S[email protected] } 1425a35252c8S[email protected] 1426f0fb4cd7SMatthias Ringwald #ifdef ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE 1427f0fb4cd7SMatthias Ringwald // send in ERTM 1428f0fb4cd7SMatthias Ringwald if (channel->mode == L2CAP_CHANNEL_MODE_ENHANCED_RETRANSMISSION){ 1429f0fb4cd7SMatthias Ringwald return l2cap_ertm_send(channel, data, len); 1430f0fb4cd7SMatthias Ringwald } 1431f0fb4cd7SMatthias Ringwald #endif 1432f0fb4cd7SMatthias Ringwald 1433f0efaa57S[email protected] if (len > channel->remote_mtu){ 1434ce8f182eSMatthias Ringwald log_error("l2cap_send cid 0x%02x, data length exceeds remote MTU.", local_cid); 1435f0efaa57S[email protected] return L2CAP_DATA_LEN_EXCEEDS_REMOTE_MTU; 1436f0efaa57S[email protected] } 1437f0efaa57S[email protected] 1438fc64f94aSMatthias Ringwald if (!hci_can_send_acl_packet_now(channel->con_handle)){ 1439ce8f182eSMatthias Ringwald log_info("l2cap_send cid 0x%02x, cannot send", local_cid); 1440b1d43497Smatthias.ringwald return BTSTACK_ACL_BUFFERS_FULL; 1441b1d43497Smatthias.ringwald } 1442b1d43497Smatthias.ringwald 14432a373862S[email protected] hci_reserve_packet_buffer(); 1444facf93fdS[email protected] uint8_t *acl_buffer = hci_get_outgoing_packet_buffer(); 14456535961aSMatthias Ringwald (void)memcpy(&acl_buffer[8], data, len); 1446f0fb4cd7SMatthias Ringwald return l2cap_send_prepared(local_cid, len); 1447b1d43497Smatthias.ringwald } 1448b1d43497Smatthias.ringwald 1449fc64f94aSMatthias Ringwald int l2cap_send_echo_request(hci_con_handle_t con_handle, uint8_t *data, uint16_t len){ 14504dc99b9dSMatthias Ringwald return l2cap_send_classic_signaling_packet(con_handle, ECHO_REQUEST, l2cap_next_sig_id(), len, data); 14510e37e417S[email protected] } 14520e37e417S[email protected] 1453e777ec95SMatthias Ringwald static inline void channelStateVarSetFlag(l2cap_channel_t *channel, uint16_t flag){ 1454e777ec95SMatthias Ringwald channel->state_var = channel->state_var | flag; 145528ca2b46S[email protected] } 145628ca2b46S[email protected] 1457e777ec95SMatthias Ringwald static inline void channelStateVarClearFlag(l2cap_channel_t *channel, uint16_t flag){ 1458e777ec95SMatthias Ringwald channel->state_var = channel->state_var & ~flag; 145928ca2b46S[email protected] } 146009e9d05bSMatthias Ringwald #endif 146128ca2b46S[email protected] 146228ca2b46S[email protected] 146309e9d05bSMatthias Ringwald #ifdef ENABLE_BLE 146463854e74SMatthias Ringwald static int l2cap_send_le_signaling_packet(hci_con_handle_t handle, L2CAP_SIGNALING_COMMANDS cmd, int identifier, ...){ 146509e9d05bSMatthias Ringwald va_list argptr; 146609e9d05bSMatthias Ringwald va_start(argptr, identifier); 1467d5a98629SMatthias Ringwald uint8_t pb_flags = 0x00; // First non-automatically-flushable packet of a higher layer message 1468*a254c508SMatthias Ringwald uint8_t result = l2cap_send_signaling_packet(handle, pb_flags, L2CAP_CID_SIGNALING_LE, cmd, identifier, argptr); 146909e9d05bSMatthias Ringwald va_end(argptr); 147051b2c70eSMatthias Ringwald return result; 147109e9d05bSMatthias Ringwald } 147209e9d05bSMatthias Ringwald #endif 147309e9d05bSMatthias Ringwald 147409e9d05bSMatthias Ringwald uint16_t l2cap_max_mtu(void){ 147509e9d05bSMatthias Ringwald return HCI_ACL_PAYLOAD_SIZE - L2CAP_HEADER_SIZE; 147609e9d05bSMatthias Ringwald } 147709e9d05bSMatthias Ringwald 14783e329ddfSandryblack #ifdef ENABLE_BLE 147909e9d05bSMatthias Ringwald uint16_t l2cap_max_le_mtu(void){ 14804ea43905SMatthias Ringwald if (l2cap_le_custom_max_mtu != 0u) return l2cap_le_custom_max_mtu; 148109e9d05bSMatthias Ringwald return l2cap_max_mtu(); 148209e9d05bSMatthias Ringwald } 1483b1d43497Smatthias.ringwald 148425818320SMatthias Ringwald void l2cap_set_max_le_mtu(uint16_t max_mtu){ 148525818320SMatthias Ringwald if (max_mtu < l2cap_max_mtu()){ 148625818320SMatthias Ringwald l2cap_le_custom_max_mtu = max_mtu; 148725818320SMatthias Ringwald } 148825818320SMatthias Ringwald } 14893e329ddfSandryblack #endif 149025818320SMatthias Ringwald 1491d2afdd38SMatthias Ringwald #ifdef ENABLE_CLASSIC 1492d2afdd38SMatthias Ringwald 14936b99230fSMatthias Ringwald static uint16_t l2cap_setup_options_mtu(uint8_t * config_options, uint16_t mtu){ 1494d64e9771SMatthias Ringwald config_options[0] = L2CAP_CONFIG_OPTION_TYPE_MAX_TRANSMISSION_UNIT; // MTU 1495d2afdd38SMatthias Ringwald config_options[1] = 2; // len param 14966b99230fSMatthias Ringwald little_endian_store_16(config_options, 2, mtu); 1497d2afdd38SMatthias Ringwald return 4; 1498d2afdd38SMatthias Ringwald } 1499d2afdd38SMatthias Ringwald 1500450ad7ecSMatthias Ringwald #ifdef ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE 15016b99230fSMatthias Ringwald static int l2cap_ertm_mode(l2cap_channel_t * channel){ 1502450ad7ecSMatthias Ringwald hci_connection_t * connection = hci_connection_for_handle(channel->con_handle); 15036b99230fSMatthias Ringwald return ((connection->l2cap_state.information_state == L2CAP_INFORMATION_STATE_DONE) 15046b99230fSMatthias Ringwald && (connection->l2cap_state.extended_feature_mask & 0x08)); 1505450ad7ecSMatthias Ringwald } 1506450ad7ecSMatthias Ringwald #endif 15076b99230fSMatthias Ringwald 15086b99230fSMatthias Ringwald static uint16_t l2cap_setup_options_request(l2cap_channel_t * channel, uint8_t * config_options){ 15096b99230fSMatthias Ringwald #ifdef ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE 1510313d3a26SMatthias Ringwald // use ERTM options if supported by remote and channel ready to use it 1511313d3a26SMatthias Ringwald if (l2cap_ertm_mode(channel) && channel->mode == L2CAP_CHANNEL_MODE_ENHANCED_RETRANSMISSION){ 15127cbe539fSMatthias Ringwald return l2cap_setup_options_ertm_request(channel, config_options); 15136b99230fSMatthias Ringwald } 15146b99230fSMatthias Ringwald #endif 15156b99230fSMatthias Ringwald uint16_t mtu = channel->local_mtu; 15166b99230fSMatthias Ringwald return l2cap_setup_options_mtu(config_options, mtu); 15176b99230fSMatthias Ringwald } 15186b99230fSMatthias Ringwald 1519b8134563SMatthias Ringwald static uint16_t l2cap_setup_options_mtu_response(l2cap_channel_t * channel, uint8_t * config_options){ 152032717978SMatthias Ringwald uint16_t mtu = btstack_min(channel->local_mtu, channel->remote_mtu); 15216b99230fSMatthias Ringwald return l2cap_setup_options_mtu(config_options, mtu); 15226dca2a0cSMatthias Ringwald } 15236dca2a0cSMatthias Ringwald 15241b9cb13dSMatthias Ringwald static uint32_t l2cap_extended_features_mask(void){ 15251b9cb13dSMatthias Ringwald // extended features request supported, features: fixed channels, unicast connectionless data reception 15261b9cb13dSMatthias Ringwald uint32_t features = 0x280; 15271b9cb13dSMatthias Ringwald #ifdef ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE 152854901195SMatthias Ringwald features |= 0x0028; 15291b9cb13dSMatthias Ringwald #endif 15301b9cb13dSMatthias Ringwald return features; 15311b9cb13dSMatthias Ringwald } 1532d2afdd38SMatthias Ringwald #endif 15331b9cb13dSMatthias Ringwald 15343a600bd4SMatthias Ringwald // 1535b3264428SMatthias Ringwald #ifdef ENABLE_CLASSIC 1536c80ea152SMatthias Ringwald 1537c80ea152SMatthias Ringwald // returns true if channel was finalized 1538c80ea152SMatthias Ringwald static bool l2cap_run_for_classic_channel(l2cap_channel_t * channel){ 153909e9d05bSMatthias Ringwald 1540f2c70799Sandryblack #ifdef ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE 1541f2c70799Sandryblack uint8_t config_options[18]; 1542f2c70799Sandryblack #else 154343ec931dSMatthias Ringwald uint8_t config_options[10]; 1544f2c70799Sandryblack #endif 1545baf94f06S[email protected] 15462cd0be45Smatthias.ringwald switch (channel->state){ 15472cd0be45Smatthias.ringwald 1548df3354fcS[email protected] case L2CAP_STATE_WAIT_INCOMING_SECURITY_LEVEL_UPDATE: 1549ad671560S[email protected] case L2CAP_STATE_WAIT_CLIENT_ACCEPT_OR_REJECT: 155059607b77SMatthias Ringwald if (!hci_can_send_acl_packet_now(channel->con_handle)) return false; 1551a00031e2S[email protected] if (channel->state_var & L2CAP_CHANNEL_STATE_VAR_SEND_CONN_RESP_PEND) { 1552ad671560S[email protected] channelStateVarClearFlag(channel, L2CAP_CHANNEL_STATE_VAR_SEND_CONN_RESP_PEND); 155367d696b3SMatthias Ringwald channelStateVarSetFlag(channel, L2CAP_CHANNEL_STATE_VAR_SENT_CONN_RESP_PEND); 15544dc99b9dSMatthias Ringwald l2cap_send_classic_signaling_packet(channel->con_handle, CONNECTION_RESPONSE, channel->remote_sig_id, 15554dc99b9dSMatthias Ringwald channel->local_cid, channel->remote_cid, 1, 0); 1556ad671560S[email protected] } 1557ad671560S[email protected] break; 1558ad671560S[email protected] 155902b22dc4Smatthias.ringwald case L2CAP_STATE_WILL_SEND_CREATE_CONNECTION: 156059607b77SMatthias Ringwald if (!hci_can_send_command_packet_now()) break; 156164472d52Smatthias.ringwald // send connection request - set state first 156264472d52Smatthias.ringwald channel->state = L2CAP_STATE_WAIT_CONNECTION_COMPLETE; 156302b22dc4Smatthias.ringwald // BD_ADDR, Packet_Type, Page_Scan_Repetition_Mode, Reserved, Clock_Offset, Allow_Role_Switch 15646535961aSMatthias Ringwald (void)memcpy(l2cap_outgoing_classic_addr, channel->address, 6); 1565b4eb4420SMatthias Ringwald hci_send_cmd(&hci_create_connection, channel->address, hci_usable_acl_packet_types(), 0, 0, 0, hci_get_allow_role_switch()); 156602b22dc4Smatthias.ringwald break; 156702b22dc4Smatthias.ringwald 1568e7ff783cSmatthias.ringwald case L2CAP_STATE_WILL_SEND_CONNECTION_RESPONSE_DECLINE: 156959607b77SMatthias Ringwald if (!hci_can_send_acl_packet_now(channel->con_handle)) return false; 157022c29ab4SMatthias Ringwald channel->state = L2CAP_STATE_INVALID; 15714dc99b9dSMatthias Ringwald l2cap_send_classic_signaling_packet(channel->con_handle, CONNECTION_RESPONSE, channel->remote_sig_id, 15724dc99b9dSMatthias Ringwald channel->local_cid, channel->remote_cid, channel->reason, 0); 1573e7ff783cSmatthias.ringwald // discard channel - l2cap_finialize_channel_close without sending l2cap close event 1574817374d9SMatthias Ringwald btstack_linked_list_remove(&l2cap_channels, (btstack_linked_item_t *) channel); 1575c45d6b2cSMatthias Ringwald l2cap_free_channel_entry(channel); 157675e67d8aSMatthias Ringwald channel = NULL; 1577e7ff783cSmatthias.ringwald break; 1578e7ff783cSmatthias.ringwald 1579552d92a1Smatthias.ringwald case L2CAP_STATE_WILL_SEND_CONNECTION_RESPONSE_ACCEPT: 158059607b77SMatthias Ringwald if (!hci_can_send_acl_packet_now(channel->con_handle)) return false; 1581fa8473a4Smatthias.ringwald channel->state = L2CAP_STATE_CONFIG; 158228ca2b46S[email protected] channelStateVarSetFlag(channel, L2CAP_CHANNEL_STATE_VAR_SEND_CONF_REQ); 15834dc99b9dSMatthias Ringwald l2cap_send_classic_signaling_packet(channel->con_handle, CONNECTION_RESPONSE, channel->remote_sig_id, 15844dc99b9dSMatthias Ringwald channel->local_cid, channel->remote_cid, 0, 0); 1585552d92a1Smatthias.ringwald break; 1586552d92a1Smatthias.ringwald 15876fdcc387Smatthias.ringwald case L2CAP_STATE_WILL_SEND_CONNECTION_REQUEST: 158859607b77SMatthias Ringwald if (!hci_can_send_acl_packet_now(channel->con_handle)) return false; 15896fdcc387Smatthias.ringwald // success, start l2cap handshake 1590b1988dceSmatthias.ringwald channel->local_sig_id = l2cap_next_sig_id(); 15916fdcc387Smatthias.ringwald channel->state = L2CAP_STATE_WAIT_CONNECT_RSP; 15924dc99b9dSMatthias Ringwald l2cap_send_classic_signaling_packet(channel->con_handle, CONNECTION_REQUEST, channel->local_sig_id, 15934dc99b9dSMatthias Ringwald channel->psm, channel->local_cid); 15945932bd7cS[email protected] l2cap_start_rtx(channel); 15956fdcc387Smatthias.ringwald break; 15966fdcc387Smatthias.ringwald 1597fa8473a4Smatthias.ringwald case L2CAP_STATE_CONFIG: 159859607b77SMatthias Ringwald if (!hci_can_send_acl_packet_now(channel->con_handle)) return false; 159961c3f6deSMatthias Ringwald #ifdef ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE 160061c3f6deSMatthias Ringwald // fallback to basic mode if ERTM requested but not not supported by remote 160161c3f6deSMatthias Ringwald if (channel->mode == L2CAP_CHANNEL_MODE_ENHANCED_RETRANSMISSION){ 160261c3f6deSMatthias Ringwald if (!l2cap_ertm_mode(channel)){ 160361c3f6deSMatthias Ringwald l2cap_emit_simple_event_with_cid(channel, L2CAP_EVENT_ERTM_BUFFER_RELEASED); 160461c3f6deSMatthias Ringwald channel->mode = L2CAP_CHANNEL_MODE_BASIC; 160561c3f6deSMatthias Ringwald } 160661c3f6deSMatthias Ringwald } 160761c3f6deSMatthias Ringwald #endif 160873cf2b3dSmatthias.ringwald if (channel->state_var & L2CAP_CHANNEL_STATE_VAR_SEND_CONF_RSP){ 160963a7246aSmatthias.ringwald uint16_t flags = 0; 161028ca2b46S[email protected] channelStateVarClearFlag(channel, L2CAP_CHANNEL_STATE_VAR_SEND_CONF_RSP); 161163a7246aSmatthias.ringwald if (channel->state_var & L2CAP_CHANNEL_STATE_VAR_SEND_CONF_RSP_CONT) { 161263a7246aSmatthias.ringwald flags = 1; 161363a7246aSmatthias.ringwald } else { 161428ca2b46S[email protected] channelStateVarSetFlag(channel, L2CAP_CHANNEL_STATE_VAR_SENT_CONF_RSP); 161563a7246aSmatthias.ringwald } 161663a7246aSmatthias.ringwald if (channel->state_var & L2CAP_CHANNEL_STATE_VAR_SEND_CONF_RSP_INVALID){ 1617ac8f1300SMatthias Ringwald channelStateVarClearFlag(channel, L2CAP_CHANNEL_STATE_VAR_SENT_CONF_RSP); 16184dc99b9dSMatthias Ringwald l2cap_send_classic_signaling_packet(channel->con_handle, CONFIGURE_RESPONSE, channel->remote_sig_id, 16194dc99b9dSMatthias Ringwald channel->remote_cid, flags, L2CAP_CONF_RESULT_UNKNOWN_OPTIONS, 16204dc99b9dSMatthias Ringwald 1, &channel->unknown_option); 1621ac8f1300SMatthias Ringwald #ifdef ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE 1622ac8f1300SMatthias Ringwald } else if (channel->state_var & L2CAP_CHANNEL_STATE_VAR_SEND_CONF_RSP_REJECTED){ 1623ac8f1300SMatthias Ringwald channelStateVarClearFlag(channel, L2CAP_CHANNEL_STATE_VAR_SEND_CONF_RSP_REJECTED); 1624ac8f1300SMatthias Ringwald channelStateVarClearFlag(channel, L2CAP_CHANNEL_STATE_VAR_SENT_CONF_RSP); 1625b8134563SMatthias Ringwald uint16_t options_size = l2cap_setup_options_ertm_response(channel, config_options); 16264dc99b9dSMatthias Ringwald l2cap_send_classic_signaling_packet(channel->con_handle, CONFIGURE_RESPONSE, channel->remote_sig_id, 16274dc99b9dSMatthias Ringwald channel->remote_cid, flags, 16284dc99b9dSMatthias Ringwald L2CAP_CONF_RESULT_UNACCEPTABLE_PARAMETERS, options_size, 16294dc99b9dSMatthias Ringwald &config_options); 1630b8134563SMatthias Ringwald } else if (channel->state_var & L2CAP_CHANNEL_STATE_VAR_SEND_CONF_RSP_ERTM){ 1631b8134563SMatthias Ringwald channelStateVarClearFlag(channel, L2CAP_CHANNEL_STATE_VAR_SEND_CONF_RSP_ERTM); 1632b8134563SMatthias Ringwald channelStateVarClearFlag(channel, L2CAP_CHANNEL_STATE_VAR_SEND_CONF_RSP_MTU); 1633b8134563SMatthias Ringwald uint16_t options_size = l2cap_setup_options_ertm_response(channel, config_options); 16344dc99b9dSMatthias Ringwald l2cap_send_classic_signaling_packet(channel->con_handle, CONFIGURE_RESPONSE, channel->remote_sig_id, 16354dc99b9dSMatthias Ringwald channel->remote_cid, flags, L2CAP_CONF_RESULT_SUCCESS, 16364dc99b9dSMatthias Ringwald options_size, &config_options); 1637ac8f1300SMatthias Ringwald #endif 1638ac8f1300SMatthias Ringwald } else if (channel->state_var & L2CAP_CHANNEL_STATE_VAR_SEND_CONF_RSP_MTU){ 163963a7246aSmatthias.ringwald channelStateVarClearFlag(channel,L2CAP_CHANNEL_STATE_VAR_SEND_CONF_RSP_MTU); 1640b8134563SMatthias Ringwald uint16_t options_size = l2cap_setup_options_mtu_response(channel, config_options); 16414dc99b9dSMatthias Ringwald l2cap_send_classic_signaling_packet(channel->con_handle, CONFIGURE_RESPONSE, channel->remote_sig_id, 16424dc99b9dSMatthias Ringwald channel->remote_cid, flags, L2CAP_CONF_RESULT_SUCCESS, 16434dc99b9dSMatthias Ringwald options_size, &config_options); 164463a7246aSmatthias.ringwald } else { 16454dc99b9dSMatthias Ringwald l2cap_send_classic_signaling_packet(channel->con_handle, CONFIGURE_RESPONSE, channel->remote_sig_id, 16464dc99b9dSMatthias Ringwald channel->remote_cid, flags, L2CAP_CONF_RESULT_SUCCESS, 0, NULL); 164763a7246aSmatthias.ringwald } 164863a7246aSmatthias.ringwald channelStateVarClearFlag(channel, L2CAP_CHANNEL_STATE_VAR_SEND_CONF_RSP_CONT); 1649fa8473a4Smatthias.ringwald } 165073cf2b3dSmatthias.ringwald else if (channel->state_var & L2CAP_CHANNEL_STATE_VAR_SEND_CONF_REQ){ 165128ca2b46S[email protected] channelStateVarClearFlag(channel, L2CAP_CHANNEL_STATE_VAR_SEND_CONF_REQ); 165228ca2b46S[email protected] channelStateVarSetFlag(channel, L2CAP_CHANNEL_STATE_VAR_SENT_CONF_REQ); 1653b1988dceSmatthias.ringwald channel->local_sig_id = l2cap_next_sig_id(); 16546b99230fSMatthias Ringwald uint16_t options_size = l2cap_setup_options_request(channel, config_options); 16554dc99b9dSMatthias Ringwald l2cap_send_classic_signaling_packet(channel->con_handle, CONFIGURE_REQUEST, channel->local_sig_id, 16564dc99b9dSMatthias Ringwald channel->remote_cid, 0, options_size, &config_options); 16575932bd7cS[email protected] l2cap_start_rtx(channel); 1658fa8473a4Smatthias.ringwald } 1659fa8473a4Smatthias.ringwald if (l2cap_channel_ready_for_open(channel)){ 1660552d92a1Smatthias.ringwald channel->state = L2CAP_STATE_OPEN; 1661552d92a1Smatthias.ringwald l2cap_emit_channel_opened(channel, 0); // success 1662fa8473a4Smatthias.ringwald } 1663552d92a1Smatthias.ringwald break; 1664552d92a1Smatthias.ringwald 1665e7ff783cSmatthias.ringwald case L2CAP_STATE_WILL_SEND_DISCONNECT_RESPONSE: 166659607b77SMatthias Ringwald if (!hci_can_send_acl_packet_now(channel->con_handle)) return false; 166722c29ab4SMatthias Ringwald channel->state = L2CAP_STATE_INVALID; 16684dc99b9dSMatthias Ringwald l2cap_send_classic_signaling_packet(channel->con_handle, DISCONNECTION_RESPONSE, channel->remote_sig_id, 16694dc99b9dSMatthias Ringwald channel->local_cid, channel->remote_cid); 16705932bd7cS[email protected] // we don't start an RTX timer for a disconnect - there's no point in closing the channel if the other side doesn't respond :) 1671*a254c508SMatthias Ringwald l2cap_finalize_channel_close(channel); // -- remove from list 167264cb054cSMatthias Ringwald channel = NULL; 1673e7ff783cSmatthias.ringwald break; 1674e7ff783cSmatthias.ringwald 1675e7ff783cSmatthias.ringwald case L2CAP_STATE_WILL_SEND_DISCONNECT_REQUEST: 16766ddb7e9cSMatthias Ringwald if (!hci_can_send_acl_packet_now(channel->con_handle)) return false; 1677b1988dceSmatthias.ringwald channel->local_sig_id = l2cap_next_sig_id(); 16782cd0be45Smatthias.ringwald channel->state = L2CAP_STATE_WAIT_DISCONNECT; 16794dc99b9dSMatthias Ringwald l2cap_send_classic_signaling_packet(channel->con_handle, DISCONNECTION_REQUEST, channel->local_sig_id, 16804dc99b9dSMatthias Ringwald channel->remote_cid, channel->local_cid); 16812cd0be45Smatthias.ringwald break; 16822cd0be45Smatthias.ringwald default: 16832cd0be45Smatthias.ringwald break; 16842cd0be45Smatthias.ringwald } 168538f62777SMatthias Ringwald 168675e67d8aSMatthias Ringwald // handle channel finalize on L2CAP_STATE_WILL_SEND_DISCONNECT_RESPONSE and L2CAP_STATE_WILL_SEND_CONNECTION_RESPONSE_DECLINE 1687c80ea152SMatthias Ringwald return channel == NULL; 1688c80ea152SMatthias Ringwald } 1689c80ea152SMatthias Ringwald 1690c80ea152SMatthias Ringwald #ifdef ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE 1691c80ea152SMatthias Ringwald static void l2cap_run_for_classic_channel_ertm(l2cap_channel_t * channel){ 16929700d53bSMilanka Ringwald 16939700d53bSMilanka Ringwald // ERTM mode 16943a600bd4SMatthias Ringwald if (channel->mode != L2CAP_CHANNEL_MODE_ENHANCED_RETRANSMISSION) return; 16959700d53bSMilanka Ringwald 16969700d53bSMilanka Ringwald // check if we can still send 16973a600bd4SMatthias Ringwald if (channel->con_handle == HCI_CON_HANDLE_INVALID) return; 16983a600bd4SMatthias Ringwald if (!hci_can_send_acl_packet_now(channel->con_handle)) return; 1699675e6881SMatthias Ringwald 1700d84e866fSMatthias Ringwald if (channel->send_supervisor_frame_receiver_ready){ 170178cd8a22SMatthias Ringwald channel->send_supervisor_frame_receiver_ready = 0; 1702d2afdd38SMatthias Ringwald log_info("Send S-Frame: RR %u, final %u", channel->req_seq, channel->set_final_bit_after_packet_with_poll_bit_set); 1703d2afdd38SMatthias Ringwald uint16_t control = l2cap_encanced_control_field_for_supevisor_frame( L2CAP_SUPERVISORY_FUNCTION_RR_RECEIVER_READY, 0, channel->set_final_bit_after_packet_with_poll_bit_set, channel->req_seq); 1704d2afdd38SMatthias Ringwald channel->set_final_bit_after_packet_with_poll_bit_set = 0; 170538f62777SMatthias Ringwald l2cap_ertm_send_supervisor_frame(channel, control); 17063a600bd4SMatthias Ringwald return; 170738f62777SMatthias Ringwald } 170862041d70SMatthias Ringwald if (channel->send_supervisor_frame_receiver_ready_poll){ 170978cd8a22SMatthias Ringwald channel->send_supervisor_frame_receiver_ready_poll = 0; 171062041d70SMatthias Ringwald log_info("Send S-Frame: RR %u with poll=1 ", channel->req_seq); 171162041d70SMatthias Ringwald uint16_t control = l2cap_encanced_control_field_for_supevisor_frame( L2CAP_SUPERVISORY_FUNCTION_RR_RECEIVER_READY, 1, 0, channel->req_seq); 171262041d70SMatthias Ringwald l2cap_ertm_send_supervisor_frame(channel, control); 17133a600bd4SMatthias Ringwald return; 171462041d70SMatthias Ringwald } 17158f1c9639SMatthias Ringwald if (channel->send_supervisor_frame_receiver_not_ready){ 171678cd8a22SMatthias Ringwald channel->send_supervisor_frame_receiver_not_ready = 0; 17178f1c9639SMatthias Ringwald log_info("Send S-Frame: RNR %u", channel->req_seq); 17188f1c9639SMatthias Ringwald uint16_t control = l2cap_encanced_control_field_for_supevisor_frame( L2CAP_SUPERVISORY_FUNCTION_RNR_RECEIVER_NOT_READY, 0, 0, channel->req_seq); 17198f1c9639SMatthias Ringwald l2cap_ertm_send_supervisor_frame(channel, control); 17203a600bd4SMatthias Ringwald return; 17218f1c9639SMatthias Ringwald } 1722c7309e8dSMatthias Ringwald if (channel->send_supervisor_frame_reject){ 1723c7309e8dSMatthias Ringwald channel->send_supervisor_frame_reject = 0; 1724c7309e8dSMatthias Ringwald log_info("Send S-Frame: REJ %u", channel->req_seq); 1725c7309e8dSMatthias Ringwald uint16_t control = l2cap_encanced_control_field_for_supevisor_frame( L2CAP_SUPERVISORY_FUNCTION_REJ_REJECT, 0, 0, channel->req_seq); 1726c7309e8dSMatthias Ringwald l2cap_ertm_send_supervisor_frame(channel, control); 17273a600bd4SMatthias Ringwald return; 1728c7309e8dSMatthias Ringwald } 1729df2191a7SMatthias Ringwald if (channel->send_supervisor_frame_selective_reject){ 1730df2191a7SMatthias Ringwald channel->send_supervisor_frame_selective_reject = 0; 1731df2191a7SMatthias Ringwald log_info("Send S-Frame: SREJ %u", channel->expected_tx_seq); 1732f85ade6bSMatthias Ringwald uint16_t control = l2cap_encanced_control_field_for_supevisor_frame( L2CAP_SUPERVISORY_FUNCTION_SREJ_SELECTIVE_REJECT, 0, channel->set_final_bit_after_packet_with_poll_bit_set, channel->expected_tx_seq); 1733f85ade6bSMatthias Ringwald channel->set_final_bit_after_packet_with_poll_bit_set = 0; 1734df2191a7SMatthias Ringwald l2cap_ertm_send_supervisor_frame(channel, control); 17353a600bd4SMatthias Ringwald return; 1736df2191a7SMatthias Ringwald } 17377b7901d8SMatthias Ringwald 17387b7901d8SMatthias Ringwald if (channel->srej_active){ 17397b7901d8SMatthias Ringwald int i; 17407b7901d8SMatthias Ringwald for (i=0;i<channel->num_tx_buffers;i++){ 17417b7901d8SMatthias Ringwald l2cap_ertm_tx_packet_state_t * tx_state = &channel->tx_packets_state[i]; 17427b7901d8SMatthias Ringwald if (tx_state->retransmission_requested) { 17437b7901d8SMatthias Ringwald tx_state->retransmission_requested = 0; 1744d2afdd38SMatthias Ringwald uint8_t final = channel->set_final_bit_after_packet_with_poll_bit_set; 1745d2afdd38SMatthias Ringwald channel->set_final_bit_after_packet_with_poll_bit_set = 0; 1746d2afdd38SMatthias Ringwald l2cap_ertm_send_information_frame(channel, i, final); 17477b7901d8SMatthias Ringwald break; 17487b7901d8SMatthias Ringwald } 17497b7901d8SMatthias Ringwald } 17507b7901d8SMatthias Ringwald if (i == channel->num_tx_buffers){ 17517b7901d8SMatthias Ringwald // no retransmission request found 17527b7901d8SMatthias Ringwald channel->srej_active = 0; 17537b7901d8SMatthias Ringwald } else { 17547b7901d8SMatthias Ringwald // packet was sent 17553a600bd4SMatthias Ringwald return; 17563a600bd4SMatthias Ringwald } 17573a600bd4SMatthias Ringwald } 17583a600bd4SMatthias Ringwald } 1759c80ea152SMatthias Ringwald #endif /* ERTM */ 1760c80ea152SMatthias Ringwald #endif /* Classic */ 17613a600bd4SMatthias Ringwald 17620d1523feSMatthias Ringwald static void l2cap_run_signaling_response(void) { 17633a600bd4SMatthias Ringwald 17643a600bd4SMatthias Ringwald // check pending signaling responses 176591c8d67dSMatthias Ringwald while (l2cap_signaling_responses_pending){ 17663a600bd4SMatthias Ringwald 176791c8d67dSMatthias Ringwald hci_con_handle_t handle = l2cap_signaling_responses[0].handle; 17683a600bd4SMatthias Ringwald 17693a600bd4SMatthias Ringwald if (!hci_can_send_acl_packet_now(handle)) break; 17703a600bd4SMatthias Ringwald 177191c8d67dSMatthias Ringwald uint8_t sig_id = l2cap_signaling_responses[0].sig_id; 177291c8d67dSMatthias Ringwald uint8_t response_code = l2cap_signaling_responses[0].code; 1773*a254c508SMatthias Ringwald uint16_t result = l2cap_signaling_responses[0].data; // CONNECTION_REQUEST, COMMAND_REJECT, REJECT_SM_PAIRING, L2CAP_CREDIT_BASED_CONNECTION_REQUEST 1774e6cdcf4bSMatthias Ringwald uint8_t buffer[2]; // REJECT_SM_PAIRING 1775*a254c508SMatthias Ringwald uint16_t source_cid = l2cap_signaling_responses[0].cid; // CONNECTION_REQUEST, REJECT_SM_PAIRING 17763a600bd4SMatthias Ringwald #ifdef ENABLE_CLASSIC 177791c8d67dSMatthias Ringwald uint16_t info_type = l2cap_signaling_responses[0].data; // INFORMATION_REQUEST 17783a600bd4SMatthias Ringwald #endif 1779*a254c508SMatthias Ringwald #ifdef ENABLE_L2CAP_ENHANCED_DATA_CHANNELS 1780*a254c508SMatthias Ringwald uint8_t num_channels = l2cap_signaling_responses[0].cid >> 8; // L2CAP_CREDIT_BASED_CONNECTION_REQUEST 1781*a254c508SMatthias Ringwald uint16_t signaling_cid = (uint16_t) l2cap_signaling_responses[0].cid & 0xff; // L2CAP_CREDIT_BASED_CONNECTION_REQUEST, L2CAP_CREDIT_BASED_CONNECTION_REQUEST 1782*a254c508SMatthias Ringwald #endif 17833a600bd4SMatthias Ringwald 17843a600bd4SMatthias Ringwald // remove first item before sending (to avoid sending response mutliple times) 178591c8d67dSMatthias Ringwald l2cap_signaling_responses_pending--; 17863a600bd4SMatthias Ringwald int i; 178791c8d67dSMatthias Ringwald for (i=0; i < l2cap_signaling_responses_pending; i++){ 178891c8d67dSMatthias Ringwald (void)memcpy(&l2cap_signaling_responses[i], 178991c8d67dSMatthias Ringwald &l2cap_signaling_responses[i + 1], 17903a600bd4SMatthias Ringwald sizeof(l2cap_signaling_response_t)); 17913a600bd4SMatthias Ringwald } 17923a600bd4SMatthias Ringwald 17933a600bd4SMatthias Ringwald switch (response_code){ 17943a600bd4SMatthias Ringwald #ifdef ENABLE_CLASSIC 17953a600bd4SMatthias Ringwald case CONNECTION_REQUEST: 17964dc99b9dSMatthias Ringwald l2cap_send_classic_signaling_packet(handle, CONNECTION_RESPONSE, sig_id, source_cid, 0, result, 0); 17973a600bd4SMatthias Ringwald break; 17983a600bd4SMatthias Ringwald case ECHO_REQUEST: 17994dc99b9dSMatthias Ringwald l2cap_send_classic_signaling_packet(handle, ECHO_RESPONSE, sig_id, 0, NULL); 18003a600bd4SMatthias Ringwald break; 18013a600bd4SMatthias Ringwald case INFORMATION_REQUEST: 18023a600bd4SMatthias Ringwald switch (info_type){ 18033a600bd4SMatthias Ringwald case L2CAP_INFO_TYPE_CONNECTIONLESS_MTU: { 18043a600bd4SMatthias Ringwald uint16_t connectionless_mtu = hci_max_acl_data_packet_length(); 18054dc99b9dSMatthias Ringwald l2cap_send_classic_signaling_packet(handle, INFORMATION_RESPONSE, sig_id, info_type, 0, 18064dc99b9dSMatthias Ringwald sizeof(connectionless_mtu), &connectionless_mtu); 18073a600bd4SMatthias Ringwald } 18083a600bd4SMatthias Ringwald break; 18093a600bd4SMatthias Ringwald case L2CAP_INFO_TYPE_EXTENDED_FEATURES_SUPPORTED: { 18103a600bd4SMatthias Ringwald uint32_t features = l2cap_extended_features_mask(); 18114dc99b9dSMatthias Ringwald l2cap_send_classic_signaling_packet(handle, INFORMATION_RESPONSE, sig_id, info_type, 0, 18124dc99b9dSMatthias Ringwald sizeof(features), &features); 18133a600bd4SMatthias Ringwald } 18143a600bd4SMatthias Ringwald break; 18153a600bd4SMatthias Ringwald case L2CAP_INFO_TYPE_FIXED_CHANNELS_SUPPORTED: { 18163a600bd4SMatthias Ringwald uint8_t map[8]; 18173a600bd4SMatthias Ringwald memset(map, 0, 8); 181881a22226SMatthias Ringwald // L2CAP Signaling Channel (bit 1) + Connectionless reception (bit 2) 181981a22226SMatthias Ringwald map[0] = (1 << 1) | (1 << 2); 18203dc9ca3aSMatthias Ringwald #if defined(ENABLE_BLE) || defined (ENABLE_EXPLICIT_BR_EDR_SECURITY_MANAGER) 182181a22226SMatthias Ringwald // BR/EDR Security Manager (bit 7) 182281a22226SMatthias Ringwald map[0] |= (1 << 7); 182381a22226SMatthias Ringwald #endif 18244dc99b9dSMatthias Ringwald l2cap_send_classic_signaling_packet(handle, INFORMATION_RESPONSE, sig_id, info_type, 0, 18254dc99b9dSMatthias Ringwald sizeof(map), &map); 18263a600bd4SMatthias Ringwald } 18273a600bd4SMatthias Ringwald break; 18283a600bd4SMatthias Ringwald default: 18293a600bd4SMatthias Ringwald // all other types are not supported 18304dc99b9dSMatthias Ringwald l2cap_send_classic_signaling_packet(handle, INFORMATION_RESPONSE, sig_id, info_type, 1, 0, NULL); 18313a600bd4SMatthias Ringwald break; 18323a600bd4SMatthias Ringwald } 18333a600bd4SMatthias Ringwald break; 18343a600bd4SMatthias Ringwald case COMMAND_REJECT: 18354dc99b9dSMatthias Ringwald l2cap_send_classic_signaling_packet(handle, COMMAND_REJECT, sig_id, result, 0, NULL); 18363a600bd4SMatthias Ringwald break; 18373a600bd4SMatthias Ringwald #endif 18383a600bd4SMatthias Ringwald #ifdef ENABLE_BLE 18393a600bd4SMatthias Ringwald case LE_CREDIT_BASED_CONNECTION_REQUEST: 18403a600bd4SMatthias Ringwald l2cap_send_le_signaling_packet(handle, LE_CREDIT_BASED_CONNECTION_RESPONSE, sig_id, 0, 0, 0, 0, result); 18413a600bd4SMatthias Ringwald break; 18423a600bd4SMatthias Ringwald case COMMAND_REJECT_LE: 18433a600bd4SMatthias Ringwald l2cap_send_le_signaling_packet(handle, COMMAND_REJECT, sig_id, result, 0, NULL); 18443a600bd4SMatthias Ringwald break; 18453a600bd4SMatthias Ringwald #endif 1846*a254c508SMatthias Ringwald #ifdef ENABLE_L2CAP_ENHANCED_DATA_CHANNELS 1847*a254c508SMatthias Ringwald case L2CAP_CREDIT_BASED_CONNECTION_REQUEST: { 1848*a254c508SMatthias Ringwald // send variable size array or cids with each cid being zero 1849*a254c508SMatthias Ringwald uint16_t cids[6]; 1850*a254c508SMatthias Ringwald (void) memset(cids, 0xff, sizeof(cids)); 1851*a254c508SMatthias Ringwald (void) memset(cids, 0x00, num_channels * sizeof(uint16_t)); 1852*a254c508SMatthias Ringwald l2cap_send_general_signaling_packet(handle, signaling_cid, L2CAP_CREDIT_BASED_CONNECTION_RESPONSE, 1853*a254c508SMatthias Ringwald sig_id, 0, 0, 0, result, cids); 1854*a254c508SMatthias Ringwald break; 1855*a254c508SMatthias Ringwald } 1856*a254c508SMatthias Ringwald 1857*a254c508SMatthias Ringwald case L2CAP_CREDIT_BASED_RECONFIGURE_REQUEST: 1858*a254c508SMatthias Ringwald l2cap_send_general_signaling_packet(handle, signaling_cid, L2CAP_CREDIT_BASED_RECONFIGURE_RESPONSE, 1859*a254c508SMatthias Ringwald sig_id, result); 1860*a254c508SMatthias Ringwald break; 1861*a254c508SMatthias Ringwald #endif 1862e6cdcf4bSMatthias Ringwald case SM_PAIRING_FAILED: 1863e6cdcf4bSMatthias Ringwald buffer[0] = SM_CODE_PAIRING_FAILED; 1864e6cdcf4bSMatthias Ringwald buffer[1] = result; 1865e6cdcf4bSMatthias Ringwald l2cap_send_connectionless(handle, source_cid, buffer, 2); 1866e6cdcf4bSMatthias Ringwald break; 18673a600bd4SMatthias Ringwald default: 18683a600bd4SMatthias Ringwald // should not happen 18693a600bd4SMatthias Ringwald break; 18703a600bd4SMatthias Ringwald } 18713a600bd4SMatthias Ringwald } 1872ea6a43faSMatthias Ringwald } 18733a600bd4SMatthias Ringwald 1874*a254c508SMatthias Ringwald #ifdef ENABLE_CLASSIC 18751901fae5SMatthias Ringwald static bool l2ap_run_information_requests(void){ 18761901fae5SMatthias Ringwald // send l2cap information request if requested 1877ea6a43faSMatthias Ringwald btstack_linked_list_iterator_t it; 18783a600bd4SMatthias Ringwald hci_connections_get_iterator(&it); 1879c1c10361SMatthias Ringwald uint8_t info_type; 1880c1c10361SMatthias Ringwald l2cap_information_state_t new_state; 18813a600bd4SMatthias Ringwald while(btstack_linked_list_iterator_has_next(&it)){ 18823a600bd4SMatthias Ringwald hci_connection_t * connection = (hci_connection_t *) btstack_linked_list_iterator_next(&it); 1883c1c10361SMatthias Ringwald switch (connection->l2cap_state.information_state){ 1884c1c10361SMatthias Ringwald case L2CAP_INFORMATION_STATE_W2_SEND_EXTENDED_FEATURE_REQUEST: 1885c1c10361SMatthias Ringwald info_type = L2CAP_INFO_TYPE_EXTENDED_FEATURES_SUPPORTED; 1886c1c10361SMatthias Ringwald new_state = L2CAP_INFORMATION_STATE_W4_EXTENDED_FEATURE_RESPONSE; 1887c1c10361SMatthias Ringwald break; 1888c1c10361SMatthias Ringwald case L2CAP_INFORMATION_STATE_W2_SEND_FIXED_CHANNELS_REQUEST: 1889c1c10361SMatthias Ringwald info_type = L2CAP_INFO_TYPE_FIXED_CHANNELS_SUPPORTED; 1890c1c10361SMatthias Ringwald new_state = L2CAP_INFORMATION_STATE_W4_FIXED_CHANNELS_RESPONSE; 1891c1c10361SMatthias Ringwald break; 1892c1c10361SMatthias Ringwald default: 1893c1c10361SMatthias Ringwald continue; 18947b7901d8SMatthias Ringwald } 1895c1c10361SMatthias Ringwald if (!hci_can_send_acl_packet_now(connection->con_handle)) break; 1896c1c10361SMatthias Ringwald 1897c1c10361SMatthias Ringwald connection->l2cap_state.information_state = new_state; 1898c1c10361SMatthias Ringwald uint8_t sig_id = l2cap_next_sig_id(); 1899c1c10361SMatthias Ringwald l2cap_send_classic_signaling_packet(connection->con_handle, INFORMATION_REQUEST, sig_id, info_type); 19007b7901d8SMatthias Ringwald } 1901ea6a43faSMatthias Ringwald return false; 19022cd0be45Smatthias.ringwald } 1903*a254c508SMatthias Ringwald #endif 1904da886c03S[email protected] 1905cab29d48SMatthias Ringwald #ifdef ENABLE_LE_DATA_CHANNELS 1906ea6a43faSMatthias Ringwald static void l2cap_run_le_data_channels(void){ 1907ea6a43faSMatthias Ringwald btstack_linked_list_iterator_t it; 1908421cb104SMatthias Ringwald btstack_linked_list_iterator_init(&it, &l2cap_channels); 1909efedfb4cSMatthias Ringwald while (btstack_linked_list_iterator_has_next(&it)){ 1910b5803aafSMatthias Ringwald uint16_t mps; 1911efedfb4cSMatthias Ringwald l2cap_channel_t * channel = (l2cap_channel_t *) btstack_linked_list_iterator_next(&it); 1912421cb104SMatthias Ringwald 1913421cb104SMatthias Ringwald if (channel->channel_type != L2CAP_CHANNEL_TYPE_LE_DATA_CHANNEL) continue; 1914421cb104SMatthias Ringwald 1915efedfb4cSMatthias Ringwald // log_info("l2cap_run: channel %p, state %u, var 0x%02x", channel, channel->state, channel->state_var); 1916efedfb4cSMatthias Ringwald switch (channel->state){ 19175cb87675SMatthias Ringwald case L2CAP_STATE_WILL_SEND_LE_CONNECTION_REQUEST: 19185cb87675SMatthias Ringwald if (!hci_can_send_acl_packet_now(channel->con_handle)) break; 19195cb87675SMatthias Ringwald channel->state = L2CAP_STATE_WAIT_LE_CONNECTION_RESPONSE; 19205cb87675SMatthias Ringwald // le psm, source cid, mtu, mps, initial credits 19211b8b8d05SMatthias Ringwald channel->local_sig_id = l2cap_next_sig_id(); 192263f0ac45SMatthias Ringwald channel->credits_incoming = channel->new_credits_incoming; 192363f0ac45SMatthias Ringwald channel->new_credits_incoming = 0; 1924b5803aafSMatthias Ringwald mps = btstack_min(l2cap_max_le_mtu(), channel->local_mtu); 1925b5803aafSMatthias Ringwald l2cap_send_le_signaling_packet( channel->con_handle, LE_CREDIT_BASED_CONNECTION_REQUEST, channel->local_sig_id, channel->psm, channel->local_cid, channel->local_mtu, mps, channel->credits_incoming); 19265cb87675SMatthias Ringwald break; 192723017473SMatthias Ringwald case L2CAP_STATE_WILL_SEND_LE_CONNECTION_RESPONSE_ACCEPT: 192823017473SMatthias Ringwald if (!hci_can_send_acl_packet_now(channel->con_handle)) break; 192923017473SMatthias Ringwald // TODO: support larger MPS 193023017473SMatthias Ringwald channel->state = L2CAP_STATE_OPEN; 193163f0ac45SMatthias Ringwald channel->credits_incoming = channel->new_credits_incoming; 193263f0ac45SMatthias Ringwald channel->new_credits_incoming = 0; 1933b5803aafSMatthias Ringwald mps = btstack_min(l2cap_max_le_mtu(), channel->local_mtu); 1934b5803aafSMatthias Ringwald l2cap_send_le_signaling_packet(channel->con_handle, LE_CREDIT_BASED_CONNECTION_RESPONSE, channel->remote_sig_id, channel->local_cid, channel->local_mtu, mps, channel->credits_incoming, 0); 193564e11ca9SMatthias Ringwald // notify client 193644276248SMatthias Ringwald l2cap_emit_le_channel_opened(channel, 0); 193723017473SMatthias Ringwald break; 1938e7d0c9aaSMatthias Ringwald case L2CAP_STATE_WILL_SEND_LE_CONNECTION_RESPONSE_DECLINE: 1939e7d0c9aaSMatthias Ringwald if (!hci_can_send_acl_packet_now(channel->con_handle)) break; 1940e7d0c9aaSMatthias Ringwald channel->state = L2CAP_STATE_INVALID; 194163f0ac45SMatthias Ringwald l2cap_send_le_signaling_packet(channel->con_handle, LE_CREDIT_BASED_CONNECTION_RESPONSE, channel->remote_sig_id, 0, 0, 0, 0, channel->reason); 1942e7d0c9aaSMatthias Ringwald // discard channel - l2cap_finialize_channel_close without sending l2cap close event 1943e7d0c9aaSMatthias Ringwald btstack_linked_list_iterator_remove(&it); 1944c45d6b2cSMatthias Ringwald l2cap_free_channel_entry(channel); 1945e7d0c9aaSMatthias Ringwald break; 19467f107edaSMatthias Ringwald case L2CAP_STATE_OPEN: 194785aeef60SMatthias Ringwald if (!hci_can_send_acl_packet_now(channel->con_handle)) break; 194885aeef60SMatthias Ringwald if (channel->new_credits_incoming){ 1949*a254c508SMatthias Ringwald l2cap_credit_based_send_credits(channel); 19506774d5c9SMatthias Ringwald } 195185aeef60SMatthias Ringwald break; 1952828a7f7aSMatthias Ringwald case L2CAP_STATE_WILL_SEND_DISCONNECT_REQUEST: 1953828a7f7aSMatthias Ringwald if (!hci_can_send_acl_packet_now(channel->con_handle)) break; 1954828a7f7aSMatthias Ringwald channel->local_sig_id = l2cap_next_sig_id(); 1955828a7f7aSMatthias Ringwald channel->state = L2CAP_STATE_WAIT_DISCONNECT; 1956828a7f7aSMatthias Ringwald l2cap_send_le_signaling_packet( channel->con_handle, DISCONNECTION_REQUEST, channel->local_sig_id, channel->remote_cid, channel->local_cid); 1957828a7f7aSMatthias Ringwald break; 1958828a7f7aSMatthias Ringwald case L2CAP_STATE_WILL_SEND_DISCONNECT_RESPONSE: 1959828a7f7aSMatthias Ringwald if (!hci_can_send_acl_packet_now(channel->con_handle)) break; 1960828a7f7aSMatthias Ringwald channel->state = L2CAP_STATE_INVALID; 1961828a7f7aSMatthias Ringwald l2cap_send_le_signaling_packet( channel->con_handle, DISCONNECTION_RESPONSE, channel->remote_sig_id, channel->local_cid, channel->remote_cid); 1962828a7f7aSMatthias Ringwald l2cap_le_finialize_channel_close(channel); // -- remove from list 1963828a7f7aSMatthias Ringwald break; 1964efedfb4cSMatthias Ringwald default: 1965efedfb4cSMatthias Ringwald break; 1966efedfb4cSMatthias Ringwald } 1967efedfb4cSMatthias Ringwald } 1968ea6a43faSMatthias Ringwald } 1969ea6a43faSMatthias Ringwald #endif 1970ea6a43faSMatthias Ringwald 1971*a254c508SMatthias Ringwald #ifdef ENABLE_L2CAP_ENHANCED_DATA_CHANNELS 1972*a254c508SMatthias Ringwald 1973*a254c508SMatthias Ringwald // 11BH22222 1974*a254c508SMatthias Ringwald static void l2cap_emit_enhanced_data_channel_opened(l2cap_channel_t *channel, uint8_t status) { 1975*a254c508SMatthias Ringwald log_info("opened enhanced channel status 0x%x addr_type %u addr %s handle 0x%x psm 0x%x local_cid 0x%x remote_cid 0x%x local_mtu %u, remote_mtu %u", 1976*a254c508SMatthias Ringwald status, channel->address_type, bd_addr_to_str(channel->address), channel->con_handle, channel->psm, 1977*a254c508SMatthias Ringwald channel->local_cid, channel->remote_cid, channel->local_mtu, channel->remote_mtu); 1978*a254c508SMatthias Ringwald uint8_t event[23]; 1979*a254c508SMatthias Ringwald event[0] = L2CAP_EVENT_DATA_CHANNEL_OPENED; 1980*a254c508SMatthias Ringwald event[1] = sizeof(event) - 2u; 1981*a254c508SMatthias Ringwald event[2] = status; 1982*a254c508SMatthias Ringwald event[3] = channel->address_type; 1983*a254c508SMatthias Ringwald reverse_bd_addr(channel->address, &event[4]); 1984*a254c508SMatthias Ringwald little_endian_store_16(event, 10, channel->con_handle); 1985*a254c508SMatthias Ringwald event[12] = (channel->state_var & L2CAP_CHANNEL_STATE_VAR_INCOMING) ? 1 : 0; 1986*a254c508SMatthias Ringwald little_endian_store_16(event, 13, channel->psm); 1987*a254c508SMatthias Ringwald little_endian_store_16(event, 15, channel->local_cid); 1988*a254c508SMatthias Ringwald little_endian_store_16(event, 17, channel->remote_cid); 1989*a254c508SMatthias Ringwald little_endian_store_16(event, 19, channel->local_mtu); 1990*a254c508SMatthias Ringwald little_endian_store_16(event, 21, channel->remote_mtu); 1991*a254c508SMatthias Ringwald hci_dump_packet(HCI_EVENT_PACKET, 0, event, sizeof(event)); 1992*a254c508SMatthias Ringwald l2cap_dispatch_to_channel(channel, HCI_EVENT_PACKET, event, sizeof(event)); 1993*a254c508SMatthias Ringwald } 1994*a254c508SMatthias Ringwald 1995*a254c508SMatthias Ringwald static void l2cap_emit_enhanced_data_channel_reconfigure_complete(l2cap_channel_t *channel, uint16_t result) { 1996*a254c508SMatthias Ringwald // emit event 1997*a254c508SMatthias Ringwald uint8_t event[6]; 1998*a254c508SMatthias Ringwald event[0] = L2CAP_EVENT_DATA_CHANNEL_RECONFIGURATION_COMPLETE; 1999*a254c508SMatthias Ringwald event[1] = sizeof(event) - 2; 2000*a254c508SMatthias Ringwald little_endian_store_16(event, 2, channel->local_cid); 2001*a254c508SMatthias Ringwald little_endian_store_16(event, 4, result); 2002*a254c508SMatthias Ringwald l2cap_dispatch_to_channel(channel, HCI_EVENT_PACKET, event, sizeof(event)); 2003*a254c508SMatthias Ringwald } 2004*a254c508SMatthias Ringwald 2005*a254c508SMatthias Ringwald static void l2cap_run_enhanced_data_channels(void) { 2006*a254c508SMatthias Ringwald hci_con_handle_t con_handle = HCI_CON_HANDLE_INVALID; 2007*a254c508SMatthias Ringwald // num max channels + 1 for signaling pdu generator 2008*a254c508SMatthias Ringwald uint16_t cids[L2CAP_ENHANCED_DATA_CHANNEL_MAX_CID_ARRAY_SIZE + 1]; 2009*a254c508SMatthias Ringwald uint8_t num_cids = 0; 2010*a254c508SMatthias Ringwald uint8_t sig_id; 2011*a254c508SMatthias Ringwald uint16_t spsm; 2012*a254c508SMatthias Ringwald L2CAP_STATE matching_state; 2013*a254c508SMatthias Ringwald bool match_remote_sig_cid; 2014*a254c508SMatthias Ringwald uint8_t result = 0; 2015*a254c508SMatthias Ringwald uint16_t local_mtu; 2016*a254c508SMatthias Ringwald uint16_t initial_credits; 2017*a254c508SMatthias Ringwald uint16_t signaling_cid; 2018*a254c508SMatthias Ringwald L2CAP_STATE new_state; 2019*a254c508SMatthias Ringwald 2020*a254c508SMatthias Ringwald // pick first channel that needs to send a combined signaling pdu and setup collection via break 2021*a254c508SMatthias Ringwald // then collect all others that belong to the same pdu 2022*a254c508SMatthias Ringwald btstack_linked_list_iterator_t it; 2023*a254c508SMatthias Ringwald btstack_linked_list_iterator_init(&it, &l2cap_channels); 2024*a254c508SMatthias Ringwald while (btstack_linked_list_iterator_has_next(&it)) { 2025*a254c508SMatthias Ringwald l2cap_channel_t *channel = (l2cap_channel_t *) btstack_linked_list_iterator_next(&it); 2026*a254c508SMatthias Ringwald if (channel->channel_type != L2CAP_CHANNEL_TYPE_ENHANCED_DATA_CHANNEL) continue; 2027*a254c508SMatthias Ringwald if (con_handle == HCI_CON_HANDLE_INVALID) { 2028*a254c508SMatthias Ringwald switch (channel->state) { 2029*a254c508SMatthias Ringwald case L2CAP_STATE_WILL_SEND_ENHANCED_CONNECTION_REQUEST: 2030*a254c508SMatthias Ringwald if (!hci_can_send_acl_packet_now(channel->con_handle)) continue; 2031*a254c508SMatthias Ringwald local_mtu = channel->local_mtu; 2032*a254c508SMatthias Ringwald spsm = channel->psm; 2033*a254c508SMatthias Ringwald result = channel->reason; 2034*a254c508SMatthias Ringwald initial_credits = channel->credits_incoming; 2035*a254c508SMatthias Ringwald sig_id = channel->local_sig_id; 2036*a254c508SMatthias Ringwald new_state = L2CAP_STATE_WAIT_ENHANCED_CONNECTION_RESPONSE; 2037*a254c508SMatthias Ringwald match_remote_sig_cid = false; 2038*a254c508SMatthias Ringwald break; 2039*a254c508SMatthias Ringwald case L2CAP_STATE_WILL_SEND_ENHANCED_CONNECTION_RESPONSE: 2040*a254c508SMatthias Ringwald if (!hci_can_send_acl_packet_now(channel->con_handle)) continue; 2041*a254c508SMatthias Ringwald local_mtu = channel->local_mtu; 2042*a254c508SMatthias Ringwald initial_credits = channel->credits_incoming; 2043*a254c508SMatthias Ringwald sig_id = channel->remote_sig_id; 2044*a254c508SMatthias Ringwald new_state = L2CAP_STATE_OPEN; 2045*a254c508SMatthias Ringwald match_remote_sig_cid = true; 2046*a254c508SMatthias Ringwald break; 2047*a254c508SMatthias Ringwald case L2CAP_STATE_WILL_SEND_EHNANCED_RENEGOTIATION_REQUEST: 2048*a254c508SMatthias Ringwald if (!hci_can_send_acl_packet_now(channel->con_handle)) continue; 2049*a254c508SMatthias Ringwald sig_id = channel->local_sig_id; 2050*a254c508SMatthias Ringwald local_mtu = channel->renegotiate_mtu; 2051*a254c508SMatthias Ringwald new_state = L2CAP_STATE_WAIT_ENHANCED_RENEGOTIATION_RESPONSE; 2052*a254c508SMatthias Ringwald match_remote_sig_cid = false; 2053*a254c508SMatthias Ringwald break; 2054*a254c508SMatthias Ringwald case L2CAP_STATE_OPEN: 2055*a254c508SMatthias Ringwald if (!hci_can_send_acl_packet_now(channel->con_handle)) continue; 2056*a254c508SMatthias Ringwald if (channel->new_credits_incoming) { 2057*a254c508SMatthias Ringwald l2cap_credit_based_send_credits(channel); 2058*a254c508SMatthias Ringwald } 2059*a254c508SMatthias Ringwald continue; 2060*a254c508SMatthias Ringwald case L2CAP_STATE_WILL_SEND_DISCONNECT_REQUEST: 2061*a254c508SMatthias Ringwald if (!hci_can_send_acl_packet_now(channel->con_handle)) continue; 2062*a254c508SMatthias Ringwald channel->local_sig_id = l2cap_next_sig_id(); 2063*a254c508SMatthias Ringwald channel->state = L2CAP_STATE_WAIT_DISCONNECT; 2064*a254c508SMatthias Ringwald signaling_cid = channel->address_type == BD_ADDR_TYPE_ACL ? L2CAP_CID_SIGNALING : L2CAP_CID_SIGNALING_LE; 2065*a254c508SMatthias Ringwald l2cap_send_general_signaling_packet(channel->con_handle, signaling_cid, DISCONNECTION_REQUEST, 2066*a254c508SMatthias Ringwald channel->local_sig_id, channel->remote_cid, channel->local_cid); 2067*a254c508SMatthias Ringwald continue; 2068*a254c508SMatthias Ringwald case L2CAP_STATE_WILL_SEND_DISCONNECT_RESPONSE: 2069*a254c508SMatthias Ringwald if (!hci_can_send_acl_packet_now(channel->con_handle)) continue; 2070*a254c508SMatthias Ringwald channel->state = L2CAP_STATE_INVALID; 2071*a254c508SMatthias Ringwald signaling_cid = channel->address_type == BD_ADDR_TYPE_ACL ? L2CAP_CID_SIGNALING : L2CAP_CID_SIGNALING_LE; 2072*a254c508SMatthias Ringwald l2cap_send_general_signaling_packet(channel->con_handle, signaling_cid, DISCONNECTION_RESPONSE, 2073*a254c508SMatthias Ringwald channel->remote_sig_id, channel->local_cid, 2074*a254c508SMatthias Ringwald channel->remote_cid); 2075*a254c508SMatthias Ringwald l2cap_le_finialize_channel_close(channel); // -- remove from list 2076*a254c508SMatthias Ringwald continue; 2077*a254c508SMatthias Ringwald default: 2078*a254c508SMatthias Ringwald continue; 2079*a254c508SMatthias Ringwald } 2080*a254c508SMatthias Ringwald 2081*a254c508SMatthias Ringwald // channel picked - setup cid array and collect info 2082*a254c508SMatthias Ringwald (void) memset(cids, 0xff, sizeof(cids)); 2083*a254c508SMatthias Ringwald (void) memset(cids, 0, channel->num_cids * sizeof(uint16_t)); 2084*a254c508SMatthias Ringwald matching_state = channel->state; 2085*a254c508SMatthias Ringwald con_handle = channel->con_handle; 2086*a254c508SMatthias Ringwald signaling_cid = channel->address_type == BD_ADDR_TYPE_ACL ? L2CAP_CID_SIGNALING : L2CAP_CID_SIGNALING_LE; 2087*a254c508SMatthias Ringwald num_cids = channel->num_cids; 2088*a254c508SMatthias Ringwald 2089*a254c508SMatthias Ringwald } else { 2090*a254c508SMatthias Ringwald // check if it matches first channel by state, con_handle, and signaling id 2091*a254c508SMatthias Ringwald if (matching_state != channel->state) continue; 2092*a254c508SMatthias Ringwald if (channel->con_handle != con_handle) continue; 2093*a254c508SMatthias Ringwald if (match_remote_sig_cid) { 2094*a254c508SMatthias Ringwald if (channel->remote_sig_id != sig_id) continue; 2095*a254c508SMatthias Ringwald } else { 2096*a254c508SMatthias Ringwald if (channel->local_sig_id != sig_id) continue; 2097*a254c508SMatthias Ringwald } 2098*a254c508SMatthias Ringwald } 2099*a254c508SMatthias Ringwald 2100*a254c508SMatthias Ringwald // add this cid 2101*a254c508SMatthias Ringwald cids[channel->cid_index] = channel->local_cid; 2102*a254c508SMatthias Ringwald 2103*a254c508SMatthias Ringwald // set new state 2104*a254c508SMatthias Ringwald channel->state = new_state; 2105*a254c508SMatthias Ringwald 2106*a254c508SMatthias Ringwald // handle open for L2CAP_STATE_WILL_SEND_ENHANCED_CONNECTION_RESPONSE 2107*a254c508SMatthias Ringwald if (matching_state == L2CAP_STATE_WILL_SEND_ENHANCED_CONNECTION_RESPONSE) { 2108*a254c508SMatthias Ringwald if (channel->reason == 0) { 2109*a254c508SMatthias Ringwald l2cap_emit_enhanced_data_channel_opened(channel, ERROR_CODE_SUCCESS); 2110*a254c508SMatthias Ringwald } else { 2111*a254c508SMatthias Ringwald result = channel->reason; 2112*a254c508SMatthias Ringwald btstack_linked_list_iterator_remove(&it); 2113*a254c508SMatthias Ringwald btstack_memory_l2cap_channel_free(channel); 2114*a254c508SMatthias Ringwald } 2115*a254c508SMatthias Ringwald } 2116*a254c508SMatthias Ringwald } 2117*a254c508SMatthias Ringwald 2118*a254c508SMatthias Ringwald if (con_handle != HCI_CON_HANDLE_INVALID) { 2119*a254c508SMatthias Ringwald // TODO: get MTU for both BR/EDR and LE 2120*a254c508SMatthias Ringwald uint16_t mps = btstack_min(l2cap_enhanced_mps_max, btstack_min(l2cap_max_le_mtu(), local_mtu)); 2121*a254c508SMatthias Ringwald switch (matching_state) { 2122*a254c508SMatthias Ringwald case L2CAP_STATE_WILL_SEND_ENHANCED_CONNECTION_REQUEST: 2123*a254c508SMatthias Ringwald log_info("send combined connection request for %u cids", num_cids); 2124*a254c508SMatthias Ringwald l2cap_send_general_signaling_packet(con_handle, signaling_cid, L2CAP_CREDIT_BASED_CONNECTION_REQUEST, 2125*a254c508SMatthias Ringwald sig_id, spsm, local_mtu, mps, initial_credits, cids); 2126*a254c508SMatthias Ringwald break; 2127*a254c508SMatthias Ringwald case L2CAP_STATE_WILL_SEND_ENHANCED_CONNECTION_RESPONSE: 2128*a254c508SMatthias Ringwald log_info("send combined connection response for %u cids", num_cids); 2129*a254c508SMatthias Ringwald l2cap_send_general_signaling_packet(con_handle, signaling_cid, L2CAP_CREDIT_BASED_CONNECTION_RESPONSE, 2130*a254c508SMatthias Ringwald sig_id, local_mtu, mps, initial_credits, result, cids); 2131*a254c508SMatthias Ringwald break; 2132*a254c508SMatthias Ringwald case L2CAP_STATE_WILL_SEND_EHNANCED_RENEGOTIATION_REQUEST: 2133*a254c508SMatthias Ringwald log_info("send combined renegotiation request for %u cids", num_cids); 2134*a254c508SMatthias Ringwald l2cap_send_general_signaling_packet(con_handle, signaling_cid, L2CAP_CREDIT_BASED_RECONFIGURE_REQUEST, 2135*a254c508SMatthias Ringwald sig_id, local_mtu, mps, cids); 2136*a254c508SMatthias Ringwald break; 2137*a254c508SMatthias Ringwald default: 2138*a254c508SMatthias Ringwald break; 2139*a254c508SMatthias Ringwald } 2140*a254c508SMatthias Ringwald } 2141*a254c508SMatthias Ringwald } 2142*a254c508SMatthias Ringwald #endif 2143*a254c508SMatthias Ringwald 2144ea6a43faSMatthias Ringwald // MARK: L2CAP_RUN 2145ea6a43faSMatthias Ringwald // process outstanding signaling tasks 2146ea6a43faSMatthias Ringwald static void l2cap_run(void){ 2147ea6a43faSMatthias Ringwald 2148ea6a43faSMatthias Ringwald // log_info("l2cap_run: entered"); 2149ea6a43faSMatthias Ringwald l2cap_run_signaling_response(); 2150ea6a43faSMatthias Ringwald 2151*a254c508SMatthias Ringwald #ifdef ENABLE_CLASSIC 21521901fae5SMatthias Ringwald bool done = l2ap_run_information_requests(); 2153ea6a43faSMatthias Ringwald if (done) return; 2154*a254c508SMatthias Ringwald #endif 2155ea6a43faSMatthias Ringwald 2156ea6a43faSMatthias Ringwald #if defined(ENABLE_CLASSIC) || defined(ENABLE_BLE) 2157ea6a43faSMatthias Ringwald btstack_linked_list_iterator_t it; 2158ea6a43faSMatthias Ringwald #endif 2159ea6a43faSMatthias Ringwald 2160ea6a43faSMatthias Ringwald #ifdef ENABLE_CLASSIC 2161ea6a43faSMatthias Ringwald btstack_linked_list_iterator_init(&it, &l2cap_channels); 2162ea6a43faSMatthias Ringwald while (btstack_linked_list_iterator_has_next(&it)){ 2163ea6a43faSMatthias Ringwald 2164ea6a43faSMatthias Ringwald l2cap_channel_t * channel = (l2cap_channel_t *) btstack_linked_list_iterator_next(&it); 2165ea6a43faSMatthias Ringwald 2166ea6a43faSMatthias Ringwald if (channel->channel_type != L2CAP_CHANNEL_TYPE_CLASSIC) continue; 2167ea6a43faSMatthias Ringwald 2168ea6a43faSMatthias Ringwald // log_info("l2cap_run: channel %p, state %u, var 0x%02x", channel, channel->state, channel->state_var); 2169c80ea152SMatthias Ringwald bool finalized = l2cap_run_for_classic_channel(channel); 2170c80ea152SMatthias Ringwald 2171c80ea152SMatthias Ringwald if (!finalized) { 2172c80ea152SMatthias Ringwald #ifdef ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE 2173c80ea152SMatthias Ringwald l2cap_run_for_classic_channel_ertm(channel); 2174c80ea152SMatthias Ringwald #endif 2175c80ea152SMatthias Ringwald } 2176ea6a43faSMatthias Ringwald } 2177ea6a43faSMatthias Ringwald #endif 2178ea6a43faSMatthias Ringwald 2179ea6a43faSMatthias Ringwald #ifdef ENABLE_LE_DATA_CHANNELS 2180ea6a43faSMatthias Ringwald l2cap_run_le_data_channels(); 218109e9d05bSMatthias Ringwald #endif 2182efedfb4cSMatthias Ringwald 2183*a254c508SMatthias Ringwald #ifdef ENABLE_L2CAP_ENHANCED_DATA_CHANNELS 2184*a254c508SMatthias Ringwald l2cap_run_enhanced_data_channels(); 2185*a254c508SMatthias Ringwald #endif 2186*a254c508SMatthias Ringwald 218709e9d05bSMatthias Ringwald #ifdef ENABLE_BLE 2188da886c03S[email protected] // send l2cap con paramter update if necessary 2189da886c03S[email protected] hci_connections_get_iterator(&it); 2190665d90f2SMatthias Ringwald while(btstack_linked_list_iterator_has_next(&it)){ 2191665d90f2SMatthias Ringwald hci_connection_t * connection = (hci_connection_t *) btstack_linked_list_iterator_next(&it); 2192c1ab6cc1SMatthias Ringwald if ((connection->address_type != BD_ADDR_TYPE_LE_PUBLIC) && (connection->address_type != BD_ADDR_TYPE_LE_RANDOM)) continue; 2193b68d7bc3SMatthias Ringwald if (!hci_can_send_acl_packet_now(connection->con_handle)) continue; 2194da886c03S[email protected] switch (connection->le_con_parameter_update_state){ 2195b68d7bc3SMatthias Ringwald case CON_PARAMETER_UPDATE_SEND_REQUEST: 2196b68d7bc3SMatthias Ringwald connection->le_con_parameter_update_state = CON_PARAMETER_UPDATE_NONE; 2197fe8aebe6SMatthias Ringwald l2cap_send_le_signaling_packet(connection->con_handle, CONNECTION_PARAMETER_UPDATE_REQUEST, l2cap_next_sig_id(), 2198b68d7bc3SMatthias Ringwald connection->le_conn_interval_min, connection->le_conn_interval_max, connection->le_conn_latency, connection->le_supervision_timeout); 2199b68d7bc3SMatthias Ringwald break; 2200da886c03S[email protected] case CON_PARAMETER_UPDATE_SEND_RESPONSE: 2201b68d7bc3SMatthias Ringwald connection->le_con_parameter_update_state = CON_PARAMETER_UPDATE_CHANGE_HCI_CON_PARAMETERS; 2202b68d7bc3SMatthias Ringwald l2cap_send_le_signaling_packet(connection->con_handle, CONNECTION_PARAMETER_UPDATE_RESPONSE, connection->le_con_param_update_identifier, 0); 2203da886c03S[email protected] break; 2204da886c03S[email protected] case CON_PARAMETER_UPDATE_DENY: 2205b68d7bc3SMatthias Ringwald connection->le_con_parameter_update_state = CON_PARAMETER_UPDATE_NONE; 2206b68d7bc3SMatthias Ringwald l2cap_send_le_signaling_packet(connection->con_handle, CONNECTION_PARAMETER_UPDATE_RESPONSE, connection->le_con_param_update_identifier, 1); 2207da886c03S[email protected] break; 2208da886c03S[email protected] default: 2209da886c03S[email protected] break; 2210da886c03S[email protected] } 2211da886c03S[email protected] } 22124d7157c3S[email protected] #endif 2213da886c03S[email protected] 2214*a254c508SMatthias Ringwald if (l2cap_call_notify_channel_in_run){ 2215*a254c508SMatthias Ringwald l2cap_call_notify_channel_in_run = false; 2216*a254c508SMatthias Ringwald l2cap_notify_channel_can_send(); 2217*a254c508SMatthias Ringwald } 2218*a254c508SMatthias Ringwald 221922c29ab4SMatthias Ringwald // log_info("l2cap_run: exit"); 22202cd0be45Smatthias.ringwald } 22212cd0be45Smatthias.ringwald 222209e9d05bSMatthias Ringwald #ifdef ENABLE_CLASSIC 22231b9cb13dSMatthias Ringwald static void l2cap_ready_to_connect(l2cap_channel_t * channel){ 22241b9cb13dSMatthias Ringwald 22251b9cb13dSMatthias Ringwald #ifdef ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE 2226d676fa4bSMatthias Ringwald // assumption: outgoing connection 2227d676fa4bSMatthias Ringwald if (channel->mode == L2CAP_CHANNEL_MODE_ENHANCED_RETRANSMISSION){ 2228d676fa4bSMatthias Ringwald // ERTM requested: trigger information request if not already started then wait for response 22291b9cb13dSMatthias Ringwald hci_connection_t * connection = hci_connection_for_handle(channel->con_handle); 22301b3d75ddSMatthias Ringwald switch (connection->l2cap_state.information_state){ 22311b3d75ddSMatthias Ringwald case L2CAP_INFORMATION_STATE_DONE: 22321b3d75ddSMatthias Ringwald break; 22331b3d75ddSMatthias Ringwald case L2CAP_INFORMATION_STATE_IDLE: 22341b9cb13dSMatthias Ringwald connection->l2cap_state.information_state = L2CAP_INFORMATION_STATE_W2_SEND_EXTENDED_FEATURE_REQUEST; 22351b3d75ddSMatthias Ringwald /* fall through */ 22361b3d75ddSMatthias Ringwald default: 22371b9cb13dSMatthias Ringwald channel->state = L2CAP_STATE_WAIT_OUTGOING_EXTENDED_FEATURES; 22381b9cb13dSMatthias Ringwald return; 22391b9cb13dSMatthias Ringwald } 2240d676fa4bSMatthias Ringwald } 22411b9cb13dSMatthias Ringwald #endif 22421b9cb13dSMatthias Ringwald 22431b9cb13dSMatthias Ringwald // fine, go ahead 22441b9cb13dSMatthias Ringwald channel->state = L2CAP_STATE_WILL_SEND_CONNECTION_REQUEST; 22451b9cb13dSMatthias Ringwald } 22461b9cb13dSMatthias Ringwald 2247c2ac1eb3SMatthias Ringwald static void l2cap_handle_connection_complete(hci_con_handle_t con_handle, l2cap_channel_t * channel){ 2248c2ac1eb3SMatthias Ringwald if ((channel->state == L2CAP_STATE_WAIT_CONNECTION_COMPLETE) || (channel->state == L2CAP_STATE_WILL_SEND_CREATE_CONNECTION)) { 2249c2ac1eb3SMatthias Ringwald log_info("connection complete con_handle %04x - for channel %p cid 0x%04x", (int) con_handle, channel, channel->local_cid); 2250c2ac1eb3SMatthias Ringwald channel->con_handle = con_handle; 2251c2ac1eb3SMatthias Ringwald // query remote features if pairing is required 2252c2ac1eb3SMatthias Ringwald if (channel->required_security_level > LEVEL_0){ 2253c2ac1eb3SMatthias Ringwald channel->state = L2CAP_STATE_WAIT_REMOTE_SUPPORTED_FEATURES; 2254c2ac1eb3SMatthias Ringwald hci_remote_features_query(con_handle); 2255c2ac1eb3SMatthias Ringwald } else { 2256c2ac1eb3SMatthias Ringwald l2cap_ready_to_connect(channel); 2257c2ac1eb3SMatthias Ringwald } 2258c2ac1eb3SMatthias Ringwald } 2259c2ac1eb3SMatthias Ringwald } 2260c2ac1eb3SMatthias Ringwald 22612df5dadcS[email protected] static void l2cap_handle_remote_supported_features_received(l2cap_channel_t * channel){ 22622df5dadcS[email protected] if (channel->state != L2CAP_STATE_WAIT_REMOTE_SUPPORTED_FEATURES) return; 22632076cfd2SMatthias Ringwald // double check if all feature pages are complete 22642076cfd2SMatthias Ringwald 22652076cfd2SMatthias Ringwald bool security_required = channel->required_security_level > LEVEL_0; 22662df5dadcS[email protected] 22675d5b5d8dSMatthias Ringwald // abort if Secure Connections Only Mode with legacy connection 22682076cfd2SMatthias Ringwald if (security_required && gap_get_secure_connections_only_mode() && gap_secure_connection(channel->con_handle) == 0){ 22695d5b5d8dSMatthias Ringwald l2cap_handle_channel_open_failed(channel, L2CAP_CONNECTION_RESPONSE_RESULT_REFUSED_SECURITY); 22705d5b5d8dSMatthias Ringwald btstack_linked_list_remove(&l2cap_channels, (btstack_linked_item_t *) channel); 22715d5b5d8dSMatthias Ringwald l2cap_free_channel_entry(channel); 22725d5b5d8dSMatthias Ringwald return; 22735d5b5d8dSMatthias Ringwald } 22745d5b5d8dSMatthias Ringwald 22752076cfd2SMatthias Ringwald if ((channel->state_var & L2CAP_CHANNEL_STATE_VAR_INCOMING) != 0){ 2276903b29f9SMatthias Ringwald 2277903b29f9SMatthias Ringwald // Core V5.2, Vol 3, Part C, 5.2.2.2 - Security Mode 4 2278903b29f9SMatthias Ringwald // When a remote device attempts to access a service offered by a Bluetooth device that is in security mode 4 2279903b29f9SMatthias Ringwald // and a sufficient link key exists and authentication has not been performed the local device shall authenticate 2280903b29f9SMatthias Ringwald // the remote device and enable encryption after the channel establishment request is received but before a channel 2281903b29f9SMatthias Ringwald // establishment confirmation (L2CAP_ConnectRsp with result code of 0x0000 or a higher-level channel establishment 2282903b29f9SMatthias Ringwald // confirmation such as that of RFCOMM) is sent. 2283903b29f9SMatthias Ringwald 2284903b29f9SMatthias Ringwald // If the remote device has indicated support for Secure Simple Pairing, a channel establishment request is 2285903b29f9SMatthias Ringwald // received for a service other than SDP, and encryption has not yet been enabled, then the local device shall 2286903b29f9SMatthias Ringwald // disconnect the ACL link with error code 0x05 - Authentication Failure. 2287903b29f9SMatthias Ringwald 2288903b29f9SMatthias Ringwald // => Disconnect if l2cap request received in mode 4 and ssp supported, non-sdp psm, not encrypted, no link key available 2289903b29f9SMatthias Ringwald if ((gap_get_security_mode() == GAP_SECURITY_MODE_4) 2290903b29f9SMatthias Ringwald && gap_ssp_supported_on_both_sides(channel->con_handle) 2291903b29f9SMatthias Ringwald && (channel->psm != PSM_SDP) 2292903b29f9SMatthias Ringwald && (gap_encryption_key_size(channel->con_handle) == 0) 2293903b29f9SMatthias Ringwald && (gap_bonded(channel->con_handle) == false)){ 2294903b29f9SMatthias Ringwald hci_disconnect_security_block(channel->con_handle); 2295903b29f9SMatthias Ringwald return; 2296903b29f9SMatthias Ringwald } 2297903b29f9SMatthias Ringwald 22982076cfd2SMatthias Ringwald // incoming: assert security requirements 22992076cfd2SMatthias Ringwald channel->state = L2CAP_STATE_WAIT_INCOMING_SECURITY_LEVEL_UPDATE; 23002076cfd2SMatthias Ringwald if (channel->required_security_level <= gap_security_level(channel->con_handle)){ 23012076cfd2SMatthias Ringwald l2cap_handle_security_level_incoming_sufficient(channel); 23022076cfd2SMatthias Ringwald } else { 23032076cfd2SMatthias Ringwald // send connection pending if not already done 23042076cfd2SMatthias Ringwald if ((channel->state_var & L2CAP_CHANNEL_STATE_VAR_SENT_CONN_RESP_PEND) == 0){ 23052076cfd2SMatthias Ringwald channel->state_var |= L2CAP_CHANNEL_STATE_VAR_SEND_CONN_RESP_PEND; 23062076cfd2SMatthias Ringwald } 23072076cfd2SMatthias Ringwald gap_request_security_level(channel->con_handle, channel->required_security_level); 23082076cfd2SMatthias Ringwald } 23092076cfd2SMatthias Ringwald } else { 23102076cfd2SMatthias Ringwald // outgoing: we have been waiting for remote supported features 23112076cfd2SMatthias Ringwald if (security_required){ 231224fd61d9SMatthias Ringwald // request security level 23132df5dadcS[email protected] channel->state = L2CAP_STATE_WAIT_OUTGOING_SECURITY_LEVEL_UPDATE; 231424fd61d9SMatthias Ringwald gap_request_security_level(channel->con_handle, channel->required_security_level); 23152076cfd2SMatthias Ringwald } else { 23161b9cb13dSMatthias Ringwald l2cap_ready_to_connect(channel); 23172df5dadcS[email protected] } 23182076cfd2SMatthias Ringwald } 23192076cfd2SMatthias Ringwald } 232009e9d05bSMatthias Ringwald #endif 23212df5dadcS[email protected] 232209e9d05bSMatthias Ringwald #ifdef L2CAP_USES_CHANNELS 23235d18f623SMatthias Ringwald static l2cap_channel_t * l2cap_create_channel_entry(btstack_packet_handler_t packet_handler, l2cap_channel_type_t channel_type, bd_addr_t address, bd_addr_type_t address_type, 2324da144af5SMatthias Ringwald uint16_t psm, uint16_t local_mtu, gap_security_level_t security_level){ 2325da144af5SMatthias Ringwald 2326da144af5SMatthias Ringwald l2cap_channel_t * channel = btstack_memory_l2cap_channel_get(); 2327da144af5SMatthias Ringwald if (!channel) { 2328da144af5SMatthias Ringwald return NULL; 2329da144af5SMatthias Ringwald } 2330da144af5SMatthias Ringwald 2331da144af5SMatthias Ringwald // fill in 2332da144af5SMatthias Ringwald channel->packet_handler = packet_handler; 23335d18f623SMatthias Ringwald channel->channel_type = channel_type; 2334da144af5SMatthias Ringwald bd_addr_copy(channel->address, address); 2335da144af5SMatthias Ringwald channel->address_type = address_type; 2336da144af5SMatthias Ringwald channel->psm = psm; 2337da144af5SMatthias Ringwald channel->local_mtu = local_mtu; 2338b37a9357SMatthias Ringwald channel->remote_mtu = L2CAP_DEFAULT_MTU; 2339da144af5SMatthias Ringwald channel->required_security_level = security_level; 2340da144af5SMatthias Ringwald 2341da144af5SMatthias Ringwald // 2342da144af5SMatthias Ringwald channel->local_cid = l2cap_next_local_cid(); 2343e0780573SMatthias Ringwald channel->con_handle = HCI_CON_HANDLE_INVALID; 2344da144af5SMatthias Ringwald 2345da144af5SMatthias Ringwald // set initial state 2346da144af5SMatthias Ringwald channel->state = L2CAP_STATE_WILL_SEND_CREATE_CONNECTION; 2347da144af5SMatthias Ringwald channel->state_var = L2CAP_CHANNEL_STATE_VAR_NONE; 2348da144af5SMatthias Ringwald channel->remote_sig_id = L2CAP_SIG_ID_INVALID; 2349da144af5SMatthias Ringwald channel->local_sig_id = L2CAP_SIG_ID_INVALID; 235038f62777SMatthias Ringwald 2351c45d6b2cSMatthias Ringwald log_info("create channel %p, local_cid 0x%04x", channel, channel->local_cid); 2352e5ac0afcSMatthias Ringwald 2353da144af5SMatthias Ringwald return channel; 2354da144af5SMatthias Ringwald } 2355c45d6b2cSMatthias Ringwald 2356c45d6b2cSMatthias Ringwald static void l2cap_free_channel_entry(l2cap_channel_t * channel){ 2357c45d6b2cSMatthias Ringwald log_info("free channel %p, local_cid 0x%04x", channel, channel->local_cid); 23588f4dd6c1SMatthias Ringwald // assert all timers are stopped 2359b5bab9c8SMatthias Ringwald l2cap_stop_rtx(channel); 23608f4dd6c1SMatthias Ringwald #ifdef ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE 23618f4dd6c1SMatthias Ringwald l2cap_ertm_stop_retransmission_timer(channel); 23628f4dd6c1SMatthias Ringwald l2cap_ertm_stop_monitor_timer(channel); 23638f4dd6c1SMatthias Ringwald #endif 2364b5bab9c8SMatthias Ringwald // free memory 2365c45d6b2cSMatthias Ringwald btstack_memory_l2cap_channel_free(channel); 2366c45d6b2cSMatthias Ringwald } 236709e9d05bSMatthias Ringwald #endif 236809e9d05bSMatthias Ringwald 236909e9d05bSMatthias Ringwald #ifdef ENABLE_CLASSIC 2370da144af5SMatthias Ringwald 23719077cb15SMatthias Ringwald /** 23729077cb15SMatthias Ringwald * @brief Creates L2CAP channel to the PSM of a remote device with baseband address. A new baseband connection will be initiated if necessary. 23739077cb15SMatthias Ringwald * @param packet_handler 23749077cb15SMatthias Ringwald * @param address 23759077cb15SMatthias Ringwald * @param psm 23769077cb15SMatthias Ringwald * @param mtu 23779077cb15SMatthias Ringwald * @param local_cid 23789077cb15SMatthias Ringwald */ 23799077cb15SMatthias Ringwald 23809d139fbaSMatthias Ringwald uint8_t l2cap_create_channel(btstack_packet_handler_t channel_packet_handler, bd_addr_t address, uint16_t psm, uint16_t mtu, uint16_t * out_local_cid){ 238124fd61d9SMatthias Ringwald // limit MTU to the size of our outgoing HCI buffer 23829d139fbaSMatthias Ringwald uint16_t local_mtu = btstack_min(mtu, l2cap_max_mtu()); 2383da144af5SMatthias Ringwald 238424fd61d9SMatthias Ringwald // determine security level based on psm 238524fd61d9SMatthias Ringwald const gap_security_level_t security_level = l2cap_security_level_0_allowed_for_PSM(psm) ? LEVEL_0 : gap_get_security_level(); 238685621840SMilanka Ringwald log_info("create channel addr %s psm 0x%x mtu %u -> local mtu %u, sec level %u", bd_addr_to_str(address), psm, mtu, local_mtu, (int) security_level); 2387da144af5SMatthias Ringwald 238824fd61d9SMatthias Ringwald l2cap_channel_t * channel = l2cap_create_channel_entry(channel_packet_handler, L2CAP_CHANNEL_TYPE_CLASSIC, address, BD_ADDR_TYPE_ACL, psm, local_mtu, security_level); 2389fc64f94aSMatthias Ringwald if (!channel) { 23909077cb15SMatthias Ringwald return BTSTACK_MEMORY_ALLOC_FAILED; 23919077cb15SMatthias Ringwald } 23929077cb15SMatthias Ringwald 23931b9cb13dSMatthias Ringwald #ifdef ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE 23941b9cb13dSMatthias Ringwald channel->mode = L2CAP_CHANNEL_MODE_BASIC; 23951b9cb13dSMatthias Ringwald #endif 23961b9cb13dSMatthias Ringwald 23979077cb15SMatthias Ringwald // add to connections list 2398da4c2b27SMatthias Ringwald btstack_linked_list_add_tail(&l2cap_channels, (btstack_linked_item_t *) channel); 23999077cb15SMatthias Ringwald 24009077cb15SMatthias Ringwald // store local_cid 24019077cb15SMatthias Ringwald if (out_local_cid){ 2402fc64f94aSMatthias Ringwald *out_local_cid = channel->local_cid; 24039077cb15SMatthias Ringwald } 24049077cb15SMatthias Ringwald 240524fd61d9SMatthias Ringwald // state: L2CAP_STATE_WILL_SEND_CREATE_CONNECTION 240624fd61d9SMatthias Ringwald 240724fd61d9SMatthias Ringwald // check if hci connection is already usable, 2408f16129ceSMatthias Ringwald hci_connection_t * conn = hci_connection_for_bd_addr_and_type(address, BD_ADDR_TYPE_ACL); 2409a536dfccSMatthias Ringwald if (conn && conn->state == OPEN){ 241024fd61d9SMatthias Ringwald // simulate connection complete 2411fc64f94aSMatthias Ringwald l2cap_handle_connection_complete(conn->con_handle, channel); 241224fd61d9SMatthias Ringwald 2413c2ac1eb3SMatthias Ringwald // state: L2CAP_STATE_WAIT_REMOTE_SUPPORTED_FEATURES or L2CAP_STATE_WILL_SEND_CONNECTION_REQUEST 241424fd61d9SMatthias Ringwald 2415c2ac1eb3SMatthias Ringwald // simulate if remote supported features if requested and already received 2416c2ac1eb3SMatthias Ringwald if ((channel->state == L2CAP_STATE_WAIT_REMOTE_SUPPORTED_FEATURES) && hci_remote_features_available(conn->con_handle)) { 241724fd61d9SMatthias Ringwald // simulate remote features received 2418fc64f94aSMatthias Ringwald l2cap_handle_remote_supported_features_received(channel); 24199077cb15SMatthias Ringwald } 24209077cb15SMatthias Ringwald } 24219077cb15SMatthias Ringwald 24229077cb15SMatthias Ringwald l2cap_run(); 24239077cb15SMatthias Ringwald 2424c8b2b785SMilanka Ringwald return ERROR_CODE_SUCCESS; 24259077cb15SMatthias Ringwald } 24269077cb15SMatthias Ringwald 24271ea99aafSMilanka Ringwald void l2cap_disconnect(uint16_t local_cid, uint8_t reason){ 242885621840SMilanka Ringwald log_info("disconnect local_cid 0x%x reason 0x%x", local_cid, reason); 24298e95beceSMatthias Ringwald UNUSED(reason); 2430b35f641cSmatthias.ringwald // find channel for local_cid 2431b35f641cSmatthias.ringwald l2cap_channel_t * channel = l2cap_get_channel_for_local_cid(local_cid); 2432f62db1e3Smatthias.ringwald if (channel) { 2433e7ff783cSmatthias.ringwald channel->state = L2CAP_STATE_WILL_SEND_DISCONNECT_REQUEST; 2434f62db1e3Smatthias.ringwald } 24352cd0be45Smatthias.ringwald // process 24362cd0be45Smatthias.ringwald l2cap_run(); 243743625864Smatthias.ringwald } 24381e6aba47Smatthias.ringwald 2439afde0c52Smatthias.ringwald static void l2cap_handle_connection_failed_for_addr(bd_addr_t address, uint8_t status){ 2440ceec418aSMatthias Ringwald // mark all channels before emitting open events as these could trigger new connetion requests to the same device 2441665d90f2SMatthias Ringwald btstack_linked_list_iterator_t it; 2442665d90f2SMatthias Ringwald btstack_linked_list_iterator_init(&it, &l2cap_channels); 2443665d90f2SMatthias Ringwald while (btstack_linked_list_iterator_has_next(&it)){ 2444665d90f2SMatthias Ringwald l2cap_channel_t * channel = (l2cap_channel_t *) btstack_linked_list_iterator_next(&it); 2445fad84cafSMatthias Ringwald if (!l2cap_is_dynamic_channel_type(channel->channel_type)) continue; 2446058e3d6bSMatthias Ringwald if (bd_addr_cmp( channel->address, address) != 0) continue; 2447c22aecc9S[email protected] // channel for this address found 2448c22aecc9S[email protected] switch (channel->state){ 2449c22aecc9S[email protected] case L2CAP_STATE_WAIT_CONNECTION_COMPLETE: 2450c22aecc9S[email protected] case L2CAP_STATE_WILL_SEND_CREATE_CONNECTION: 2451ceec418aSMatthias Ringwald channel->state = L2CAP_STATE_EMIT_OPEN_FAILED_AND_DISCARD; 2452c22aecc9S[email protected] break; 2453c22aecc9S[email protected] default: 2454c22aecc9S[email protected] break; 2455afde0c52Smatthias.ringwald } 2456afde0c52Smatthias.ringwald } 2457ceec418aSMatthias Ringwald // emit and free marked entries. restart loop to deal with list changes 2458ceec418aSMatthias Ringwald int done = 0; 2459ceec418aSMatthias Ringwald while (!done) { 2460ceec418aSMatthias Ringwald done = 1; 2461ceec418aSMatthias Ringwald btstack_linked_list_iterator_init(&it, &l2cap_channels); 2462ceec418aSMatthias Ringwald while (btstack_linked_list_iterator_has_next(&it)){ 2463ceec418aSMatthias Ringwald l2cap_channel_t * channel = (l2cap_channel_t *) btstack_linked_list_iterator_next(&it); 2464fad84cafSMatthias Ringwald if (!l2cap_is_dynamic_channel_type(channel->channel_type)) continue; 2465ceec418aSMatthias Ringwald if (channel->state == L2CAP_STATE_EMIT_OPEN_FAILED_AND_DISCARD){ 2466ceec418aSMatthias Ringwald done = 0; 2467ceec418aSMatthias Ringwald // failure, forward error code 246866a72640SMatthias Ringwald l2cap_handle_channel_open_failed(channel, status); 2469ceec418aSMatthias Ringwald // discard channel 2470ceec418aSMatthias Ringwald btstack_linked_list_remove(&l2cap_channels, (btstack_linked_item_t *) channel); 2471c45d6b2cSMatthias Ringwald l2cap_free_channel_entry(channel); 2472ceec418aSMatthias Ringwald break; 2473ceec418aSMatthias Ringwald } 2474ceec418aSMatthias Ringwald } 2475ceec418aSMatthias Ringwald } 2476ceec418aSMatthias Ringwald 2477afde0c52Smatthias.ringwald } 2478afde0c52Smatthias.ringwald 2479afde0c52Smatthias.ringwald static void l2cap_handle_connection_success_for_addr(bd_addr_t address, hci_con_handle_t handle){ 2480665d90f2SMatthias Ringwald btstack_linked_list_iterator_t it; 2481665d90f2SMatthias Ringwald btstack_linked_list_iterator_init(&it, &l2cap_channels); 2482665d90f2SMatthias Ringwald while (btstack_linked_list_iterator_has_next(&it)){ 2483665d90f2SMatthias Ringwald l2cap_channel_t * channel = (l2cap_channel_t *) btstack_linked_list_iterator_next(&it); 2484fad84cafSMatthias Ringwald if (!l2cap_is_dynamic_channel_type(channel->channel_type)) continue; 2485058e3d6bSMatthias Ringwald if ( ! bd_addr_cmp( channel->address, address) ){ 24862df5dadcS[email protected] l2cap_handle_connection_complete(handle, channel); 2487afde0c52Smatthias.ringwald } 2488afde0c52Smatthias.ringwald } 24896fdcc387Smatthias.ringwald // process 24906fdcc387Smatthias.ringwald l2cap_run(); 2491afde0c52Smatthias.ringwald } 249209e9d05bSMatthias Ringwald #endif 2493b448a0e7Smatthias.ringwald 24946774d5c9SMatthias Ringwald static bool l2cap_channel_ready_to_send(l2cap_channel_t * channel){ 24956774d5c9SMatthias Ringwald switch (channel->channel_type){ 24966774d5c9SMatthias Ringwald #ifdef ENABLE_CLASSIC 24976774d5c9SMatthias Ringwald case L2CAP_CHANNEL_TYPE_CLASSIC: 24984fc83f45SMatthias Ringwald if (channel->state != L2CAP_STATE_OPEN) return false; 24996774d5c9SMatthias Ringwald #ifdef ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE 2500d89ab698SMatthias Ringwald // send if we have more data and remote windows isn't full yet 2501d89ab698SMatthias Ringwald if (channel->mode == L2CAP_CHANNEL_MODE_ENHANCED_RETRANSMISSION) { 2502d89ab698SMatthias Ringwald if (channel->unacked_frames >= btstack_min(channel->num_stored_tx_frames, channel->remote_tx_window_size)) return false; 25036774d5c9SMatthias Ringwald return hci_can_send_acl_classic_packet_now() != 0; 2504d89ab698SMatthias Ringwald } 2505d89ab698SMatthias Ringwald #endif 2506d89ab698SMatthias Ringwald if (!channel->waiting_for_can_send_now) return false; 2507d89ab698SMatthias Ringwald return (hci_can_send_acl_classic_packet_now() != 0); 25086774d5c9SMatthias Ringwald case L2CAP_CHANNEL_TYPE_CONNECTIONLESS: 25096774d5c9SMatthias Ringwald if (!channel->waiting_for_can_send_now) return false; 25106774d5c9SMatthias Ringwald return hci_can_send_acl_classic_packet_now() != 0; 25116774d5c9SMatthias Ringwald #endif 25126774d5c9SMatthias Ringwald #ifdef ENABLE_BLE 2513904f1e16SMatthias Ringwald case L2CAP_CHANNEL_TYPE_FIXED: 25146774d5c9SMatthias Ringwald if (!channel->waiting_for_can_send_now) return false; 25156774d5c9SMatthias Ringwald return hci_can_send_acl_le_packet_now() != 0; 25166774d5c9SMatthias Ringwald #ifdef ENABLE_LE_DATA_CHANNELS 25176774d5c9SMatthias Ringwald case L2CAP_CHANNEL_TYPE_LE_DATA_CHANNEL: 25184fc83f45SMatthias Ringwald if (channel->state != L2CAP_STATE_OPEN) return false; 25196774d5c9SMatthias Ringwald if (channel->send_sdu_buffer == NULL) return false; 25204ea43905SMatthias Ringwald if (channel->credits_outgoing == 0u) return false; 25216774d5c9SMatthias Ringwald return hci_can_send_acl_le_packet_now() != 0; 25226774d5c9SMatthias Ringwald #endif 25236774d5c9SMatthias Ringwald #endif 2524*a254c508SMatthias Ringwald #ifdef ENABLE_L2CAP_ENHANCED_DATA_CHANNELS 2525*a254c508SMatthias Ringwald case L2CAP_CHANNEL_TYPE_ENHANCED_DATA_CHANNEL: 2526*a254c508SMatthias Ringwald if (channel->state != L2CAP_STATE_OPEN) return false; 2527*a254c508SMatthias Ringwald if (channel->send_sdu_buffer == NULL) return false; 2528*a254c508SMatthias Ringwald if (channel->credits_outgoing == 0u) return false; 2529*a254c508SMatthias Ringwald if (channel->address_type == BD_ADDR_TYPE_ACL) { 2530*a254c508SMatthias Ringwald return hci_can_send_acl_classic_packet_now() != 0; 2531*a254c508SMatthias Ringwald } else { 2532*a254c508SMatthias Ringwald return hci_can_send_acl_le_packet_now() != 0; 2533*a254c508SMatthias Ringwald } 2534*a254c508SMatthias Ringwald #endif 25356774d5c9SMatthias Ringwald default: 25366774d5c9SMatthias Ringwald return false; 25376774d5c9SMatthias Ringwald } 25386774d5c9SMatthias Ringwald } 25396774d5c9SMatthias Ringwald 25406774d5c9SMatthias Ringwald static void l2cap_channel_trigger_send(l2cap_channel_t * channel){ 25416774d5c9SMatthias Ringwald switch (channel->channel_type){ 2542d89ab698SMatthias Ringwald #ifdef ENABLE_CLASSIC 2543d89ab698SMatthias Ringwald case L2CAP_CHANNEL_TYPE_CLASSIC: 2544d89ab698SMatthias Ringwald #ifdef ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE 2545d89ab698SMatthias Ringwald if (channel->mode == L2CAP_CHANNEL_MODE_ENHANCED_RETRANSMISSION) { 2546d89ab698SMatthias Ringwald l2cap_ertm_channel_send_information_frame(channel); 2547d89ab698SMatthias Ringwald return; 2548d89ab698SMatthias Ringwald } 2549d89ab698SMatthias Ringwald #endif 2550d89ab698SMatthias Ringwald channel->waiting_for_can_send_now = 0; 2551d89ab698SMatthias Ringwald l2cap_emit_can_send_now(channel->packet_handler, channel->local_cid); 2552d89ab698SMatthias Ringwald break; 2553d89ab698SMatthias Ringwald case L2CAP_CHANNEL_TYPE_CONNECTIONLESS: 2554d89ab698SMatthias Ringwald channel->waiting_for_can_send_now = 0; 2555d89ab698SMatthias Ringwald l2cap_emit_can_send_now(channel->packet_handler, channel->local_cid); 2556d89ab698SMatthias Ringwald break; 2557d89ab698SMatthias Ringwald #endif 25586774d5c9SMatthias Ringwald #ifdef ENABLE_BLE 2559904f1e16SMatthias Ringwald case L2CAP_CHANNEL_TYPE_FIXED: 2560d89ab698SMatthias Ringwald channel->waiting_for_can_send_now = 0; 2561d89ab698SMatthias Ringwald l2cap_emit_can_send_now(channel->packet_handler, channel->local_cid); 2562d89ab698SMatthias Ringwald break; 2563*a254c508SMatthias Ringwald #endif 25646774d5c9SMatthias Ringwald #ifdef ENABLE_LE_DATA_CHANNELS 25656774d5c9SMatthias Ringwald case L2CAP_CHANNEL_TYPE_LE_DATA_CHANNEL: 2566*a254c508SMatthias Ringwald l2cap_credit_based_send_pdu(channel); 25676774d5c9SMatthias Ringwald break; 25686774d5c9SMatthias Ringwald #endif 2569*a254c508SMatthias Ringwald #ifdef ENABLE_L2CAP_ENHANCED_DATA_CHANNELS 2570*a254c508SMatthias Ringwald case L2CAP_CHANNEL_TYPE_ENHANCED_DATA_CHANNEL: 2571*a254c508SMatthias Ringwald l2cap_credit_based_send_pdu(channel); 2572*a254c508SMatthias Ringwald break; 25736774d5c9SMatthias Ringwald #endif 25746774d5c9SMatthias Ringwald default: 25756774d5c9SMatthias Ringwald break; 25766774d5c9SMatthias Ringwald } 25776774d5c9SMatthias Ringwald } 25786774d5c9SMatthias Ringwald 257933c40538SMatthias Ringwald static void l2cap_notify_channel_can_send(void){ 25806774d5c9SMatthias Ringwald bool done = false; 25817740e150SMatthias Ringwald while (!done){ 25826774d5c9SMatthias Ringwald done = true; 258333c40538SMatthias Ringwald btstack_linked_list_iterator_t it; 258433c40538SMatthias Ringwald btstack_linked_list_iterator_init(&it, &l2cap_channels); 258533c40538SMatthias Ringwald while (btstack_linked_list_iterator_has_next(&it)){ 258633c40538SMatthias Ringwald l2cap_channel_t * channel = (l2cap_channel_t *) btstack_linked_list_iterator_next(&it); 25876774d5c9SMatthias Ringwald bool ready = l2cap_channel_ready_to_send(channel); 25886774d5c9SMatthias Ringwald if (!ready) continue; 25896774d5c9SMatthias Ringwald 25906774d5c9SMatthias Ringwald // requeue channel for fairness 25917740e150SMatthias Ringwald btstack_linked_list_remove(&l2cap_channels, (btstack_linked_item_t *) channel); 25927740e150SMatthias Ringwald btstack_linked_list_add_tail(&l2cap_channels, (btstack_linked_item_t *) channel); 25936774d5c9SMatthias Ringwald 25946774d5c9SMatthias Ringwald // trigger sending 25956774d5c9SMatthias Ringwald l2cap_channel_trigger_send(channel); 25966774d5c9SMatthias Ringwald 25977740e150SMatthias Ringwald // exit inner loop as we just broke the iterator, but try again 25986774d5c9SMatthias Ringwald done = false; 25997740e150SMatthias Ringwald break; 26007740e150SMatthias Ringwald } 260133c40538SMatthias Ringwald } 260233c40538SMatthias Ringwald } 260333c40538SMatthias Ringwald 26042053036dSMatthias Ringwald #ifdef L2CAP_USES_CHANNELS 26052053036dSMatthias Ringwald 26062053036dSMatthias Ringwald static int l2cap_send_open_failed_on_hci_disconnect(l2cap_channel_t * channel){ 26072053036dSMatthias Ringwald // open cannot fail for for incoming connections 26082053036dSMatthias Ringwald if (channel->state_var & L2CAP_CHANNEL_STATE_VAR_INCOMING) return 0; 26092053036dSMatthias Ringwald 26102053036dSMatthias Ringwald // check state 26112053036dSMatthias Ringwald switch (channel->state){ 26122053036dSMatthias Ringwald case L2CAP_STATE_WILL_SEND_CREATE_CONNECTION: 26132053036dSMatthias Ringwald case L2CAP_STATE_WAIT_CONNECTION_COMPLETE: 26142053036dSMatthias Ringwald case L2CAP_STATE_WAIT_REMOTE_SUPPORTED_FEATURES: 26152053036dSMatthias Ringwald case L2CAP_STATE_WAIT_OUTGOING_SECURITY_LEVEL_UPDATE: 26162053036dSMatthias Ringwald case L2CAP_STATE_WAIT_CLIENT_ACCEPT_OR_REJECT: 26172053036dSMatthias Ringwald case L2CAP_STATE_WAIT_OUTGOING_EXTENDED_FEATURES: 26182053036dSMatthias Ringwald case L2CAP_STATE_WAIT_CONNECT_RSP: 26192053036dSMatthias Ringwald case L2CAP_STATE_CONFIG: 26202053036dSMatthias Ringwald case L2CAP_STATE_WILL_SEND_CONNECTION_REQUEST: 26212053036dSMatthias Ringwald case L2CAP_STATE_WILL_SEND_LE_CONNECTION_REQUEST: 26222053036dSMatthias Ringwald case L2CAP_STATE_WAIT_LE_CONNECTION_RESPONSE: 2623ceec418aSMatthias Ringwald case L2CAP_STATE_EMIT_OPEN_FAILED_AND_DISCARD: 26242053036dSMatthias Ringwald return 1; 26252053036dSMatthias Ringwald 26262053036dSMatthias Ringwald case L2CAP_STATE_OPEN: 26272053036dSMatthias Ringwald case L2CAP_STATE_CLOSED: 26282053036dSMatthias Ringwald case L2CAP_STATE_WAIT_INCOMING_EXTENDED_FEATURES: 26292053036dSMatthias Ringwald case L2CAP_STATE_WAIT_DISCONNECT: 26302053036dSMatthias Ringwald case L2CAP_STATE_WILL_SEND_CONNECTION_RESPONSE_INSUFFICIENT_SECURITY: 26312053036dSMatthias Ringwald case L2CAP_STATE_WILL_SEND_CONNECTION_RESPONSE_DECLINE: 26322053036dSMatthias Ringwald case L2CAP_STATE_WILL_SEND_CONNECTION_RESPONSE_ACCEPT: 26332053036dSMatthias Ringwald case L2CAP_STATE_WILL_SEND_DISCONNECT_REQUEST: 26342053036dSMatthias Ringwald case L2CAP_STATE_WILL_SEND_DISCONNECT_RESPONSE: 26352053036dSMatthias Ringwald case L2CAP_STATE_WILL_SEND_LE_CONNECTION_RESPONSE_DECLINE: 26362053036dSMatthias Ringwald case L2CAP_STATE_WILL_SEND_LE_CONNECTION_RESPONSE_ACCEPT: 26372053036dSMatthias Ringwald case L2CAP_STATE_INVALID: 26382053036dSMatthias Ringwald case L2CAP_STATE_WAIT_INCOMING_SECURITY_LEVEL_UPDATE: 26392053036dSMatthias Ringwald return 0; 26407bbeb3adSMilanka Ringwald 26417bbeb3adSMilanka Ringwald default: 26427bbeb3adSMilanka Ringwald // get a "warning" about new states 26437bbeb3adSMilanka Ringwald btstack_assert(false); 26446aa7d794SMatthias Ringwald return 0; 26452053036dSMatthias Ringwald } 26467bbeb3adSMilanka Ringwald } 264713aa3e4bSMatthias Ringwald #endif 26482053036dSMatthias Ringwald 264913aa3e4bSMatthias Ringwald #ifdef ENABLE_CLASSIC 26502053036dSMatthias Ringwald static void l2cap_handle_hci_disconnect_event(l2cap_channel_t * channel){ 26512053036dSMatthias Ringwald if (l2cap_send_open_failed_on_hci_disconnect(channel)){ 265266a72640SMatthias Ringwald l2cap_handle_channel_open_failed(channel, L2CAP_CONNECTION_BASEBAND_DISCONNECT); 26532053036dSMatthias Ringwald } else { 265466a72640SMatthias Ringwald l2cap_handle_channel_closed(channel); 26552053036dSMatthias Ringwald } 2656c45d6b2cSMatthias Ringwald l2cap_free_channel_entry(channel); 26572053036dSMatthias Ringwald } 26582053036dSMatthias Ringwald #endif 26592053036dSMatthias Ringwald 26602cf36df7SMatthias Ringwald #ifdef ENABLE_LE_DATA_CHANNELS 26612cf36df7SMatthias Ringwald static void l2cap_handle_hci_le_disconnect_event(l2cap_channel_t * channel){ 26622cf36df7SMatthias Ringwald if (l2cap_send_open_failed_on_hci_disconnect(channel)){ 26632cf36df7SMatthias Ringwald l2cap_emit_le_channel_opened(channel, L2CAP_CONNECTION_BASEBAND_DISCONNECT); 26642cf36df7SMatthias Ringwald } else { 26652cf36df7SMatthias Ringwald l2cap_emit_le_channel_closed(channel); 26662cf36df7SMatthias Ringwald } 2667c45d6b2cSMatthias Ringwald l2cap_free_channel_entry(channel); 26682cf36df7SMatthias Ringwald } 26692cf36df7SMatthias Ringwald #endif 26702053036dSMatthias Ringwald 2671298c2fecSMatthias Ringwald #ifdef ENABLE_CLASSIC 2672298c2fecSMatthias Ringwald static void l2cap_check_classic_timeout(hci_con_handle_t handle){ 2673298c2fecSMatthias Ringwald if (gap_get_connection_type(handle) != GAP_CONNECTION_ACL) { 2674298c2fecSMatthias Ringwald return; 2675298c2fecSMatthias Ringwald } 2676298c2fecSMatthias Ringwald if (hci_authentication_active_for_handle(handle)) { 2677298c2fecSMatthias Ringwald return; 2678298c2fecSMatthias Ringwald } 2679298c2fecSMatthias Ringwald bool hci_con_used = false; 2680298c2fecSMatthias Ringwald btstack_linked_list_iterator_t it; 2681298c2fecSMatthias Ringwald btstack_linked_list_iterator_init(&it, &l2cap_channels); 2682298c2fecSMatthias Ringwald while (btstack_linked_list_iterator_has_next(&it)){ 2683298c2fecSMatthias Ringwald l2cap_channel_t * channel = (l2cap_channel_t *) btstack_linked_list_iterator_next(&it); 2684298c2fecSMatthias Ringwald if (!l2cap_is_dynamic_channel_type(channel->channel_type)) continue; 2685298c2fecSMatthias Ringwald if (channel->con_handle != handle) continue; 2686298c2fecSMatthias Ringwald hci_con_used = true; 2687298c2fecSMatthias Ringwald break; 2688298c2fecSMatthias Ringwald } 2689298c2fecSMatthias Ringwald if (hci_con_used) { 2690298c2fecSMatthias Ringwald return; 2691298c2fecSMatthias Ringwald } 2692298c2fecSMatthias Ringwald if (!hci_can_send_command_packet_now()) { 2693298c2fecSMatthias Ringwald return; 2694298c2fecSMatthias Ringwald } 2695298c2fecSMatthias Ringwald hci_send_cmd(&hci_disconnect, handle, 0x13); // remote closed connection 2696298c2fecSMatthias Ringwald } 26972076cfd2SMatthias Ringwald 2698298c2fecSMatthias Ringwald static void l2cap_handle_features_complete(hci_con_handle_t handle){ 26996ffc78ceSMatthias Ringwald if (hci_remote_features_available(handle) == false){ 2700298c2fecSMatthias Ringwald return; 2701298c2fecSMatthias Ringwald } 2702298c2fecSMatthias Ringwald btstack_linked_list_iterator_t it; 2703298c2fecSMatthias Ringwald btstack_linked_list_iterator_init(&it, &l2cap_channels); 2704298c2fecSMatthias Ringwald while (btstack_linked_list_iterator_has_next(&it)){ 2705298c2fecSMatthias Ringwald l2cap_channel_t * channel = (l2cap_channel_t *) btstack_linked_list_iterator_next(&it); 2706298c2fecSMatthias Ringwald if (!l2cap_is_dynamic_channel_type(channel->channel_type)) continue; 2707298c2fecSMatthias Ringwald if (channel->con_handle != handle) continue; 2708298c2fecSMatthias Ringwald log_info("remote supported features, channel %p, cid %04x - state %u", channel, channel->local_cid, channel->state); 2709298c2fecSMatthias Ringwald l2cap_handle_remote_supported_features_received(channel); 2710298c2fecSMatthias Ringwald } 2711298c2fecSMatthias Ringwald } 2712fd0e4a3aSMatthias Ringwald 2713fd0e4a3aSMatthias Ringwald static void l2cap_handle_security_level_incoming_sufficient(l2cap_channel_t * channel){ 2714fd0e4a3aSMatthias Ringwald channel->state = L2CAP_STATE_WAIT_CLIENT_ACCEPT_OR_REJECT; 2715fd0e4a3aSMatthias Ringwald l2cap_emit_incoming_connection(channel); 2716fd0e4a3aSMatthias Ringwald } 2717fd0e4a3aSMatthias Ringwald 2718298c2fecSMatthias Ringwald static void l2cap_handle_security_level(hci_con_handle_t handle, gap_security_level_t actual_level){ 271985621840SMilanka Ringwald log_info("security level update for handle 0x%04x", handle); 27201b3d75ddSMatthias Ringwald 27211b3d75ddSMatthias Ringwald // trigger l2cap information requests 27221b3d75ddSMatthias Ringwald if (actual_level > LEVEL_0){ 27231b3d75ddSMatthias Ringwald hci_connection_t * hci_connection = hci_connection_for_handle(handle); 27241b3d75ddSMatthias Ringwald btstack_assert(hci_connection != NULL); 27251b3d75ddSMatthias Ringwald if (hci_connection->l2cap_state.information_state == L2CAP_INFORMATION_STATE_IDLE){ 27261b3d75ddSMatthias Ringwald hci_connection->l2cap_state.information_state = L2CAP_INFORMATION_STATE_W2_SEND_EXTENDED_FEATURE_REQUEST; 27271b3d75ddSMatthias Ringwald } 27281b3d75ddSMatthias Ringwald } 27291b3d75ddSMatthias Ringwald 2730298c2fecSMatthias Ringwald btstack_linked_list_iterator_t it; 2731298c2fecSMatthias Ringwald btstack_linked_list_iterator_init(&it, &l2cap_channels); 2732298c2fecSMatthias Ringwald while (btstack_linked_list_iterator_has_next(&it)){ 2733298c2fecSMatthias Ringwald l2cap_channel_t * channel = (l2cap_channel_t *) btstack_linked_list_iterator_next(&it); 2734298c2fecSMatthias Ringwald if (!l2cap_is_dynamic_channel_type(channel->channel_type)) continue; 2735298c2fecSMatthias Ringwald if (channel->con_handle != handle) continue; 2736298c2fecSMatthias Ringwald 2737298c2fecSMatthias Ringwald gap_security_level_t required_level = channel->required_security_level; 2738298c2fecSMatthias Ringwald 2739298c2fecSMatthias Ringwald log_info("channel %p, cid %04x - state %u: actual %u >= required %u?", channel, channel->local_cid, channel->state, actual_level, required_level); 2740298c2fecSMatthias Ringwald 2741298c2fecSMatthias Ringwald switch (channel->state){ 2742298c2fecSMatthias Ringwald case L2CAP_STATE_WAIT_INCOMING_SECURITY_LEVEL_UPDATE: 2743d7387af3SMatthias Ringwald if (actual_level >= required_level){ 2744fd0e4a3aSMatthias Ringwald l2cap_handle_security_level_incoming_sufficient(channel); 2745298c2fecSMatthias Ringwald } else { 2746298c2fecSMatthias Ringwald channel->reason = 0x0003; // security block 2747298c2fecSMatthias Ringwald channel->state = L2CAP_STATE_WILL_SEND_CONNECTION_RESPONSE_DECLINE; 2748298c2fecSMatthias Ringwald } 2749298c2fecSMatthias Ringwald break; 2750298c2fecSMatthias Ringwald 2751298c2fecSMatthias Ringwald case L2CAP_STATE_WAIT_OUTGOING_SECURITY_LEVEL_UPDATE: 2752298c2fecSMatthias Ringwald if (actual_level >= required_level){ 2753298c2fecSMatthias Ringwald l2cap_ready_to_connect(channel); 2754298c2fecSMatthias Ringwald } else { 275518660401SMatthias Ringwald // security level insufficient, report error and free channel 275618660401SMatthias Ringwald l2cap_handle_channel_open_failed(channel, L2CAP_CONNECTION_RESPONSE_RESULT_REFUSED_SECURITY); 275718660401SMatthias Ringwald btstack_linked_list_remove(&l2cap_channels, (btstack_linked_item_t *) channel); 275818660401SMatthias Ringwald l2cap_free_channel_entry(channel); 2759298c2fecSMatthias Ringwald } 2760298c2fecSMatthias Ringwald break; 2761298c2fecSMatthias Ringwald 2762298c2fecSMatthias Ringwald default: 2763298c2fecSMatthias Ringwald break; 2764298c2fecSMatthias Ringwald } 2765298c2fecSMatthias Ringwald } 2766298c2fecSMatthias Ringwald } 2767298c2fecSMatthias Ringwald #endif 2768298c2fecSMatthias Ringwald 2769298c2fecSMatthias Ringwald #ifdef L2CAP_USES_CHANNELS 2770298c2fecSMatthias Ringwald static void l2cap_handle_disconnection_complete(hci_con_handle_t handle){ 2771d7f7a5c3SMatthias Ringwald // collect channels to close 2772d7f7a5c3SMatthias Ringwald btstack_linked_list_t channels_to_close = NULL; 2773298c2fecSMatthias Ringwald btstack_linked_list_iterator_t it; 2774298c2fecSMatthias Ringwald btstack_linked_list_iterator_init(&it, &l2cap_channels); 2775298c2fecSMatthias Ringwald while (btstack_linked_list_iterator_has_next(&it)) { 2776298c2fecSMatthias Ringwald l2cap_channel_t *channel = (l2cap_channel_t *) btstack_linked_list_iterator_next(&it); 2777298c2fecSMatthias Ringwald if (!l2cap_is_dynamic_channel_type(channel->channel_type)) continue; 2778298c2fecSMatthias Ringwald if (channel->con_handle != handle) continue; 2779298c2fecSMatthias Ringwald btstack_linked_list_iterator_remove(&it); 2780d7f7a5c3SMatthias Ringwald btstack_linked_list_add(&channels_to_close, (btstack_linked_item_t *) channel); 2781d7f7a5c3SMatthias Ringwald } 2782d7f7a5c3SMatthias Ringwald // send l2cap open failed or closed events for all channels on this handle and free them 2783d7f7a5c3SMatthias Ringwald btstack_linked_list_iterator_init(&it, &channels_to_close); 2784d7f7a5c3SMatthias Ringwald while (btstack_linked_list_iterator_has_next(&it)) { 2785d7f7a5c3SMatthias Ringwald l2cap_channel_t *channel = (l2cap_channel_t *) btstack_linked_list_iterator_next(&it); 2786d7f7a5c3SMatthias Ringwald btstack_linked_list_iterator_remove(&it); 2787298c2fecSMatthias Ringwald switch(channel->channel_type){ 2788298c2fecSMatthias Ringwald #ifdef ENABLE_CLASSIC 2789298c2fecSMatthias Ringwald case L2CAP_CHANNEL_TYPE_CLASSIC: 2790298c2fecSMatthias Ringwald l2cap_handle_hci_disconnect_event(channel); 2791298c2fecSMatthias Ringwald break; 2792298c2fecSMatthias Ringwald #endif 2793298c2fecSMatthias Ringwald #ifdef ENABLE_LE_DATA_CHANNELS 2794298c2fecSMatthias Ringwald case L2CAP_CHANNEL_TYPE_LE_DATA_CHANNEL: 2795298c2fecSMatthias Ringwald l2cap_handle_hci_le_disconnect_event(channel); 2796298c2fecSMatthias Ringwald break; 2797298c2fecSMatthias Ringwald #endif 2798*a254c508SMatthias Ringwald #ifdef ENABLE_L2CAP_ENHANCED_DATA_CHANNELS 2799*a254c508SMatthias Ringwald case L2CAP_CHANNEL_TYPE_ENHANCED_DATA_CHANNEL: 2800*a254c508SMatthias Ringwald switch (channel->state) { 2801*a254c508SMatthias Ringwald case L2CAP_STATE_WILL_SEND_ENHANCED_CONNECTION_REQUEST: 2802*a254c508SMatthias Ringwald case L2CAP_STATE_WAIT_ENHANCED_CONNECTION_RESPONSE: 2803*a254c508SMatthias Ringwald // emit open failed if disconnected before connection complete 2804*a254c508SMatthias Ringwald l2cap_emit_enhanced_data_channel_opened(channel, L2CAP_CONNECTION_BASEBAND_DISCONNECT); 2805*a254c508SMatthias Ringwald break; 2806*a254c508SMatthias Ringwald case L2CAP_STATE_WILL_SEND_EHNANCED_RENEGOTIATION_REQUEST: 2807*a254c508SMatthias Ringwald case L2CAP_STATE_WAIT_ENHANCED_RENEGOTIATION_RESPONSE: 2808*a254c508SMatthias Ringwald // emit reconfigure failure - result = 0xffff 2809*a254c508SMatthias Ringwald l2cap_emit_enhanced_data_channel_reconfigure_complete(channel, 0xffff); 2810*a254c508SMatthias Ringwald break; 2811*a254c508SMatthias Ringwald default: 2812*a254c508SMatthias Ringwald l2cap_emit_simple_event_with_cid(channel, L2CAP_EVENT_DATA_CHANNEL_CLOSED); 2813*a254c508SMatthias Ringwald break; 2814*a254c508SMatthias Ringwald } 2815*a254c508SMatthias Ringwald l2cap_free_channel_entry(channel); 2816*a254c508SMatthias Ringwald break; 2817*a254c508SMatthias Ringwald #endif 2818298c2fecSMatthias Ringwald default: 2819298c2fecSMatthias Ringwald break; 2820298c2fecSMatthias Ringwald } 2821298c2fecSMatthias Ringwald } 2822298c2fecSMatthias Ringwald } 2823298c2fecSMatthias Ringwald #endif 2824298c2fecSMatthias Ringwald 2825d9a7306aSMatthias Ringwald static void l2cap_hci_event_handler(uint8_t packet_type, uint16_t cid, uint8_t *packet, uint16_t size){ 2826afde0c52Smatthias.ringwald 28275774a392SMatthias Ringwald UNUSED(packet_type); // ok: registered with hci_event_callback_registration 28285774a392SMatthias Ringwald UNUSED(cid); // ok: there is no channel 28295774a392SMatthias Ringwald UNUSED(size); // ok: fixed format events read from HCI buffer 28309ec2630cSMatthias Ringwald 28315774a392SMatthias Ringwald #ifdef ENABLE_CLASSIC 2832afde0c52Smatthias.ringwald bd_addr_t address; 2833298c2fecSMatthias Ringwald gap_security_level_t security_level; 28345774a392SMatthias Ringwald #endif 28355774a392SMatthias Ringwald #ifdef L2CAP_USES_CHANNELS 28365774a392SMatthias Ringwald hci_con_handle_t handle; 28375774a392SMatthias Ringwald #endif 2838afde0c52Smatthias.ringwald 28390e2df43fSMatthias Ringwald switch(hci_event_packet_get_type(packet)){ 2840afde0c52Smatthias.ringwald 284109e9d05bSMatthias Ringwald // Notify channel packet handler if they can send now 284209e9d05bSMatthias Ringwald case HCI_EVENT_TRANSPORT_PACKET_SENT: 284309e9d05bSMatthias Ringwald case HCI_EVENT_NUMBER_OF_COMPLETED_PACKETS: 2844eea99214SMatthias Ringwald case BTSTACK_EVENT_NR_CONNECTIONS_CHANGED: 2845*a254c508SMatthias Ringwald l2cap_call_notify_channel_in_run = true; 284609e9d05bSMatthias Ringwald break; 284709e9d05bSMatthias Ringwald 284809e9d05bSMatthias Ringwald case HCI_EVENT_COMMAND_STATUS: 2849ece97caeSMatthias Ringwald #ifdef ENABLE_CLASSIC 2850ece97caeSMatthias Ringwald // check command status for create connection for errors 2851ece97caeSMatthias Ringwald if (HCI_EVENT_IS_COMMAND_STATUS(packet, hci_create_connection)){ 2852ece97caeSMatthias Ringwald // cache outgoing address and reset 28536535961aSMatthias Ringwald (void)memcpy(address, l2cap_outgoing_classic_addr, 6); 2854ece97caeSMatthias Ringwald memset(l2cap_outgoing_classic_addr, 0, 6); 2855ece97caeSMatthias Ringwald // error => outgoing connection failed 2856ece97caeSMatthias Ringwald uint8_t status = hci_event_command_status_get_status(packet); 2857ece97caeSMatthias Ringwald if (status){ 2858ece97caeSMatthias Ringwald l2cap_handle_connection_failed_for_addr(address, status); 2859ece97caeSMatthias Ringwald } 2860ece97caeSMatthias Ringwald } 2861ece97caeSMatthias Ringwald #endif 286209e9d05bSMatthias Ringwald l2cap_run(); // try sending signaling packets first 286309e9d05bSMatthias Ringwald break; 286409e9d05bSMatthias Ringwald 286509e9d05bSMatthias Ringwald #ifdef ENABLE_CLASSIC 2866afde0c52Smatthias.ringwald // handle connection complete events 2867afde0c52Smatthias.ringwald case HCI_EVENT_CONNECTION_COMPLETE: 2868724d70a2SMatthias Ringwald reverse_bd_addr(&packet[5], address); 2869afde0c52Smatthias.ringwald if (packet[2] == 0){ 2870f8fbdce0SMatthias Ringwald handle = little_endian_read_16(packet, 3); 2871afde0c52Smatthias.ringwald l2cap_handle_connection_success_for_addr(address, handle); 2872afde0c52Smatthias.ringwald } else { 2873afde0c52Smatthias.ringwald l2cap_handle_connection_failed_for_addr(address, packet[2]); 2874afde0c52Smatthias.ringwald } 2875afde0c52Smatthias.ringwald break; 2876afde0c52Smatthias.ringwald 2877afde0c52Smatthias.ringwald // handle successful create connection cancel command 2878afde0c52Smatthias.ringwald case HCI_EVENT_COMMAND_COMPLETE: 2879073bd0faSMatthias Ringwald if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_create_connection_cancel)) { 2880afde0c52Smatthias.ringwald if (packet[5] == 0){ 2881724d70a2SMatthias Ringwald reverse_bd_addr(&packet[6], address); 2882afde0c52Smatthias.ringwald // CONNECTION TERMINATED BY LOCAL HOST (0X16) 2883afde0c52Smatthias.ringwald l2cap_handle_connection_failed_for_addr(address, 0x16); 288403cfbabcSmatthias.ringwald } 28851e6aba47Smatthias.ringwald } 288639d59809Smatthias.ringwald l2cap_run(); // try sending signaling packets first 288739d59809Smatthias.ringwald break; 288809e9d05bSMatthias Ringwald #endif 288927a923d0Smatthias.ringwald 28902053036dSMatthias Ringwald #ifdef L2CAP_USES_CHANNELS 28911e6aba47Smatthias.ringwald // handle disconnection complete events 2892afde0c52Smatthias.ringwald case HCI_EVENT_DISCONNECTION_COMPLETE: 2893d0662982SMatthias Ringwald handle = little_endian_read_16(packet, 3); 2894298c2fecSMatthias Ringwald l2cap_handle_disconnection_complete(handle); 2895421cb104SMatthias Ringwald break; 289609e9d05bSMatthias Ringwald #endif 28979909e5e4SMatthias Ringwald 2898ee091cf1Smatthias.ringwald // HCI Connection Timeouts 289909e9d05bSMatthias Ringwald #ifdef ENABLE_CLASSIC 2900afde0c52Smatthias.ringwald case L2CAP_EVENT_TIMEOUT_CHECK: 2901f8fbdce0SMatthias Ringwald handle = little_endian_read_16(packet, 2); 2902298c2fecSMatthias Ringwald l2cap_check_classic_timeout(handle); 2903afde0c52Smatthias.ringwald break; 2904ee091cf1Smatthias.ringwald 2905df3354fcS[email protected] case HCI_EVENT_READ_REMOTE_SUPPORTED_FEATURES_COMPLETE: 29063aabc0d9SMatthias Ringwald case HCI_EVENT_READ_REMOTE_EXTENDED_FEATURES_COMPLETE: 2907f8fbdce0SMatthias Ringwald handle = little_endian_read_16(packet, 3); 2908298c2fecSMatthias Ringwald l2cap_handle_features_complete(handle); 2909c22aecc9S[email protected] break; 2910df3354fcS[email protected] 29115611a760SMatthias Ringwald case GAP_EVENT_SECURITY_LEVEL: 2912f8fbdce0SMatthias Ringwald handle = little_endian_read_16(packet, 2); 2913298c2fecSMatthias Ringwald security_level = (gap_security_level_t) packet[4]; 2914298c2fecSMatthias Ringwald l2cap_handle_security_level(handle, security_level); 2915f85a9399S[email protected] break; 291609e9d05bSMatthias Ringwald #endif 2917afde0c52Smatthias.ringwald default: 2918afde0c52Smatthias.ringwald break; 2919afde0c52Smatthias.ringwald } 2920afde0c52Smatthias.ringwald 2921bd63148eS[email protected] l2cap_run(); 29221e6aba47Smatthias.ringwald } 29231e6aba47Smatthias.ringwald 2924e74c5f58SMatthias Ringwald static void l2cap_register_signaling_response(hci_con_handle_t handle, uint8_t code, uint8_t sig_id, uint16_t cid, uint16_t data){ 2925*a254c508SMatthias Ringwald // Vol 3, Part A, 4.3: "The DCID and SCID fields shall be ignored when the result field indicates the connection was refused." 292691c8d67dSMatthias Ringwald if (l2cap_signaling_responses_pending < NR_PENDING_SIGNALING_RESPONSES) { 292791c8d67dSMatthias Ringwald l2cap_signaling_responses[l2cap_signaling_responses_pending].handle = handle; 292891c8d67dSMatthias Ringwald l2cap_signaling_responses[l2cap_signaling_responses_pending].code = code; 292991c8d67dSMatthias Ringwald l2cap_signaling_responses[l2cap_signaling_responses_pending].sig_id = sig_id; 293091c8d67dSMatthias Ringwald l2cap_signaling_responses[l2cap_signaling_responses_pending].cid = cid; 293191c8d67dSMatthias Ringwald l2cap_signaling_responses[l2cap_signaling_responses_pending].data = data; 293291c8d67dSMatthias Ringwald l2cap_signaling_responses_pending++; 29332b360848Smatthias.ringwald l2cap_run(); 29342b360848Smatthias.ringwald } 29352b360848Smatthias.ringwald } 29362b360848Smatthias.ringwald 293709e9d05bSMatthias Ringwald #ifdef ENABLE_CLASSIC 293809e9d05bSMatthias Ringwald static void l2cap_handle_disconnect_request(l2cap_channel_t *channel, uint16_t identifier){ 29391dbbb889SMatthias Ringwald switch (channel->state){ 29401dbbb889SMatthias Ringwald case L2CAP_STATE_CONFIG: 29411dbbb889SMatthias Ringwald case L2CAP_STATE_OPEN: 29421dbbb889SMatthias Ringwald case L2CAP_STATE_WILL_SEND_DISCONNECT_REQUEST: 29431dbbb889SMatthias Ringwald case L2CAP_STATE_WAIT_DISCONNECT: 29441dbbb889SMatthias Ringwald break; 29451dbbb889SMatthias Ringwald default: 29461dbbb889SMatthias Ringwald // ignore in other states 29471dbbb889SMatthias Ringwald return; 29481dbbb889SMatthias Ringwald } 29491dbbb889SMatthias Ringwald 295009e9d05bSMatthias Ringwald channel->remote_sig_id = identifier; 295109e9d05bSMatthias Ringwald channel->state = L2CAP_STATE_WILL_SEND_DISCONNECT_RESPONSE; 295209e9d05bSMatthias Ringwald l2cap_run(); 295309e9d05bSMatthias Ringwald } 295409e9d05bSMatthias Ringwald 2955b35f641cSmatthias.ringwald static void l2cap_handle_connection_request(hci_con_handle_t handle, uint8_t sig_id, uint16_t psm, uint16_t source_cid){ 2956645658c9Smatthias.ringwald 29579da54300S[email protected] // log_info("l2cap_handle_connection_request for handle %u, psm %u cid 0x%02x", handle, psm, source_cid); 2958645658c9Smatthias.ringwald l2cap_service_t *service = l2cap_get_service(psm); 2959645658c9Smatthias.ringwald if (!service) { 2960645658c9Smatthias.ringwald // 0x0002 PSM not supported 2961e74c5f58SMatthias Ringwald l2cap_register_signaling_response(handle, CONNECTION_REQUEST, sig_id, source_cid, 0x0002); 2962645658c9Smatthias.ringwald return; 2963645658c9Smatthias.ringwald } 2964645658c9Smatthias.ringwald 29655061f3afS[email protected] hci_connection_t * hci_connection = hci_connection_for_handle( handle ); 2966645658c9Smatthias.ringwald if (!hci_connection) { 29672b360848Smatthias.ringwald // 29689da54300S[email protected] log_error("no hci_connection for handle %u", handle); 2969645658c9Smatthias.ringwald return; 2970645658c9Smatthias.ringwald } 29712bd8b7e7S[email protected] 2972645658c9Smatthias.ringwald // alloc structure 2973d7387af3SMatthias Ringwald gap_security_level_t required_level = service->required_security_level; 2974d7387af3SMatthias Ringwald if (gap_get_secure_connections_only_mode() && (required_level != LEVEL_0)){ 2975d7387af3SMatthias Ringwald required_level = LEVEL_4; 2976d7387af3SMatthias Ringwald } 2977f16129ceSMatthias Ringwald l2cap_channel_t * channel = l2cap_create_channel_entry(service->packet_handler, L2CAP_CHANNEL_TYPE_CLASSIC, hci_connection->address, BD_ADDR_TYPE_ACL, 2978d7387af3SMatthias Ringwald psm, service->mtu, required_level); 29792b360848Smatthias.ringwald if (!channel){ 29802b360848Smatthias.ringwald // 0x0004 No resources available 2981e74c5f58SMatthias Ringwald l2cap_register_signaling_response(handle, CONNECTION_REQUEST, sig_id, source_cid, 0x0004); 29822b360848Smatthias.ringwald return; 29832b360848Smatthias.ringwald } 2984da144af5SMatthias Ringwald 2985fc64f94aSMatthias Ringwald channel->con_handle = handle; 2986b35f641cSmatthias.ringwald channel->remote_cid = source_cid; 2987b1988dceSmatthias.ringwald channel->remote_sig_id = sig_id; 2988645658c9Smatthias.ringwald 2989f53da564S[email protected] // limit local mtu to max acl packet length - l2cap header 29902985cb84Smatthias.ringwald if (channel->local_mtu > l2cap_max_mtu()) { 29912985cb84Smatthias.ringwald channel->local_mtu = l2cap_max_mtu(); 29929775e25bSmatthias.ringwald } 29939775e25bSmatthias.ringwald 2994645658c9Smatthias.ringwald // set initial state 29952076cfd2SMatthias Ringwald channel->state = L2CAP_STATE_WAIT_REMOTE_SUPPORTED_FEATURES; 29962076cfd2SMatthias Ringwald channel->state_var = L2CAP_CHANNEL_STATE_VAR_INCOMING; 2997e405ae81Smatthias.ringwald 2998645658c9Smatthias.ringwald // add to connections list 2999da4c2b27SMatthias Ringwald btstack_linked_list_add_tail(&l2cap_channels, (btstack_linked_item_t *) channel); 3000645658c9Smatthias.ringwald 3001c0f91826SMatthias Ringwald // 3002c0f91826SMatthias Ringwald if (required_level > LEVEL_0){ 30032076cfd2SMatthias Ringwald // send conn resp pending if remote supported features have not been received yet 3004d6596031SMatthias Ringwald if (hci_remote_features_available(handle)) { 30052076cfd2SMatthias Ringwald l2cap_handle_remote_supported_features_received(channel); 3006d4d525abSMatthias Ringwald } else { 30072076cfd2SMatthias Ringwald channel->state_var |= L2CAP_CHANNEL_STATE_VAR_SEND_CONN_RESP_PEND; 3008d6596031SMatthias Ringwald hci_remote_features_query(handle); 3009e405ae81Smatthias.ringwald } 3010c0f91826SMatthias Ringwald } else { 3011c0f91826SMatthias Ringwald l2cap_handle_security_level_incoming_sufficient(channel); 3012c0f91826SMatthias Ringwald } 3013d4d525abSMatthias Ringwald } 3014645658c9Smatthias.ringwald 3015ce8f182eSMatthias Ringwald void l2cap_accept_connection(uint16_t local_cid){ 3016e0abb8e7S[email protected] log_info("L2CAP_ACCEPT_CONNECTION local_cid 0x%x", local_cid); 3017b35f641cSmatthias.ringwald l2cap_channel_t * channel = l2cap_get_channel_for_local_cid(local_cid); 3018e405ae81Smatthias.ringwald if (!channel) { 301985621840SMilanka Ringwald log_error("accept called but local_cid 0x%x not found", local_cid); 3020e405ae81Smatthias.ringwald return; 3021e405ae81Smatthias.ringwald } 3022e405ae81Smatthias.ringwald 302343ec931dSMatthias Ringwald #ifdef ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE 302443ec931dSMatthias Ringwald // configure L2CAP Basic mode 302543ec931dSMatthias Ringwald channel->mode = L2CAP_CHANNEL_MODE_BASIC; 302643ec931dSMatthias Ringwald #endif 302743ec931dSMatthias Ringwald 3028552d92a1Smatthias.ringwald channel->state = L2CAP_STATE_WILL_SEND_CONNECTION_RESPONSE_ACCEPT; 3029e405ae81Smatthias.ringwald 3030552d92a1Smatthias.ringwald // process 3031552d92a1Smatthias.ringwald l2cap_run(); 3032e405ae81Smatthias.ringwald } 3033645658c9Smatthias.ringwald 30347ef6a7bbSMatthias Ringwald void l2cap_decline_connection(uint16_t local_cid){ 303585621840SMilanka Ringwald log_info("decline local_cid 0x%x", local_cid); 3036b35f641cSmatthias.ringwald l2cap_channel_t * channel = l2cap_get_channel_for_local_cid( local_cid); 3037e405ae81Smatthias.ringwald if (!channel) { 3038ce8f182eSMatthias Ringwald log_error( "l2cap_decline_connection called but local_cid 0x%x not found", local_cid); 3039e405ae81Smatthias.ringwald return; 3040e405ae81Smatthias.ringwald } 3041e7ff783cSmatthias.ringwald channel->state = L2CAP_STATE_WILL_SEND_CONNECTION_RESPONSE_DECLINE; 30427ef6a7bbSMatthias Ringwald channel->reason = 0x04; // no resources available 3043e7ff783cSmatthias.ringwald l2cap_run(); 3044645658c9Smatthias.ringwald } 3045645658c9Smatthias.ringwald 3046e9cfb251SMatthias Ringwald // @pre command len is valid, see check in l2cap_signaling_handler_channel 30477f02f414SMatthias Ringwald static void l2cap_signaling_handle_configure_request(l2cap_channel_t *channel, uint8_t *command){ 3048b1988dceSmatthias.ringwald 3049fcb125edSMatthias Ringwald #ifdef ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE 3050fcb125edSMatthias Ringwald uint8_t use_fcs = 1; 3051fcb125edSMatthias Ringwald #endif 3052fcb125edSMatthias Ringwald 3053b1988dceSmatthias.ringwald channel->remote_sig_id = command[L2CAP_SIGNALING_COMMAND_SIGID_OFFSET]; 3054b1988dceSmatthias.ringwald 3055f8fbdce0SMatthias Ringwald uint16_t flags = little_endian_read_16(command, 6); 305663a7246aSmatthias.ringwald if (flags & 1) { 305763a7246aSmatthias.ringwald channelStateVarSetFlag(channel, L2CAP_CHANNEL_STATE_VAR_SEND_CONF_RSP_CONT); 305863a7246aSmatthias.ringwald } 305963a7246aSmatthias.ringwald 30602784b77dSmatthias.ringwald // accept the other's configuration options 3061f8fbdce0SMatthias Ringwald uint16_t end_pos = 4 + little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_LENGTH_OFFSET); 30623de7c0caSmatthias.ringwald uint16_t pos = 8; 30633de7c0caSmatthias.ringwald while (pos < end_pos){ 306463a7246aSmatthias.ringwald uint8_t option_hint = command[pos] >> 7; 306563a7246aSmatthias.ringwald uint8_t option_type = command[pos] & 0x7f; 30663844aeadSMatthias Ringwald // log_info("l2cap cid %u, hint %u, type %u", channel->local_cid, option_hint, option_type); 306763a7246aSmatthias.ringwald pos++; 30681dc511deSmatthias.ringwald uint8_t length = command[pos++]; 30691dc511deSmatthias.ringwald // MTU { type(8): 1, len(8):2, MTU(16) } 3070c1ab6cc1SMatthias Ringwald if ((option_type == L2CAP_CONFIG_OPTION_TYPE_MAX_TRANSMISSION_UNIT) && (length == 2)){ 3071f8fbdce0SMatthias Ringwald channel->remote_mtu = little_endian_read_16(command, pos); 30723844aeadSMatthias Ringwald log_info("Remote MTU %u", channel->remote_mtu); 30739d139fbaSMatthias Ringwald if (channel->remote_mtu > l2cap_max_mtu()){ 30749d139fbaSMatthias Ringwald log_info("Remote MTU %u larger than outgoing buffer, only using MTU = %u", channel->remote_mtu, l2cap_max_mtu()); 30759d139fbaSMatthias Ringwald channel->remote_mtu = l2cap_max_mtu(); 30769d139fbaSMatthias Ringwald } 307763a7246aSmatthias.ringwald channelStateVarSetFlag(channel, L2CAP_CHANNEL_STATE_VAR_SEND_CONF_RSP_MTU); 307863a7246aSmatthias.ringwald } 30790fe7a9d0S[email protected] // Flush timeout { type(8):2, len(8): 2, Flush Timeout(16)} 3080e53a3388SMatthias Ringwald if ((option_type == L2CAP_CONFIG_OPTION_TYPE_FLUSH_TIMEOUT) && (length == 2)){ 3081f8fbdce0SMatthias Ringwald channel->flush_timeout = little_endian_read_16(command, pos); 30823844aeadSMatthias Ringwald log_info("Flush timeout: %u ms", channel->flush_timeout); 30830fe7a9d0S[email protected] } 3084f2fa388dSMatthias Ringwald 30856dca2a0cSMatthias Ringwald #ifdef ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE 30866dca2a0cSMatthias Ringwald // Retransmission and Flow Control Option 3087671fb338SMatthias Ringwald if (option_type == L2CAP_CONFIG_OPTION_TYPE_RETRANSMISSION_AND_FLOW_CONTROL && length == 9){ 30883232a1c6SMatthias Ringwald l2cap_channel_mode_t mode = (l2cap_channel_mode_t) command[pos]; 3089ac8f1300SMatthias Ringwald switch(channel->mode){ 3090ac8f1300SMatthias Ringwald case L2CAP_CHANNEL_MODE_ENHANCED_RETRANSMISSION: 309125cd60d3SMatthias Ringwald // Store remote config 3092bbc0a9e7SMatthias Ringwald channel->remote_tx_window_size = command[pos+1]; 3093bbc0a9e7SMatthias Ringwald channel->remote_max_transmit = command[pos+2]; 3094bbc0a9e7SMatthias Ringwald channel->remote_retransmission_timeout_ms = little_endian_read_16(command, pos + 3); 3095bbc0a9e7SMatthias Ringwald channel->remote_monitor_timeout_ms = little_endian_read_16(command, pos + 5); 30963844aeadSMatthias Ringwald channel->remote_mps = little_endian_read_16(command, pos + 7); 30973844aeadSMatthias Ringwald log_info("FC&C config: tx window: %u, max transmit %u, retrans timeout %u, monitor timeout %u, mps %u", 3098bbc0a9e7SMatthias Ringwald channel->remote_tx_window_size, 3099bbc0a9e7SMatthias Ringwald channel->remote_max_transmit, 3100bbc0a9e7SMatthias Ringwald channel->remote_retransmission_timeout_ms, 31013844aeadSMatthias Ringwald channel->remote_monitor_timeout_ms, 31023844aeadSMatthias Ringwald channel->remote_mps); 310325cd60d3SMatthias Ringwald // If ERTM mandatory, but remote doens't offer ERTM -> disconnect 310425cd60d3SMatthias Ringwald if (channel->ertm_mandatory && mode != L2CAP_CHANNEL_MODE_ENHANCED_RETRANSMISSION){ 310525cd60d3SMatthias Ringwald channel->state = L2CAP_STATE_WILL_SEND_DISCONNECT_REQUEST; 3106ac8f1300SMatthias Ringwald } else { 3107b8134563SMatthias Ringwald channelStateVarSetFlag(channel, L2CAP_CHANNEL_STATE_VAR_SEND_CONF_RSP_ERTM); 3108ac8f1300SMatthias Ringwald } 3109ac8f1300SMatthias Ringwald break; 3110ac8f1300SMatthias Ringwald case L2CAP_CHANNEL_MODE_BASIC: 3111ac8f1300SMatthias Ringwald switch (mode){ 3112ac8f1300SMatthias Ringwald case L2CAP_CHANNEL_MODE_ENHANCED_RETRANSMISSION: 3113ac8f1300SMatthias Ringwald // remote asks for ERTM, but we want basic mode. disconnect if this happens a second time 3114ac8f1300SMatthias Ringwald if (channel->state_var & L2CAP_CHANNEL_STATE_VAR_BASIC_FALLBACK_TRIED){ 3115ac8f1300SMatthias Ringwald channel->state = L2CAP_STATE_WILL_SEND_DISCONNECT_REQUEST; 3116ac8f1300SMatthias Ringwald } 3117ac8f1300SMatthias Ringwald channelStateVarSetFlag(channel, L2CAP_CHANNEL_STATE_VAR_BASIC_FALLBACK_TRIED); 3118ac8f1300SMatthias Ringwald channelStateVarSetFlag(channel, L2CAP_CHANNEL_STATE_VAR_SEND_CONF_RSP_REJECTED); 3119ac8f1300SMatthias Ringwald break; 3120ac8f1300SMatthias Ringwald default: // case L2CAP_CHANNEL_MODE_BASIC: 3121ac8f1300SMatthias Ringwald // TODO store and evaluate configuration 3122b8134563SMatthias Ringwald channelStateVarSetFlag(channel, L2CAP_CHANNEL_STATE_VAR_SEND_CONF_RSP_ERTM); 3123ac8f1300SMatthias Ringwald break; 3124ac8f1300SMatthias Ringwald } 3125ac8f1300SMatthias Ringwald break; 3126ac8f1300SMatthias Ringwald default: 3127ac8f1300SMatthias Ringwald break; 3128ac8f1300SMatthias Ringwald } 31293232a1c6SMatthias Ringwald } 31306574158aSMatthias Ringwald if (option_type == L2CAP_CONFIG_OPTION_TYPE_FRAME_CHECK_SEQUENCE && length == 1){ 3131fcb125edSMatthias Ringwald use_fcs = command[pos]; 31326574158aSMatthias Ringwald } 31336dca2a0cSMatthias Ringwald #endif 313463a7246aSmatthias.ringwald // check for unknown options 3135505f1c30SMatthias Ringwald if ((option_hint == 0) && ((option_type < L2CAP_CONFIG_OPTION_TYPE_MAX_TRANSMISSION_UNIT) || (option_type > L2CAP_CONFIG_OPTION_TYPE_EXTENDED_WINDOW_SIZE))){ 3136da9b76deSMatthias Ringwald log_info("l2cap cid %u, unknown option 0x%02x", channel->local_cid, option_type); 3137da9b76deSMatthias Ringwald channel->unknown_option = option_type; 313863a7246aSmatthias.ringwald channelStateVarSetFlag(channel, L2CAP_CHANNEL_STATE_VAR_SEND_CONF_RSP_INVALID); 31391dc511deSmatthias.ringwald } 31401dc511deSmatthias.ringwald pos += length; 31411dc511deSmatthias.ringwald } 3142fcb125edSMatthias Ringwald 3143fcb125edSMatthias Ringwald #ifdef ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE 3144fcb125edSMatthias Ringwald // "FCS" has precedence over "No FCS" 3145fcb125edSMatthias Ringwald uint8_t update = channel->fcs_option || use_fcs; 3146fcb125edSMatthias Ringwald log_info("local fcs: %u, remote fcs: %u -> %u", channel->fcs_option, use_fcs, update); 3147fcb125edSMatthias Ringwald channel->fcs_option = update; 314867f8f607SMatthias Ringwald // If ERTM mandatory, but remote didn't send Retransmission and Flowcontrol options -> disconnect 314967f8f607SMatthias Ringwald if (((channel->state_var & L2CAP_CHANNEL_STATE_VAR_SEND_CONF_RSP_ERTM) == 0) & (channel->ertm_mandatory)){ 315067f8f607SMatthias Ringwald channel->state = L2CAP_STATE_WILL_SEND_DISCONNECT_REQUEST; 315167f8f607SMatthias Ringwald } 3152fcb125edSMatthias Ringwald #endif 31532784b77dSmatthias.ringwald } 31542784b77dSmatthias.ringwald 3155e9cfb251SMatthias Ringwald // @pre command len is valid, see check in l2cap_signaling_handler_channel 3156f2fa388dSMatthias Ringwald static void l2cap_signaling_handle_configure_response(l2cap_channel_t *channel, uint8_t result, uint8_t *command){ 3157f2fa388dSMatthias Ringwald log_info("l2cap_signaling_handle_configure_response"); 31583232a1c6SMatthias Ringwald #ifdef ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE 31593232a1c6SMatthias Ringwald uint16_t end_pos = 4 + little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_LENGTH_OFFSET); 3160f2fa388dSMatthias Ringwald uint16_t pos = 10; 31613232a1c6SMatthias Ringwald while (pos < end_pos){ 31623232a1c6SMatthias Ringwald uint8_t option_hint = command[pos] >> 7; 31633232a1c6SMatthias Ringwald uint8_t option_type = command[pos] & 0x7f; 3164fcb125edSMatthias Ringwald // log_info("l2cap cid %u, hint %u, type %u", channel->local_cid, option_hint, option_type); 31653232a1c6SMatthias Ringwald pos++; 31663232a1c6SMatthias Ringwald uint8_t length = command[pos++]; 31673232a1c6SMatthias Ringwald 31683232a1c6SMatthias Ringwald // Retransmission and Flow Control Option 3169671fb338SMatthias Ringwald if (option_type == L2CAP_CONFIG_OPTION_TYPE_RETRANSMISSION_AND_FLOW_CONTROL && length == 9){ 3170ac8f1300SMatthias Ringwald switch (channel->mode){ 3171ac8f1300SMatthias Ringwald case L2CAP_CHANNEL_MODE_ENHANCED_RETRANSMISSION: 3172f2fa388dSMatthias Ringwald if (channel->ertm_mandatory){ 3173ac8f1300SMatthias Ringwald // ?? 3174f2fa388dSMatthias Ringwald } else { 3175ac8f1300SMatthias Ringwald // On 'Reject - Unacceptable Parameters' to our optional ERTM request, fall back to BASIC mode 3176ac8f1300SMatthias Ringwald if (result == L2CAP_CONF_RESULT_UNACCEPTABLE_PARAMETERS){ 317766a72640SMatthias Ringwald l2cap_emit_simple_event_with_cid(channel, L2CAP_EVENT_ERTM_BUFFER_RELEASED); 3178f2fa388dSMatthias Ringwald channel->mode = L2CAP_CHANNEL_MODE_BASIC; 31793232a1c6SMatthias Ringwald } 31803232a1c6SMatthias Ringwald } 3181ac8f1300SMatthias Ringwald break; 3182ac8f1300SMatthias Ringwald case L2CAP_CHANNEL_MODE_BASIC: 3183ac8f1300SMatthias Ringwald if (result == L2CAP_CONF_RESULT_UNACCEPTABLE_PARAMETERS){ 3184ac8f1300SMatthias Ringwald // On 'Reject - Unacceptable Parameters' to our Basic mode request, disconnect 3185ac8f1300SMatthias Ringwald channel->state = L2CAP_STATE_WILL_SEND_DISCONNECT_REQUEST; 3186ac8f1300SMatthias Ringwald } 3187ac8f1300SMatthias Ringwald break; 3188ac8f1300SMatthias Ringwald default: 3189ac8f1300SMatthias Ringwald break; 31903232a1c6SMatthias Ringwald } 3191f2fa388dSMatthias Ringwald } 31923232a1c6SMatthias Ringwald 31933232a1c6SMatthias Ringwald // check for unknown options 3194671fb338SMatthias Ringwald if (option_hint == 0 && (option_type < L2CAP_CONFIG_OPTION_TYPE_MAX_TRANSMISSION_UNIT || option_type > L2CAP_CONFIG_OPTION_TYPE_EXTENDED_WINDOW_SIZE)){ 3195da9b76deSMatthias Ringwald log_info("l2cap cid %u, unknown option 0x%02x", channel->local_cid, option_type); 3196da9b76deSMatthias Ringwald channel->unknown_option = option_type; 31973232a1c6SMatthias Ringwald channelStateVarSetFlag(channel, L2CAP_CHANNEL_STATE_VAR_SEND_CONF_RSP_INVALID); 31983232a1c6SMatthias Ringwald } 31993232a1c6SMatthias Ringwald 32003232a1c6SMatthias Ringwald pos += length; 32013232a1c6SMatthias Ringwald } 3202688f9764SMatthias Ringwald #else 32035774a392SMatthias Ringwald UNUSED(channel); // ok: no code 32045774a392SMatthias Ringwald UNUSED(result); // ok: no code 32055774a392SMatthias Ringwald UNUSED(command); // ok: no code 32063232a1c6SMatthias Ringwald #endif 32073232a1c6SMatthias Ringwald } 32083232a1c6SMatthias Ringwald 3209fa8473a4Smatthias.ringwald static int l2cap_channel_ready_for_open(l2cap_channel_t *channel){ 32109da54300S[email protected] // log_info("l2cap_channel_ready_for_open 0x%02x", channel->state_var); 321173cf2b3dSmatthias.ringwald if ((channel->state_var & L2CAP_CHANNEL_STATE_VAR_RCVD_CONF_RSP) == 0) return 0; 321273cf2b3dSmatthias.ringwald if ((channel->state_var & L2CAP_CHANNEL_STATE_VAR_SENT_CONF_RSP) == 0) return 0; 3213019f9b43SMatthias Ringwald // addition check that fixes re-entrance issue causing l2cap event channel opened twice 3214019f9b43SMatthias Ringwald if (channel->state == L2CAP_STATE_OPEN) return 0; 3215fa8473a4Smatthias.ringwald return 1; 3216fa8473a4Smatthias.ringwald } 3217fa8473a4Smatthias.ringwald 3218fa8473a4Smatthias.ringwald 3219e9cfb251SMatthias Ringwald // @pre command len is valid, see check in l2cap_signaling_handler_dispatch 32207f02f414SMatthias Ringwald static void l2cap_signaling_handler_channel(l2cap_channel_t *channel, uint8_t *command){ 32211e6aba47Smatthias.ringwald 322200d93d79Smatthias.ringwald uint8_t code = command[L2CAP_SIGNALING_COMMAND_CODE_OFFSET]; 322300d93d79Smatthias.ringwald uint8_t identifier = command[L2CAP_SIGNALING_COMMAND_SIGID_OFFSET]; 3224e9cfb251SMatthias Ringwald uint16_t cmd_len = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_LENGTH_OFFSET); 322538e5900eSmatthias.ringwald uint16_t result = 0; 32261e6aba47Smatthias.ringwald 32279da54300S[email protected] log_info("L2CAP signaling handler code %u, state %u", code, channel->state); 3228b35f641cSmatthias.ringwald 32299a011532Smatthias.ringwald // handle DISCONNECT REQUESTS seperately 32309a011532Smatthias.ringwald if (code == DISCONNECTION_REQUEST){ 32319a011532Smatthias.ringwald l2cap_handle_disconnect_request(channel, identifier); 32329a011532Smatthias.ringwald return; 32339a011532Smatthias.ringwald } 32349a011532Smatthias.ringwald 323556081214Smatthias.ringwald // @STATEMACHINE(l2cap) 32361e6aba47Smatthias.ringwald switch (channel->state) { 32371e6aba47Smatthias.ringwald 32381e6aba47Smatthias.ringwald case L2CAP_STATE_WAIT_CONNECT_RSP: 32391e6aba47Smatthias.ringwald switch (code){ 32401e6aba47Smatthias.ringwald case CONNECTION_RESPONSE: 3241e9cfb251SMatthias Ringwald if (cmd_len < 8){ 3242e9cfb251SMatthias Ringwald // command imcomplete 3243e9cfb251SMatthias Ringwald l2cap_register_signaling_response(channel->con_handle, COMMAND_REJECT, identifier, 0, L2CAP_REJ_CMD_UNKNOWN); 3244e9cfb251SMatthias Ringwald break; 3245e9cfb251SMatthias Ringwald } 32465932bd7cS[email protected] l2cap_stop_rtx(channel); 3247f8fbdce0SMatthias Ringwald result = little_endian_read_16 (command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET+4); 324838e5900eSmatthias.ringwald switch (result) { 324938e5900eSmatthias.ringwald case 0: 3250169f8b28Smatthias.ringwald // successful connection 3251f8fbdce0SMatthias Ringwald channel->remote_cid = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET); 3252fa8473a4Smatthias.ringwald channel->state = L2CAP_STATE_CONFIG; 325328ca2b46S[email protected] channelStateVarSetFlag(channel, L2CAP_CHANNEL_STATE_VAR_SEND_CONF_REQ); 325438e5900eSmatthias.ringwald break; 325538e5900eSmatthias.ringwald case 1: 32565932bd7cS[email protected] // connection pending. get some coffee, but start the ERTX 32575932bd7cS[email protected] l2cap_start_ertx(channel); 325838e5900eSmatthias.ringwald break; 325938e5900eSmatthias.ringwald default: 3260eb920dbeSmatthias.ringwald // channel closed 3261eb920dbeSmatthias.ringwald channel->state = L2CAP_STATE_CLOSED; 3262f32b992eSmatthias.ringwald // map l2cap connection response result to BTstack status enumeration 326366a72640SMatthias Ringwald l2cap_handle_channel_open_failed(channel, L2CAP_CONNECTION_RESPONSE_RESULT_SUCCESSFUL + result); 3264eb920dbeSmatthias.ringwald 3265eb920dbeSmatthias.ringwald // drop link key if security block 3266c1ab6cc1SMatthias Ringwald if ((L2CAP_CONNECTION_RESPONSE_RESULT_SUCCESSFUL + result) == L2CAP_CONNECTION_RESPONSE_RESULT_REFUSED_SECURITY){ 326715a95bd5SMatthias Ringwald gap_drop_link_key_for_bd_addr(channel->address); 3268eb920dbeSmatthias.ringwald } 3269eb920dbeSmatthias.ringwald 3270eb920dbeSmatthias.ringwald // discard channel 3271665d90f2SMatthias Ringwald btstack_linked_list_remove(&l2cap_channels, (btstack_linked_item_t *) channel); 3272c45d6b2cSMatthias Ringwald l2cap_free_channel_entry(channel); 327338e5900eSmatthias.ringwald break; 32741e6aba47Smatthias.ringwald } 32751e6aba47Smatthias.ringwald break; 327638e5900eSmatthias.ringwald 327738e5900eSmatthias.ringwald default: 32781e6aba47Smatthias.ringwald //@TODO: implement other signaling packets 327938e5900eSmatthias.ringwald break; 32801e6aba47Smatthias.ringwald } 32811e6aba47Smatthias.ringwald break; 32821e6aba47Smatthias.ringwald 3283fa8473a4Smatthias.ringwald case L2CAP_STATE_CONFIG: 3284ae280e73Smatthias.ringwald switch (code) { 3285ae280e73Smatthias.ringwald case CONFIGURE_REQUEST: 3286e9cfb251SMatthias Ringwald if (cmd_len < 4){ 3287e9cfb251SMatthias Ringwald // command incomplete 3288e9cfb251SMatthias Ringwald l2cap_register_signaling_response(channel->con_handle, COMMAND_REJECT, identifier, 0, L2CAP_REJ_CMD_UNKNOWN); 3289e9cfb251SMatthias Ringwald break; 3290e9cfb251SMatthias Ringwald } 329128ca2b46S[email protected] channelStateVarSetFlag(channel, L2CAP_CHANNEL_STATE_VAR_SEND_CONF_RSP); 3292ae280e73Smatthias.ringwald l2cap_signaling_handle_configure_request(channel, command); 329363a7246aSmatthias.ringwald if (!(channel->state_var & L2CAP_CHANNEL_STATE_VAR_SEND_CONF_RSP_CONT)){ 329463a7246aSmatthias.ringwald // only done if continuation not set 329563a7246aSmatthias.ringwald channelStateVarSetFlag(channel, L2CAP_CHANNEL_STATE_VAR_RCVD_CONF_REQ); 329663a7246aSmatthias.ringwald } 3297ae280e73Smatthias.ringwald break; 32981e6aba47Smatthias.ringwald case CONFIGURE_RESPONSE: 3299e9cfb251SMatthias Ringwald if (cmd_len < 6){ 3300e9cfb251SMatthias Ringwald // command incomplete 3301e9cfb251SMatthias Ringwald l2cap_register_signaling_response(channel->con_handle, COMMAND_REJECT, identifier, 0, L2CAP_REJ_CMD_UNKNOWN); 3302e9cfb251SMatthias Ringwald break; 3303e9cfb251SMatthias Ringwald } 3304e9cfb251SMatthias Ringwald result = little_endian_read_16 (command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET+4); 33055932bd7cS[email protected] l2cap_stop_rtx(channel); 3306f2fa388dSMatthias Ringwald l2cap_signaling_handle_configure_response(channel, result, command); 33075932bd7cS[email protected] switch (result){ 33085932bd7cS[email protected] case 0: // success 33095932bd7cS[email protected] channelStateVarSetFlag(channel, L2CAP_CHANNEL_STATE_VAR_RCVD_CONF_RSP); 33105932bd7cS[email protected] break; 33115932bd7cS[email protected] case 4: // pending 33125932bd7cS[email protected] l2cap_start_ertx(channel); 33135932bd7cS[email protected] break; 33145932bd7cS[email protected] default: 3315a32d6a03SMatthias Ringwald #ifdef ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE 3316a32d6a03SMatthias Ringwald if (channel->mode == L2CAP_CHANNEL_MODE_ENHANCED_RETRANSMISSION && channel->ertm_mandatory){ 3317a32d6a03SMatthias Ringwald // remote does not offer ertm but it's required 3318a32d6a03SMatthias Ringwald channel->state = L2CAP_STATE_WILL_SEND_DISCONNECT_REQUEST; 3319a32d6a03SMatthias Ringwald break; 3320a32d6a03SMatthias Ringwald } 3321a32d6a03SMatthias Ringwald #endif 3322fe9d8984S[email protected] // retry on negative result 3323fe9d8984S[email protected] channelStateVarSetFlag(channel, L2CAP_CHANNEL_STATE_VAR_SEND_CONF_REQ); 3324fe9d8984S[email protected] break; 3325fe9d8984S[email protected] } 33265a67bd4aSmatthias.ringwald break; 33275a67bd4aSmatthias.ringwald default: 33285a67bd4aSmatthias.ringwald break; 33291e6aba47Smatthias.ringwald } 3330fa8473a4Smatthias.ringwald if (l2cap_channel_ready_for_open(channel)){ 33312e4c1850SMatthias Ringwald 33322e4c1850SMatthias Ringwald #ifdef ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE 33332e4c1850SMatthias Ringwald // assert that packet can be stored in fragment buffers in ertm 33342e4c1850SMatthias Ringwald if (channel->mode == L2CAP_CHANNEL_MODE_ENHANCED_RETRANSMISSION){ 33352e4c1850SMatthias Ringwald uint16_t effective_mps = btstack_min(channel->remote_mps, channel->local_mps); 33362e4c1850SMatthias Ringwald uint16_t usable_mtu = channel->num_tx_buffers == 1 ? effective_mps : channel->num_tx_buffers * effective_mps - 2; 33372e4c1850SMatthias Ringwald if (usable_mtu < channel->remote_mtu){ 33382e4c1850SMatthias Ringwald log_info("Remote MTU %u > max storable ERTM packet, only using MTU = %u", channel->remote_mtu, usable_mtu); 33392e4c1850SMatthias Ringwald channel->remote_mtu = usable_mtu; 33402e4c1850SMatthias Ringwald } 33412e4c1850SMatthias Ringwald } 33422e4c1850SMatthias Ringwald #endif 3343fa8473a4Smatthias.ringwald // for open: 33445a67bd4aSmatthias.ringwald channel->state = L2CAP_STATE_OPEN; 3345fa8473a4Smatthias.ringwald l2cap_emit_channel_opened(channel, 0); 3346c8e4258aSmatthias.ringwald } 3347c8e4258aSmatthias.ringwald break; 3348f62db1e3Smatthias.ringwald 3349f62db1e3Smatthias.ringwald case L2CAP_STATE_WAIT_DISCONNECT: 3350f62db1e3Smatthias.ringwald switch (code) { 3351f62db1e3Smatthias.ringwald case DISCONNECTION_RESPONSE: 3352*a254c508SMatthias Ringwald l2cap_finalize_channel_close(channel); 335327a923d0Smatthias.ringwald break; 33545a67bd4aSmatthias.ringwald default: 33555a67bd4aSmatthias.ringwald //@TODO: implement other signaling packets 33565a67bd4aSmatthias.ringwald break; 335727a923d0Smatthias.ringwald } 335827a923d0Smatthias.ringwald break; 335984836b65Smatthias.ringwald 336084836b65Smatthias.ringwald case L2CAP_STATE_CLOSED: 336184836b65Smatthias.ringwald // @TODO handle incoming requests 336284836b65Smatthias.ringwald break; 336384836b65Smatthias.ringwald 336484836b65Smatthias.ringwald case L2CAP_STATE_OPEN: 336584836b65Smatthias.ringwald //@TODO: implement other signaling packets, e.g. re-configure 336684836b65Smatthias.ringwald break; 336710642e45Smatthias.ringwald default: 336810642e45Smatthias.ringwald break; 336927a923d0Smatthias.ringwald } 33709da54300S[email protected] // log_info("new state %u", channel->state); 337127a923d0Smatthias.ringwald } 337227a923d0Smatthias.ringwald 3373*a254c508SMatthias Ringwald #ifdef ENABLE_CLASSIC 3374f3cc96b2SMatthias Ringwald static void l2cap_handle_information_request_complete(hci_connection_t * connection){ 3375f3cc96b2SMatthias Ringwald 3376f3cc96b2SMatthias Ringwald connection->l2cap_state.information_state = L2CAP_INFORMATION_STATE_DONE; 3377f3cc96b2SMatthias Ringwald 33789f0b00b1SMatthias Ringwald // emit event 33799f0b00b1SMatthias Ringwald uint8_t event[8]; 33809f0b00b1SMatthias Ringwald event[0] = L2CAP_EVENT_INFORMATION_RESPONSE; 33819f0b00b1SMatthias Ringwald event[1] = sizeof(event) - 2; 33829f0b00b1SMatthias Ringwald little_endian_store_16(event, 2, connection->con_handle); 33839f0b00b1SMatthias Ringwald little_endian_store_16(event, 4, connection->l2cap_state.extended_feature_mask); 33849f0b00b1SMatthias Ringwald little_endian_store_16(event, 6, connection->l2cap_state.fixed_channels_supported); 33859f0b00b1SMatthias Ringwald l2cap_emit_event(event, sizeof(event)); 33869f0b00b1SMatthias Ringwald 3387f3cc96b2SMatthias Ringwald // trigger connection request 3388f3cc96b2SMatthias Ringwald btstack_linked_list_iterator_t it; 3389f3cc96b2SMatthias Ringwald btstack_linked_list_iterator_init(&it, &l2cap_channels); 3390f3cc96b2SMatthias Ringwald while (btstack_linked_list_iterator_has_next(&it)){ 3391f3cc96b2SMatthias Ringwald l2cap_channel_t * channel = (l2cap_channel_t *) btstack_linked_list_iterator_next(&it); 3392f3cc96b2SMatthias Ringwald if (!l2cap_is_dynamic_channel_type(channel->channel_type)) continue; 3393f3cc96b2SMatthias Ringwald if (channel->con_handle != connection->con_handle) continue; 3394f3cc96b2SMatthias Ringwald 339563d7a647SMatthias Ringwald // incoming connection: information request was triggered after user has accepted connection, 339663d7a647SMatthias Ringwald // now: verify channel configuration, esp. if ertm will be mandatory 3397f3cc96b2SMatthias Ringwald if (channel->state == L2CAP_STATE_WAIT_INCOMING_EXTENDED_FEATURES){ 339863d7a647SMatthias Ringwald // default: continue 339963d7a647SMatthias Ringwald channel->state = L2CAP_STATE_WILL_SEND_CONNECTION_RESPONSE_ACCEPT; 3400*a254c508SMatthias Ringwald #ifdef ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE 340163d7a647SMatthias Ringwald if ((channel->mode == L2CAP_CHANNEL_MODE_ENHANCED_RETRANSMISSION) && ((connection->l2cap_state.extended_feature_mask & 0x08) == 0)){ 340263d7a647SMatthias Ringwald // ERTM not possible, select basic mode and release buffer 340363d7a647SMatthias Ringwald channel->mode = L2CAP_CHANNEL_MODE_BASIC; 340463d7a647SMatthias Ringwald l2cap_emit_simple_event_with_cid(channel, L2CAP_EVENT_ERTM_BUFFER_RELEASED); 340563d7a647SMatthias Ringwald 340663d7a647SMatthias Ringwald // bail if ERTM is mandatory 340763d7a647SMatthias Ringwald if (channel->ertm_mandatory){ 340863d7a647SMatthias Ringwald // We chose 'no resources available' for "ERTM mandatory but you don't even know ERTM exists" 340963d7a647SMatthias Ringwald log_info("ERTM mandatory -> reject connection"); 341063d7a647SMatthias Ringwald channel->state = L2CAP_STATE_WILL_SEND_CONNECTION_RESPONSE_DECLINE; 341163d7a647SMatthias Ringwald channel->reason = 0x04; // no resources available 341263d7a647SMatthias Ringwald } else { 341363d7a647SMatthias Ringwald log_info("ERTM not supported by remote -> use Basic mode"); 341463d7a647SMatthias Ringwald } 341563d7a647SMatthias Ringwald } 3416*a254c508SMatthias Ringwald #endif 3417f3cc96b2SMatthias Ringwald continue; 3418f3cc96b2SMatthias Ringwald } 3419f3cc96b2SMatthias Ringwald 342063d7a647SMatthias Ringwald // outgoing connection: information request is triggered before connection request 3421f3cc96b2SMatthias Ringwald if (channel->state == L2CAP_STATE_WAIT_OUTGOING_EXTENDED_FEATURES){ 3422f3cc96b2SMatthias Ringwald 3423f3cc96b2SMatthias Ringwald #ifdef ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE 3424f3cc96b2SMatthias Ringwald // if ERTM was requested, but is not listed in extended feature mask: 3425f3cc96b2SMatthias Ringwald if ((channel->mode == L2CAP_CHANNEL_MODE_ENHANCED_RETRANSMISSION) && ((connection->l2cap_state.extended_feature_mask & 0x08) == 0)){ 3426f3cc96b2SMatthias Ringwald 3427f3cc96b2SMatthias Ringwald if (channel->ertm_mandatory){ 3428f3cc96b2SMatthias Ringwald // bail if ERTM is mandatory 3429f3cc96b2SMatthias Ringwald channel->state = L2CAP_STATE_CLOSED; 3430f3cc96b2SMatthias Ringwald // map l2cap connection response result to BTstack status enumeration 3431f3cc96b2SMatthias Ringwald l2cap_handle_channel_open_failed(channel, L2CAP_CONNECTION_RESPONSE_RESULT_ERTM_NOT_SUPPORTED); 3432f3cc96b2SMatthias Ringwald // discard channel 3433f3cc96b2SMatthias Ringwald btstack_linked_list_remove(&l2cap_channels, (btstack_linked_item_t *) channel); 3434f3cc96b2SMatthias Ringwald l2cap_free_channel_entry(channel); 3435f3cc96b2SMatthias Ringwald continue; 3436f3cc96b2SMatthias Ringwald 3437f3cc96b2SMatthias Ringwald } else { 3438f3cc96b2SMatthias Ringwald // fallback to Basic mode 3439f3cc96b2SMatthias Ringwald l2cap_emit_simple_event_with_cid(channel, L2CAP_EVENT_ERTM_BUFFER_RELEASED); 3440f3cc96b2SMatthias Ringwald channel->mode = L2CAP_CHANNEL_MODE_BASIC; 3441f3cc96b2SMatthias Ringwald } 3442f3cc96b2SMatthias Ringwald } 3443f3cc96b2SMatthias Ringwald #endif 3444f3cc96b2SMatthias Ringwald 3445f3cc96b2SMatthias Ringwald // respond to connection request 3446f3cc96b2SMatthias Ringwald channel->state = L2CAP_STATE_WILL_SEND_CONNECTION_REQUEST; 3447f3cc96b2SMatthias Ringwald continue; 3448f3cc96b2SMatthias Ringwald } 3449f3cc96b2SMatthias Ringwald } 3450f3cc96b2SMatthias Ringwald } 3451*a254c508SMatthias Ringwald #endif 345200d93d79Smatthias.ringwald 3453ed2ed8e1SMatthias Ringwald // @pre command len is valid, see check in l2cap_acl_classic_handler 34547f02f414SMatthias Ringwald static void l2cap_signaling_handler_dispatch(hci_con_handle_t handle, uint8_t * command){ 345500d93d79Smatthias.ringwald 3456947e749bSMatthias Ringwald hci_connection_t * connection; 3457*a254c508SMatthias Ringwald btstack_linked_list_iterator_t it; 3458947e749bSMatthias Ringwald 3459947e749bSMatthias Ringwald // get code, signal identifier and command len 346000d93d79Smatthias.ringwald uint8_t code = command[L2CAP_SIGNALING_COMMAND_CODE_OFFSET]; 346100d93d79Smatthias.ringwald uint8_t sig_id = command[L2CAP_SIGNALING_COMMAND_SIGID_OFFSET]; 34620493bf3aSMatthias Ringwald uint16_t cmd_len = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_LENGTH_OFFSET); 346300d93d79Smatthias.ringwald 346400d93d79Smatthias.ringwald // general commands without an assigned channel 346500d93d79Smatthias.ringwald switch(code) { 346600d93d79Smatthias.ringwald 34670493bf3aSMatthias Ringwald case CONNECTION_REQUEST: 34680493bf3aSMatthias Ringwald if (cmd_len == 4){ 3469f8fbdce0SMatthias Ringwald uint16_t psm = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET); 3470f8fbdce0SMatthias Ringwald uint16_t source_cid = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET+2); 347100d93d79Smatthias.ringwald l2cap_handle_connection_request(handle, sig_id, psm, source_cid); 34720493bf3aSMatthias Ringwald } else { 34730493bf3aSMatthias Ringwald l2cap_register_signaling_response(handle, COMMAND_REJECT, sig_id, 0, L2CAP_REJ_CMD_UNKNOWN); 347400d93d79Smatthias.ringwald } 34750493bf3aSMatthias Ringwald return; 347600d93d79Smatthias.ringwald 34772b360848Smatthias.ringwald case ECHO_REQUEST: 3478e74c5f58SMatthias Ringwald l2cap_register_signaling_response(handle, code, sig_id, 0, 0); 34792b83fb7dSmatthias.ringwald return; 348000d93d79Smatthias.ringwald 34810493bf3aSMatthias Ringwald case INFORMATION_REQUEST: 34820493bf3aSMatthias Ringwald if (cmd_len == 2) { 34833e64cb44SMatthias Ringwald uint16_t info_type = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET); 34843e64cb44SMatthias Ringwald l2cap_register_signaling_response(handle, code, sig_id, 0, info_type); 34850493bf3aSMatthias Ringwald return; 3486*a254c508SMatthias Ringwald } 3487*a254c508SMatthias Ringwald break; 348800d93d79Smatthias.ringwald 3489947e749bSMatthias Ringwald case INFORMATION_RESPONSE: 3490947e749bSMatthias Ringwald connection = hci_connection_for_handle(handle); 34911b9cb13dSMatthias Ringwald if (!connection) return; 3492c1c10361SMatthias Ringwald switch (connection->l2cap_state.information_state){ 3493c1c10361SMatthias Ringwald case L2CAP_INFORMATION_STATE_W4_EXTENDED_FEATURE_RESPONSE: 34940defadfbSMatthias Ringwald // get extended features from response if valid 34950defadfbSMatthias Ringwald if (cmd_len >= 6) { 34961b9cb13dSMatthias Ringwald uint16_t info_type = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET); 34971b9cb13dSMatthias Ringwald uint16_t result = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET+2); 34980defadfbSMatthias Ringwald if (result == 0 && info_type == L2CAP_INFO_TYPE_EXTENDED_FEATURES_SUPPORTED) { 34991b9cb13dSMatthias Ringwald connection->l2cap_state.extended_feature_mask = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET+4); 35000defadfbSMatthias Ringwald } 3501543b84e4SMatthias Ringwald log_info("extended features mask 0x%02x", connection->l2cap_state.extended_feature_mask); 3502c1c10361SMatthias Ringwald if ((connection->l2cap_state.extended_feature_mask & 0x80) != 0){ 3503c1c10361SMatthias Ringwald connection->l2cap_state.information_state = L2CAP_INFORMATION_STATE_W2_SEND_FIXED_CHANNELS_REQUEST; 3504c1c10361SMatthias Ringwald } else { 3505f3cc96b2SMatthias Ringwald // information request complete 3506f3cc96b2SMatthias Ringwald l2cap_handle_information_request_complete(connection); 3507c1c10361SMatthias Ringwald } 3508c1c10361SMatthias Ringwald } 3509c1c10361SMatthias Ringwald break; 3510c1c10361SMatthias Ringwald case L2CAP_INFORMATION_STATE_W4_FIXED_CHANNELS_RESPONSE: 3511c1c10361SMatthias Ringwald if (cmd_len >= 12) { 3512c1c10361SMatthias Ringwald uint16_t info_type = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET); 3513c1c10361SMatthias Ringwald uint16_t result = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET+2); 3514c1c10361SMatthias Ringwald if (result == 0 && info_type == L2CAP_INFO_TYPE_FIXED_CHANNELS_SUPPORTED) { 35153cc0a368SMatthias Ringwald connection->l2cap_state.fixed_channels_supported = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET + 4); 3516c1c10361SMatthias Ringwald } 35173cc0a368SMatthias Ringwald log_info("fixed channels mask 0x%02x", connection->l2cap_state.fixed_channels_supported); 3518c1c10361SMatthias Ringwald // information request complete 3519c1c10361SMatthias Ringwald l2cap_handle_information_request_complete(connection); 3520c1c10361SMatthias Ringwald } 3521c1c10361SMatthias Ringwald break; 3522c1c10361SMatthias Ringwald default: 3523c1c10361SMatthias Ringwald break; 3524c1c10361SMatthias Ringwald } 35251b9cb13dSMatthias Ringwald return; 35261b9cb13dSMatthias Ringwald 3527*a254c508SMatthias Ringwald #ifdef ENABLE_L2CAP_ENHANCED_DATA_CHANNELS 3528*a254c508SMatthias Ringwald case L2CAP_CREDIT_BASED_CONNECTION_REQUEST: 3529*a254c508SMatthias Ringwald case L2CAP_CREDIT_BASED_CONNECTION_RESPONSE: 3530*a254c508SMatthias Ringwald case L2CAP_CREDIT_BASED_RECONFIGURE_REQUEST: 3531*a254c508SMatthias Ringwald case L2CAP_CREDIT_BASED_RECONFIGURE_RESPONSE: 3532*a254c508SMatthias Ringwald l2cap_enhanced_signaling_handler_dispatch(handle, L2CAP_CID_SIGNALING, command, sig_id); 3533*a254c508SMatthias Ringwald return; 3534*a254c508SMatthias Ringwald case L2CAP_FLOW_CONTROL_CREDIT_INDICATION: 3535*a254c508SMatthias Ringwald // return if valid 3536*a254c508SMatthias Ringwald if (l2cap_credit_based_handle_credit_indication(handle, command, cmd_len)) return; 3537*a254c508SMatthias Ringwald break; 3538*a254c508SMatthias Ringwald 3539*a254c508SMatthias Ringwald case COMMAND_REJECT: 3540*a254c508SMatthias Ringwald btstack_linked_list_iterator_init(&it, &l2cap_channels); 3541*a254c508SMatthias Ringwald while (btstack_linked_list_iterator_has_next(&it)) { 3542*a254c508SMatthias Ringwald l2cap_channel_t *channel = (l2cap_channel_t *) btstack_linked_list_iterator_next(&it); 3543*a254c508SMatthias Ringwald if (!l2cap_is_dynamic_channel_type(channel->channel_type)) continue; 3544*a254c508SMatthias Ringwald if (channel->con_handle != handle) continue; 3545*a254c508SMatthias Ringwald if (channel->local_sig_id != sig_id) continue; 3546*a254c508SMatthias Ringwald if (channel->state != L2CAP_STATE_WAIT_ENHANCED_CONNECTION_RESPONSE) continue; 3547*a254c508SMatthias Ringwald 3548*a254c508SMatthias Ringwald // open failed 3549*a254c508SMatthias Ringwald channel->state = L2CAP_STATE_CLOSED; 3550*a254c508SMatthias Ringwald l2cap_emit_enhanced_data_channel_opened(channel, 3551*a254c508SMatthias Ringwald ERROR_CODE_CONNECTION_REJECTED_DUE_TO_LIMITED_RESOURCES); 3552*a254c508SMatthias Ringwald // drop failed channel 3553*a254c508SMatthias Ringwald btstack_linked_list_iterator_remove(&it); 3554*a254c508SMatthias Ringwald l2cap_free_channel_entry(channel); 3555*a254c508SMatthias Ringwald } 3556*a254c508SMatthias Ringwald break; 3557*a254c508SMatthias Ringwald #endif 3558*a254c508SMatthias Ringwald 355900d93d79Smatthias.ringwald default: 356000d93d79Smatthias.ringwald break; 356100d93d79Smatthias.ringwald } 356200d93d79Smatthias.ringwald 356300d93d79Smatthias.ringwald // Get potential destination CID 3564f8fbdce0SMatthias Ringwald uint16_t dest_cid = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET); 356500d93d79Smatthias.ringwald 356600d93d79Smatthias.ringwald // Find channel for this sig_id and connection handle 3567665d90f2SMatthias Ringwald btstack_linked_list_iterator_init(&it, &l2cap_channels); 3568665d90f2SMatthias Ringwald while (btstack_linked_list_iterator_has_next(&it)){ 3569665d90f2SMatthias Ringwald l2cap_channel_t * channel = (l2cap_channel_t *) btstack_linked_list_iterator_next(&it); 3570fad84cafSMatthias Ringwald if (!l2cap_is_dynamic_channel_type(channel->channel_type)) continue; 3571fc64f94aSMatthias Ringwald if (channel->con_handle != handle) continue; 357200d93d79Smatthias.ringwald if (code & 1) { 3573b1988dceSmatthias.ringwald // match odd commands (responses) by previous signaling identifier 3574b1988dceSmatthias.ringwald if (channel->local_sig_id == sig_id) { 357500d93d79Smatthias.ringwald l2cap_signaling_handler_channel(channel, command); 3576*a254c508SMatthias Ringwald return; 357700d93d79Smatthias.ringwald } 357800d93d79Smatthias.ringwald } else { 3579b1988dceSmatthias.ringwald // match even commands (requests) by local channel id 358000d93d79Smatthias.ringwald if (channel->local_cid == dest_cid) { 358100d93d79Smatthias.ringwald l2cap_signaling_handler_channel(channel, command); 3582*a254c508SMatthias Ringwald return; 3583*a254c508SMatthias Ringwald } 3584*a254c508SMatthias Ringwald } 3585*a254c508SMatthias Ringwald } 3586*a254c508SMatthias Ringwald 3587*a254c508SMatthias Ringwald // send command reject 3588*a254c508SMatthias Ringwald l2cap_register_signaling_response(handle, COMMAND_REJECT, sig_id, 0, L2CAP_REJ_CMD_UNKNOWN); 3589*a254c508SMatthias Ringwald } 3590*a254c508SMatthias Ringwald #endif 3591*a254c508SMatthias Ringwald 3592*a254c508SMatthias Ringwald #ifdef L2CAP_USES_CHANNELS 3593*a254c508SMatthias Ringwald static l2cap_service_t * l2cap_get_service_internal(btstack_linked_list_t * services, uint16_t psm){ 3594*a254c508SMatthias Ringwald btstack_linked_list_iterator_t it; 3595*a254c508SMatthias Ringwald btstack_linked_list_iterator_init(&it, services); 3596*a254c508SMatthias Ringwald while (btstack_linked_list_iterator_has_next(&it)){ 3597*a254c508SMatthias Ringwald l2cap_service_t * service = (l2cap_service_t *) btstack_linked_list_iterator_next(&it); 3598*a254c508SMatthias Ringwald if ( service->psm == psm){ 3599*a254c508SMatthias Ringwald return service; 3600*a254c508SMatthias Ringwald }; 3601*a254c508SMatthias Ringwald } 3602*a254c508SMatthias Ringwald return NULL; 3603*a254c508SMatthias Ringwald } 3604*a254c508SMatthias Ringwald #endif 3605*a254c508SMatthias Ringwald 3606*a254c508SMatthias Ringwald #ifdef ENABLE_L2CAP_ENHANCED_DATA_CHANNELS 3607*a254c508SMatthias Ringwald 3608*a254c508SMatthias Ringwald static uint8_t l2cap_enhanced_setup_channels(btstack_linked_list_t * channels, 3609*a254c508SMatthias Ringwald btstack_packet_handler_t packet_handler, uint8_t num_channels, 3610*a254c508SMatthias Ringwald hci_connection_t * connection, uint16_t psm, uint16_t mtu, gap_security_level_t security_level){ 3611*a254c508SMatthias Ringwald uint8_t i; 3612*a254c508SMatthias Ringwald uint8_t status = ERROR_CODE_SUCCESS; 3613*a254c508SMatthias Ringwald for (i=0;i<num_channels;i++){ 3614*a254c508SMatthias Ringwald l2cap_channel_t * channel = l2cap_create_channel_entry(packet_handler, L2CAP_CHANNEL_TYPE_ENHANCED_DATA_CHANNEL, connection->address, connection->address_type, psm, mtu, security_level); 3615*a254c508SMatthias Ringwald if (!channel) { 3616*a254c508SMatthias Ringwald status = BTSTACK_MEMORY_ALLOC_FAILED; 3617*a254c508SMatthias Ringwald break; 3618*a254c508SMatthias Ringwald } 3619*a254c508SMatthias Ringwald channel->con_handle = connection->con_handle; 3620*a254c508SMatthias Ringwald btstack_linked_list_add_tail(channels, (btstack_linked_item_t *) channel); 3621*a254c508SMatthias Ringwald } 3622*a254c508SMatthias Ringwald 3623*a254c508SMatthias Ringwald // free channels if not all allocated 3624*a254c508SMatthias Ringwald if (status != ERROR_CODE_SUCCESS){ 3625*a254c508SMatthias Ringwald while (true) { 3626*a254c508SMatthias Ringwald l2cap_channel_t * channel = (l2cap_channel_t *) btstack_linked_list_pop(channels); 3627*a254c508SMatthias Ringwald if (channel == NULL) break; 3628*a254c508SMatthias Ringwald l2cap_free_channel_entry(channel); 3629*a254c508SMatthias Ringwald } 3630*a254c508SMatthias Ringwald } 3631*a254c508SMatthias Ringwald 3632*a254c508SMatthias Ringwald return status; 3633*a254c508SMatthias Ringwald } 3634*a254c508SMatthias Ringwald 3635*a254c508SMatthias Ringwald static inline l2cap_service_t * l2cap_enhanced_get_service(uint16_t spsm){ 3636*a254c508SMatthias Ringwald return l2cap_get_service_internal(&l2cap_enhanced_services, spsm); 3637*a254c508SMatthias Ringwald } 3638*a254c508SMatthias Ringwald 3639*a254c508SMatthias Ringwald static inline uint8_t l2cap_enhanced_status_for_result(uint16_t result) { 3640*a254c508SMatthias Ringwald switch (result) { 3641*a254c508SMatthias Ringwald case 0x0000: 3642*a254c508SMatthias Ringwald return ERROR_CODE_SUCCESS; 3643*a254c508SMatthias Ringwald case 0x0002: 3644*a254c508SMatthias Ringwald return L2CAP_CONNECTION_RESPONSE_RESULT_REFUSED_PSM; 3645*a254c508SMatthias Ringwald case 0x0004: 3646*a254c508SMatthias Ringwald return L2CAP_CONNECTION_RESPONSE_RESULT_REFUSED_RESOURCES; 3647*a254c508SMatthias Ringwald case 0x0005: 3648*a254c508SMatthias Ringwald case 0x0006: 3649*a254c508SMatthias Ringwald case 0x0007: 3650*a254c508SMatthias Ringwald case 0x0008: 3651*a254c508SMatthias Ringwald return L2CAP_CONNECTION_RESPONSE_RESULT_REFUSED_SECURITY; 3652*a254c508SMatthias Ringwald default: 3653*a254c508SMatthias Ringwald // invalid Source CID, Source CID already allocated, unacceptable parameters 3654*a254c508SMatthias Ringwald return L2CAP_CONNECTION_RESPONSE_UNKNOWN_ERROR; 3655*a254c508SMatthias Ringwald } 3656*a254c508SMatthias Ringwald } 3657*a254c508SMatthias Ringwald 3658*a254c508SMatthias Ringwald static int l2cap_enhanced_signaling_handler_dispatch(hci_con_handle_t handle, uint16_t signaling_cid, uint8_t *command, 3659*a254c508SMatthias Ringwald uint8_t sig_id) { 3660*a254c508SMatthias Ringwald 3661*a254c508SMatthias Ringwald hci_connection_t *connection; 3662*a254c508SMatthias Ringwald btstack_linked_list_iterator_t it; 3663*a254c508SMatthias Ringwald l2cap_service_t *service; 3664*a254c508SMatthias Ringwald uint16_t spsm; 3665*a254c508SMatthias Ringwald uint8_t num_channels; 3666*a254c508SMatthias Ringwald uint16_t num_channels_and_signaling_cid; 3667*a254c508SMatthias Ringwald uint8_t i; 3668*a254c508SMatthias Ringwald uint16_t new_mtu; 3669*a254c508SMatthias Ringwald uint16_t new_mps; 3670*a254c508SMatthias Ringwald uint16_t initial_credits; 3671*a254c508SMatthias Ringwald uint16_t result; 3672*a254c508SMatthias Ringwald uint8_t status; 3673*a254c508SMatthias Ringwald 3674*a254c508SMatthias Ringwald uint8_t code = command[L2CAP_SIGNALING_COMMAND_CODE_OFFSET]; 3675*a254c508SMatthias Ringwald uint16_t len = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_LENGTH_OFFSET); 3676*a254c508SMatthias Ringwald log_info("enhanced dispatch: command 0x%02x, sig id %u, len %u", code, sig_id, len); 3677*a254c508SMatthias Ringwald 3678*a254c508SMatthias Ringwald switch (code) { 3679*a254c508SMatthias Ringwald case L2CAP_CREDIT_BASED_CONNECTION_REQUEST: 3680*a254c508SMatthias Ringwald // check size 3681*a254c508SMatthias Ringwald if (len < 10u) return 0u; 3682*a254c508SMatthias Ringwald 3683*a254c508SMatthias Ringwald // get hci connection, bail if not found (must not happen) 3684*a254c508SMatthias Ringwald connection = hci_connection_for_handle(handle); 3685*a254c508SMatthias Ringwald btstack_assert(connection != NULL); 3686*a254c508SMatthias Ringwald 3687*a254c508SMatthias Ringwald // get num channels to establish 3688*a254c508SMatthias Ringwald num_channels = (len - 8) / sizeof(uint16_t); 3689*a254c508SMatthias Ringwald 3690*a254c508SMatthias Ringwald // combine signaling cid and number channels for l2cap_register_signaling_response 3691*a254c508SMatthias Ringwald num_channels_and_signaling_cid = (num_channels << 8) | signaling_cid; 3692*a254c508SMatthias Ringwald 3693*a254c508SMatthias Ringwald // check if service registered 3694*a254c508SMatthias Ringwald spsm = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET); 3695*a254c508SMatthias Ringwald service = l2cap_enhanced_get_service(spsm); 3696*a254c508SMatthias Ringwald 3697*a254c508SMatthias Ringwald if (service) { 3698*a254c508SMatthias Ringwald 3699*a254c508SMatthias Ringwald uint16_t remote_mtu = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET + 2); 3700*a254c508SMatthias Ringwald uint16_t remote_mps = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET + 4); 3701*a254c508SMatthias Ringwald uint16_t credits_outgoing = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET + 6); 3702*a254c508SMatthias Ringwald 3703*a254c508SMatthias Ringwald // param: check remote mtu 3704*a254c508SMatthias Ringwald if (service->mtu > remote_mtu) { 3705*a254c508SMatthias Ringwald // 0x000B All connections refused – invalid parameters 3706*a254c508SMatthias Ringwald l2cap_register_signaling_response(handle, L2CAP_CREDIT_BASED_CONNECTION_REQUEST, sig_id, 3707*a254c508SMatthias Ringwald num_channels_and_signaling_cid, 0x000C); 3708*a254c508SMatthias Ringwald return 1; 3709*a254c508SMatthias Ringwald } 3710*a254c508SMatthias Ringwald 3711*a254c508SMatthias Ringwald // security: check authentication 3712*a254c508SMatthias Ringwald if (service->required_security_level >= LEVEL_3) { 3713*a254c508SMatthias Ringwald if (!gap_authenticated(handle)) { 3714*a254c508SMatthias Ringwald // 0x0005 Connection refused – insufficient authentication 3715*a254c508SMatthias Ringwald l2cap_register_signaling_response(handle, L2CAP_CREDIT_BASED_CONNECTION_REQUEST, sig_id, 3716*a254c508SMatthias Ringwald num_channels_and_signaling_cid, 0x0005); 3717*a254c508SMatthias Ringwald return 1; 3718*a254c508SMatthias Ringwald } 3719*a254c508SMatthias Ringwald } 3720*a254c508SMatthias Ringwald 3721*a254c508SMatthias Ringwald // security: check encryption 3722*a254c508SMatthias Ringwald // L2CAP.TS.p31 does not check for 0x0008 Connection refused - insufficient encryption which might be send for no encryption 3723*a254c508SMatthias Ringwald if (service->required_security_level >= LEVEL_2) { 3724*a254c508SMatthias Ringwald if (gap_encryption_key_size(handle) < 16) { 3725*a254c508SMatthias Ringwald // 0x0007 Connection refused – insufficient encryption key size 3726*a254c508SMatthias Ringwald l2cap_register_signaling_response(handle, L2CAP_CREDIT_BASED_CONNECTION_REQUEST, sig_id, 3727*a254c508SMatthias Ringwald num_channels_and_signaling_cid, 0x0007); 3728*a254c508SMatthias Ringwald return 1; 3729*a254c508SMatthias Ringwald } 3730*a254c508SMatthias Ringwald } 3731*a254c508SMatthias Ringwald 3732*a254c508SMatthias Ringwald // report the last result code != 0 3733*a254c508SMatthias Ringwald result = 0; 3734*a254c508SMatthias Ringwald // store one of the local cids for the event 3735*a254c508SMatthias Ringwald uint16_t a_local_cid = 0; 3736*a254c508SMatthias Ringwald for (i = 0; i < num_channels; i++) { 3737*a254c508SMatthias Ringwald 3738*a254c508SMatthias Ringwald // check source cids 3739*a254c508SMatthias Ringwald uint16_t source_cid = little_endian_read_16(command, 12 + (i * 2)); 3740*a254c508SMatthias Ringwald if (source_cid < 0x40u) { 3741*a254c508SMatthias Ringwald // 0x0009 Connection refused - Invalid Source CID 3742*a254c508SMatthias Ringwald result = 0x0009; 3743*a254c508SMatthias Ringwald continue; 3744*a254c508SMatthias Ringwald } 3745*a254c508SMatthias Ringwald 3746*a254c508SMatthias Ringwald // go through list of channels for this ACL connection and check if we get a match 3747*a254c508SMatthias Ringwald btstack_linked_list_iterator_init(&it, &l2cap_channels); 3748*a254c508SMatthias Ringwald bool source_cid_allocated = false; 3749*a254c508SMatthias Ringwald while (btstack_linked_list_iterator_has_next(&it)) { 3750*a254c508SMatthias Ringwald l2cap_channel_t *channel = (l2cap_channel_t *) btstack_linked_list_iterator_next(&it); 3751*a254c508SMatthias Ringwald if (!l2cap_is_dynamic_channel_type(channel->channel_type)) continue; 3752*a254c508SMatthias Ringwald if (channel->con_handle != handle) continue; 3753*a254c508SMatthias Ringwald if (channel->remote_cid != source_cid) continue; 3754*a254c508SMatthias Ringwald source_cid_allocated = true; 3755*a254c508SMatthias Ringwald break; 3756*a254c508SMatthias Ringwald } 3757*a254c508SMatthias Ringwald if (source_cid_allocated) { 3758*a254c508SMatthias Ringwald result = 0x00a; 3759*a254c508SMatthias Ringwald continue; 3760*a254c508SMatthias Ringwald } 3761*a254c508SMatthias Ringwald 3762*a254c508SMatthias Ringwald // setup channel 3763*a254c508SMatthias Ringwald l2cap_channel_t *channel = l2cap_create_channel_entry(service->packet_handler, 3764*a254c508SMatthias Ringwald L2CAP_CHANNEL_TYPE_ENHANCED_DATA_CHANNEL, 3765*a254c508SMatthias Ringwald connection->address, 3766*a254c508SMatthias Ringwald connection->address_type, spsm, 3767*a254c508SMatthias Ringwald service->mtu, 3768*a254c508SMatthias Ringwald service->required_security_level); 3769*a254c508SMatthias Ringwald 3770*a254c508SMatthias Ringwald if (channel == NULL) { 3771*a254c508SMatthias Ringwald // Some connections refused – insufficient resources available 3772*a254c508SMatthias Ringwald result = 0x004; 3773*a254c508SMatthias Ringwald continue; 3774*a254c508SMatthias Ringwald } 3775*a254c508SMatthias Ringwald 3776*a254c508SMatthias Ringwald // setup state 3777*a254c508SMatthias Ringwald channel->state = L2CAP_STATE_WAIT_CLIENT_ACCEPT_OR_REJECT; 3778*a254c508SMatthias Ringwald channel->state_var |= L2CAP_CHANNEL_STATE_VAR_INCOMING; 3779*a254c508SMatthias Ringwald channel->con_handle = connection->con_handle; 3780*a254c508SMatthias Ringwald channel->remote_sig_id = sig_id; 3781*a254c508SMatthias Ringwald channel->remote_cid = source_cid; 3782*a254c508SMatthias Ringwald channel->remote_mtu = remote_mtu; 3783*a254c508SMatthias Ringwald channel->remote_mps = remote_mps; 3784*a254c508SMatthias Ringwald channel->credits_outgoing = credits_outgoing; 3785*a254c508SMatthias Ringwald channel->cid_index = i; 3786*a254c508SMatthias Ringwald channel->num_cids = num_channels; 3787*a254c508SMatthias Ringwald 3788*a254c508SMatthias Ringwald // if more than one error, we can report any of them 3789*a254c508SMatthias Ringwald channel->reason = result; 3790*a254c508SMatthias Ringwald 3791*a254c508SMatthias Ringwald btstack_linked_list_add_tail(&l2cap_channels, (btstack_linked_item_t *) channel); 3792*a254c508SMatthias Ringwald 3793*a254c508SMatthias Ringwald a_local_cid = channel->local_cid; 3794*a254c508SMatthias Ringwald } 3795*a254c508SMatthias Ringwald 3796*a254c508SMatthias Ringwald // if no channels have been created, all have been refused, and we can respond right away 3797*a254c508SMatthias Ringwald if (a_local_cid == 0) { 3798*a254c508SMatthias Ringwald l2cap_register_signaling_response(handle, L2CAP_CREDIT_BASED_CONNECTION_REQUEST, sig_id, 3799*a254c508SMatthias Ringwald num_channels_and_signaling_cid, result); 3800*a254c508SMatthias Ringwald return 1; 3801*a254c508SMatthias Ringwald } 3802*a254c508SMatthias Ringwald 3803*a254c508SMatthias Ringwald // emit incoming data connection event 3804*a254c508SMatthias Ringwald uint8_t event[16]; 3805*a254c508SMatthias Ringwald event[0] = L2CAP_EVENT_DATA_CHANNEL_INCOMING; 3806*a254c508SMatthias Ringwald event[1] = sizeof(event) - 2; 3807*a254c508SMatthias Ringwald event[2] = connection->address_type; 3808*a254c508SMatthias Ringwald reverse_bd_addr(connection->address, &event[3]); 3809*a254c508SMatthias Ringwald little_endian_store_16(event, 9, connection->con_handle); 3810*a254c508SMatthias Ringwald little_endian_store_16(event, 11, spsm); 3811*a254c508SMatthias Ringwald event[13] = num_channels; 3812*a254c508SMatthias Ringwald little_endian_store_16(event, 14, a_local_cid); 3813*a254c508SMatthias Ringwald hci_dump_packet(HCI_EVENT_PACKET, 0, event, sizeof(event)); 3814*a254c508SMatthias Ringwald (*service->packet_handler)(HCI_EVENT_PACKET, a_local_cid, event, sizeof(event)); 3815*a254c508SMatthias Ringwald 3816*a254c508SMatthias Ringwald } else { 3817*a254c508SMatthias Ringwald // All connections refused – SPSM not supported 3818*a254c508SMatthias Ringwald l2cap_register_signaling_response(handle, L2CAP_CREDIT_BASED_CONNECTION_REQUEST, sig_id, 3819*a254c508SMatthias Ringwald num_channels_and_signaling_cid, 0x0002); 3820*a254c508SMatthias Ringwald } 3821*a254c508SMatthias Ringwald return 1; 3822*a254c508SMatthias Ringwald 3823*a254c508SMatthias Ringwald case L2CAP_CREDIT_BASED_CONNECTION_RESPONSE: 3824*a254c508SMatthias Ringwald // check size 3825*a254c508SMatthias Ringwald if (len < 10u) return 0u; 3826*a254c508SMatthias Ringwald 3827*a254c508SMatthias Ringwald // get hci connection, ignore if not found 3828*a254c508SMatthias Ringwald connection = hci_connection_for_handle(handle); 3829*a254c508SMatthias Ringwald if (connection == NULL) return 0; 3830*a254c508SMatthias Ringwald 3831*a254c508SMatthias Ringwald // get channel config: mtu, mps, initial credits, result 3832*a254c508SMatthias Ringwald new_mtu = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET + 0); 3833*a254c508SMatthias Ringwald new_mps = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET + 2); 3834*a254c508SMatthias Ringwald initial_credits = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET + 4); 3835*a254c508SMatthias Ringwald result = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET + 6); 3836*a254c508SMatthias Ringwald status = l2cap_enhanced_status_for_result(result); 3837*a254c508SMatthias Ringwald 3838*a254c508SMatthias Ringwald // get num channels to modify 3839*a254c508SMatthias Ringwald num_channels = (len - 8) / sizeof(uint16_t); 3840*a254c508SMatthias Ringwald btstack_linked_list_iterator_init(&it, &l2cap_channels); 3841*a254c508SMatthias Ringwald while (btstack_linked_list_iterator_has_next(&it)) { 3842*a254c508SMatthias Ringwald l2cap_channel_t *channel = (l2cap_channel_t *) btstack_linked_list_iterator_next(&it); 3843*a254c508SMatthias Ringwald if (!l2cap_is_dynamic_channel_type(channel->channel_type)) continue; 3844*a254c508SMatthias Ringwald if (channel->con_handle != handle) continue; 3845*a254c508SMatthias Ringwald if (channel->local_sig_id != sig_id) continue; 3846*a254c508SMatthias Ringwald if (channel->state != L2CAP_STATE_WAIT_ENHANCED_CONNECTION_RESPONSE) continue; 3847*a254c508SMatthias Ringwald if (channel->cid_index < num_channels) { 3848*a254c508SMatthias Ringwald uint16_t remote_cid = little_endian_read_16(command, 12 + channel->cid_index * sizeof(uint16_t)); 3849*a254c508SMatthias Ringwald if (remote_cid != 0) { 3850*a254c508SMatthias Ringwald channel->state = L2CAP_STATE_OPEN; 3851*a254c508SMatthias Ringwald channel->remote_cid = remote_cid; 3852*a254c508SMatthias Ringwald channel->remote_mtu = new_mtu; 3853*a254c508SMatthias Ringwald channel->remote_mps = new_mps; 3854*a254c508SMatthias Ringwald channel->credits_outgoing = initial_credits; 3855*a254c508SMatthias Ringwald l2cap_emit_enhanced_data_channel_opened(channel, ERROR_CODE_SUCCESS); 3856*a254c508SMatthias Ringwald continue; 3857*a254c508SMatthias Ringwald } 3858*a254c508SMatthias Ringwald } 3859*a254c508SMatthias Ringwald // open failed 3860*a254c508SMatthias Ringwald l2cap_emit_enhanced_data_channel_opened(channel, status); 3861*a254c508SMatthias Ringwald // drop failed channel 3862*a254c508SMatthias Ringwald btstack_linked_list_iterator_remove(&it); 3863*a254c508SMatthias Ringwald btstack_memory_l2cap_channel_free(channel); 3864*a254c508SMatthias Ringwald } 3865*a254c508SMatthias Ringwald return 1; 3866*a254c508SMatthias Ringwald 3867*a254c508SMatthias Ringwald case L2CAP_CREDIT_BASED_RECONFIGURE_REQUEST: 3868*a254c508SMatthias Ringwald // check minimal size 3869*a254c508SMatthias Ringwald if (len < 6) return 0u; 3870*a254c508SMatthias Ringwald 3871*a254c508SMatthias Ringwald // get hci connection, bail if not found (must not happen) 3872*a254c508SMatthias Ringwald connection = hci_connection_for_handle(handle); 3873*a254c508SMatthias Ringwald btstack_assert(connection != NULL); 3874*a254c508SMatthias Ringwald 3875*a254c508SMatthias Ringwald // get num channels to modify 3876*a254c508SMatthias Ringwald num_channels = (len - 4) / sizeof(uint16_t); 3877*a254c508SMatthias Ringwald 3878*a254c508SMatthias Ringwald // get new mtu and mps 3879*a254c508SMatthias Ringwald new_mtu = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET + 0); 3880*a254c508SMatthias Ringwald new_mps = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET + 2); 3881*a254c508SMatthias Ringwald 3882*a254c508SMatthias Ringwald // validate request 3883*a254c508SMatthias Ringwald result = 0; 3884*a254c508SMatthias Ringwald for (i = 0; i < num_channels; i++) { 3885*a254c508SMatthias Ringwald // check cid 3886*a254c508SMatthias Ringwald uint16_t remote_cid = little_endian_read_16(command, 8 + (i * sizeof(uint16_t))); 3887*a254c508SMatthias Ringwald l2cap_channel_t *channel = l2cap_get_channel_for_remote_handle_and_cid(handle, remote_cid); 3888*a254c508SMatthias Ringwald if (channel == NULL) { 3889*a254c508SMatthias Ringwald // 0x0003 Reconfiguration failed - one or more Destination CIDs invalid 3890*a254c508SMatthias Ringwald result = 0x0003; 3891*a254c508SMatthias Ringwald break; 3892*a254c508SMatthias Ringwald } 3893*a254c508SMatthias Ringwald // check MTU is not reduced 3894*a254c508SMatthias Ringwald if (channel->remote_mtu > new_mtu) { 3895*a254c508SMatthias Ringwald // 0x0001 Reconfiguration failed - reduction in size of MTU not allowed 3896*a254c508SMatthias Ringwald result = 0x0001; 3897*a254c508SMatthias Ringwald break; 3898*a254c508SMatthias Ringwald } 3899*a254c508SMatthias Ringwald // check MPS reduction 3900*a254c508SMatthias Ringwald if ((num_channels > 1) && (channel->remote_mps > new_mps)) { 3901*a254c508SMatthias Ringwald // 0x002 Reconfiguration failed - reduction in size of MPS not allowed for more than one channel at a time 3902*a254c508SMatthias Ringwald result = 0x0002; 3903*a254c508SMatthias Ringwald break; 3904*a254c508SMatthias Ringwald } 3905*a254c508SMatthias Ringwald // check MPS valid 3906*a254c508SMatthias Ringwald if (new_mps < l2cap_enhanced_mps_min) { 3907*a254c508SMatthias Ringwald // 0x0002 Reconfiguration failed - other unacceptable parameters 3908*a254c508SMatthias Ringwald result = 0x0004; 39094e32727eSmatthias.ringwald break; 391000d93d79Smatthias.ringwald } 391100d93d79Smatthias.ringwald } 3912*a254c508SMatthias Ringwald 3913*a254c508SMatthias Ringwald // send reject 3914*a254c508SMatthias Ringwald if (result != 0) { 3915*a254c508SMatthias Ringwald l2cap_register_signaling_response(handle, L2CAP_CREDIT_BASED_RECONFIGURE_REQUEST, sig_id, signaling_cid, 3916*a254c508SMatthias Ringwald result); 3917*a254c508SMatthias Ringwald return 1; 391800d93d79Smatthias.ringwald } 3919*a254c508SMatthias Ringwald 3920*a254c508SMatthias Ringwald // update channels 3921*a254c508SMatthias Ringwald for (i = 0; i < num_channels; i++) { 3922*a254c508SMatthias Ringwald uint16_t remote_cid = little_endian_read_16(command, 8 + (i * sizeof(uint16_t))); 3923*a254c508SMatthias Ringwald l2cap_channel_t *channel = l2cap_get_channel_for_remote_handle_and_cid(handle, remote_cid); 3924*a254c508SMatthias Ringwald channel->remote_mps = new_mps; 3925*a254c508SMatthias Ringwald channel->remote_mtu = new_mtu; 3926*a254c508SMatthias Ringwald // emit event 3927*a254c508SMatthias Ringwald uint8_t event[8]; 3928*a254c508SMatthias Ringwald event[0] = L2CAP_EVENT_DATA_CHANNEL_RECONFIGURED; 3929*a254c508SMatthias Ringwald event[1] = sizeof(event) - 2; 3930*a254c508SMatthias Ringwald little_endian_store_16(event, 2, channel->local_cid); 3931*a254c508SMatthias Ringwald little_endian_store_16(event, 4, new_mtu); 3932*a254c508SMatthias Ringwald little_endian_store_16(event, 6, new_mps); 3933*a254c508SMatthias Ringwald l2cap_dispatch_to_channel(channel, HCI_EVENT_PACKET, event, sizeof(event)); 393400d93d79Smatthias.ringwald } 3935*a254c508SMatthias Ringwald 3936*a254c508SMatthias Ringwald // send accept 3937*a254c508SMatthias Ringwald l2cap_register_signaling_response(handle, L2CAP_CREDIT_BASED_RECONFIGURE_REQUEST, sig_id, signaling_cid, 0); 3938*a254c508SMatthias Ringwald return 1; 3939*a254c508SMatthias Ringwald 3940*a254c508SMatthias Ringwald case L2CAP_CREDIT_BASED_RECONFIGURE_RESPONSE: 3941*a254c508SMatthias Ringwald // check size 3942*a254c508SMatthias Ringwald if (len < 2u) return 0u; 3943*a254c508SMatthias Ringwald 3944*a254c508SMatthias Ringwald result = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET + 0); 3945*a254c508SMatthias Ringwald btstack_linked_list_iterator_init(&it, &l2cap_channels); 3946*a254c508SMatthias Ringwald while (btstack_linked_list_iterator_has_next(&it)) { 3947*a254c508SMatthias Ringwald l2cap_channel_t *channel = (l2cap_channel_t *) btstack_linked_list_iterator_next(&it); 3948*a254c508SMatthias Ringwald if (!l2cap_is_dynamic_channel_type(channel->channel_type)) continue; 3949*a254c508SMatthias Ringwald if (channel->con_handle != handle) continue; 3950*a254c508SMatthias Ringwald if (channel->local_sig_id != sig_id) continue; 3951*a254c508SMatthias Ringwald if (channel->state != L2CAP_STATE_WAIT_ENHANCED_RENEGOTIATION_RESPONSE) continue; 3952*a254c508SMatthias Ringwald // complete request 3953*a254c508SMatthias Ringwald if (result == 0) { 3954*a254c508SMatthias Ringwald channel->receive_sdu_buffer = channel->renegotiate_sdu_buffer; 3955*a254c508SMatthias Ringwald channel->local_mtu = channel->renegotiate_mtu; 3956*a254c508SMatthias Ringwald } 3957*a254c508SMatthias Ringwald channel->state = L2CAP_STATE_OPEN; 3958*a254c508SMatthias Ringwald // emit event 3959*a254c508SMatthias Ringwald l2cap_emit_enhanced_data_channel_reconfigure_complete(channel, result); 3960*a254c508SMatthias Ringwald } 3961*a254c508SMatthias Ringwald break; 3962*a254c508SMatthias Ringwald 3963*a254c508SMatthias Ringwald default: 3964*a254c508SMatthias Ringwald btstack_unreachable(); 3965*a254c508SMatthias Ringwald break; 3966*a254c508SMatthias Ringwald } 3967*a254c508SMatthias Ringwald return 0; 3968*a254c508SMatthias Ringwald } 3969*a254c508SMatthias Ringwald 397009e9d05bSMatthias Ringwald #endif 397100d93d79Smatthias.ringwald 3972e7d0c9aaSMatthias Ringwald #ifdef ENABLE_BLE 397309e9d05bSMatthias Ringwald 397409e9d05bSMatthias Ringwald static void l2cap_emit_connection_parameter_update_response(hci_con_handle_t con_handle, uint16_t result){ 397509e9d05bSMatthias Ringwald uint8_t event[6]; 397609e9d05bSMatthias Ringwald event[0] = L2CAP_EVENT_CONNECTION_PARAMETER_UPDATE_RESPONSE; 397709e9d05bSMatthias Ringwald event[1] = 4; 397809e9d05bSMatthias Ringwald little_endian_store_16(event, 2, con_handle); 397909e9d05bSMatthias Ringwald little_endian_store_16(event, 4, result); 39800b81d2a5SMatthias Ringwald l2cap_emit_event(event, sizeof(event)); 398109e9d05bSMatthias Ringwald } 398209e9d05bSMatthias Ringwald 39836b65794dSMilanka Ringwald // @return valid 3984c48b2a2cSMatthias Ringwald static int l2cap_le_signaling_handler_dispatch(hci_con_handle_t handle, uint8_t * command, uint8_t sig_id){ 3985e7d0c9aaSMatthias Ringwald hci_connection_t * connection; 3986c48b2a2cSMatthias Ringwald uint16_t result; 3987f299206dSMatthias Ringwald uint8_t event[12]; 398883fd9c76SMatthias Ringwald 3989*a254c508SMatthias Ringwald #ifdef ENABLE_L2CAP_CREDIT_BASED_CHANNELS 3990a3dc965aSMatthias Ringwald l2cap_channel_t * channel; 3991*a254c508SMatthias Ringwald btstack_linked_list_iterator_t it; 3992*a254c508SMatthias Ringwald #endif 3993*a254c508SMatthias Ringwald #ifdef ENABLE_LE_DATA_CHANNELS 3994a3dc965aSMatthias Ringwald uint16_t local_cid; 399583fd9c76SMatthias Ringwald uint16_t le_psm; 3996e7d0c9aaSMatthias Ringwald l2cap_service_t * service; 399711cae19eSMilanka Ringwald uint16_t source_cid; 399883fd9c76SMatthias Ringwald #endif 399900d93d79Smatthias.ringwald 40001b8b8d05SMatthias Ringwald uint8_t code = command[L2CAP_SIGNALING_COMMAND_CODE_OFFSET]; 4001adcfabadSMatthias Ringwald uint16_t len = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_LENGTH_OFFSET); 400285621840SMilanka Ringwald log_info("le dispatch: command 0x%02x, sig id %u, len %u", code, sig_id, len); 40031b8b8d05SMatthias Ringwald 40041b8b8d05SMatthias Ringwald switch (code){ 400500d93d79Smatthias.ringwald 4006c48b2a2cSMatthias Ringwald case CONNECTION_PARAMETER_UPDATE_REQUEST: 4007adcfabadSMatthias Ringwald // check size 40084ea43905SMatthias Ringwald if (len < 8u) return 0u; 4009e7d0c9aaSMatthias Ringwald connection = hci_connection_for_handle(handle); 40109305033eSMatthias Ringwald if (connection != NULL){ 40116d91fb6cSMatthias Ringwald if (connection->role != HCI_ROLE_MASTER){ 40126d91fb6cSMatthias Ringwald // reject command without notifying upper layer when not in master role 4013c48b2a2cSMatthias Ringwald return 0; 40146d91fb6cSMatthias Ringwald } 4015a4c06b28SMatthias Ringwald le_connection_parameter_range_t existing_range; 40164ced4e8cSMatthias Ringwald gap_get_connection_parameter_range(&existing_range); 4017d5e694a3SMatthias Ringwald uint16_t le_conn_interval_min = little_endian_read_16(command,L2CAP_SIGNALING_COMMAND_DATA_OFFSET); 4018d5e694a3SMatthias Ringwald uint16_t le_conn_interval_max = little_endian_read_16(command,L2CAP_SIGNALING_COMMAND_DATA_OFFSET+2); 4019d5e694a3SMatthias Ringwald uint16_t le_conn_latency = little_endian_read_16(command,L2CAP_SIGNALING_COMMAND_DATA_OFFSET+4); 4020d5e694a3SMatthias Ringwald uint16_t le_supervision_timeout = little_endian_read_16(command,L2CAP_SIGNALING_COMMAND_DATA_OFFSET+6); 4021da886c03S[email protected] 402273cd8a2aSMatthias Ringwald int update_parameter = gap_connection_parameter_range_included(&existing_range, le_conn_interval_min, le_conn_interval_max, le_conn_latency, le_supervision_timeout); 4023da886c03S[email protected] if (update_parameter){ 4024da886c03S[email protected] connection->le_con_parameter_update_state = CON_PARAMETER_UPDATE_SEND_RESPONSE; 4025da886c03S[email protected] connection->le_conn_interval_min = le_conn_interval_min; 4026da886c03S[email protected] connection->le_conn_interval_max = le_conn_interval_max; 4027da886c03S[email protected] connection->le_conn_latency = le_conn_latency; 4028da886c03S[email protected] connection->le_supervision_timeout = le_supervision_timeout; 4029da886c03S[email protected] } else { 4030da886c03S[email protected] connection->le_con_parameter_update_state = CON_PARAMETER_UPDATE_DENY; 4031da886c03S[email protected] } 4032c48b2a2cSMatthias Ringwald connection->le_con_param_update_identifier = sig_id; 4033da886c03S[email protected] } 4034da886c03S[email protected] 4035c48b2a2cSMatthias Ringwald event[0] = L2CAP_EVENT_CONNECTION_PARAMETER_UPDATE_REQUEST; 4036c48b2a2cSMatthias Ringwald event[1] = 8; 4037f299206dSMatthias Ringwald little_endian_store_16(event, 2, handle); 40386535961aSMatthias Ringwald (void)memcpy(&event[4], &command[4], 8); 40390b81d2a5SMatthias Ringwald l2cap_emit_event(event, sizeof(event)); 4040ccf076adS[email protected] break; 4041c48b2a2cSMatthias Ringwald 40421fcd10b7SMatthias Ringwald case CONNECTION_PARAMETER_UPDATE_RESPONSE: 40431fcd10b7SMatthias Ringwald // check size 40444ea43905SMatthias Ringwald if (len < 2u) return 0u; 40451fcd10b7SMatthias Ringwald result = little_endian_read_16(command, 4); 40461fcd10b7SMatthias Ringwald l2cap_emit_connection_parameter_update_response(handle, result); 40471fcd10b7SMatthias Ringwald break; 40481fcd10b7SMatthias Ringwald 4049*a254c508SMatthias Ringwald #ifdef ENABLE_L2CAP_ENHANCED_DATA_CHANNELS 4050*a254c508SMatthias Ringwald case L2CAP_CREDIT_BASED_CONNECTION_REQUEST: 4051*a254c508SMatthias Ringwald case L2CAP_CREDIT_BASED_CONNECTION_RESPONSE: 4052*a254c508SMatthias Ringwald case L2CAP_CREDIT_BASED_RECONFIGURE_REQUEST: 4053*a254c508SMatthias Ringwald case L2CAP_CREDIT_BASED_RECONFIGURE_RESPONSE: 4054*a254c508SMatthias Ringwald return l2cap_enhanced_signaling_handler_dispatch(handle, L2CAP_CID_SIGNALING_LE, command, sig_id); 4055*a254c508SMatthias Ringwald #endif 4056a3dc965aSMatthias Ringwald 4057*a254c508SMatthias Ringwald #ifdef ENABLE_L2CAP_CREDIT_BASED_CHANNELS 405863f0ac45SMatthias Ringwald case COMMAND_REJECT: 4059421cb104SMatthias Ringwald btstack_linked_list_iterator_init(&it, &l2cap_channels); 406063f0ac45SMatthias Ringwald while (btstack_linked_list_iterator_has_next(&it)){ 4061*a254c508SMatthias Ringwald channel = (l2cap_channel_t *) btstack_linked_list_iterator_next(&it); 4062*a254c508SMatthias Ringwald if (!l2cap_is_dynamic_channel_type(channel->channel_type)) continue; 4063*a254c508SMatthias Ringwald if (channel->con_handle != handle) continue; 4064*a254c508SMatthias Ringwald if (channel->local_sig_id != sig_id) continue; 4065*a254c508SMatthias Ringwald #ifdef ENABLE_LE_DATA_CHANNELS 406663f0ac45SMatthias Ringwald // if received while waiting for le connection response, assume legacy device 406763f0ac45SMatthias Ringwald if (channel->state == L2CAP_STATE_WAIT_LE_CONNECTION_RESPONSE){ 406863f0ac45SMatthias Ringwald channel->state = L2CAP_STATE_CLOSED; 406963f0ac45SMatthias Ringwald // no official value for this, use: Connection refused – LE_PSM not supported - 0x0002 407044276248SMatthias Ringwald l2cap_emit_le_channel_opened(channel, 0x0002); 407163f0ac45SMatthias Ringwald 407263f0ac45SMatthias Ringwald // discard channel 4073421cb104SMatthias Ringwald btstack_linked_list_remove(&l2cap_channels, (btstack_linked_item_t *) channel); 4074c45d6b2cSMatthias Ringwald l2cap_free_channel_entry(channel); 4075*a254c508SMatthias Ringwald continue; 4076*a254c508SMatthias Ringwald } 4077*a254c508SMatthias Ringwald #endif 4078*a254c508SMatthias Ringwald #ifdef ENABLE_L2CAP_ENHANCED_DATA_CHANNELS 4079*a254c508SMatthias Ringwald // if received while waiting for le connection response, assume legacy device 4080*a254c508SMatthias Ringwald if (channel->state == L2CAP_STATE_WAIT_ENHANCED_CONNECTION_RESPONSE){ 4081*a254c508SMatthias Ringwald channel->state = L2CAP_STATE_CLOSED; 4082*a254c508SMatthias Ringwald // treat as SPSM not supported 4083*a254c508SMatthias Ringwald l2cap_emit_enhanced_data_channel_opened(channel, L2CAP_CONNECTION_RESPONSE_RESULT_REFUSED_PSM); 4084*a254c508SMatthias Ringwald 4085*a254c508SMatthias Ringwald // discard channel 4086*a254c508SMatthias Ringwald btstack_linked_list_remove(&l2cap_channels, (btstack_linked_item_t *) channel); 4087*a254c508SMatthias Ringwald l2cap_free_channel_entry(channel); 4088*a254c508SMatthias Ringwald continue; 4089*a254c508SMatthias Ringwald } 4090*a254c508SMatthias Ringwald #endif 409163f0ac45SMatthias Ringwald } 409263f0ac45SMatthias Ringwald break; 4093*a254c508SMatthias Ringwald #endif 409463f0ac45SMatthias Ringwald 4095*a254c508SMatthias Ringwald #ifdef ENABLE_LE_DATA_CHANNELS 4096e7d0c9aaSMatthias Ringwald case LE_CREDIT_BASED_CONNECTION_REQUEST: 4097adcfabadSMatthias Ringwald // check size 40984ea43905SMatthias Ringwald if (len < 10u) return 0u; 4099e7d0c9aaSMatthias Ringwald 4100e7d0c9aaSMatthias Ringwald // get hci connection, bail if not found (must not happen) 4101e7d0c9aaSMatthias Ringwald connection = hci_connection_for_handle(handle); 4102e7d0c9aaSMatthias Ringwald if (!connection) return 0; 4103e7d0c9aaSMatthias Ringwald 4104e7d0c9aaSMatthias Ringwald // check if service registered 4105e7d0c9aaSMatthias Ringwald le_psm = little_endian_read_16(command, 4); 4106e7d0c9aaSMatthias Ringwald service = l2cap_le_get_service(le_psm); 410711cae19eSMilanka Ringwald source_cid = little_endian_read_16(command, 6); 4108e7d0c9aaSMatthias Ringwald 4109e7d0c9aaSMatthias Ringwald if (service){ 41104ea43905SMatthias Ringwald if (source_cid < 0x40u){ 4111e7d0c9aaSMatthias Ringwald // 0x0009 Connection refused - Invalid Source CID 4112e74c5f58SMatthias Ringwald l2cap_register_signaling_response(handle, LE_CREDIT_BASED_CONNECTION_REQUEST, sig_id, source_cid, 0x0009); 4113e7d0c9aaSMatthias Ringwald return 1; 4114e7d0c9aaSMatthias Ringwald } 4115e7d0c9aaSMatthias Ringwald 4116e7d0c9aaSMatthias Ringwald // go through list of channels for this ACL connection and check if we get a match 4117421cb104SMatthias Ringwald btstack_linked_list_iterator_init(&it, &l2cap_channels); 4118e7d0c9aaSMatthias Ringwald while (btstack_linked_list_iterator_has_next(&it)){ 41191b8b8d05SMatthias Ringwald l2cap_channel_t * a_channel = (l2cap_channel_t *) btstack_linked_list_iterator_next(&it); 4120fad84cafSMatthias Ringwald if (!l2cap_is_dynamic_channel_type(a_channel->channel_type)) continue; 41211b8b8d05SMatthias Ringwald if (a_channel->con_handle != handle) continue; 41221b8b8d05SMatthias Ringwald if (a_channel->remote_cid != source_cid) continue; 4123e7d0c9aaSMatthias Ringwald // 0x000a Connection refused - Source CID already allocated 4124e74c5f58SMatthias Ringwald l2cap_register_signaling_response(handle, LE_CREDIT_BASED_CONNECTION_REQUEST, sig_id, source_cid, 0x000a); 4125e7d0c9aaSMatthias Ringwald return 1; 4126e7d0c9aaSMatthias Ringwald } 4127e7d0c9aaSMatthias Ringwald 412883fd9c76SMatthias Ringwald // security: check encryption 412983fd9c76SMatthias Ringwald if (service->required_security_level >= LEVEL_2){ 41309c6e867eSMatthias Ringwald if (gap_encryption_key_size(handle) == 0){ 413183fd9c76SMatthias Ringwald // 0x0008 Connection refused - insufficient encryption 4132e74c5f58SMatthias Ringwald l2cap_register_signaling_response(handle, LE_CREDIT_BASED_CONNECTION_REQUEST, sig_id, source_cid, 0x0008); 413383fd9c76SMatthias Ringwald return 1; 413483fd9c76SMatthias Ringwald } 413583fd9c76SMatthias Ringwald // anything less than 16 byte key size is insufficient 41369c6e867eSMatthias Ringwald if (gap_encryption_key_size(handle) < 16){ 413783fd9c76SMatthias Ringwald // 0x0007 Connection refused – insufficient encryption key size 4138e74c5f58SMatthias Ringwald l2cap_register_signaling_response(handle, LE_CREDIT_BASED_CONNECTION_REQUEST, sig_id, source_cid, 0x0007); 413983fd9c76SMatthias Ringwald return 1; 414083fd9c76SMatthias Ringwald } 414183fd9c76SMatthias Ringwald } 414283fd9c76SMatthias Ringwald 414383fd9c76SMatthias Ringwald // security: check authencation 414483fd9c76SMatthias Ringwald if (service->required_security_level >= LEVEL_3){ 41459c6e867eSMatthias Ringwald if (!gap_authenticated(handle)){ 414683fd9c76SMatthias Ringwald // 0x0005 Connection refused – insufficient authentication 4147e74c5f58SMatthias Ringwald l2cap_register_signaling_response(handle, LE_CREDIT_BASED_CONNECTION_REQUEST, sig_id, source_cid, 0x0005); 414883fd9c76SMatthias Ringwald return 1; 414983fd9c76SMatthias Ringwald } 415083fd9c76SMatthias Ringwald } 415183fd9c76SMatthias Ringwald 415283fd9c76SMatthias Ringwald // security: check authorization 415383fd9c76SMatthias Ringwald if (service->required_security_level >= LEVEL_4){ 41549c6e867eSMatthias Ringwald if (gap_authorization_state(handle) != AUTHORIZATION_GRANTED){ 415583fd9c76SMatthias Ringwald // 0x0006 Connection refused – insufficient authorization 4156e74c5f58SMatthias Ringwald l2cap_register_signaling_response(handle, LE_CREDIT_BASED_CONNECTION_REQUEST, sig_id, source_cid, 0x0006); 415783fd9c76SMatthias Ringwald return 1; 415883fd9c76SMatthias Ringwald } 415983fd9c76SMatthias Ringwald } 4160e7d0c9aaSMatthias Ringwald 4161e7d0c9aaSMatthias Ringwald // allocate channel 41625d18f623SMatthias Ringwald channel = l2cap_create_channel_entry(service->packet_handler, L2CAP_CHANNEL_TYPE_LE_DATA_CHANNEL, connection->address, 4163e7d0c9aaSMatthias Ringwald BD_ADDR_TYPE_LE_RANDOM, le_psm, service->mtu, service->required_security_level); 4164e7d0c9aaSMatthias Ringwald if (!channel){ 4165e7d0c9aaSMatthias Ringwald // 0x0004 Connection refused – no resources available 4166e74c5f58SMatthias Ringwald l2cap_register_signaling_response(handle, LE_CREDIT_BASED_CONNECTION_REQUEST, sig_id, source_cid, 0x0004); 4167e7d0c9aaSMatthias Ringwald return 1; 4168e7d0c9aaSMatthias Ringwald } 4169e7d0c9aaSMatthias Ringwald 4170e7d0c9aaSMatthias Ringwald channel->con_handle = handle; 4171e7d0c9aaSMatthias Ringwald channel->remote_cid = source_cid; 4172e7d0c9aaSMatthias Ringwald channel->remote_sig_id = sig_id; 41737f107edaSMatthias Ringwald channel->remote_mtu = little_endian_read_16(command, 8); 41747f107edaSMatthias Ringwald channel->remote_mps = little_endian_read_16(command, 10); 41757f107edaSMatthias Ringwald channel->credits_outgoing = little_endian_read_16(command, 12); 4176e7d0c9aaSMatthias Ringwald 4177e7d0c9aaSMatthias Ringwald // set initial state 4178e7d0c9aaSMatthias Ringwald channel->state = L2CAP_STATE_WAIT_CLIENT_ACCEPT_OR_REJECT; 4179c99bb618SMatthias Ringwald channel->state_var |= L2CAP_CHANNEL_STATE_VAR_INCOMING; 4180e7d0c9aaSMatthias Ringwald 4181e7d0c9aaSMatthias Ringwald // add to connections list 4182da4c2b27SMatthias Ringwald btstack_linked_list_add_tail(&l2cap_channels, (btstack_linked_item_t *) channel); 4183e7d0c9aaSMatthias Ringwald 4184e7d0c9aaSMatthias Ringwald // post connection request event 418544276248SMatthias Ringwald l2cap_emit_le_incoming_connection(channel); 4186e7d0c9aaSMatthias Ringwald 4187e7d0c9aaSMatthias Ringwald } else { 4188e7d0c9aaSMatthias Ringwald // Connection refused – LE_PSM not supported 4189e74c5f58SMatthias Ringwald l2cap_register_signaling_response(handle, LE_CREDIT_BASED_CONNECTION_REQUEST, sig_id, source_cid, 0x0002); 4190e7d0c9aaSMatthias Ringwald } 4191e7d0c9aaSMatthias Ringwald break; 41921b8b8d05SMatthias Ringwald 41931b8b8d05SMatthias Ringwald case LE_CREDIT_BASED_CONNECTION_RESPONSE: 4194adcfabadSMatthias Ringwald // check size 41954ea43905SMatthias Ringwald if (len < 10u) return 0u; 4196adcfabadSMatthias Ringwald 41971b8b8d05SMatthias Ringwald // Find channel for this sig_id and connection handle 41981b8b8d05SMatthias Ringwald channel = NULL; 4199421cb104SMatthias Ringwald btstack_linked_list_iterator_init(&it, &l2cap_channels); 42001b8b8d05SMatthias Ringwald while (btstack_linked_list_iterator_has_next(&it)){ 42011b8b8d05SMatthias Ringwald l2cap_channel_t * a_channel = (l2cap_channel_t *) btstack_linked_list_iterator_next(&it); 4202fad84cafSMatthias Ringwald if (!l2cap_is_dynamic_channel_type(a_channel->channel_type)) continue; 42031b8b8d05SMatthias Ringwald if (a_channel->con_handle != handle) continue; 42041b8b8d05SMatthias Ringwald if (a_channel->local_sig_id != sig_id) continue; 42051b8b8d05SMatthias Ringwald channel = a_channel; 42061b8b8d05SMatthias Ringwald break; 42071b8b8d05SMatthias Ringwald } 42081b8b8d05SMatthias Ringwald if (!channel) break; 42091b8b8d05SMatthias Ringwald 42101b8b8d05SMatthias Ringwald // cid + 0 42111b8b8d05SMatthias Ringwald result = little_endian_read_16 (command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET+8); 42121b8b8d05SMatthias Ringwald if (result){ 42131b8b8d05SMatthias Ringwald channel->state = L2CAP_STATE_CLOSED; 42141b8b8d05SMatthias Ringwald // map l2cap connection response result to BTstack status enumeration 421544276248SMatthias Ringwald l2cap_emit_le_channel_opened(channel, result); 42161b8b8d05SMatthias Ringwald 42171b8b8d05SMatthias Ringwald // discard channel 4218421cb104SMatthias Ringwald btstack_linked_list_remove(&l2cap_channels, (btstack_linked_item_t *) channel); 4219c45d6b2cSMatthias Ringwald l2cap_free_channel_entry(channel); 42201b8b8d05SMatthias Ringwald break; 42211b8b8d05SMatthias Ringwald } 42221b8b8d05SMatthias Ringwald 42231b8b8d05SMatthias Ringwald // success 42241b8b8d05SMatthias Ringwald channel->remote_cid = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET + 0); 42251b8b8d05SMatthias Ringwald channel->remote_mtu = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET + 2); 42261b8b8d05SMatthias Ringwald channel->remote_mps = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET + 4); 42271b8b8d05SMatthias Ringwald channel->credits_outgoing = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET + 6); 42281b8b8d05SMatthias Ringwald channel->state = L2CAP_STATE_OPEN; 422944276248SMatthias Ringwald l2cap_emit_le_channel_opened(channel, result); 42301b8b8d05SMatthias Ringwald break; 4231*a254c508SMatthias Ringwald #endif 42321b8b8d05SMatthias Ringwald 4233*a254c508SMatthias Ringwald #ifdef ENABLE_L2CAP_CREDIT_BASED_CHANNELS 4234*a254c508SMatthias Ringwald case L2CAP_FLOW_CONTROL_CREDIT_INDICATION: 4235*a254c508SMatthias Ringwald return l2cap_credit_based_handle_credit_indication(handle, command, len) ? 1 : 0; 423685aeef60SMatthias Ringwald 4237828a7f7aSMatthias Ringwald case DISCONNECTION_REQUEST: 4238adcfabadSMatthias Ringwald 4239adcfabadSMatthias Ringwald // check size 42404ea43905SMatthias Ringwald if (len < 4u) return 0u; 4241adcfabadSMatthias Ringwald 4242828a7f7aSMatthias Ringwald // find channel 4243828a7f7aSMatthias Ringwald local_cid = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET + 0); 42447d5c2f20SMatthias Ringwald channel = l2cap_get_channel_for_local_cid_and_handle(local_cid, handle); 424563f34e00SMatthias Ringwald if (!channel) { 424685621840SMilanka Ringwald log_error("credit: no channel for cid 0x%02x", local_cid); 424763f34e00SMatthias Ringwald break; 424863f34e00SMatthias Ringwald } 4249828a7f7aSMatthias Ringwald channel->remote_sig_id = sig_id; 4250828a7f7aSMatthias Ringwald channel->state = L2CAP_STATE_WILL_SEND_DISCONNECT_RESPONSE; 4251828a7f7aSMatthias Ringwald break; 4252828a7f7aSMatthias Ringwald 425363f0ac45SMatthias Ringwald case DISCONNECTION_RESPONSE: 4254*a254c508SMatthias Ringwald // check size 4255*a254c508SMatthias Ringwald if (len < 4u) return 0u; 4256*a254c508SMatthias Ringwald 4257*a254c508SMatthias Ringwald // find channel 4258*a254c508SMatthias Ringwald local_cid = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET + 0); 4259*a254c508SMatthias Ringwald channel = l2cap_get_channel_for_local_cid_and_handle(local_cid, handle); 4260*a254c508SMatthias Ringwald if (!channel) break; 4261*a254c508SMatthias Ringwald if (channel->local_sig_id == sig_id) { 4262*a254c508SMatthias Ringwald l2cap_signaling_handler_channel(channel, command); 4263*a254c508SMatthias Ringwald } 426463f0ac45SMatthias Ringwald break; 4265*a254c508SMatthias Ringwald #endif 426663f0ac45SMatthias Ringwald 4267c48b2a2cSMatthias Ringwald default: 4268c48b2a2cSMatthias Ringwald // command unknown -> reject command 4269c48b2a2cSMatthias Ringwald return 0; 4270ccf076adS[email protected] } 4271c48b2a2cSMatthias Ringwald return 1; 4272c48b2a2cSMatthias Ringwald } 4273e7d0c9aaSMatthias Ringwald #endif 4274c48b2a2cSMatthias Ringwald 4275bb0a72a6SMatthias Ringwald #ifdef ENABLE_CLASSIC 42760b667d41SMatthias Ringwald static void l2cap_acl_classic_handler_for_channel(l2cap_channel_t * l2cap_channel, uint8_t * packet, uint16_t size){ 42774fc83f45SMatthias Ringwald 42784fc83f45SMatthias Ringwald // forward data only in OPEN state 42794fc83f45SMatthias Ringwald if (l2cap_channel->state != L2CAP_STATE_OPEN) return; 42804fc83f45SMatthias Ringwald 4281*a254c508SMatthias Ringwald #ifdef ENABLE_L2CAP_CREDIT_BASED_CHANNELS 4282*a254c508SMatthias Ringwald if (l2cap_channel->channel_type == L2CAP_CHANNEL_TYPE_ENHANCED_DATA_CHANNEL){ 4283*a254c508SMatthias Ringwald l2cap_credit_based_handle_pdu(l2cap_channel, packet, size); 4284*a254c508SMatthias Ringwald return; 4285*a254c508SMatthias Ringwald } 4286*a254c508SMatthias Ringwald #endif 4287*a254c508SMatthias Ringwald 428827e0774aSMatthias Ringwald #ifdef ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE 428927e0774aSMatthias Ringwald if (l2cap_channel->mode == L2CAP_CHANNEL_MODE_ENHANCED_RETRANSMISSION){ 429027e0774aSMatthias Ringwald 42916574158aSMatthias Ringwald int fcs_size = l2cap_channel->fcs_option ? 2 : 0; 429207c7de86SMatthias Ringwald 42936574158aSMatthias Ringwald // assert control + FCS fields are inside 42940b667d41SMatthias Ringwald if (size < COMPLETE_L2CAP_HEADER+2+fcs_size) return; 42956574158aSMatthias Ringwald 42966574158aSMatthias Ringwald if (l2cap_channel->fcs_option){ 4297fcb125edSMatthias Ringwald // verify FCS (required if one side requested it) 429827e0774aSMatthias Ringwald uint16_t fcs_calculated = crc16_calc(&packet[4], size - (4+2)); 429927e0774aSMatthias Ringwald uint16_t fcs_packet = little_endian_read_16(packet, size-2); 4300e288be62SMatthias Ringwald 4301e288be62SMatthias Ringwald #ifdef L2CAP_ERTM_SIMULATE_FCS_ERROR_INTERVAL 4302e288be62SMatthias Ringwald // simulate fcs error 4303e288be62SMatthias Ringwald static int counter = 0; 4304e288be62SMatthias Ringwald if (++counter == L2CAP_ERTM_SIMULATE_FCS_ERROR_INTERVAL) { 4305e288be62SMatthias Ringwald log_info("Simulate fcs error"); 4306e288be62SMatthias Ringwald fcs_calculated++; 4307e288be62SMatthias Ringwald counter = 0; 4308e288be62SMatthias Ringwald } 4309e288be62SMatthias Ringwald #endif 4310e288be62SMatthias Ringwald 43116574158aSMatthias Ringwald if (fcs_calculated == fcs_packet){ 43126574158aSMatthias Ringwald log_info("Packet FCS 0x%04x verified", fcs_packet); 43136574158aSMatthias Ringwald } else { 431427e0774aSMatthias Ringwald log_error("FCS mismatch! Packet 0x%04x, calculated 0x%04x", fcs_packet, fcs_calculated); 4315ef2faf56SMatthias Ringwald // ERTM State Machine in Bluetooth Spec does not handle 'I-Frame with invalid FCS' 43160b667d41SMatthias Ringwald return; 431727e0774aSMatthias Ringwald } 43186574158aSMatthias Ringwald } 431927e0774aSMatthias Ringwald 432027e0774aSMatthias Ringwald // switch on packet type 432127e0774aSMatthias Ringwald uint16_t control = little_endian_read_16(packet, COMPLETE_L2CAP_HEADER); 432238f62777SMatthias Ringwald uint8_t req_seq = (control >> 8) & 0x3f; 43232bea1b8dSMatthias Ringwald int final = (control >> 7) & 0x01; 432427e0774aSMatthias Ringwald if (control & 1){ 432527e0774aSMatthias Ringwald // S-Frame 432678cd8a22SMatthias Ringwald int poll = (control >> 4) & 0x01; 4327bdbe2e49SMatthias Ringwald l2cap_supervisory_function_t s = (l2cap_supervisory_function_t) ((control >> 2) & 0x03); 43289ffcbce4SMatthias Ringwald log_info("Control: 0x%04x => Supervisory function %u, ReqSeq %02u", control, (int) s, req_seq); 43297b7901d8SMatthias Ringwald l2cap_ertm_tx_packet_state_t * tx_state; 4330bdbe2e49SMatthias Ringwald switch (s){ 4331bdbe2e49SMatthias Ringwald case L2CAP_SUPERVISORY_FUNCTION_RR_RECEIVER_READY: 43329ffcbce4SMatthias Ringwald log_info("L2CAP_SUPERVISORY_FUNCTION_RR_RECEIVER_READY"); 43331e1a46bbSMatthias Ringwald l2cap_ertm_process_req_seq(l2cap_channel, req_seq); 43343233d8abSMatthias Ringwald if (poll && final){ 43353233d8abSMatthias Ringwald // S-frames shall not be transmitted with both the F-bit and the P-bit set to 1 at the same time. 43363233d8abSMatthias Ringwald log_error("P=F=1 in S-Frame"); 43373233d8abSMatthias Ringwald break; 43383233d8abSMatthias Ringwald } 433978cd8a22SMatthias Ringwald if (poll){ 4340f85ade6bSMatthias Ringwald // check if we did request selective retransmission before <==> we have stored SDU segments 4341f85ade6bSMatthias Ringwald int i; 4342f85ade6bSMatthias Ringwald int num_stored_out_of_order_packets = 0; 4343f85ade6bSMatthias Ringwald for (i=0;i<l2cap_channel->num_rx_buffers;i++){ 4344f85ade6bSMatthias Ringwald int index = l2cap_channel->rx_store_index + i; 4345f85ade6bSMatthias Ringwald if (index >= l2cap_channel->num_rx_buffers){ 4346f85ade6bSMatthias Ringwald index -= l2cap_channel->num_rx_buffers; 4347f85ade6bSMatthias Ringwald } 4348f85ade6bSMatthias Ringwald l2cap_ertm_rx_packet_state_t * rx_state = &l2cap_channel->rx_packets_state[index]; 4349f85ade6bSMatthias Ringwald if (!rx_state->valid) continue; 4350f85ade6bSMatthias Ringwald num_stored_out_of_order_packets++; 4351f85ade6bSMatthias Ringwald } 4352f85ade6bSMatthias Ringwald if (num_stored_out_of_order_packets){ 4353f85ade6bSMatthias Ringwald l2cap_channel->send_supervisor_frame_selective_reject = 1; 4354f85ade6bSMatthias Ringwald } else { 4355d2afdd38SMatthias Ringwald l2cap_channel->send_supervisor_frame_receiver_ready = 1; 435678cd8a22SMatthias Ringwald } 4357f85ade6bSMatthias Ringwald l2cap_channel->set_final_bit_after_packet_with_poll_bit_set = 1; 4358f85ade6bSMatthias Ringwald } 43593233d8abSMatthias Ringwald if (final){ 4360550189ffSMatthias Ringwald // Stop-MonitorTimer 4361550189ffSMatthias Ringwald l2cap_ertm_stop_monitor_timer(l2cap_channel); 4362550189ffSMatthias Ringwald // If UnackedFrames > 0 then Start-RetransTimer 436394301352SMatthias Ringwald if (l2cap_channel->unacked_frames){ 4364550189ffSMatthias Ringwald l2cap_ertm_start_retransmission_timer(l2cap_channel); 4365550189ffSMatthias Ringwald } 43663233d8abSMatthias Ringwald // final bit set <- response to RR with poll bit set. All not acknowledged packets need to be retransmitted 4367ef2faf56SMatthias Ringwald l2cap_ertm_retransmit_unacknowleded_frames(l2cap_channel); 43683233d8abSMatthias Ringwald } 4369bdbe2e49SMatthias Ringwald break; 43709ffcbce4SMatthias Ringwald case L2CAP_SUPERVISORY_FUNCTION_REJ_REJECT: 43719ffcbce4SMatthias Ringwald log_info("L2CAP_SUPERVISORY_FUNCTION_REJ_REJECT"); 43721e1a46bbSMatthias Ringwald l2cap_ertm_process_req_seq(l2cap_channel, req_seq); 4373600cf12dSMatthias Ringwald // restart transmittion from last unacknowledted packet (earlier packets already freed in l2cap_ertm_process_req_seq) 4374ef2faf56SMatthias Ringwald l2cap_ertm_retransmit_unacknowleded_frames(l2cap_channel); 43759ffcbce4SMatthias Ringwald break; 43769ffcbce4SMatthias Ringwald case L2CAP_SUPERVISORY_FUNCTION_RNR_RECEIVER_NOT_READY: 43779ffcbce4SMatthias Ringwald log_error("L2CAP_SUPERVISORY_FUNCTION_RNR_RECEIVER_NOT_READY"); 43789ffcbce4SMatthias Ringwald break; 43799ffcbce4SMatthias Ringwald case L2CAP_SUPERVISORY_FUNCTION_SREJ_SELECTIVE_REJECT: 43807b7901d8SMatthias Ringwald log_info("L2CAP_SUPERVISORY_FUNCTION_SREJ_SELECTIVE_REJECT"); 43817b7901d8SMatthias Ringwald if (poll){ 43821e1a46bbSMatthias Ringwald l2cap_ertm_process_req_seq(l2cap_channel, req_seq); 43837b7901d8SMatthias Ringwald } 43847b7901d8SMatthias Ringwald // find requested i-frame 43857b7901d8SMatthias Ringwald tx_state = l2cap_ertm_get_tx_state(l2cap_channel, req_seq); 43867b7901d8SMatthias Ringwald if (tx_state){ 43877b7901d8SMatthias Ringwald log_info("Retransmission for tx_seq %u requested", req_seq); 4388d2afdd38SMatthias Ringwald l2cap_channel->set_final_bit_after_packet_with_poll_bit_set = poll; 43897b7901d8SMatthias Ringwald tx_state->retransmission_requested = 1; 43907b7901d8SMatthias Ringwald l2cap_channel->srej_active = 1; 43917b7901d8SMatthias Ringwald } 43929ffcbce4SMatthias Ringwald break; 4393bdbe2e49SMatthias Ringwald default: 4394bdbe2e49SMatthias Ringwald break; 4395bdbe2e49SMatthias Ringwald } 439627e0774aSMatthias Ringwald } else { 439727e0774aSMatthias Ringwald // I-Frame 439827e0774aSMatthias Ringwald // get control 439927e0774aSMatthias Ringwald l2cap_segmentation_and_reassembly_t sar = (l2cap_segmentation_and_reassembly_t) (control >> 14); 440038f62777SMatthias Ringwald uint8_t tx_seq = (control >> 1) & 0x3f; 440138f62777SMatthias Ringwald log_info("Control: 0x%04x => SAR %u, ReqSeq %02u, R?, TxSeq %02u", control, (int) sar, req_seq, tx_seq); 4402e8e9809fSMatthias Ringwald log_info("SAR: pos %u", l2cap_channel->reassembly_pos); 440338f62777SMatthias Ringwald log_info("State: expected_tx_seq %02u, req_seq %02u", l2cap_channel->expected_tx_seq, l2cap_channel->req_seq); 44041e1a46bbSMatthias Ringwald l2cap_ertm_process_req_seq(l2cap_channel, req_seq); 440511b576c5SMatthias Ringwald if (final){ 440611b576c5SMatthias Ringwald // final bit set <- response to RR with poll bit set. All not acknowledged packets need to be retransmitted 4407ef2faf56SMatthias Ringwald l2cap_ertm_retransmit_unacknowleded_frames(l2cap_channel); 440811b576c5SMatthias Ringwald } 440907c7de86SMatthias Ringwald 441007c7de86SMatthias Ringwald // get SDU 4411826c39d0SMatthias Ringwald const uint8_t * payload_data = &packet[COMPLETE_L2CAP_HEADER+2]; 4412826c39d0SMatthias Ringwald uint16_t payload_len = size-(COMPLETE_L2CAP_HEADER+2+fcs_size); 441307c7de86SMatthias Ringwald 441407c7de86SMatthias Ringwald // assert SDU size is smaller or equal to our buffers 4415826c39d0SMatthias Ringwald uint16_t max_payload_size = 0; 4416826c39d0SMatthias Ringwald switch (sar){ 4417826c39d0SMatthias Ringwald case L2CAP_SEGMENTATION_AND_REASSEMBLY_UNSEGMENTED_L2CAP_SDU: 4418826c39d0SMatthias Ringwald case L2CAP_SEGMENTATION_AND_REASSEMBLY_START_OF_L2CAP_SDU: 4419826c39d0SMatthias Ringwald // SDU Length + MPS 4420826c39d0SMatthias Ringwald max_payload_size = l2cap_channel->local_mps + 2; 4421826c39d0SMatthias Ringwald break; 4422826c39d0SMatthias Ringwald case L2CAP_SEGMENTATION_AND_REASSEMBLY_CONTINUATION_OF_L2CAP_SDU: 4423826c39d0SMatthias Ringwald case L2CAP_SEGMENTATION_AND_REASSEMBLY_END_OF_L2CAP_SDU: 4424826c39d0SMatthias Ringwald max_payload_size = l2cap_channel->local_mps; 4425826c39d0SMatthias Ringwald break; 44267bbeb3adSMilanka Ringwald default: 44277bbeb3adSMilanka Ringwald btstack_assert(false); 44287bbeb3adSMilanka Ringwald break; 4429826c39d0SMatthias Ringwald } 4430826c39d0SMatthias Ringwald if (payload_len > max_payload_size){ 4431826c39d0SMatthias Ringwald log_info("payload len %u > max payload %u -> drop packet", payload_len, max_payload_size); 44320b667d41SMatthias Ringwald return; 4433826c39d0SMatthias Ringwald } 443407c7de86SMatthias Ringwald 443538f62777SMatthias Ringwald // check ordering 443638f62777SMatthias Ringwald if (l2cap_channel->expected_tx_seq == tx_seq){ 443738f62777SMatthias Ringwald log_info("Received expected frame with TxSeq == ExpectedTxSeq == %02u", tx_seq); 443838f62777SMatthias Ringwald l2cap_channel->expected_tx_seq = l2cap_next_ertm_seq_nr(l2cap_channel->expected_tx_seq); 4439f85ade6bSMatthias Ringwald l2cap_channel->req_seq = l2cap_channel->expected_tx_seq; 4440d48432d4SMatthias Ringwald 4441e32be409SMatthias Ringwald // process SDU 4442826c39d0SMatthias Ringwald l2cap_ertm_handle_in_sequence_sdu(l2cap_channel, sar, payload_data, payload_len); 4443d48432d4SMatthias Ringwald 444470734707SMatthias Ringwald // process stored segments 4445ff3cc4a5SMatthias Ringwald while (true){ 444670734707SMatthias Ringwald int index = l2cap_channel->rx_store_index; 444770734707SMatthias Ringwald l2cap_ertm_rx_packet_state_t * rx_state = &l2cap_channel->rx_packets_state[index]; 444870734707SMatthias Ringwald if (!rx_state->valid) break; 4449f85ade6bSMatthias Ringwald 4450f85ade6bSMatthias Ringwald log_info("Processing stored frame with TxSeq == ExpectedTxSeq == %02u", l2cap_channel->expected_tx_seq); 4451f85ade6bSMatthias Ringwald l2cap_channel->expected_tx_seq = l2cap_next_ertm_seq_nr(l2cap_channel->expected_tx_seq); 4452f85ade6bSMatthias Ringwald l2cap_channel->req_seq = l2cap_channel->expected_tx_seq; 4453f85ade6bSMatthias Ringwald 445470734707SMatthias Ringwald rx_state->valid = 0; 445570734707SMatthias Ringwald l2cap_ertm_handle_in_sequence_sdu(l2cap_channel, rx_state->sar, &l2cap_channel->rx_packets_data[index], rx_state->len); 4456f85ade6bSMatthias Ringwald 4457f85ade6bSMatthias Ringwald // update rx store index 445870734707SMatthias Ringwald index++; 445970734707SMatthias Ringwald if (index >= l2cap_channel->num_rx_buffers){ 446070734707SMatthias Ringwald index = 0; 446170734707SMatthias Ringwald } 446270734707SMatthias Ringwald l2cap_channel->rx_store_index = index; 446370734707SMatthias Ringwald } 446470734707SMatthias Ringwald 4465f85ade6bSMatthias Ringwald // 4466f85ade6bSMatthias Ringwald l2cap_channel->send_supervisor_frame_receiver_ready = 1; 4467f85ade6bSMatthias Ringwald 4468c7309e8dSMatthias Ringwald } else { 4469df2191a7SMatthias Ringwald int delta = (tx_seq - l2cap_channel->expected_tx_seq) & 0x3f; 4470df2191a7SMatthias Ringwald if (delta < 2){ 447170734707SMatthias Ringwald // store segment 4472826c39d0SMatthias Ringwald l2cap_ertm_handle_out_of_sequence_sdu(l2cap_channel, sar, delta, payload_data, payload_len); 447370734707SMatthias Ringwald 4474df2191a7SMatthias Ringwald log_info("Received unexpected frame TxSeq %u but expected %u -> send S-SREJ", tx_seq, l2cap_channel->expected_tx_seq); 4475df2191a7SMatthias Ringwald l2cap_channel->send_supervisor_frame_selective_reject = 1; 4476df2191a7SMatthias Ringwald } else { 4477df2191a7SMatthias Ringwald log_info("Received unexpected frame TxSeq %u but expected %u -> send S-REJ", tx_seq, l2cap_channel->expected_tx_seq); 4478c7309e8dSMatthias Ringwald l2cap_channel->send_supervisor_frame_reject = 1; 447927e0774aSMatthias Ringwald } 448038f62777SMatthias Ringwald } 4481df2191a7SMatthias Ringwald } 44820b667d41SMatthias Ringwald return; 448327e0774aSMatthias Ringwald } 448427e0774aSMatthias Ringwald #endif 44850b667d41SMatthias Ringwald 44860763891bSMatthias Ringwald // check size 448717b0e9ffSMatthias Ringwald uint16_t payload_size = size - COMPLETE_L2CAP_HEADER; 448817b0e9ffSMatthias Ringwald if (l2cap_channel->local_mtu < payload_size) return; 44890763891bSMatthias Ringwald 449017b0e9ffSMatthias Ringwald l2cap_dispatch_to_channel(l2cap_channel, L2CAP_DATA_PACKET, &packet[COMPLETE_L2CAP_HEADER], payload_size); 44910b667d41SMatthias Ringwald } 44920b667d41SMatthias Ringwald #endif 44930b667d41SMatthias Ringwald 44940b667d41SMatthias Ringwald static void l2cap_acl_classic_handler(hci_con_handle_t handle, uint8_t *packet, uint16_t size){ 44950b667d41SMatthias Ringwald #ifdef ENABLE_CLASSIC 44960b667d41SMatthias Ringwald l2cap_channel_t * l2cap_channel; 44970b667d41SMatthias Ringwald l2cap_fixed_channel_t * l2cap_fixed_channel; 44980b667d41SMatthias Ringwald 44990b667d41SMatthias Ringwald uint16_t channel_id = READ_L2CAP_CHANNEL_ID(packet); 45007d5c2f20SMatthias Ringwald uint8_t broadcast_flag = READ_ACL_FLAGS(packet) >> 2; 45010b667d41SMatthias Ringwald switch (channel_id) { 45020b667d41SMatthias Ringwald 45030b667d41SMatthias Ringwald case L2CAP_CID_SIGNALING: { 45047d5c2f20SMatthias Ringwald if (broadcast_flag != 0) break; 45050b667d41SMatthias Ringwald uint32_t command_offset = 8; 45060b667d41SMatthias Ringwald while ((command_offset + L2CAP_SIGNALING_COMMAND_DATA_OFFSET) < size) { 45070b667d41SMatthias Ringwald // assert signaling command is fully inside packet 45080b667d41SMatthias Ringwald uint16_t data_len = little_endian_read_16(packet, command_offset + L2CAP_SIGNALING_COMMAND_LENGTH_OFFSET); 45090b667d41SMatthias Ringwald uint32_t next_command_offset = command_offset + L2CAP_SIGNALING_COMMAND_DATA_OFFSET + data_len; 45100b667d41SMatthias Ringwald if (next_command_offset > size){ 45110b667d41SMatthias Ringwald log_error("l2cap signaling command len invalid -> drop"); 45120b667d41SMatthias Ringwald break; 45130b667d41SMatthias Ringwald } 45140b667d41SMatthias Ringwald // handle signaling command 45150b667d41SMatthias Ringwald l2cap_signaling_handler_dispatch(handle, &packet[command_offset]); 45160b667d41SMatthias Ringwald // go to next command 45170b667d41SMatthias Ringwald command_offset = next_command_offset; 45180b667d41SMatthias Ringwald } 45190b667d41SMatthias Ringwald break; 45200b667d41SMatthias Ringwald } 452181a22226SMatthias Ringwald 45220b667d41SMatthias Ringwald case L2CAP_CID_CONNECTIONLESS_CHANNEL: 45237d5c2f20SMatthias Ringwald if (broadcast_flag == 0) break; 45240b667d41SMatthias Ringwald l2cap_fixed_channel = l2cap_fixed_channel_for_channel_id(L2CAP_CID_CONNECTIONLESS_CHANNEL); 45250b667d41SMatthias Ringwald if (!l2cap_fixed_channel) break; 45260b667d41SMatthias Ringwald if (!l2cap_fixed_channel->packet_handler) break; 45270b667d41SMatthias Ringwald (*l2cap_fixed_channel->packet_handler)(UCD_DATA_PACKET, handle, &packet[COMPLETE_L2CAP_HEADER], size-COMPLETE_L2CAP_HEADER); 45280b667d41SMatthias Ringwald break; 45290b667d41SMatthias Ringwald 453081a22226SMatthias Ringwald #ifdef ENABLE_BLE 453181a22226SMatthias Ringwald case L2CAP_CID_BR_EDR_SECURITY_MANAGER: 453281a22226SMatthias Ringwald l2cap_fixed_channel = l2cap_fixed_channel_for_channel_id(L2CAP_CID_SECURITY_MANAGER_PROTOCOL); 4533e6cdcf4bSMatthias Ringwald if ((l2cap_fixed_channel == NULL) || (l2cap_fixed_channel->packet_handler == NULL)){ 4534e6cdcf4bSMatthias Ringwald // Pairing Failed 4535e6cdcf4bSMatthias Ringwald l2cap_register_signaling_response(handle, (uint8_t) SM_PAIRING_FAILED, 0, L2CAP_CID_BR_EDR_SECURITY_MANAGER, SM_REASON_PAIRING_NOT_SUPPORTED); 4536e6cdcf4bSMatthias Ringwald } else { 453781a22226SMatthias Ringwald (*l2cap_fixed_channel->packet_handler)(SM_DATA_PACKET, handle, &packet[COMPLETE_L2CAP_HEADER], size-COMPLETE_L2CAP_HEADER); 4538e6cdcf4bSMatthias Ringwald } 453981a22226SMatthias Ringwald break; 454081a22226SMatthias Ringwald #endif 454181a22226SMatthias Ringwald 45420b667d41SMatthias Ringwald default: 45437d5c2f20SMatthias Ringwald if (broadcast_flag != 0) break; 45440b667d41SMatthias Ringwald // Find channel for this channel_id and connection handle 45457d5c2f20SMatthias Ringwald l2cap_channel = l2cap_get_channel_for_local_cid_and_handle(channel_id, handle); 45467d5c2f20SMatthias Ringwald if (l2cap_channel != NULL){ 45470b667d41SMatthias Ringwald l2cap_acl_classic_handler_for_channel(l2cap_channel, packet, size); 454800d93d79Smatthias.ringwald } 4549bb0a72a6SMatthias Ringwald break; 4550bb0a72a6SMatthias Ringwald } 4551bb0a72a6SMatthias Ringwald #else 4552bb0a72a6SMatthias Ringwald UNUSED(handle); // ok: no code 4553bb0a72a6SMatthias Ringwald UNUSED(packet); // ok: no code 4554bb0a72a6SMatthias Ringwald UNUSED(size); // ok: no code 455509e9d05bSMatthias Ringwald #endif 4556bb0a72a6SMatthias Ringwald } 4557bb0a72a6SMatthias Ringwald 4558bb0a72a6SMatthias Ringwald static void l2cap_acl_le_handler(hci_con_handle_t handle, uint8_t *packet, uint16_t size){ 4559bb0a72a6SMatthias Ringwald #ifdef ENABLE_BLE 4560bb0a72a6SMatthias Ringwald 4561fad84cafSMatthias Ringwald l2cap_fixed_channel_t * l2cap_fixed_channel; 4562fad84cafSMatthias Ringwald 4563bb0a72a6SMatthias Ringwald #ifdef ENABLE_LE_DATA_CHANNELS 4564bb0a72a6SMatthias Ringwald l2cap_channel_t * l2cap_channel; 4565bb0a72a6SMatthias Ringwald #endif 4566bb0a72a6SMatthias Ringwald uint16_t channel_id = READ_L2CAP_CHANNEL_ID(packet); 4567bb0a72a6SMatthias Ringwald switch (channel_id) { 4568bb0a72a6SMatthias Ringwald 4569bb0a72a6SMatthias Ringwald case L2CAP_CID_SIGNALING_LE: { 4570bb0a72a6SMatthias Ringwald uint16_t sig_id = packet[COMPLETE_L2CAP_HEADER + 1]; 4571adcfabadSMatthias Ringwald uint16_t len = little_endian_read_16(packet, COMPLETE_L2CAP_HEADER + 2); 45724ea43905SMatthias Ringwald if ((COMPLETE_L2CAP_HEADER + 4u + len) > size) break; 4573bb0a72a6SMatthias Ringwald int valid = l2cap_le_signaling_handler_dispatch(handle, &packet[COMPLETE_L2CAP_HEADER], sig_id); 4574bb0a72a6SMatthias Ringwald if (!valid){ 4575bb0a72a6SMatthias Ringwald l2cap_register_signaling_response(handle, COMMAND_REJECT_LE, sig_id, 0, L2CAP_REJ_CMD_UNKNOWN); 4576bb0a72a6SMatthias Ringwald } 4577bb0a72a6SMatthias Ringwald break; 4578bb0a72a6SMatthias Ringwald } 4579bb0a72a6SMatthias Ringwald 4580bb0a72a6SMatthias Ringwald case L2CAP_CID_ATTRIBUTE_PROTOCOL: 4581fad84cafSMatthias Ringwald l2cap_fixed_channel = l2cap_fixed_channel_for_channel_id(L2CAP_CID_ATTRIBUTE_PROTOCOL); 4582fad84cafSMatthias Ringwald if (!l2cap_fixed_channel) break; 4583fad84cafSMatthias Ringwald if (!l2cap_fixed_channel->packet_handler) break; 4584fad84cafSMatthias Ringwald (*l2cap_fixed_channel->packet_handler)(ATT_DATA_PACKET, handle, &packet[COMPLETE_L2CAP_HEADER], size-COMPLETE_L2CAP_HEADER); 4585bb0a72a6SMatthias Ringwald break; 4586bb0a72a6SMatthias Ringwald 4587bb0a72a6SMatthias Ringwald case L2CAP_CID_SECURITY_MANAGER_PROTOCOL: 4588fad84cafSMatthias Ringwald l2cap_fixed_channel = l2cap_fixed_channel_for_channel_id(L2CAP_CID_SECURITY_MANAGER_PROTOCOL); 4589e6cdcf4bSMatthias Ringwald if ((l2cap_fixed_channel == NULL) || (l2cap_fixed_channel->packet_handler == NULL)){ 4590e6cdcf4bSMatthias Ringwald // Pairing Failed 4591e6cdcf4bSMatthias Ringwald l2cap_register_signaling_response(handle, (uint8_t) SM_PAIRING_FAILED, 0, L2CAP_CID_SECURITY_MANAGER_PROTOCOL, SM_REASON_PAIRING_NOT_SUPPORTED); 4592e6cdcf4bSMatthias Ringwald } else { 4593fad84cafSMatthias Ringwald (*l2cap_fixed_channel->packet_handler)(SM_DATA_PACKET, handle, &packet[COMPLETE_L2CAP_HEADER], size-COMPLETE_L2CAP_HEADER); 4594e6cdcf4bSMatthias Ringwald } 4595bb0a72a6SMatthias Ringwald break; 4596bb0a72a6SMatthias Ringwald 4597bb0a72a6SMatthias Ringwald default: 4598bb0a72a6SMatthias Ringwald 4599a3dc965aSMatthias Ringwald #ifdef ENABLE_LE_DATA_CHANNELS 46007d5c2f20SMatthias Ringwald l2cap_channel = l2cap_get_channel_for_local_cid_and_handle(channel_id, handle); 46017d5c2f20SMatthias Ringwald if (l2cap_channel != NULL) { 4602*a254c508SMatthias Ringwald l2cap_credit_based_handle_pdu(l2cap_channel, packet, size); 460364e11ca9SMatthias Ringwald } 460464e11ca9SMatthias Ringwald #endif 46055652b5ffS[email protected] break; 46065652b5ffS[email protected] } 4607bb0a72a6SMatthias Ringwald #else 4608bb0a72a6SMatthias Ringwald UNUSED(handle); // ok: no code 4609bb0a72a6SMatthias Ringwald UNUSED(packet); // ok: no code 4610bb0a72a6SMatthias Ringwald UNUSED(size); // ok: no code 4611bb0a72a6SMatthias Ringwald #endif 4612bb0a72a6SMatthias Ringwald } 4613bb0a72a6SMatthias Ringwald 4614bb0a72a6SMatthias Ringwald static void l2cap_acl_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 4615bb0a72a6SMatthias Ringwald UNUSED(packet_type); // ok: registered with hci_register_acl_packet_handler 4616bb0a72a6SMatthias Ringwald UNUSED(channel); // ok: there is no channel 4617bb0a72a6SMatthias Ringwald 4618adcfabadSMatthias Ringwald // Assert full L2CAP header present 4619adcfabadSMatthias Ringwald if (size < COMPLETE_L2CAP_HEADER) return; 4620adcfabadSMatthias Ringwald 4621f16129ceSMatthias Ringwald // Dispatch to Classic or LE handler (SCO packets are not dispatched to L2CAP) 4622bb0a72a6SMatthias Ringwald hci_con_handle_t handle = READ_ACL_CONNECTION_HANDLE(packet); 4623bb0a72a6SMatthias Ringwald hci_connection_t *conn = hci_connection_for_handle(handle); 4624bb0a72a6SMatthias Ringwald if (!conn) return; 4625f16129ceSMatthias Ringwald if (conn->address_type == BD_ADDR_TYPE_ACL){ 4626bb0a72a6SMatthias Ringwald l2cap_acl_classic_handler(handle, packet, size); 4627bb0a72a6SMatthias Ringwald } else { 4628bb0a72a6SMatthias Ringwald l2cap_acl_le_handler(handle, packet, size); 4629bb0a72a6SMatthias Ringwald } 463000d93d79Smatthias.ringwald 46311eb2563eS[email protected] l2cap_run(); 46322718e2e7Smatthias.ringwald } 463300d93d79Smatthias.ringwald 463409e9d05bSMatthias Ringwald // Bluetooth 4.0 - allows to register handler for Attribute Protocol and Security Manager Protocol 4635b45b7749SMilanka Ringwald void l2cap_register_fixed_channel(btstack_packet_handler_t packet_handler, uint16_t channel_id) { 4636fad84cafSMatthias Ringwald l2cap_fixed_channel_t * channel = l2cap_fixed_channel_for_channel_id(channel_id); 4637fad84cafSMatthias Ringwald if (!channel) return; 4638b45b7749SMilanka Ringwald channel->packet_handler = packet_handler; 463909e9d05bSMatthias Ringwald } 464009e9d05bSMatthias Ringwald 464109e9d05bSMatthias Ringwald #ifdef ENABLE_CLASSIC 464215ec09bbSmatthias.ringwald // finalize closed channel - l2cap_handle_disconnect_request & DISCONNECTION_RESPONSE 4643*a254c508SMatthias Ringwald void l2cap_finalize_channel_close(l2cap_channel_t * channel){ 4644f62db1e3Smatthias.ringwald channel->state = L2CAP_STATE_CLOSED; 464566a72640SMatthias Ringwald l2cap_handle_channel_closed(channel); 4646f62db1e3Smatthias.ringwald // discard channel 4647665d90f2SMatthias Ringwald btstack_linked_list_remove(&l2cap_channels, (btstack_linked_item_t *) channel); 4648c45d6b2cSMatthias Ringwald l2cap_free_channel_entry(channel); 4649c8e4258aSmatthias.ringwald } 465013aa3e4bSMatthias Ringwald #endif 46511e6aba47Smatthias.ringwald 465213aa3e4bSMatthias Ringwald #ifdef ENABLE_CLASSIC 46537192e786SMatthias Ringwald static inline l2cap_service_t * l2cap_get_service(uint16_t psm){ 46547192e786SMatthias Ringwald return l2cap_get_service_internal(&l2cap_services, psm); 46557192e786SMatthias Ringwald } 46567192e786SMatthias Ringwald 46578ad4dfffSMatthias Ringwald static void l2cap_update_minimal_security_level(void){ 46588ad4dfffSMatthias Ringwald // update minimal service security level 46598ad4dfffSMatthias Ringwald gap_security_level_t minimal_level = LEVEL_1; 46608ad4dfffSMatthias Ringwald btstack_linked_list_iterator_t it; 46618ad4dfffSMatthias Ringwald btstack_linked_list_iterator_init(&it, &l2cap_services); 46628ad4dfffSMatthias Ringwald while (btstack_linked_list_iterator_has_next(&it)){ 46638ad4dfffSMatthias Ringwald l2cap_service_t * service = (l2cap_service_t *) btstack_linked_list_iterator_next(&it); 46648ad4dfffSMatthias Ringwald if (service->required_security_level > minimal_level){ 46658ad4dfffSMatthias Ringwald minimal_level = service->required_security_level; 46668ad4dfffSMatthias Ringwald }; 46678ad4dfffSMatthias Ringwald } 46688ad4dfffSMatthias Ringwald gap_set_minimal_service_security_level(minimal_level); 46698ad4dfffSMatthias Ringwald } 46708ad4dfffSMatthias Ringwald 4671be2053a6SMatthias Ringwald uint8_t l2cap_register_service(btstack_packet_handler_t service_packet_handler, uint16_t psm, uint16_t mtu, gap_security_level_t security_level){ 4672be2053a6SMatthias Ringwald 4673be2053a6SMatthias Ringwald log_info("L2CAP_REGISTER_SERVICE psm 0x%x mtu %u", psm, mtu); 4674e0abb8e7S[email protected] 46754bb582b6Smatthias.ringwald // check for alread registered psm 46769d9bbc01Smatthias.ringwald l2cap_service_t *service = l2cap_get_service(psm); 4677277abc2cSmatthias.ringwald if (service) { 467885621840SMilanka Ringwald log_error("register: PSM %u already registered", psm); 4679be2053a6SMatthias Ringwald return L2CAP_SERVICE_ALREADY_REGISTERED; 4680277abc2cSmatthias.ringwald } 46819d9bbc01Smatthias.ringwald 46824bb582b6Smatthias.ringwald // alloc structure 4683bb69aaaeS[email protected] service = btstack_memory_l2cap_service_get(); 4684277abc2cSmatthias.ringwald if (!service) { 468585621840SMilanka Ringwald log_error("register: no memory for l2cap_service_t"); 4686be2053a6SMatthias Ringwald return BTSTACK_MEMORY_ALLOC_FAILED; 4687277abc2cSmatthias.ringwald } 46889d9bbc01Smatthias.ringwald 46899d9bbc01Smatthias.ringwald // fill in 46909d9bbc01Smatthias.ringwald service->psm = psm; 46919d9bbc01Smatthias.ringwald service->mtu = mtu; 469205ae8de3SMatthias Ringwald service->packet_handler = service_packet_handler; 4693df3354fcS[email protected] service->required_security_level = security_level; 46949d9bbc01Smatthias.ringwald 46959d9bbc01Smatthias.ringwald // add to services list 4696665d90f2SMatthias Ringwald btstack_linked_list_add(&l2cap_services, (btstack_linked_item_t *) service); 4697c0e866bfSmatthias.ringwald 46988ad4dfffSMatthias Ringwald l2cap_update_minimal_security_level(); 46998ad4dfffSMatthias Ringwald 470047a15588SMatthias Ringwald #ifndef ENABLE_EXPLICIT_CONNECTABLE_MODE_CONTROL 4701c0e866bfSmatthias.ringwald // enable page scan 470215a95bd5SMatthias Ringwald gap_connectable_control(1); 470347a15588SMatthias Ringwald #endif 47045842b6d9Smatthias.ringwald 47058ad4dfffSMatthias Ringwald 4706c8b2b785SMilanka Ringwald return ERROR_CODE_SUCCESS; 47079d9bbc01Smatthias.ringwald } 47089d9bbc01Smatthias.ringwald 47097e8856ebSMatthias Ringwald uint8_t l2cap_unregister_service(uint16_t psm){ 4710e0abb8e7S[email protected] 471185621840SMilanka Ringwald log_info("unregister psm 0x%x", psm); 4712e0abb8e7S[email protected] 47139d9bbc01Smatthias.ringwald l2cap_service_t *service = l2cap_get_service(psm); 47147e8856ebSMatthias Ringwald if (!service) return L2CAP_SERVICE_DOES_NOT_EXIST; 4715665d90f2SMatthias Ringwald btstack_linked_list_remove(&l2cap_services, (btstack_linked_item_t *) service); 4716d3a9df87Smatthias.ringwald btstack_memory_l2cap_service_free(service); 4717c0e866bfSmatthias.ringwald 47188ad4dfffSMatthias Ringwald l2cap_update_minimal_security_level(); 47198ad4dfffSMatthias Ringwald 472047a15588SMatthias Ringwald #ifndef ENABLE_EXPLICIT_CONNECTABLE_MODE_CONTROL 4721c0e866bfSmatthias.ringwald // disable page scan when no services registered 47227e8856ebSMatthias Ringwald if (btstack_linked_list_empty(&l2cap_services)) { 472315a95bd5SMatthias Ringwald gap_connectable_control(0); 47249d9bbc01Smatthias.ringwald } 472547a15588SMatthias Ringwald #endif 472647a15588SMatthias Ringwald 4727c8b2b785SMilanka Ringwald return ERROR_CODE_SUCCESS; 47287e8856ebSMatthias Ringwald } 472909e9d05bSMatthias Ringwald #endif 47309d9bbc01Smatthias.ringwald 47317192e786SMatthias Ringwald 4732*a254c508SMatthias Ringwald #ifdef ENABLE_L2CAP_CREDIT_BASED_CHANNELS 4733*a254c508SMatthias Ringwald 4734*a254c508SMatthias Ringwald static void l2cap_credit_based_send_pdu(l2cap_channel_t *channel) { 4735*a254c508SMatthias Ringwald btstack_assert(channel != NULL); 4736*a254c508SMatthias Ringwald btstack_assert(channel->send_sdu_buffer != NULL); 4737*a254c508SMatthias Ringwald btstack_assert(channel->credits_outgoing > 0); 4738*a254c508SMatthias Ringwald 4739*a254c508SMatthias Ringwald // send part of SDU 4740*a254c508SMatthias Ringwald hci_reserve_packet_buffer(); 4741*a254c508SMatthias Ringwald uint8_t *acl_buffer = hci_get_outgoing_packet_buffer(); 4742*a254c508SMatthias Ringwald uint8_t *l2cap_payload = acl_buffer + 8; 4743*a254c508SMatthias Ringwald uint16_t pos = 0; 4744*a254c508SMatthias Ringwald if (!channel->send_sdu_pos) { 4745*a254c508SMatthias Ringwald // store SDU len 4746*a254c508SMatthias Ringwald channel->send_sdu_pos += 2u; 4747*a254c508SMatthias Ringwald little_endian_store_16(l2cap_payload, pos, channel->send_sdu_len); 4748*a254c508SMatthias Ringwald pos += 2u; 4749*a254c508SMatthias Ringwald } 4750*a254c508SMatthias Ringwald uint16_t payload_size = btstack_min(channel->send_sdu_len + 2u - channel->send_sdu_pos, channel->remote_mps - pos); 4751*a254c508SMatthias Ringwald log_info("len %u, pos %u => payload %u, credits %u", channel->send_sdu_len, channel->send_sdu_pos, payload_size, 4752*a254c508SMatthias Ringwald channel->credits_outgoing); 4753*a254c508SMatthias Ringwald (void) memcpy(&l2cap_payload[pos], 4754*a254c508SMatthias Ringwald &channel->send_sdu_buffer[channel->send_sdu_pos - 2u], 4755*a254c508SMatthias Ringwald payload_size); // -2 for virtual SDU len 4756*a254c508SMatthias Ringwald pos += payload_size; 4757*a254c508SMatthias Ringwald channel->send_sdu_pos += payload_size; 4758*a254c508SMatthias Ringwald l2cap_setup_header(acl_buffer, channel->con_handle, 0, channel->remote_cid, pos); 4759*a254c508SMatthias Ringwald 4760*a254c508SMatthias Ringwald channel->credits_outgoing--; 4761*a254c508SMatthias Ringwald 4762*a254c508SMatthias Ringwald // update state (mark SDU as done) before calling hci_send_acl_packet_buffer (trigger l2cap_le_send_pdu again) 4763*a254c508SMatthias Ringwald bool done = channel->send_sdu_pos >= (channel->send_sdu_len + 2u); 4764*a254c508SMatthias Ringwald if (done) { 4765*a254c508SMatthias Ringwald channel->send_sdu_buffer = NULL; 4766*a254c508SMatthias Ringwald } 4767*a254c508SMatthias Ringwald 4768*a254c508SMatthias Ringwald hci_send_acl_packet_buffer(8u + pos); 4769*a254c508SMatthias Ringwald 4770*a254c508SMatthias Ringwald if (done) { 4771*a254c508SMatthias Ringwald // send done event 4772*a254c508SMatthias Ringwald l2cap_emit_simple_event_with_cid(channel, L2CAP_EVENT_LE_PACKET_SENT); 4773*a254c508SMatthias Ringwald // inform about can send now 4774*a254c508SMatthias Ringwald l2cap_le_notify_channel_can_send(channel); 4775*a254c508SMatthias Ringwald } 4776*a254c508SMatthias Ringwald } 4777*a254c508SMatthias Ringwald 4778*a254c508SMatthias Ringwald static uint8_t l2cap_credit_based_send_data(uint16_t local_cid, const uint8_t * data, uint16_t size){ 4779*a254c508SMatthias Ringwald 4780*a254c508SMatthias Ringwald l2cap_channel_t * channel = l2cap_get_channel_for_local_cid(local_cid); 4781*a254c508SMatthias Ringwald if (!channel) { 4782*a254c508SMatthias Ringwald log_error("l2cap send, no channel for cid 0x%02x", local_cid); 4783*a254c508SMatthias Ringwald return L2CAP_LOCAL_CID_DOES_NOT_EXIST; 4784*a254c508SMatthias Ringwald } 4785*a254c508SMatthias Ringwald 4786*a254c508SMatthias Ringwald if (size > channel->remote_mtu){ 4787*a254c508SMatthias Ringwald log_error("l2cap send, cid 0x%02x, data length exceeds remote MTU.", local_cid); 4788*a254c508SMatthias Ringwald return L2CAP_DATA_LEN_EXCEEDS_REMOTE_MTU; 4789*a254c508SMatthias Ringwald } 4790*a254c508SMatthias Ringwald 4791*a254c508SMatthias Ringwald if (channel->send_sdu_buffer){ 4792*a254c508SMatthias Ringwald log_info("l2cap send, cid 0x%02x, cannot send", local_cid); 4793*a254c508SMatthias Ringwald return BTSTACK_ACL_BUFFERS_FULL; 4794*a254c508SMatthias Ringwald } 4795*a254c508SMatthias Ringwald 4796*a254c508SMatthias Ringwald channel->send_sdu_buffer = data; 4797*a254c508SMatthias Ringwald channel->send_sdu_len = size; 4798*a254c508SMatthias Ringwald channel->send_sdu_pos = 0; 4799*a254c508SMatthias Ringwald 4800*a254c508SMatthias Ringwald l2cap_notify_channel_can_send(); 4801*a254c508SMatthias Ringwald return ERROR_CODE_SUCCESS; 4802*a254c508SMatthias Ringwald } 4803*a254c508SMatthias Ringwald 4804*a254c508SMatthias Ringwald static uint8_t l2cap_credit_based_provide_credits(uint16_t local_cid, uint16_t credits){ 4805*a254c508SMatthias Ringwald l2cap_channel_t * channel = l2cap_get_channel_for_local_cid(local_cid); 4806*a254c508SMatthias Ringwald if (!channel) { 4807*a254c508SMatthias Ringwald log_error("le credits no channel for cid 0x%02x", local_cid); 4808*a254c508SMatthias Ringwald return L2CAP_LOCAL_CID_DOES_NOT_EXIST; 4809*a254c508SMatthias Ringwald } 4810*a254c508SMatthias Ringwald 4811*a254c508SMatthias Ringwald // check state 4812*a254c508SMatthias Ringwald if (channel->state != L2CAP_STATE_OPEN){ 4813*a254c508SMatthias Ringwald log_error("le credits but channel 0x%02x not open yet", local_cid); 4814*a254c508SMatthias Ringwald } 4815*a254c508SMatthias Ringwald 4816*a254c508SMatthias Ringwald // ignore if set to automatic credits 4817*a254c508SMatthias Ringwald if (channel->automatic_credits) return ERROR_CODE_SUCCESS; 4818*a254c508SMatthias Ringwald 4819*a254c508SMatthias Ringwald // assert incoming credits + credits <= 0xffff 4820*a254c508SMatthias Ringwald uint32_t total_credits = channel->credits_incoming; 4821*a254c508SMatthias Ringwald total_credits += channel->new_credits_incoming; 4822*a254c508SMatthias Ringwald total_credits += credits; 4823*a254c508SMatthias Ringwald if (total_credits > 0xffffu){ 4824*a254c508SMatthias Ringwald log_error("le credits overrun: current %u, scheduled %u, additional %u", channel->credits_incoming, 4825*a254c508SMatthias Ringwald channel->new_credits_incoming, credits); 4826*a254c508SMatthias Ringwald } 4827*a254c508SMatthias Ringwald 4828*a254c508SMatthias Ringwald // set credits_granted 4829*a254c508SMatthias Ringwald channel->new_credits_incoming += credits; 4830*a254c508SMatthias Ringwald 4831*a254c508SMatthias Ringwald // go 4832*a254c508SMatthias Ringwald l2cap_run(); 4833*a254c508SMatthias Ringwald return ERROR_CODE_SUCCESS; 4834*a254c508SMatthias Ringwald } 4835*a254c508SMatthias Ringwald 4836*a254c508SMatthias Ringwald static void l2cap_credit_based_send_credits(l2cap_channel_t *channel) { 4837*a254c508SMatthias Ringwald log_info("l2cap: sending %u credits", channel->new_credits_incoming); 4838*a254c508SMatthias Ringwald channel->local_sig_id = l2cap_next_sig_id(); 4839*a254c508SMatthias Ringwald uint16_t new_credits = channel->new_credits_incoming; 4840*a254c508SMatthias Ringwald channel->new_credits_incoming = 0; 4841*a254c508SMatthias Ringwald channel->credits_incoming += new_credits; 4842*a254c508SMatthias Ringwald uint16_t signaling_cid = channel->address_type == BD_ADDR_TYPE_ACL ? L2CAP_CID_SIGNALING : L2CAP_CID_SIGNALING_LE; 4843*a254c508SMatthias Ringwald l2cap_send_general_signaling_packet(channel->con_handle, signaling_cid, L2CAP_FLOW_CONTROL_CREDIT_INDICATION, channel->local_sig_id, channel->local_cid, new_credits); 4844*a254c508SMatthias Ringwald } 4845*a254c508SMatthias Ringwald 4846*a254c508SMatthias Ringwald // @return valid 4847*a254c508SMatthias Ringwald static bool l2cap_credit_based_handle_credit_indication(hci_con_handle_t handle, const uint8_t * command, uint16_t len){ 4848*a254c508SMatthias Ringwald // check size 4849*a254c508SMatthias Ringwald if (len < 4u) return false; 4850*a254c508SMatthias Ringwald 4851*a254c508SMatthias Ringwald // find channel 4852*a254c508SMatthias Ringwald uint16_t remote_cid = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET + 0); 4853*a254c508SMatthias Ringwald l2cap_channel_t * channel = l2cap_get_channel_for_remote_handle_and_cid(handle, remote_cid); 4854*a254c508SMatthias Ringwald if (!channel) { 4855*a254c508SMatthias Ringwald log_error("credit: no channel for handle 0x%04x/cid 0x%02x", handle, remote_cid); 4856*a254c508SMatthias Ringwald return true; 4857*a254c508SMatthias Ringwald } 4858*a254c508SMatthias Ringwald uint16_t new_credits = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET + 2); 4859*a254c508SMatthias Ringwald uint16_t credits_before = channel->credits_outgoing; 4860*a254c508SMatthias Ringwald channel->credits_outgoing += new_credits; 4861*a254c508SMatthias Ringwald // check for credit overrun 4862*a254c508SMatthias Ringwald if (credits_before > channel->credits_outgoing) { 4863*a254c508SMatthias Ringwald log_error("credit: new credits caused overrrun for cid 0x%02x, disconnecting", channel->local_cid); 4864*a254c508SMatthias Ringwald channel->state = L2CAP_STATE_WILL_SEND_DISCONNECT_REQUEST; 4865*a254c508SMatthias Ringwald return true; 4866*a254c508SMatthias Ringwald } 4867*a254c508SMatthias Ringwald log_info("credit: %u credits for 0x%02x, now %u", new_credits, channel->local_cid, channel->credits_outgoing); 4868*a254c508SMatthias Ringwald l2cap_call_notify_channel_in_run = true; 4869*a254c508SMatthias Ringwald return true; 4870*a254c508SMatthias Ringwald } 4871*a254c508SMatthias Ringwald 4872*a254c508SMatthias Ringwald static void l2cap_credit_based_handle_pdu(l2cap_channel_t * l2cap_channel, const uint8_t * packet, uint16_t size){ 4873*a254c508SMatthias Ringwald // ignore empty packets 4874*a254c508SMatthias Ringwald if (size == COMPLETE_L2CAP_HEADER) return; 4875*a254c508SMatthias Ringwald 4876*a254c508SMatthias Ringwald // credit counting 4877*a254c508SMatthias Ringwald if (l2cap_channel->credits_incoming == 0u){ 4878*a254c508SMatthias Ringwald log_info("Data Channel packet received but no incoming credits"); 4879*a254c508SMatthias Ringwald l2cap_channel->state = L2CAP_STATE_WILL_SEND_DISCONNECT_REQUEST; 4880*a254c508SMatthias Ringwald return; 4881*a254c508SMatthias Ringwald } 4882*a254c508SMatthias Ringwald l2cap_channel->credits_incoming--; 4883*a254c508SMatthias Ringwald 4884*a254c508SMatthias Ringwald // automatic credits 4885*a254c508SMatthias Ringwald if ((l2cap_channel->credits_incoming < L2CAP_LE_DATA_CHANNELS_AUTOMATIC_CREDITS_WATERMARK) && l2cap_channel->automatic_credits){ 4886*a254c508SMatthias Ringwald l2cap_channel->new_credits_incoming = L2CAP_LE_DATA_CHANNELS_AUTOMATIC_CREDITS_INCREMENT; 4887*a254c508SMatthias Ringwald } 4888*a254c508SMatthias Ringwald 4889*a254c508SMatthias Ringwald // first fragment 4890*a254c508SMatthias Ringwald uint16_t pos = 0; 4891*a254c508SMatthias Ringwald if (!l2cap_channel->receive_sdu_len){ 4892*a254c508SMatthias Ringwald if (size < (COMPLETE_L2CAP_HEADER + 2)) return; 4893*a254c508SMatthias Ringwald uint16_t sdu_len = little_endian_read_16(packet, COMPLETE_L2CAP_HEADER); 4894*a254c508SMatthias Ringwald if(sdu_len > l2cap_channel->local_mtu) return; // SDU would be larger than our buffer 4895*a254c508SMatthias Ringwald l2cap_channel->receive_sdu_len = sdu_len; 4896*a254c508SMatthias Ringwald l2cap_channel->receive_sdu_pos = 0; 4897*a254c508SMatthias Ringwald pos += 2u; 4898*a254c508SMatthias Ringwald size -= 2u; 4899*a254c508SMatthias Ringwald } 4900*a254c508SMatthias Ringwald uint16_t fragment_size = size-COMPLETE_L2CAP_HEADER; 4901*a254c508SMatthias Ringwald uint16_t remaining_space = l2cap_channel->local_mtu - l2cap_channel->receive_sdu_pos; 4902*a254c508SMatthias Ringwald if (fragment_size > remaining_space) return; // SDU would cause buffer overrun 4903*a254c508SMatthias Ringwald (void)memcpy(&l2cap_channel->receive_sdu_buffer[l2cap_channel->receive_sdu_pos], 4904*a254c508SMatthias Ringwald &packet[COMPLETE_L2CAP_HEADER + pos], 4905*a254c508SMatthias Ringwald fragment_size); 4906*a254c508SMatthias Ringwald l2cap_channel->receive_sdu_pos += size - COMPLETE_L2CAP_HEADER; 4907*a254c508SMatthias Ringwald // done? 4908*a254c508SMatthias Ringwald log_debug("le packet pos %u, len %u", l2cap_channel->receive_sdu_pos, l2cap_channel->receive_sdu_len); 4909*a254c508SMatthias Ringwald if (l2cap_channel->receive_sdu_pos >= l2cap_channel->receive_sdu_len){ 4910*a254c508SMatthias Ringwald l2cap_dispatch_to_channel(l2cap_channel, L2CAP_DATA_PACKET, l2cap_channel->receive_sdu_buffer, l2cap_channel->receive_sdu_len); 4911*a254c508SMatthias Ringwald l2cap_channel->receive_sdu_len = 0; 4912*a254c508SMatthias Ringwald } 4913*a254c508SMatthias Ringwald } 4914*a254c508SMatthias Ringwald 4915*a254c508SMatthias Ringwald static uint8_t l2cap_credit_based_disconnect(uint16_t local_cid){ 4916*a254c508SMatthias Ringwald l2cap_channel_t * channel = l2cap_get_channel_for_local_cid(local_cid); 4917*a254c508SMatthias Ringwald if (!channel) { 4918*a254c508SMatthias Ringwald return L2CAP_LOCAL_CID_DOES_NOT_EXIST; 4919*a254c508SMatthias Ringwald } 4920*a254c508SMatthias Ringwald channel->state = L2CAP_STATE_WILL_SEND_DISCONNECT_REQUEST; 4921*a254c508SMatthias Ringwald l2cap_run(); 4922*a254c508SMatthias Ringwald return ERROR_CODE_SUCCESS; 4923*a254c508SMatthias Ringwald } 4924*a254c508SMatthias Ringwald #endif 4925*a254c508SMatthias Ringwald 4926cab29d48SMatthias Ringwald #ifdef ENABLE_LE_DATA_CHANNELS 492783fd9c76SMatthias Ringwald 492857be49d6SMatthias Ringwald static void l2cap_le_notify_channel_can_send(l2cap_channel_t *channel){ 492957be49d6SMatthias Ringwald if (!channel->waiting_for_can_send_now) return; 493057be49d6SMatthias Ringwald if (channel->send_sdu_buffer) return; 493157be49d6SMatthias Ringwald channel->waiting_for_can_send_now = 0; 493285621840SMilanka Ringwald log_debug("le can send now, local_cid 0x%x", channel->local_cid); 493357be49d6SMatthias Ringwald l2cap_emit_simple_event_with_cid(channel, L2CAP_EVENT_LE_CAN_SEND_NOW); 493457be49d6SMatthias Ringwald } 493557be49d6SMatthias Ringwald 493657be49d6SMatthias Ringwald // 1BH2222 493757be49d6SMatthias Ringwald static void l2cap_emit_le_incoming_connection(l2cap_channel_t *channel) { 493885621840SMilanka Ringwald log_info("le incoming addr_type %u, addr %s handle 0x%x psm 0x%x local_cid 0x%x remote_cid 0x%x, remote_mtu %u", 493957be49d6SMatthias Ringwald channel->address_type, bd_addr_to_str(channel->address), channel->con_handle, channel->psm, channel->local_cid, channel->remote_cid, channel->remote_mtu); 494057be49d6SMatthias Ringwald uint8_t event[19]; 494157be49d6SMatthias Ringwald event[0] = L2CAP_EVENT_LE_INCOMING_CONNECTION; 49424ea43905SMatthias Ringwald event[1] = sizeof(event) - 2u; 494357be49d6SMatthias Ringwald event[2] = channel->address_type; 494457be49d6SMatthias Ringwald reverse_bd_addr(channel->address, &event[3]); 494557be49d6SMatthias Ringwald little_endian_store_16(event, 9, channel->con_handle); 494657be49d6SMatthias Ringwald little_endian_store_16(event, 11, channel->psm); 494757be49d6SMatthias Ringwald little_endian_store_16(event, 13, channel->local_cid); 494857be49d6SMatthias Ringwald little_endian_store_16(event, 15, channel->remote_cid); 494957be49d6SMatthias Ringwald little_endian_store_16(event, 17, channel->remote_mtu); 495057be49d6SMatthias Ringwald hci_dump_packet( HCI_EVENT_PACKET, 0, event, sizeof(event)); 495157be49d6SMatthias Ringwald l2cap_dispatch_to_channel(channel, HCI_EVENT_PACKET, event, sizeof(event)); 495257be49d6SMatthias Ringwald } 495357be49d6SMatthias Ringwald // 11BH22222 495457be49d6SMatthias Ringwald static void l2cap_emit_le_channel_opened(l2cap_channel_t *channel, uint8_t status) { 495585621840SMilanka Ringwald log_info("opened le channel status 0x%x addr_type %u addr %s handle 0x%x psm 0x%x local_cid 0x%x remote_cid 0x%x local_mtu %u, remote_mtu %u", 495657be49d6SMatthias Ringwald status, channel->address_type, bd_addr_to_str(channel->address), channel->con_handle, channel->psm, 495757be49d6SMatthias Ringwald channel->local_cid, channel->remote_cid, channel->local_mtu, channel->remote_mtu); 4958c99bb618SMatthias Ringwald uint8_t event[23]; 495957be49d6SMatthias Ringwald event[0] = L2CAP_EVENT_LE_CHANNEL_OPENED; 49604ea43905SMatthias Ringwald event[1] = sizeof(event) - 2u; 496157be49d6SMatthias Ringwald event[2] = status; 496257be49d6SMatthias Ringwald event[3] = channel->address_type; 496357be49d6SMatthias Ringwald reverse_bd_addr(channel->address, &event[4]); 496457be49d6SMatthias Ringwald little_endian_store_16(event, 10, channel->con_handle); 4965c1ab6cc1SMatthias Ringwald event[12] = (channel->state_var & L2CAP_CHANNEL_STATE_VAR_INCOMING) ? 1 : 0; 4966c99bb618SMatthias Ringwald little_endian_store_16(event, 13, channel->psm); 4967c99bb618SMatthias Ringwald little_endian_store_16(event, 15, channel->local_cid); 4968c99bb618SMatthias Ringwald little_endian_store_16(event, 17, channel->remote_cid); 4969c99bb618SMatthias Ringwald little_endian_store_16(event, 19, channel->local_mtu); 4970c99bb618SMatthias Ringwald little_endian_store_16(event, 21, channel->remote_mtu); 497157be49d6SMatthias Ringwald hci_dump_packet( HCI_EVENT_PACKET, 0, event, sizeof(event)); 497257be49d6SMatthias Ringwald l2cap_dispatch_to_channel(channel, HCI_EVENT_PACKET, event, sizeof(event)); 497357be49d6SMatthias Ringwald } 497487050a0bSMatthias Ringwald // 2 497587050a0bSMatthias Ringwald static void l2cap_emit_le_channel_closed(l2cap_channel_t * channel){ 497685621840SMilanka Ringwald log_info("closed local_cid 0x%x", channel->local_cid); 497787050a0bSMatthias Ringwald uint8_t event[4]; 497887050a0bSMatthias Ringwald event[0] = L2CAP_EVENT_LE_CHANNEL_CLOSED; 49794ea43905SMatthias Ringwald event[1] = sizeof(event) - 2u; 498087050a0bSMatthias Ringwald little_endian_store_16(event, 2, channel->local_cid); 498187050a0bSMatthias Ringwald hci_dump_packet( HCI_EVENT_PACKET, 0, event, sizeof(event)); 498287050a0bSMatthias Ringwald l2cap_dispatch_to_channel(channel, HCI_EVENT_PACKET, event, sizeof(event)); 498387050a0bSMatthias Ringwald } 498487050a0bSMatthias Ringwald 498557be49d6SMatthias Ringwald // finalize closed channel - l2cap_handle_disconnect_request & DISCONNECTION_RESPONSE 498657be49d6SMatthias Ringwald void l2cap_le_finialize_channel_close(l2cap_channel_t * channel){ 498757be49d6SMatthias Ringwald channel->state = L2CAP_STATE_CLOSED; 498857be49d6SMatthias Ringwald l2cap_emit_simple_event_with_cid(channel, L2CAP_EVENT_CHANNEL_CLOSED); 498957be49d6SMatthias Ringwald // discard channel 4990421cb104SMatthias Ringwald btstack_linked_list_remove(&l2cap_channels, (btstack_linked_item_t *) channel); 4991c45d6b2cSMatthias Ringwald l2cap_free_channel_entry(channel); 499257be49d6SMatthias Ringwald } 499357be49d6SMatthias Ringwald 4994e7d0c9aaSMatthias Ringwald static inline l2cap_service_t * l2cap_le_get_service(uint16_t le_psm){ 4995e7d0c9aaSMatthias Ringwald return l2cap_get_service_internal(&l2cap_le_services, le_psm); 49967192e786SMatthias Ringwald } 4997efedfb4cSMatthias Ringwald 4998da144af5SMatthias Ringwald uint8_t l2cap_le_register_service(btstack_packet_handler_t packet_handler, uint16_t psm, gap_security_level_t security_level){ 49997192e786SMatthias Ringwald 5000da144af5SMatthias Ringwald log_info("L2CAP_LE_REGISTER_SERVICE psm 0x%x", psm); 50017192e786SMatthias Ringwald 50027192e786SMatthias Ringwald // check for alread registered psm 50037192e786SMatthias Ringwald l2cap_service_t *service = l2cap_le_get_service(psm); 50047192e786SMatthias Ringwald if (service) { 5005da144af5SMatthias Ringwald return L2CAP_SERVICE_ALREADY_REGISTERED; 50067192e786SMatthias Ringwald } 50077192e786SMatthias Ringwald 50087192e786SMatthias Ringwald // alloc structure 50097192e786SMatthias Ringwald service = btstack_memory_l2cap_service_get(); 50107192e786SMatthias Ringwald if (!service) { 501185621840SMilanka Ringwald log_error("register: no memory for l2cap_service_t"); 5012da144af5SMatthias Ringwald return BTSTACK_MEMORY_ALLOC_FAILED; 50137192e786SMatthias Ringwald } 50147192e786SMatthias Ringwald 50157192e786SMatthias Ringwald // fill in 50167192e786SMatthias Ringwald service->psm = psm; 5017da144af5SMatthias Ringwald service->mtu = 0; 50187192e786SMatthias Ringwald service->packet_handler = packet_handler; 50197192e786SMatthias Ringwald service->required_security_level = security_level; 50207192e786SMatthias Ringwald 50217192e786SMatthias Ringwald // add to services list 5022665d90f2SMatthias Ringwald btstack_linked_list_add(&l2cap_le_services, (btstack_linked_item_t *) service); 50237192e786SMatthias Ringwald 50247192e786SMatthias Ringwald // done 50259dd26175SMilanka Ringwald return ERROR_CODE_SUCCESS; 50267192e786SMatthias Ringwald } 50277192e786SMatthias Ringwald 5028da144af5SMatthias Ringwald uint8_t l2cap_le_unregister_service(uint16_t psm) { 50297192e786SMatthias Ringwald log_info("L2CAP_LE_UNREGISTER_SERVICE psm 0x%x", psm); 50307192e786SMatthias Ringwald l2cap_service_t *service = l2cap_le_get_service(psm); 50319367f9b0SMatthias Ringwald if (!service) return L2CAP_SERVICE_DOES_NOT_EXIST; 5032da144af5SMatthias Ringwald 5033665d90f2SMatthias Ringwald btstack_linked_list_remove(&l2cap_le_services, (btstack_linked_item_t *) service); 50347192e786SMatthias Ringwald btstack_memory_l2cap_service_free(service); 5035c8b2b785SMilanka Ringwald return ERROR_CODE_SUCCESS; 50367192e786SMatthias Ringwald } 5037da144af5SMatthias Ringwald 5038da144af5SMatthias Ringwald uint8_t l2cap_le_accept_connection(uint16_t local_cid, uint8_t * receive_sdu_buffer, uint16_t mtu, uint16_t initial_credits){ 5039e7d0c9aaSMatthias Ringwald // get channel 5040421cb104SMatthias Ringwald l2cap_channel_t * channel = l2cap_get_channel_for_local_cid(local_cid); 5041e7d0c9aaSMatthias Ringwald if (!channel) return L2CAP_LOCAL_CID_DOES_NOT_EXIST; 5042e7d0c9aaSMatthias Ringwald 5043e7d0c9aaSMatthias Ringwald // validate state 5044e7d0c9aaSMatthias Ringwald if (channel->state != L2CAP_STATE_WAIT_CLIENT_ACCEPT_OR_REJECT){ 5045e7d0c9aaSMatthias Ringwald return ERROR_CODE_COMMAND_DISALLOWED; 5046e7d0c9aaSMatthias Ringwald } 5047e7d0c9aaSMatthias Ringwald 5048efedfb4cSMatthias Ringwald // set state accept connection 504923017473SMatthias Ringwald channel->state = L2CAP_STATE_WILL_SEND_LE_CONNECTION_RESPONSE_ACCEPT; 505023017473SMatthias Ringwald channel->receive_sdu_buffer = receive_sdu_buffer; 505123017473SMatthias Ringwald channel->local_mtu = mtu; 505285aeef60SMatthias Ringwald channel->new_credits_incoming = initial_credits; 505385aeef60SMatthias Ringwald channel->automatic_credits = initial_credits == L2CAP_LE_AUTOMATIC_CREDITS; 505485aeef60SMatthias Ringwald 5055e7d0c9aaSMatthias Ringwald // go 5056e7d0c9aaSMatthias Ringwald l2cap_run(); 5057c8b2b785SMilanka Ringwald return ERROR_CODE_SUCCESS; 5058da144af5SMatthias Ringwald } 5059da144af5SMatthias Ringwald 5060da144af5SMatthias Ringwald /** 5061da144af5SMatthias Ringwald * @brief Deny incoming LE Data Channel connection due to resource constraints 5062da144af5SMatthias Ringwald * @param local_cid L2CAP LE Data Channel Identifier 5063da144af5SMatthias Ringwald */ 5064da144af5SMatthias Ringwald 5065da144af5SMatthias Ringwald uint8_t l2cap_le_decline_connection(uint16_t local_cid){ 5066e7d0c9aaSMatthias Ringwald // get channel 5067421cb104SMatthias Ringwald l2cap_channel_t * channel = l2cap_get_channel_for_local_cid(local_cid); 5068e7d0c9aaSMatthias Ringwald if (!channel) return L2CAP_LOCAL_CID_DOES_NOT_EXIST; 5069e7d0c9aaSMatthias Ringwald 5070e7d0c9aaSMatthias Ringwald // validate state 5071e7d0c9aaSMatthias Ringwald if (channel->state != L2CAP_STATE_WAIT_CLIENT_ACCEPT_OR_REJECT){ 5072e7d0c9aaSMatthias Ringwald return ERROR_CODE_COMMAND_DISALLOWED; 5073e7d0c9aaSMatthias Ringwald } 5074e7d0c9aaSMatthias Ringwald 5075efedfb4cSMatthias Ringwald // set state decline connection 5076e7d0c9aaSMatthias Ringwald channel->state = L2CAP_STATE_WILL_SEND_LE_CONNECTION_RESPONSE_DECLINE; 5077e7d0c9aaSMatthias Ringwald channel->reason = 0x04; // no resources available 5078e7d0c9aaSMatthias Ringwald l2cap_run(); 5079c8b2b785SMilanka Ringwald return ERROR_CODE_SUCCESS; 5080da144af5SMatthias Ringwald } 5081da144af5SMatthias Ringwald 50825cc4b885SMatthias Ringwald static gap_security_level_t l2cap_le_security_level_for_connection(hci_con_handle_t con_handle){ 50835cc4b885SMatthias Ringwald uint8_t encryption_key_size = gap_encryption_key_size(con_handle); 50845cc4b885SMatthias Ringwald if (encryption_key_size == 0) return LEVEL_0; 50855cc4b885SMatthias Ringwald 50865cc4b885SMatthias Ringwald uint8_t authenticated = gap_authenticated(con_handle); 50875cc4b885SMatthias Ringwald if (!authenticated) return LEVEL_2; 50885cc4b885SMatthias Ringwald 50895cc4b885SMatthias Ringwald return encryption_key_size == 16 ? LEVEL_4 : LEVEL_3; 50905cc4b885SMatthias Ringwald } 50915cc4b885SMatthias Ringwald 50925cc4b885SMatthias Ringwald // used to handle pairing complete after triggering to increase 50935cc4b885SMatthias Ringwald static void l2cap_sm_packet_handler(uint8_t packet_type, uint16_t channel_nr, uint8_t *packet, uint16_t size) { 50945cc4b885SMatthias Ringwald UNUSED(channel_nr); 50955cc4b885SMatthias Ringwald UNUSED(size); 509648f33f37SMatthias Ringwald UNUSED(packet_type); 5097e883851fSMatthias Ringwald btstack_assert(packet_type == HCI_EVENT_PACKET); 50985cc4b885SMatthias Ringwald if (hci_event_packet_get_type(packet) != SM_EVENT_PAIRING_COMPLETE) return; 50995cc4b885SMatthias Ringwald hci_con_handle_t con_handle = sm_event_pairing_complete_get_handle(packet); 51005cc4b885SMatthias Ringwald btstack_linked_list_iterator_t it; 51015cc4b885SMatthias Ringwald btstack_linked_list_iterator_init(&it, &l2cap_channels); 51025cc4b885SMatthias Ringwald while (btstack_linked_list_iterator_has_next(&it)) { 51035cc4b885SMatthias Ringwald l2cap_channel_t *channel = (l2cap_channel_t *) btstack_linked_list_iterator_next(&it); 51045cc4b885SMatthias Ringwald if (!l2cap_is_dynamic_channel_type(channel->channel_type)) continue; 51055cc4b885SMatthias Ringwald if (channel->con_handle != con_handle) continue; 51065cc4b885SMatthias Ringwald if (channel->state != L2CAP_STATE_WAIT_OUTGOING_SECURITY_LEVEL_UPDATE) continue; 51075cc4b885SMatthias Ringwald 51085cc4b885SMatthias Ringwald // found channel, check security level 51095cc4b885SMatthias Ringwald if (l2cap_le_security_level_for_connection(con_handle) < channel->required_security_level){ 51105cc4b885SMatthias Ringwald // pairing failed or wasn't good enough, inform user 51115cc4b885SMatthias Ringwald l2cap_emit_le_channel_opened(channel, ERROR_CODE_INSUFFICIENT_SECURITY); 51125cc4b885SMatthias Ringwald // discard channel 51135cc4b885SMatthias Ringwald btstack_linked_list_remove(&l2cap_channels, (btstack_linked_item_t *) channel); 51145cc4b885SMatthias Ringwald l2cap_free_channel_entry(channel); 51155cc4b885SMatthias Ringwald } else { 51165cc4b885SMatthias Ringwald // send conn request now 51175cc4b885SMatthias Ringwald channel->state = L2CAP_STATE_WILL_SEND_LE_CONNECTION_REQUEST; 51185cc4b885SMatthias Ringwald l2cap_run(); 51195cc4b885SMatthias Ringwald } 51205cc4b885SMatthias Ringwald } 51215cc4b885SMatthias Ringwald } 51225cc4b885SMatthias Ringwald 51237dafa750SMatthias Ringwald uint8_t l2cap_le_create_channel(btstack_packet_handler_t packet_handler, hci_con_handle_t con_handle, 5124da144af5SMatthias Ringwald uint16_t psm, uint8_t * receive_sdu_buffer, uint16_t mtu, uint16_t initial_credits, gap_security_level_t security_level, 5125efedfb4cSMatthias Ringwald uint16_t * out_local_cid) { 5126efedfb4cSMatthias Ringwald 51275cc4b885SMatthias Ringwald static btstack_packet_callback_registration_t sm_event_callback_registration; 51285cc4b885SMatthias Ringwald static bool sm_callback_registered = false; 5129da144af5SMatthias Ringwald 513085621840SMilanka Ringwald log_info("create, handle 0x%04x psm 0x%x mtu %u", con_handle, psm, mtu); 51317dafa750SMatthias Ringwald 51327dafa750SMatthias Ringwald hci_connection_t * connection = hci_connection_for_handle(con_handle); 51337dafa750SMatthias Ringwald if (!connection) { 51347dafa750SMatthias Ringwald log_error("no hci_connection for handle 0x%04x", con_handle); 51357dafa750SMatthias Ringwald return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 51367dafa750SMatthias Ringwald } 51377dafa750SMatthias Ringwald 51385d18f623SMatthias Ringwald l2cap_channel_t * channel = l2cap_create_channel_entry(packet_handler, L2CAP_CHANNEL_TYPE_LE_DATA_CHANNEL, connection->address, connection->address_type, psm, mtu, security_level); 5139da144af5SMatthias Ringwald if (!channel) { 5140da144af5SMatthias Ringwald return BTSTACK_MEMORY_ALLOC_FAILED; 5141da144af5SMatthias Ringwald } 514285621840SMilanka Ringwald log_info("created %p", channel); 5143da144af5SMatthias Ringwald 5144da144af5SMatthias Ringwald // store local_cid 5145da144af5SMatthias Ringwald if (out_local_cid){ 5146da144af5SMatthias Ringwald *out_local_cid = channel->local_cid; 5147da144af5SMatthias Ringwald } 5148da144af5SMatthias Ringwald 51495cc4b885SMatthias Ringwald // setup channel entry 51507dafa750SMatthias Ringwald channel->con_handle = con_handle; 5151cd529728SMatthias Ringwald channel->receive_sdu_buffer = receive_sdu_buffer; 515285aeef60SMatthias Ringwald channel->new_credits_incoming = initial_credits; 515385aeef60SMatthias Ringwald channel->automatic_credits = initial_credits == L2CAP_LE_AUTOMATIC_CREDITS; 515485aeef60SMatthias Ringwald 5155efedfb4cSMatthias Ringwald // add to connections list 5156da4c2b27SMatthias Ringwald btstack_linked_list_add_tail(&l2cap_channels, (btstack_linked_item_t *) channel); 5157efedfb4cSMatthias Ringwald 51585cc4b885SMatthias Ringwald // check security level 51595cc4b885SMatthias Ringwald if (l2cap_le_security_level_for_connection(con_handle) < channel->required_security_level){ 51605cc4b885SMatthias Ringwald if (!sm_callback_registered){ 51615cc4b885SMatthias Ringwald sm_callback_registered = true; 51625cc4b885SMatthias Ringwald // lazy registration for SM events 51635cc4b885SMatthias Ringwald sm_event_callback_registration.callback = &l2cap_sm_packet_handler; 51645cc4b885SMatthias Ringwald sm_add_event_handler(&sm_event_callback_registration); 51655cc4b885SMatthias Ringwald } 51665cc4b885SMatthias Ringwald 51675cc4b885SMatthias Ringwald // start pairing 51685cc4b885SMatthias Ringwald channel->state = L2CAP_STATE_WAIT_OUTGOING_SECURITY_LEVEL_UPDATE; 51695cc4b885SMatthias Ringwald sm_request_pairing(con_handle); 51705cc4b885SMatthias Ringwald } else { 51715cc4b885SMatthias Ringwald // send conn request right away 51725cc4b885SMatthias Ringwald channel->state = L2CAP_STATE_WILL_SEND_LE_CONNECTION_REQUEST; 517363f0ac45SMatthias Ringwald l2cap_run(); 51745cc4b885SMatthias Ringwald } 51755cc4b885SMatthias Ringwald 5176c8b2b785SMilanka Ringwald return ERROR_CODE_SUCCESS; 5177da144af5SMatthias Ringwald } 5178da144af5SMatthias Ringwald 5179da144af5SMatthias Ringwald /** 5180da144af5SMatthias Ringwald * @brief Provide credtis for LE Data Channel 5181da144af5SMatthias Ringwald * @param local_cid L2CAP LE Data Channel Identifier 5182da144af5SMatthias Ringwald * @param credits Number additional credits for peer 5183da144af5SMatthias Ringwald */ 518464e11ca9SMatthias Ringwald uint8_t l2cap_le_provide_credits(uint16_t local_cid, uint16_t credits){ 5185*a254c508SMatthias Ringwald return l2cap_credit_based_provide_credits(local_cid, credits); 5186da144af5SMatthias Ringwald } 5187da144af5SMatthias Ringwald 5188da144af5SMatthias Ringwald /** 5189da144af5SMatthias Ringwald * @brief Check if outgoing buffer is available and that there's space on the Bluetooth module 5190da144af5SMatthias Ringwald * @param local_cid L2CAP LE Data Channel Identifier 5191da144af5SMatthias Ringwald */ 51926106bf3fSMatthias Ringwald bool l2cap_le_can_send_now(uint16_t local_cid){ 5193421cb104SMatthias Ringwald l2cap_channel_t * channel = l2cap_get_channel_for_local_cid(local_cid); 519444276248SMatthias Ringwald if (!channel) { 519585621840SMilanka Ringwald log_error("le can send now, no channel for cid 0x%02x", local_cid); 51966106bf3fSMatthias Ringwald return false; 5197da144af5SMatthias Ringwald } 5198da144af5SMatthias Ringwald 519944276248SMatthias Ringwald // check state 52006106bf3fSMatthias Ringwald if (channel->state != L2CAP_STATE_OPEN) return false; 520144276248SMatthias Ringwald 520244276248SMatthias Ringwald // check queue 52036106bf3fSMatthias Ringwald if (channel->send_sdu_buffer) return false; 520444276248SMatthias Ringwald 520544276248SMatthias Ringwald // fine, go ahead 52066106bf3fSMatthias Ringwald return true; 520744276248SMatthias Ringwald } 520844276248SMatthias Ringwald 5209da144af5SMatthias Ringwald /** 5210da144af5SMatthias Ringwald * @brief Request emission of L2CAP_EVENT_CAN_SEND_NOW as soon as possible 5211da144af5SMatthias Ringwald * @note L2CAP_EVENT_CAN_SEND_NOW might be emitted during call to this function 5212da144af5SMatthias Ringwald * so packet handler should be ready to handle it 5213da144af5SMatthias Ringwald * @param local_cid L2CAP LE Data Channel Identifier 5214da144af5SMatthias Ringwald */ 521564e11ca9SMatthias Ringwald uint8_t l2cap_le_request_can_send_now_event(uint16_t local_cid){ 5216421cb104SMatthias Ringwald l2cap_channel_t * channel = l2cap_get_channel_for_local_cid(local_cid); 521744276248SMatthias Ringwald if (!channel) { 521885621840SMilanka Ringwald log_error("can send now, no channel for cid 0x%02x", local_cid); 5219c8b2b785SMilanka Ringwald return L2CAP_LOCAL_CID_DOES_NOT_EXIST; 522044276248SMatthias Ringwald } 522144276248SMatthias Ringwald channel->waiting_for_can_send_now = 1; 522244276248SMatthias Ringwald l2cap_le_notify_channel_can_send(channel); 5223c8b2b785SMilanka Ringwald return ERROR_CODE_SUCCESS; 5224da144af5SMatthias Ringwald } 5225da144af5SMatthias Ringwald 5226da144af5SMatthias Ringwald /** 5227da144af5SMatthias Ringwald * @brief Send data via LE Data Channel 5228da144af5SMatthias Ringwald * @note Since data larger then the maximum PDU needs to be segmented into multiple PDUs, data needs to stay valid until ... event 5229da144af5SMatthias Ringwald * @param local_cid L2CAP LE Data Channel Identifier 5230da144af5SMatthias Ringwald * @param data data to send 5231da144af5SMatthias Ringwald * @param size data size 5232da144af5SMatthias Ringwald */ 5233b45b7749SMilanka Ringwald uint8_t l2cap_le_send_data(uint16_t local_cid, uint8_t * data, uint16_t size){ 5234*a254c508SMatthias Ringwald return l2cap_credit_based_send_data(local_cid, data, size); 523564e11ca9SMatthias Ringwald } 523664e11ca9SMatthias Ringwald 5237da144af5SMatthias Ringwald 5238da144af5SMatthias Ringwald /** 5239da144af5SMatthias Ringwald * @brief Disconnect from LE Data Channel 5240da144af5SMatthias Ringwald * @param local_cid L2CAP LE Data Channel Identifier 5241da144af5SMatthias Ringwald */ 5242*a254c508SMatthias Ringwald uint8_t l2cap_le_disconnect(uint16_t local_cid){ 5243*a254c508SMatthias Ringwald return l2cap_credit_based_disconnect(local_cid); 5244*a254c508SMatthias Ringwald } 5245*a254c508SMatthias Ringwald #endif 5246*a254c508SMatthias Ringwald 5247*a254c508SMatthias Ringwald #ifdef ENABLE_L2CAP_ENHANCED_DATA_CHANNELS 5248*a254c508SMatthias Ringwald 5249*a254c508SMatthias Ringwald uint8_t l2cap_enhanced_register_service(btstack_packet_handler_t packet_handler, uint16_t psm, uint16_t min_remote_mtu, gap_security_level_t security_level){ 5250*a254c508SMatthias Ringwald 5251*a254c508SMatthias Ringwald // check for already registered psm 5252*a254c508SMatthias Ringwald l2cap_service_t *service = l2cap_le_get_service(psm); 5253*a254c508SMatthias Ringwald if (service) { 5254*a254c508SMatthias Ringwald return L2CAP_SERVICE_ALREADY_REGISTERED; 5255828a7f7aSMatthias Ringwald } 5256828a7f7aSMatthias Ringwald 5257*a254c508SMatthias Ringwald // alloc structure 5258*a254c508SMatthias Ringwald service = btstack_memory_l2cap_service_get(); 5259*a254c508SMatthias Ringwald if (!service) { 5260*a254c508SMatthias Ringwald log_error("register: no memory for l2cap_service_t"); 5261*a254c508SMatthias Ringwald return BTSTACK_MEMORY_ALLOC_FAILED; 5262*a254c508SMatthias Ringwald } 5263*a254c508SMatthias Ringwald 5264*a254c508SMatthias Ringwald // fill in 5265*a254c508SMatthias Ringwald service->psm = psm; 5266*a254c508SMatthias Ringwald service->mtu = min_remote_mtu; 5267*a254c508SMatthias Ringwald service->packet_handler = packet_handler; 5268*a254c508SMatthias Ringwald service->required_security_level = security_level; 5269*a254c508SMatthias Ringwald 5270*a254c508SMatthias Ringwald // add to services list 5271*a254c508SMatthias Ringwald btstack_linked_list_add(&l2cap_enhanced_services, (btstack_linked_item_t *) service); 5272*a254c508SMatthias Ringwald 5273*a254c508SMatthias Ringwald // done 5274*a254c508SMatthias Ringwald return ERROR_CODE_SUCCESS; 5275*a254c508SMatthias Ringwald } 5276*a254c508SMatthias Ringwald 5277*a254c508SMatthias Ringwald uint8_t l2cap_enhanced_unregister_service(uint16_t psm) { 5278*a254c508SMatthias Ringwald l2cap_service_t *service = l2cap_le_get_service(psm); 5279*a254c508SMatthias Ringwald if (!service) return L2CAP_SERVICE_DOES_NOT_EXIST; 5280*a254c508SMatthias Ringwald 5281*a254c508SMatthias Ringwald btstack_linked_list_remove(&l2cap_enhanced_services, (btstack_linked_item_t *) service); 5282*a254c508SMatthias Ringwald btstack_memory_l2cap_service_free(service); 5283*a254c508SMatthias Ringwald return ERROR_CODE_SUCCESS; 5284*a254c508SMatthias Ringwald } 5285*a254c508SMatthias Ringwald 5286*a254c508SMatthias Ringwald void l2cap_enhanced_mps_set_min(uint16_t mps_min){ 5287*a254c508SMatthias Ringwald l2cap_enhanced_mps_min = mps_min; 5288*a254c508SMatthias Ringwald } 5289*a254c508SMatthias Ringwald 5290*a254c508SMatthias Ringwald void l2cap_enhanced_mps_set_max(uint16_t mps_max){ 5291*a254c508SMatthias Ringwald l2cap_enhanced_mps_max = mps_max; 5292*a254c508SMatthias Ringwald } 5293*a254c508SMatthias Ringwald 5294*a254c508SMatthias Ringwald uint8_t l2cap_enhanced_create_channels(btstack_packet_handler_t packet_handler, hci_con_handle_t con_handle, 5295*a254c508SMatthias Ringwald gap_security_level_t security_level, 5296*a254c508SMatthias Ringwald uint16_t psm, uint8_t num_channels, uint16_t initial_credits, uint16_t mtu, 5297*a254c508SMatthias Ringwald uint8_t ** receive_sdu_buffers, uint16_t * out_local_cid){ 5298*a254c508SMatthias Ringwald 5299*a254c508SMatthias Ringwald log_info("create enhanced, handle 0x%04x psm 0x%x mtu %u", con_handle, psm, mtu); 5300*a254c508SMatthias Ringwald 5301*a254c508SMatthias Ringwald hci_connection_t * connection = hci_connection_for_handle(con_handle); 5302*a254c508SMatthias Ringwald if (!connection) { 5303*a254c508SMatthias Ringwald log_error("no hci_connection for handle 0x%04x", con_handle); 5304*a254c508SMatthias Ringwald return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 5305*a254c508SMatthias Ringwald } 5306*a254c508SMatthias Ringwald 5307*a254c508SMatthias Ringwald // setup all channels 5308*a254c508SMatthias Ringwald btstack_linked_list_t channels = NULL; 5309*a254c508SMatthias Ringwald uint8_t status = l2cap_enhanced_setup_channels(&channels, packet_handler, num_channels, connection, psm, mtu, security_level); 5310*a254c508SMatthias Ringwald 5311*a254c508SMatthias Ringwald // add to connections list and set state + local_sig_id 5312*a254c508SMatthias Ringwald l2cap_channel_t * channel; 5313*a254c508SMatthias Ringwald uint8_t i = 0; 5314*a254c508SMatthias Ringwald uint8_t local_sig_id = l2cap_next_sig_id(); 5315*a254c508SMatthias Ringwald while (true) { 5316*a254c508SMatthias Ringwald channel = (l2cap_channel_t *) btstack_linked_list_pop(&channels); 5317*a254c508SMatthias Ringwald if (channel == NULL) break; 5318*a254c508SMatthias Ringwald channel->state = L2CAP_STATE_WILL_SEND_ENHANCED_CONNECTION_REQUEST; 5319*a254c508SMatthias Ringwald channel->local_sig_id = local_sig_id; 5320*a254c508SMatthias Ringwald channel->cid_index = i; 5321*a254c508SMatthias Ringwald channel->num_cids = num_channels; 5322*a254c508SMatthias Ringwald channel->credits_incoming = initial_credits; 5323*a254c508SMatthias Ringwald channel->automatic_credits = initial_credits == L2CAP_LE_AUTOMATIC_CREDITS; 5324*a254c508SMatthias Ringwald channel->receive_sdu_buffer = receive_sdu_buffers[i]; 5325*a254c508SMatthias Ringwald // store local_cid 5326*a254c508SMatthias Ringwald if (out_local_cid){ 5327*a254c508SMatthias Ringwald out_local_cid[i] = channel->local_cid; 5328*a254c508SMatthias Ringwald } 5329*a254c508SMatthias Ringwald btstack_linked_list_add_tail(&l2cap_channels, (btstack_linked_item_t *) channel); 5330*a254c508SMatthias Ringwald i++; 5331*a254c508SMatthias Ringwald } 5332*a254c508SMatthias Ringwald 5333*a254c508SMatthias Ringwald #if 0 5334*a254c508SMatthias Ringwald // check security level 5335*a254c508SMatthias Ringwald if (l2cap_le_security_level_for_connection(con_handle) < channel->required_security_level){ 5336*a254c508SMatthias Ringwald if (!sm_callback_registered){ 5337*a254c508SMatthias Ringwald sm_callback_registered = true; 5338*a254c508SMatthias Ringwald // lazy registration for SM events 5339*a254c508SMatthias Ringwald sm_event_callback_registration.callback = &l2cap_sm_packet_handler; 5340*a254c508SMatthias Ringwald sm_add_event_handler(&sm_event_callback_registration); 5341*a254c508SMatthias Ringwald } 5342*a254c508SMatthias Ringwald 5343*a254c508SMatthias Ringwald // start pairing 5344*a254c508SMatthias Ringwald channel->state = L2CAP_STATE_WAIT_OUTGOING_SECURITY_LEVEL_UPDATE; 5345*a254c508SMatthias Ringwald sm_request_pairing(con_handle); 5346*a254c508SMatthias Ringwald } else { 5347*a254c508SMatthias Ringwald // send conn request right away 5348*a254c508SMatthias Ringwald channel->state = L2CAP_STATE_WILL_SEND_LE_CONNECTION_REQUEST; 5349*a254c508SMatthias Ringwald l2cap_run(); 5350*a254c508SMatthias Ringwald } 5351*a254c508SMatthias Ringwald #endif 5352*a254c508SMatthias Ringwald 5353*a254c508SMatthias Ringwald l2cap_run(); 5354*a254c508SMatthias Ringwald 5355*a254c508SMatthias Ringwald return status; 5356*a254c508SMatthias Ringwald } 5357*a254c508SMatthias Ringwald 5358*a254c508SMatthias Ringwald uint8_t l2cap_enhanced_accept_data_channels(uint16_t local_cid, uint8_t num_channels, uint16_t initial_credits, 5359*a254c508SMatthias Ringwald uint16_t receive_buffer_size, uint8_t ** receive_buffers, uint16_t * out_local_cids){ 5360*a254c508SMatthias Ringwald 5361*a254c508SMatthias Ringwald l2cap_channel_t * channel = l2cap_get_channel_for_local_cid(local_cid); 5362*a254c508SMatthias Ringwald if (!channel) { 5363*a254c508SMatthias Ringwald 5364*a254c508SMatthias Ringwald return L2CAP_LOCAL_CID_DOES_NOT_EXIST; 5365*a254c508SMatthias Ringwald } 5366*a254c508SMatthias Ringwald // 5367*a254c508SMatthias Ringwald hci_con_handle_t con_handle = channel->con_handle; 5368*a254c508SMatthias Ringwald uint8_t local_sig_id = channel->local_sig_id; 5369*a254c508SMatthias Ringwald uint8_t channel_index = 0; 5370*a254c508SMatthias Ringwald btstack_linked_list_iterator_t it; 5371*a254c508SMatthias Ringwald btstack_linked_list_iterator_init(&it, &l2cap_channels); 5372*a254c508SMatthias Ringwald while (btstack_linked_list_iterator_has_next(&it)) { 5373*a254c508SMatthias Ringwald channel = (l2cap_channel_t *) btstack_linked_list_iterator_next(&it); 5374*a254c508SMatthias Ringwald if (!l2cap_is_dynamic_channel_type(channel->channel_type)) continue; 5375*a254c508SMatthias Ringwald if (channel->con_handle != con_handle) continue; 5376*a254c508SMatthias Ringwald if (channel->local_sig_id != local_sig_id) continue; 5377*a254c508SMatthias Ringwald if (channel->state != L2CAP_STATE_WAIT_CLIENT_ACCEPT_OR_REJECT) continue; 5378*a254c508SMatthias Ringwald 5379*a254c508SMatthias Ringwald if (channel_index < num_channels){ 5380*a254c508SMatthias Ringwald // assign buffer and cid 5381*a254c508SMatthias Ringwald out_local_cids[channel_index] = channel->local_cid; 5382*a254c508SMatthias Ringwald channel->receive_sdu_buffer = receive_buffers[channel_index]; 5383*a254c508SMatthias Ringwald channel->local_mtu = receive_buffer_size; 5384*a254c508SMatthias Ringwald channel->credits_incoming = initial_credits; 5385*a254c508SMatthias Ringwald channel->automatic_credits = initial_credits == L2CAP_LE_AUTOMATIC_CREDITS; 5386*a254c508SMatthias Ringwald channel_index++; 5387*a254c508SMatthias Ringwald } else { 5388*a254c508SMatthias Ringwald // clear local cid for response packet 5389*a254c508SMatthias Ringwald channel->local_cid = 0; 5390*a254c508SMatthias Ringwald // Some connections refused – insufficient resources available 5391*a254c508SMatthias Ringwald channel->reason = 0x004; 5392*a254c508SMatthias Ringwald } 5393*a254c508SMatthias Ringwald // update state 5394*a254c508SMatthias Ringwald channel->state = L2CAP_STATE_WILL_SEND_ENHANCED_CONNECTION_RESPONSE; 5395*a254c508SMatthias Ringwald } 5396828a7f7aSMatthias Ringwald l2cap_run(); 5397c8b2b785SMilanka Ringwald return ERROR_CODE_SUCCESS; 5398da144af5SMatthias Ringwald } 5399da144af5SMatthias Ringwald 5400*a254c508SMatthias Ringwald 5401*a254c508SMatthias Ringwald 5402*a254c508SMatthias Ringwald 5403*a254c508SMatthias Ringwald 5404*a254c508SMatthias Ringwald 5405*a254c508SMatthias Ringwald uint8_t l2cap_enhanced_decline_data_channels(uint16_t local_cid, uint16_t result){ 5406*a254c508SMatthias Ringwald l2cap_channel_t * channel = l2cap_get_channel_for_local_cid(local_cid); 5407*a254c508SMatthias Ringwald if (!channel) { 5408*a254c508SMatthias Ringwald return L2CAP_LOCAL_CID_DOES_NOT_EXIST; 5409*a254c508SMatthias Ringwald } 5410*a254c508SMatthias Ringwald // 5411*a254c508SMatthias Ringwald hci_con_handle_t con_handle = channel->con_handle; 5412*a254c508SMatthias Ringwald uint8_t local_sig_id = channel->local_sig_id; 5413*a254c508SMatthias Ringwald btstack_linked_list_iterator_t it; 5414*a254c508SMatthias Ringwald btstack_linked_list_iterator_init(&it, &l2cap_channels); 5415*a254c508SMatthias Ringwald while (btstack_linked_list_iterator_has_next(&it)) { 5416*a254c508SMatthias Ringwald channel = (l2cap_channel_t *) btstack_linked_list_iterator_next(&it); 5417*a254c508SMatthias Ringwald if (!l2cap_is_dynamic_channel_type(channel->channel_type)) continue; 5418*a254c508SMatthias Ringwald if (channel->con_handle != con_handle) continue; 5419*a254c508SMatthias Ringwald if (channel->local_sig_id != local_sig_id) continue; 5420*a254c508SMatthias Ringwald if (channel->state != L2CAP_STATE_WAIT_CLIENT_ACCEPT_OR_REJECT) continue; 5421*a254c508SMatthias Ringwald 5422*a254c508SMatthias Ringwald // prepare response 5423*a254c508SMatthias Ringwald channel->local_cid = 0; 5424*a254c508SMatthias Ringwald channel->reason = result; 5425*a254c508SMatthias Ringwald channel->state = L2CAP_STATE_WILL_SEND_ENHANCED_CONNECTION_RESPONSE; 5426*a254c508SMatthias Ringwald } 5427*a254c508SMatthias Ringwald l2cap_run(); 5428*a254c508SMatthias Ringwald return ERROR_CODE_SUCCESS; 5429*a254c508SMatthias Ringwald } 5430*a254c508SMatthias Ringwald 5431*a254c508SMatthias Ringwald uint8_t l2cap_enhanced_data_channel_request_can_send_now_event(uint16_t local_cid){ 5432*a254c508SMatthias Ringwald l2cap_channel_t * channel = l2cap_get_channel_for_local_cid(local_cid); 5433*a254c508SMatthias Ringwald if (!channel) { 5434*a254c508SMatthias Ringwald log_error("can send now, no channel for cid 0x%02x", local_cid); 5435*a254c508SMatthias Ringwald return L2CAP_LOCAL_CID_DOES_NOT_EXIST; 5436*a254c508SMatthias Ringwald } 5437*a254c508SMatthias Ringwald channel->waiting_for_can_send_now = 1; 5438*a254c508SMatthias Ringwald l2cap_le_notify_channel_can_send(channel); 5439*a254c508SMatthias Ringwald return ERROR_CODE_SUCCESS; 5440*a254c508SMatthias Ringwald } 5441*a254c508SMatthias Ringwald 5442*a254c508SMatthias Ringwald uint8_t l2cap_enhanced_reconfigure(uint8_t num_cids, uint16_t * local_cids, int16_t receive_buffer_size, uint8_t ** receive_buffers){ 5443*a254c508SMatthias Ringwald btstack_assert(receive_buffers != NULL); 5444*a254c508SMatthias Ringwald btstack_assert(local_cids != NULL); 5445*a254c508SMatthias Ringwald 5446*a254c508SMatthias Ringwald if (num_cids > L2CAP_ENHANCED_DATA_CHANNEL_MAX_CID_ARRAY_SIZE){ 5447*a254c508SMatthias Ringwald return ERROR_CODE_UNACCEPTABLE_CONNECTION_PARAMETERS; 5448*a254c508SMatthias Ringwald } 5449*a254c508SMatthias Ringwald 5450*a254c508SMatthias Ringwald // check if all cids exist and have the same con handle 5451*a254c508SMatthias Ringwald uint8_t i; 5452*a254c508SMatthias Ringwald hci_con_handle_t con_handle = HCI_CON_HANDLE_INVALID; 5453*a254c508SMatthias Ringwald for (i = 0 ; i < num_cids ; i++){ 5454*a254c508SMatthias Ringwald l2cap_channel_t * channel = l2cap_get_channel_for_local_cid(local_cids[i]); 5455*a254c508SMatthias Ringwald if (!channel) { 5456*a254c508SMatthias Ringwald return L2CAP_LOCAL_CID_DOES_NOT_EXIST; 5457*a254c508SMatthias Ringwald } 5458*a254c508SMatthias Ringwald if (channel->state != L2CAP_STATE_OPEN){ 5459*a254c508SMatthias Ringwald return ERROR_CODE_COMMAND_DISALLOWED; 5460*a254c508SMatthias Ringwald } 5461*a254c508SMatthias Ringwald if (con_handle == HCI_CON_HANDLE_INVALID){ 5462*a254c508SMatthias Ringwald con_handle = channel->con_handle; 5463*a254c508SMatthias Ringwald } else if (con_handle != channel->con_handle){ 5464*a254c508SMatthias Ringwald return ERROR_CODE_UNACCEPTABLE_CONNECTION_PARAMETERS; 5465*a254c508SMatthias Ringwald } 5466*a254c508SMatthias Ringwald } 5467*a254c508SMatthias Ringwald // set renegotiation data and state 5468*a254c508SMatthias Ringwald uint8_t sig_id = l2cap_next_sig_id(); 5469*a254c508SMatthias Ringwald for (i = 0 ; i < num_cids ; i++){ 5470*a254c508SMatthias Ringwald l2cap_channel_t * channel = l2cap_get_channel_for_local_cid(local_cids[i]); 5471*a254c508SMatthias Ringwald channel->cid_index = i; 5472*a254c508SMatthias Ringwald channel->num_cids = num_cids; 5473*a254c508SMatthias Ringwald channel->local_sig_id = sig_id; 5474*a254c508SMatthias Ringwald channel->renegotiate_mtu = receive_buffer_size; 5475*a254c508SMatthias Ringwald channel->renegotiate_sdu_buffer = receive_buffers[i]; 5476*a254c508SMatthias Ringwald channel->state = L2CAP_STATE_WILL_SEND_EHNANCED_RENEGOTIATION_REQUEST; 5477*a254c508SMatthias Ringwald } 5478*a254c508SMatthias Ringwald 5479*a254c508SMatthias Ringwald 5480*a254c508SMatthias Ringwald l2cap_run(); 5481*a254c508SMatthias Ringwald return ERROR_CODE_SUCCESS; 5482*a254c508SMatthias Ringwald } 5483*a254c508SMatthias Ringwald 5484*a254c508SMatthias Ringwald uint8_t l2cap_enhanced_send_data(uint16_t local_cid, const uint8_t * data, uint16_t size){ 5485*a254c508SMatthias Ringwald return l2cap_credit_based_send_data(local_cid, data, size); 5486*a254c508SMatthias Ringwald } 5487*a254c508SMatthias Ringwald 5488*a254c508SMatthias Ringwald uint8_t l2cap_enhanced_provide_credits(uint16_t local_cid, uint16_t credits){ 5489*a254c508SMatthias Ringwald return l2cap_credit_based_provide_credits(local_cid, credits); 5490*a254c508SMatthias Ringwald } 5491*a254c508SMatthias Ringwald 5492*a254c508SMatthias Ringwald uint8_t l2cap_enhanced_disconnect(uint16_t local_cid){ 5493*a254c508SMatthias Ringwald return l2cap_credit_based_disconnect(local_cid); 5494*a254c508SMatthias Ringwald } 5495*a254c508SMatthias Ringwald 54967f02f414SMatthias Ringwald #endif 5497