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 231713bceaSmatthias.ringwald * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS 241713bceaSmatthias.ringwald * RINGWALD 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 38ab2c6ae4SMatthias Ringwald #define __BTSTACK_FILE__ "l2cap.c" 39ab2c6ae4SMatthias Ringwald 401713bceaSmatthias.ringwald /* 4143625864Smatthias.ringwald * l2cap.c 4243625864Smatthias.ringwald * 4343625864Smatthias.ringwald * Logical Link Control and Adaption Protocl (L2CAP) 4443625864Smatthias.ringwald * 4543625864Smatthias.ringwald * Created by Matthias Ringwald on 5/16/09. 4643625864Smatthias.ringwald */ 4743625864Smatthias.ringwald 4843625864Smatthias.ringwald #include "l2cap.h" 49645658c9Smatthias.ringwald #include "hci.h" 502b3c6c9bSmatthias.ringwald #include "hci_dump.h" 51235946f1SMatthias Ringwald #include "bluetooth_sdp.h" 5216ece135SMatthias Ringwald #include "btstack_debug.h" 530e2df43fSMatthias Ringwald #include "btstack_event.h" 54d3a9df87Smatthias.ringwald #include "btstack_memory.h" 5543625864Smatthias.ringwald 56cab29d48SMatthias Ringwald #ifdef ENABLE_LE_DATA_CHANNELS 5783fd9c76SMatthias Ringwald #include "ble/sm.h" 5883fd9c76SMatthias Ringwald #endif 5983fd9c76SMatthias Ringwald 6043625864Smatthias.ringwald #include <stdarg.h> 6143625864Smatthias.ringwald #include <string.h> 6243625864Smatthias.ringwald 6343625864Smatthias.ringwald #include <stdio.h> 6443625864Smatthias.ringwald 654c744e21Smatthias.ringwald // nr of buffered acl packets in outgoing queue to get max performance 664c744e21Smatthias.ringwald #define NR_BUFFERED_ACL_PACKETS 3 674c744e21Smatthias.ringwald 6839bda6d5Smatthias.ringwald // used to cache l2cap rejects, echo, and informational requests 69e16a9cacSmatthias.ringwald #define NR_PENDING_SIGNALING_RESPONSES 3 7039bda6d5Smatthias.ringwald 7185aeef60SMatthias Ringwald // nr of credits provided to remote if credits fall below watermark 7285aeef60SMatthias Ringwald #define L2CAP_LE_DATA_CHANNELS_AUTOMATIC_CREDITS_WATERMARK 5 7385aeef60SMatthias Ringwald #define L2CAP_LE_DATA_CHANNELS_AUTOMATIC_CREDITS_INCREMENT 5 7485aeef60SMatthias Ringwald 7500d93d79Smatthias.ringwald // offsets for L2CAP SIGNALING COMMANDS 7600d93d79Smatthias.ringwald #define L2CAP_SIGNALING_COMMAND_CODE_OFFSET 0 7700d93d79Smatthias.ringwald #define L2CAP_SIGNALING_COMMAND_SIGID_OFFSET 1 7800d93d79Smatthias.ringwald #define L2CAP_SIGNALING_COMMAND_LENGTH_OFFSET 2 7900d93d79Smatthias.ringwald #define L2CAP_SIGNALING_COMMAND_DATA_OFFSET 4 8000d93d79Smatthias.ringwald 815628cf69SMatthias Ringwald // internal table 825628cf69SMatthias Ringwald #define L2CAP_FIXED_CHANNEL_TABLE_INDEX_ATTRIBUTE_PROTOCOL 0 835628cf69SMatthias Ringwald #define L2CAP_FIXED_CHANNEL_TABLE_INDEX_SECURITY_MANAGER_PROTOCOL 1 845628cf69SMatthias Ringwald #define L2CAP_FIXED_CHANNEL_TABLE_INDEX_CONNECTIONLESS_CHANNEL 2 855628cf69SMatthias Ringwald #define L2CAP_FIXED_CHANNEL_TABLE_SIZE (L2CAP_FIXED_CHANNEL_TABLE_INDEX_CONNECTIONLESS_CHANNEL+1) 865628cf69SMatthias Ringwald 8709e9d05bSMatthias Ringwald #if defined(ENABLE_LE_DATA_CHANNELS) || defined(ENABLE_CLASSIC) 8809e9d05bSMatthias Ringwald #define L2CAP_USES_CHANNELS 8909e9d05bSMatthias Ringwald #endif 9009e9d05bSMatthias Ringwald 9133c40538SMatthias Ringwald // prototypes 9233c40538SMatthias Ringwald static void l2cap_hci_event_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size); 933d50b4baSMatthias Ringwald static void l2cap_acl_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size ); 9430725612SMatthias Ringwald static void l2cap_notify_channel_can_send(void); 9509e9d05bSMatthias Ringwald static void l2cap_emit_can_send_now(btstack_packet_handler_t packet_handler, uint16_t channel); 9609e9d05bSMatthias Ringwald #ifdef ENABLE_CLASSIC 9709e9d05bSMatthias Ringwald static void l2cap_finialize_channel_close(l2cap_channel_t *channel); 9809e9d05bSMatthias Ringwald static inline l2cap_service_t * l2cap_get_service(uint16_t psm); 9909e9d05bSMatthias Ringwald static void l2cap_emit_channel_opened(l2cap_channel_t *channel, uint8_t status); 10009e9d05bSMatthias Ringwald static void l2cap_emit_channel_closed(l2cap_channel_t *channel); 10109e9d05bSMatthias Ringwald static void l2cap_emit_incoming_connection(l2cap_channel_t *channel); 10209e9d05bSMatthias Ringwald static int l2cap_channel_ready_for_open(l2cap_channel_t *channel); 10309e9d05bSMatthias Ringwald #endif 104cab29d48SMatthias Ringwald #ifdef ENABLE_LE_DATA_CHANNELS 10557be49d6SMatthias Ringwald static void l2cap_emit_le_channel_opened(l2cap_channel_t *channel, uint8_t status); 10657be49d6SMatthias Ringwald static void l2cap_emit_le_incoming_connection(l2cap_channel_t *channel); 10757be49d6SMatthias Ringwald static l2cap_channel_t * l2cap_le_get_channel_for_local_cid(uint16_t local_cid); 10844276248SMatthias Ringwald static void l2cap_le_notify_channel_can_send(l2cap_channel_t *channel); 109828a7f7aSMatthias Ringwald static void l2cap_le_finialize_channel_close(l2cap_channel_t *channel); 110e7d0c9aaSMatthias Ringwald static inline l2cap_service_t * l2cap_le_get_service(uint16_t psm); 111e7d0c9aaSMatthias Ringwald #endif 11233c40538SMatthias Ringwald 1135628cf69SMatthias Ringwald typedef struct l2cap_fixed_channel { 1145628cf69SMatthias Ringwald btstack_packet_handler_t callback; 1152125de09SMatthias Ringwald uint8_t waiting_for_can_send_now; 1165628cf69SMatthias Ringwald } l2cap_fixed_channel_t; 1175628cf69SMatthias Ringwald 11809e9d05bSMatthias Ringwald #ifdef ENABLE_CLASSIC 1195628cf69SMatthias Ringwald static btstack_linked_list_t l2cap_channels; 1205628cf69SMatthias Ringwald static btstack_linked_list_t l2cap_services; 12109e9d05bSMatthias Ringwald static uint8_t require_security_level2_for_outgoing_sdp; 12209e9d05bSMatthias Ringwald #endif 12357be49d6SMatthias Ringwald 12457be49d6SMatthias Ringwald #ifdef ENABLE_LE_DATA_CHANNELS 1255628cf69SMatthias Ringwald static btstack_linked_list_t l2cap_le_channels; 1265628cf69SMatthias Ringwald static btstack_linked_list_t l2cap_le_services; 12757be49d6SMatthias Ringwald #endif 12839bda6d5Smatthias.ringwald 12939bda6d5Smatthias.ringwald // used to cache l2cap rejects, echo, and informational requests 1302b83fb7dSmatthias.ringwald static l2cap_signaling_response_t signaling_responses[NR_PENDING_SIGNALING_RESPONSES]; 1312b83fb7dSmatthias.ringwald static int signaling_responses_pending; 1322b83fb7dSmatthias.ringwald 133fb37a842SMatthias Ringwald static btstack_packet_callback_registration_t hci_event_callback_registration; 1345628cf69SMatthias Ringwald static l2cap_fixed_channel_t fixed_channels[L2CAP_FIXED_CHANNEL_TABLE_SIZE]; 13539bda6d5Smatthias.ringwald 136d6ed9f9cSMatthias Ringwald #ifdef ENABLE_BLE 137d6ed9f9cSMatthias Ringwald // only used for connection parameter update events 138d6ed9f9cSMatthias Ringwald static btstack_packet_handler_t l2cap_event_packet_handler; 139d6ed9f9cSMatthias Ringwald #endif 140d6ed9f9cSMatthias Ringwald 141*85ddcd84SMatthias Ringwald #ifdef ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE 142*85ddcd84SMatthias Ringwald 143*85ddcd84SMatthias Ringwald /* 144*85ddcd84SMatthias Ringwald * CRC lookup table for generator polynom D^16 + D^15 + D^2 + 1 145*85ddcd84SMatthias Ringwald */ 146*85ddcd84SMatthias Ringwald static const uint16_t crc16_table[256] = { 147*85ddcd84SMatthias Ringwald 0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, 0xc241, 0xc601, 0x06c0, 0x0780, 0xc741, 0x0500, 0xc5c1, 0xc481, 0x0440, 148*85ddcd84SMatthias Ringwald 0xcc01, 0x0cc0, 0x0d80, 0xcd41, 0x0f00, 0xcfc1, 0xce81, 0x0e40, 0x0a00, 0xcac1, 0xcb81, 0x0b40, 0xc901, 0x09c0, 0x0880, 0xc841, 149*85ddcd84SMatthias Ringwald 0xd801, 0x18c0, 0x1980, 0xd941, 0x1b00, 0xdbc1, 0xda81, 0x1a40, 0x1e00, 0xdec1, 0xdf81, 0x1f40, 0xdd01, 0x1dc0, 0x1c80, 0xdc41, 150*85ddcd84SMatthias Ringwald 0x1400, 0xd4c1, 0xd581, 0x1540, 0xd701, 0x17c0, 0x1680, 0xd641, 0xd201, 0x12c0, 0x1380, 0xd341, 0x1100, 0xd1c1, 0xd081, 0x1040, 151*85ddcd84SMatthias Ringwald 0xf001, 0x30c0, 0x3180, 0xf141, 0x3300, 0xf3c1, 0xf281, 0x3240, 0x3600, 0xf6c1, 0xf781, 0x3740, 0xf501, 0x35c0, 0x3480, 0xf441, 152*85ddcd84SMatthias Ringwald 0x3c00, 0xfcc1, 0xfd81, 0x3d40, 0xff01, 0x3fc0, 0x3e80, 0xfe41, 0xfa01, 0x3ac0, 0x3b80, 0xfb41, 0x3900, 0xf9c1, 0xf881, 0x3840, 153*85ddcd84SMatthias Ringwald 0x2800, 0xe8c1, 0xe981, 0x2940, 0xeb01, 0x2bc0, 0x2a80, 0xea41, 0xee01, 0x2ec0, 0x2f80, 0xef41, 0x2d00, 0xedc1, 0xec81, 0x2c40, 154*85ddcd84SMatthias Ringwald 0xe401, 0x24c0, 0x2580, 0xe541, 0x2700, 0xe7c1, 0xe681, 0x2640, 0x2200, 0xe2c1, 0xe381, 0x2340, 0xe101, 0x21c0, 0x2080, 0xe041, 155*85ddcd84SMatthias Ringwald 0xa001, 0x60c0, 0x6180, 0xa141, 0x6300, 0xa3c1, 0xa281, 0x6240, 0x6600, 0xa6c1, 0xa781, 0x6740, 0xa501, 0x65c0, 0x6480, 0xa441, 156*85ddcd84SMatthias Ringwald 0x6c00, 0xacc1, 0xad81, 0x6d40, 0xaf01, 0x6fc0, 0x6e80, 0xae41, 0xaa01, 0x6ac0, 0x6b80, 0xab41, 0x6900, 0xa9c1, 0xa881, 0x6840, 157*85ddcd84SMatthias Ringwald 0x7800, 0xb8c1, 0xb981, 0x7940, 0xbb01, 0x7bc0, 0x7a80, 0xba41, 0xbe01, 0x7ec0, 0x7f80, 0xbf41, 0x7d00, 0xbdc1, 0xbc81, 0x7c40, 158*85ddcd84SMatthias Ringwald 0xb401, 0x74c0, 0x7580, 0xb541, 0x7700, 0xb7c1, 0xb681, 0x7640, 0x7200, 0xb2c1, 0xb381, 0x7340, 0xb101, 0x71c0, 0x7080, 0xb041, 159*85ddcd84SMatthias Ringwald 0x5000, 0x90c1, 0x9181, 0x5140, 0x9301, 0x53c0, 0x5280, 0x9241, 0x9601, 0x56c0, 0x5780, 0x9741, 0x5500, 0x95c1, 0x9481, 0x5440, 160*85ddcd84SMatthias Ringwald 0x9c01, 0x5cc0, 0x5d80, 0x9d41, 0x5f00, 0x9fc1, 0x9e81, 0x5e40, 0x5a00, 0x9ac1, 0x9b81, 0x5b40, 0x9901, 0x59c0, 0x5880, 0x9841, 161*85ddcd84SMatthias Ringwald 0x8801, 0x48c0, 0x4980, 0x8941, 0x4b00, 0x8bc1, 0x8a81, 0x4a40, 0x4e00, 0x8ec1, 0x8f81, 0x4f40, 0x8d01, 0x4dc0, 0x4c80, 0x8c41, 162*85ddcd84SMatthias Ringwald 0x4400, 0x84c1, 0x8581, 0x4540, 0x8701, 0x47c0, 0x4680, 0x8641, 0x8201, 0x42c0, 0x4380, 0x8341, 0x4100, 0x81c1, 0x8081, 0x4040, 163*85ddcd84SMatthias Ringwald }; 164*85ddcd84SMatthias Ringwald 165*85ddcd84SMatthias Ringwald static uint16_t crc16_calc(uint8_t * data, uint16_t len){ 166*85ddcd84SMatthias Ringwald uint16_t crc = 0; // initial value = 0 167*85ddcd84SMatthias Ringwald while (len--){ 168*85ddcd84SMatthias Ringwald crc = (crc >> 8) ^ crc16_table[ (crc ^ ((uint16_t) *data++)) & 0x00FF ]; 169*85ddcd84SMatthias Ringwald } 170*85ddcd84SMatthias Ringwald return crc; 171*85ddcd84SMatthias Ringwald } 172*85ddcd84SMatthias Ringwald 173*85ddcd84SMatthias Ringwald #endif 174*85ddcd84SMatthias Ringwald 175*85ddcd84SMatthias Ringwald 17634e7e577SMatthias Ringwald static uint16_t l2cap_fixed_channel_table_channel_id_for_index(int index){ 17734e7e577SMatthias Ringwald switch (index){ 17834e7e577SMatthias Ringwald case L2CAP_FIXED_CHANNEL_TABLE_INDEX_ATTRIBUTE_PROTOCOL: 17934e7e577SMatthias Ringwald return L2CAP_CID_ATTRIBUTE_PROTOCOL; 18034e7e577SMatthias Ringwald case L2CAP_FIXED_CHANNEL_TABLE_INDEX_SECURITY_MANAGER_PROTOCOL: 18134e7e577SMatthias Ringwald return L2CAP_CID_SECURITY_MANAGER_PROTOCOL; 18234e7e577SMatthias Ringwald case L2CAP_FIXED_CHANNEL_TABLE_INDEX_CONNECTIONLESS_CHANNEL: 18334e7e577SMatthias Ringwald return L2CAP_CID_CONNECTIONLESS_CHANNEL; 18434e7e577SMatthias Ringwald default: 18534e7e577SMatthias Ringwald return 0; 18634e7e577SMatthias Ringwald } 18734e7e577SMatthias Ringwald } 1885628cf69SMatthias Ringwald static int l2cap_fixed_channel_table_index_for_channel_id(uint16_t channel_id){ 1895628cf69SMatthias Ringwald switch (channel_id){ 1905628cf69SMatthias Ringwald case L2CAP_CID_ATTRIBUTE_PROTOCOL: 1915628cf69SMatthias Ringwald return L2CAP_FIXED_CHANNEL_TABLE_INDEX_ATTRIBUTE_PROTOCOL; 1925628cf69SMatthias Ringwald case L2CAP_CID_SECURITY_MANAGER_PROTOCOL: 1935628cf69SMatthias Ringwald return L2CAP_FIXED_CHANNEL_TABLE_INDEX_SECURITY_MANAGER_PROTOCOL; 1945628cf69SMatthias Ringwald case L2CAP_CID_CONNECTIONLESS_CHANNEL: 1955628cf69SMatthias Ringwald return L2CAP_FIXED_CHANNEL_TABLE_INDEX_CONNECTIONLESS_CHANNEL; 1965628cf69SMatthias Ringwald default: 1975628cf69SMatthias Ringwald return -1; 1985628cf69SMatthias Ringwald } 1995628cf69SMatthias Ringwald } 20039bda6d5Smatthias.ringwald 20134e7e577SMatthias Ringwald static int l2cap_fixed_channel_table_index_is_le(int index){ 20234e7e577SMatthias Ringwald if (index == L2CAP_CID_CONNECTIONLESS_CHANNEL) return 0; 20334e7e577SMatthias Ringwald return 1; 20434e7e577SMatthias Ringwald } 20534e7e577SMatthias Ringwald 20671de195eSMatthias Ringwald void l2cap_init(void){ 2072b83fb7dSmatthias.ringwald signaling_responses_pending = 0; 208808a48abSmatthias.ringwald 209*85ddcd84SMatthias Ringwald uint8_t test[] = {0x0E, 0x00, 0x40, 0x00, 0x02, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09 }; 210*85ddcd84SMatthias Ringwald printf("crc16: %04x\n", crc16_calc(test, sizeof(test))); 211*85ddcd84SMatthias Ringwald 21209e9d05bSMatthias Ringwald #ifdef ENABLE_CLASSIC 213f5454fc6Smatthias.ringwald l2cap_channels = NULL; 214f5454fc6Smatthias.ringwald l2cap_services = NULL; 21509e9d05bSMatthias Ringwald require_security_level2_for_outgoing_sdp = 0; 21609e9d05bSMatthias Ringwald #endif 217a3dc965aSMatthias Ringwald 218a3dc965aSMatthias Ringwald #ifdef ENABLE_LE_DATA_CHANNELS 2197192e786SMatthias Ringwald l2cap_le_services = NULL; 2207192e786SMatthias Ringwald l2cap_le_channels = NULL; 221a3dc965aSMatthias Ringwald #endif 222f5454fc6Smatthias.ringwald 223d6ed9f9cSMatthias Ringwald #ifdef ENABLE_BLE 22433c40538SMatthias Ringwald l2cap_event_packet_handler = NULL; 225d6ed9f9cSMatthias Ringwald #endif 2265628cf69SMatthias Ringwald memset(fixed_channels, 0, sizeof(fixed_channels)); 227f5454fc6Smatthias.ringwald 228fcadd0caSmatthias.ringwald // 2292718e2e7Smatthias.ringwald // register callback with HCI 230fcadd0caSmatthias.ringwald // 231d9a7306aSMatthias Ringwald hci_event_callback_registration.callback = &l2cap_hci_event_handler; 232fb37a842SMatthias Ringwald hci_add_event_handler(&hci_event_callback_registration); 233fb37a842SMatthias Ringwald 234d9a7306aSMatthias Ringwald hci_register_acl_packet_handler(&l2cap_acl_handler); 235fb37a842SMatthias Ringwald 236be005ed6SMatthias Ringwald #ifdef ENABLE_CLASSIC 23715a95bd5SMatthias Ringwald gap_connectable_control(0); // no services yet 238be005ed6SMatthias Ringwald #endif 239fcadd0caSmatthias.ringwald } 240fcadd0caSmatthias.ringwald 241ffbf8201SMatthias Ringwald void l2cap_register_packet_handler(void (*handler)(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size)){ 242d6ed9f9cSMatthias Ringwald #ifdef ENABLE_BLE 24333c40538SMatthias Ringwald l2cap_event_packet_handler = handler; 244d6ed9f9cSMatthias Ringwald #else 245d6ed9f9cSMatthias Ringwald UNUSED(handler); 246d6ed9f9cSMatthias Ringwald #endif 2471e6aba47Smatthias.ringwald } 2481e6aba47Smatthias.ringwald 24909e9d05bSMatthias Ringwald void l2cap_request_can_send_fix_channel_now_event(hci_con_handle_t con_handle, uint16_t channel_id){ 2509ec2630cSMatthias Ringwald UNUSED(con_handle); 2519ec2630cSMatthias Ringwald 25209e9d05bSMatthias Ringwald int index = l2cap_fixed_channel_table_index_for_channel_id(channel_id); 25309e9d05bSMatthias Ringwald if (index < 0) return; 25409e9d05bSMatthias Ringwald fixed_channels[index].waiting_for_can_send_now = 1; 25509e9d05bSMatthias Ringwald l2cap_notify_channel_can_send(); 25609e9d05bSMatthias Ringwald } 25709e9d05bSMatthias Ringwald 25809e9d05bSMatthias Ringwald int l2cap_can_send_fixed_channel_packet_now(hci_con_handle_t con_handle, uint16_t channel_id){ 2599ec2630cSMatthias Ringwald UNUSED(channel_id); 2609ec2630cSMatthias Ringwald 26109e9d05bSMatthias Ringwald return hci_can_send_acl_packet_now(con_handle); 26209e9d05bSMatthias Ringwald } 26309e9d05bSMatthias Ringwald 26409e9d05bSMatthias Ringwald uint8_t *l2cap_get_outgoing_buffer(void){ 26509e9d05bSMatthias Ringwald return hci_get_outgoing_packet_buffer() + COMPLETE_L2CAP_HEADER; // 8 bytes 26609e9d05bSMatthias Ringwald } 26709e9d05bSMatthias Ringwald 26809e9d05bSMatthias Ringwald int l2cap_reserve_packet_buffer(void){ 26909e9d05bSMatthias Ringwald return hci_reserve_packet_buffer(); 27009e9d05bSMatthias Ringwald } 27109e9d05bSMatthias Ringwald 27209e9d05bSMatthias Ringwald void l2cap_release_packet_buffer(void){ 27309e9d05bSMatthias Ringwald hci_release_packet_buffer(); 27409e9d05bSMatthias Ringwald } 27509e9d05bSMatthias Ringwald 276f511cefaSMatthias 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){ 27709e9d05bSMatthias Ringwald // 0 - Connection handle : PB=pb : BC=00 278f511cefaSMatthias Ringwald little_endian_store_16(acl_buffer, 0, con_handle | (packet_boundary << 12) | (0 << 14)); 27909e9d05bSMatthias Ringwald // 2 - ACL length 28009e9d05bSMatthias Ringwald little_endian_store_16(acl_buffer, 2, len + 4); 28109e9d05bSMatthias Ringwald // 4 - L2CAP packet length 28209e9d05bSMatthias Ringwald little_endian_store_16(acl_buffer, 4, len + 0); 28309e9d05bSMatthias Ringwald // 6 - L2CAP channel DEST 28409e9d05bSMatthias Ringwald little_endian_store_16(acl_buffer, 6, remote_cid); 28509e9d05bSMatthias Ringwald } 28609e9d05bSMatthias Ringwald 287f511cefaSMatthias Ringwald // assumption - only on LE connections 28809e9d05bSMatthias Ringwald int l2cap_send_prepared_connectionless(hci_con_handle_t con_handle, uint16_t cid, uint16_t len){ 28909e9d05bSMatthias Ringwald 29009e9d05bSMatthias Ringwald if (!hci_is_packet_buffer_reserved()){ 29109e9d05bSMatthias Ringwald log_error("l2cap_send_prepared_connectionless called without reserving packet first"); 29209e9d05bSMatthias Ringwald return BTSTACK_ACL_BUFFERS_FULL; 29309e9d05bSMatthias Ringwald } 29409e9d05bSMatthias Ringwald 29509e9d05bSMatthias Ringwald if (!hci_can_send_prepared_acl_packet_now(con_handle)){ 29609e9d05bSMatthias Ringwald log_info("l2cap_send_prepared_connectionless handle 0x%02x, cid 0x%02x, cannot send", con_handle, cid); 29709e9d05bSMatthias Ringwald return BTSTACK_ACL_BUFFERS_FULL; 29809e9d05bSMatthias Ringwald } 29909e9d05bSMatthias Ringwald 30009e9d05bSMatthias Ringwald log_debug("l2cap_send_prepared_connectionless handle %u, cid 0x%02x", con_handle, cid); 30109e9d05bSMatthias Ringwald 30209e9d05bSMatthias Ringwald uint8_t *acl_buffer = hci_get_outgoing_packet_buffer(); 303f511cefaSMatthias Ringwald l2cap_setup_header(acl_buffer, con_handle, 0, cid, len); 30409e9d05bSMatthias Ringwald // send 30509e9d05bSMatthias Ringwald return hci_send_acl_packet_buffer(len+8); 30609e9d05bSMatthias Ringwald } 30709e9d05bSMatthias Ringwald 308f511cefaSMatthias Ringwald // assumption - only on LE connections 30909e9d05bSMatthias Ringwald int l2cap_send_connectionless(hci_con_handle_t con_handle, uint16_t cid, uint8_t *data, uint16_t len){ 31009e9d05bSMatthias Ringwald 31109e9d05bSMatthias Ringwald if (!hci_can_send_acl_packet_now(con_handle)){ 31209e9d05bSMatthias Ringwald log_info("l2cap_send cid 0x%02x, cannot send", cid); 31309e9d05bSMatthias Ringwald return BTSTACK_ACL_BUFFERS_FULL; 31409e9d05bSMatthias Ringwald } 31509e9d05bSMatthias Ringwald 31609e9d05bSMatthias Ringwald hci_reserve_packet_buffer(); 31709e9d05bSMatthias Ringwald uint8_t *acl_buffer = hci_get_outgoing_packet_buffer(); 31809e9d05bSMatthias Ringwald 31909e9d05bSMatthias Ringwald memcpy(&acl_buffer[8], data, len); 32009e9d05bSMatthias Ringwald 32109e9d05bSMatthias Ringwald return l2cap_send_prepared_connectionless(con_handle, cid, len); 32209e9d05bSMatthias Ringwald } 32309e9d05bSMatthias Ringwald 32409e9d05bSMatthias Ringwald static void l2cap_emit_can_send_now(btstack_packet_handler_t packet_handler, uint16_t channel) { 325d9d23054SMatthias Ringwald log_debug("L2CAP_EVENT_CHANNEL_CAN_SEND_NOW local_cid 0x%x", channel); 32609e9d05bSMatthias Ringwald uint8_t event[4]; 32709e9d05bSMatthias Ringwald event[0] = L2CAP_EVENT_CAN_SEND_NOW; 32809e9d05bSMatthias Ringwald event[1] = sizeof(event) - 2; 32909e9d05bSMatthias Ringwald little_endian_store_16(event, 2, channel); 33009e9d05bSMatthias Ringwald hci_dump_packet( HCI_EVENT_PACKET, 0, event, sizeof(event)); 33109e9d05bSMatthias Ringwald packet_handler(HCI_EVENT_PACKET, channel, event, sizeof(event)); 33209e9d05bSMatthias Ringwald } 33309e9d05bSMatthias Ringwald 33409e9d05bSMatthias Ringwald #ifdef L2CAP_USES_CHANNELS 33517a9b554SMatthias Ringwald static void l2cap_dispatch_to_channel(l2cap_channel_t *channel, uint8_t type, uint8_t * data, uint16_t size){ 33658de5610Smatthias.ringwald (* (channel->packet_handler))(type, channel->local_cid, data, size); 33758de5610Smatthias.ringwald } 33858de5610Smatthias.ringwald 33944276248SMatthias Ringwald static void l2cap_emit_simple_event_with_cid(l2cap_channel_t * channel, uint8_t event_code){ 34044276248SMatthias Ringwald uint8_t event[4]; 34144276248SMatthias Ringwald event[0] = event_code; 34244276248SMatthias Ringwald event[1] = sizeof(event) - 2; 34344276248SMatthias Ringwald little_endian_store_16(event, 2, channel->local_cid); 34444276248SMatthias Ringwald hci_dump_packet( HCI_EVENT_PACKET, 0, event, sizeof(event)); 34544276248SMatthias Ringwald l2cap_dispatch_to_channel(channel, HCI_EVENT_PACKET, event, sizeof(event)); 34644276248SMatthias Ringwald } 34709e9d05bSMatthias Ringwald #endif 34844276248SMatthias Ringwald 34909e9d05bSMatthias Ringwald #ifdef ENABLE_CLASSIC 35058de5610Smatthias.ringwald void l2cap_emit_channel_opened(l2cap_channel_t *channel, uint8_t status) { 351c9dc710bS[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", 352fc64f94aSMatthias Ringwald status, bd_addr_to_str(channel->address), channel->con_handle, channel->psm, 353c9dc710bS[email protected] channel->local_cid, channel->remote_cid, channel->local_mtu, channel->remote_mtu, channel->flush_timeout); 354bab5f4f0SMatthias Ringwald uint8_t event[24]; 35558de5610Smatthias.ringwald event[0] = L2CAP_EVENT_CHANNEL_OPENED; 35658de5610Smatthias.ringwald event[1] = sizeof(event) - 2; 35758de5610Smatthias.ringwald event[2] = status; 358724d70a2SMatthias Ringwald reverse_bd_addr(channel->address, &event[3]); 359fc64f94aSMatthias Ringwald little_endian_store_16(event, 9, channel->con_handle); 360f8fbdce0SMatthias Ringwald little_endian_store_16(event, 11, channel->psm); 361f8fbdce0SMatthias Ringwald little_endian_store_16(event, 13, channel->local_cid); 362f8fbdce0SMatthias Ringwald little_endian_store_16(event, 15, channel->remote_cid); 363f8fbdce0SMatthias Ringwald little_endian_store_16(event, 17, channel->local_mtu); 364f8fbdce0SMatthias Ringwald little_endian_store_16(event, 19, channel->remote_mtu); 365f8fbdce0SMatthias Ringwald little_endian_store_16(event, 21, channel->flush_timeout); 366bab5f4f0SMatthias Ringwald event[23] = channel->state_var & L2CAP_CHANNEL_STATE_VAR_INCOMING ? 1 : 0; 36758de5610Smatthias.ringwald hci_dump_packet( HCI_EVENT_PACKET, 0, event, sizeof(event)); 36817a9b554SMatthias Ringwald l2cap_dispatch_to_channel(channel, HCI_EVENT_PACKET, event, sizeof(event)); 36958de5610Smatthias.ringwald } 37058de5610Smatthias.ringwald 37144276248SMatthias Ringwald static void l2cap_emit_channel_closed(l2cap_channel_t *channel) { 372e0abb8e7S[email protected] log_info("L2CAP_EVENT_CHANNEL_CLOSED local_cid 0x%x", channel->local_cid); 37344276248SMatthias Ringwald l2cap_emit_simple_event_with_cid(channel, L2CAP_EVENT_CHANNEL_CLOSED); 37458de5610Smatthias.ringwald } 37558de5610Smatthias.ringwald 37644276248SMatthias Ringwald static void l2cap_emit_incoming_connection(l2cap_channel_t *channel) { 377e0abb8e7S[email protected] log_info("L2CAP_EVENT_INCOMING_CONNECTION addr %s handle 0x%x psm 0x%x local_cid 0x%x remote_cid 0x%x", 378fc64f94aSMatthias Ringwald bd_addr_to_str(channel->address), channel->con_handle, channel->psm, channel->local_cid, channel->remote_cid); 37958de5610Smatthias.ringwald uint8_t event[16]; 38058de5610Smatthias.ringwald event[0] = L2CAP_EVENT_INCOMING_CONNECTION; 38158de5610Smatthias.ringwald event[1] = sizeof(event) - 2; 382724d70a2SMatthias Ringwald reverse_bd_addr(channel->address, &event[2]); 383fc64f94aSMatthias Ringwald little_endian_store_16(event, 8, channel->con_handle); 384f8fbdce0SMatthias Ringwald little_endian_store_16(event, 10, channel->psm); 385f8fbdce0SMatthias Ringwald little_endian_store_16(event, 12, channel->local_cid); 386f8fbdce0SMatthias Ringwald little_endian_store_16(event, 14, channel->remote_cid); 38758de5610Smatthias.ringwald hci_dump_packet( HCI_EVENT_PACKET, 0, event, sizeof(event)); 38817a9b554SMatthias Ringwald l2cap_dispatch_to_channel(channel, HCI_EVENT_PACKET, event, sizeof(event)); 3890af41d30Smatthias.ringwald } 390808a48abSmatthias.ringwald 3917f02f414SMatthias Ringwald static l2cap_channel_t * l2cap_get_channel_for_local_cid(uint16_t local_cid){ 392665d90f2SMatthias Ringwald btstack_linked_list_iterator_t it; 393665d90f2SMatthias Ringwald btstack_linked_list_iterator_init(&it, &l2cap_channels); 394665d90f2SMatthias Ringwald while (btstack_linked_list_iterator_has_next(&it)){ 395665d90f2SMatthias Ringwald l2cap_channel_t * channel = (l2cap_channel_t *) btstack_linked_list_iterator_next(&it); 396b35f641cSmatthias.ringwald if ( channel->local_cid == local_cid) { 397f62db1e3Smatthias.ringwald return channel; 398f62db1e3Smatthias.ringwald } 399f62db1e3Smatthias.ringwald } 400f62db1e3Smatthias.ringwald return NULL; 401f62db1e3Smatthias.ringwald } 402f62db1e3Smatthias.ringwald 4030b9d7e78SMatthias Ringwald /// 4040b9d7e78SMatthias Ringwald 40530725612SMatthias Ringwald void l2cap_request_can_send_now_event(uint16_t local_cid){ 40630725612SMatthias Ringwald l2cap_channel_t *channel = l2cap_get_channel_for_local_cid(local_cid); 40730725612SMatthias Ringwald if (!channel) return; 40830725612SMatthias Ringwald channel->waiting_for_can_send_now = 1; 40930725612SMatthias Ringwald l2cap_notify_channel_can_send(); 41030725612SMatthias Ringwald } 41130725612SMatthias Ringwald 4126b1fde37Smatthias.ringwald int l2cap_can_send_packet_now(uint16_t local_cid){ 4136b1fde37Smatthias.ringwald l2cap_channel_t *channel = l2cap_get_channel_for_local_cid(local_cid); 4146b1fde37Smatthias.ringwald if (!channel) return 0; 4150b9d7e78SMatthias Ringwald return hci_can_send_acl_packet_now(channel->con_handle); 4167856fb31S[email protected] } 4177856fb31S[email protected] 41883e7cdd9SMatthias Ringwald int l2cap_can_send_prepared_packet_now(uint16_t local_cid){ 41983e7cdd9SMatthias Ringwald l2cap_channel_t *channel = l2cap_get_channel_for_local_cid(local_cid); 42083e7cdd9SMatthias Ringwald if (!channel) return 0; 4210b9d7e78SMatthias Ringwald return hci_can_send_prepared_acl_packet_now(channel->con_handle); 42283e7cdd9SMatthias Ringwald } 42396cbd662Smatthias.ringwald uint16_t l2cap_get_remote_mtu_for_local_cid(uint16_t local_cid){ 42496cbd662Smatthias.ringwald l2cap_channel_t * channel = l2cap_get_channel_for_local_cid(local_cid); 42596cbd662Smatthias.ringwald if (channel) { 42696cbd662Smatthias.ringwald return channel->remote_mtu; 42796cbd662Smatthias.ringwald } 42896cbd662Smatthias.ringwald return 0; 42996cbd662Smatthias.ringwald } 43096cbd662Smatthias.ringwald 431ec820d77SMatthias Ringwald static l2cap_channel_t * l2cap_channel_for_rtx_timer(btstack_timer_source_t * ts){ 432665d90f2SMatthias Ringwald btstack_linked_list_iterator_t it; 433665d90f2SMatthias Ringwald btstack_linked_list_iterator_init(&it, &l2cap_channels); 434665d90f2SMatthias Ringwald while (btstack_linked_list_iterator_has_next(&it)){ 435665d90f2SMatthias Ringwald l2cap_channel_t * channel = (l2cap_channel_t *) btstack_linked_list_iterator_next(&it); 4365932bd7cS[email protected] if ( &channel->rtx == ts) { 4375932bd7cS[email protected] return channel; 4385932bd7cS[email protected] } 4395932bd7cS[email protected] } 4405932bd7cS[email protected] return NULL; 4415932bd7cS[email protected] } 4425932bd7cS[email protected] 443ec820d77SMatthias Ringwald static void l2cap_rtx_timeout(btstack_timer_source_t * ts){ 4445932bd7cS[email protected] l2cap_channel_t * channel = l2cap_channel_for_rtx_timer(ts); 44595d2c8f4SMatthias Ringwald if (!channel) return; 4465932bd7cS[email protected] 4475932bd7cS[email protected] log_info("l2cap_rtx_timeout for local cid 0x%02x", channel->local_cid); 4485932bd7cS[email protected] 4495932bd7cS[email protected] // "When terminating the channel, it is not necessary to send a L2CAP_DisconnectReq 4505932bd7cS[email protected] // and enter WAIT_DISCONNECT state. Channels can be transitioned directly to the CLOSED state." 4515932bd7cS[email protected] // notify client 4525932bd7cS[email protected] l2cap_emit_channel_opened(channel, L2CAP_CONNECTION_RESPONSE_RESULT_RTX_TIMEOUT); 4535932bd7cS[email protected] 4545932bd7cS[email protected] // discard channel 4559dcb2fb2S[email protected] // no need to stop timer here, it is removed from list during timer callback 456665d90f2SMatthias Ringwald btstack_linked_list_remove(&l2cap_channels, (btstack_linked_item_t *) channel); 4575932bd7cS[email protected] btstack_memory_l2cap_channel_free(channel); 4585932bd7cS[email protected] } 4595932bd7cS[email protected] 4605932bd7cS[email protected] static void l2cap_stop_rtx(l2cap_channel_t * channel){ 4615932bd7cS[email protected] log_info("l2cap_stop_rtx for local cid 0x%02x", channel->local_cid); 462528a4a3bSMatthias Ringwald btstack_run_loop_remove_timer(&channel->rtx); 4635932bd7cS[email protected] } 4645932bd7cS[email protected] 4655932bd7cS[email protected] static void l2cap_start_rtx(l2cap_channel_t * channel){ 4665932bd7cS[email protected] l2cap_stop_rtx(channel); 467cb0ff06bS[email protected] log_info("l2cap_start_rtx for local cid 0x%02x", channel->local_cid); 468528a4a3bSMatthias Ringwald btstack_run_loop_set_timer_handler(&channel->rtx, l2cap_rtx_timeout); 469528a4a3bSMatthias Ringwald btstack_run_loop_set_timer(&channel->rtx, L2CAP_RTX_TIMEOUT_MS); 470528a4a3bSMatthias Ringwald btstack_run_loop_add_timer(&channel->rtx); 4715932bd7cS[email protected] } 4725932bd7cS[email protected] 4735932bd7cS[email protected] static void l2cap_start_ertx(l2cap_channel_t * channel){ 4745932bd7cS[email protected] log_info("l2cap_start_ertx for local cid 0x%02x", channel->local_cid); 4755932bd7cS[email protected] l2cap_stop_rtx(channel); 476528a4a3bSMatthias Ringwald btstack_run_loop_set_timer_handler(&channel->rtx, l2cap_rtx_timeout); 477528a4a3bSMatthias Ringwald btstack_run_loop_set_timer(&channel->rtx, L2CAP_ERTX_TIMEOUT_MS); 478528a4a3bSMatthias Ringwald btstack_run_loop_add_timer(&channel->rtx); 4795932bd7cS[email protected] } 4805932bd7cS[email protected] 48171de195eSMatthias Ringwald void l2cap_require_security_level_2_for_outgoing_sdp(void){ 482ac301f95S[email protected] require_security_level2_for_outgoing_sdp = 1; 483ac301f95S[email protected] } 484ac301f95S[email protected] 485df3354fcS[email protected] static int l2cap_security_level_0_allowed_for_PSM(uint16_t psm){ 486235946f1SMatthias Ringwald return (psm == BLUETOOTH_PROTOCOL_SDP) && (!require_security_level2_for_outgoing_sdp); 487df3354fcS[email protected] } 4885932bd7cS[email protected] 4897f02f414SMatthias Ringwald static int l2cap_send_signaling_packet(hci_con_handle_t handle, L2CAP_SIGNALING_COMMANDS cmd, uint8_t identifier, ...){ 490a35252c8S[email protected] if (!hci_can_send_acl_packet_now(handle)){ 4919da54300S[email protected] log_info("l2cap_send_signaling_packet, cannot send"); 492b1d43497Smatthias.ringwald return BTSTACK_ACL_BUFFERS_FULL; 493b1d43497Smatthias.ringwald } 494b1d43497Smatthias.ringwald 4959da54300S[email protected] // log_info("l2cap_send_signaling_packet type %u", cmd); 4962a373862S[email protected] hci_reserve_packet_buffer(); 497facf93fdS[email protected] uint8_t *acl_buffer = hci_get_outgoing_packet_buffer(); 49858de5610Smatthias.ringwald va_list argptr; 49958de5610Smatthias.ringwald va_start(argptr, identifier); 50070efece1S[email protected] uint16_t len = l2cap_create_signaling_classic(acl_buffer, handle, cmd, identifier, argptr); 50158de5610Smatthias.ringwald va_end(argptr); 5029da54300S[email protected] // log_info("l2cap_send_signaling_packet con %u!", handle); 503826f7347S[email protected] return hci_send_acl_packet_buffer(len); 50458de5610Smatthias.ringwald } 50558de5610Smatthias.ringwald 506f511cefaSMatthias Ringwald // assumption - only on Classic connections 507b1d43497Smatthias.ringwald int l2cap_send_prepared(uint16_t local_cid, uint16_t len){ 508b1d43497Smatthias.ringwald 509c8b9416aS[email protected] if (!hci_is_packet_buffer_reserved()){ 510c8b9416aS[email protected] log_error("l2cap_send_prepared called without reserving packet first"); 511c8b9416aS[email protected] return BTSTACK_ACL_BUFFERS_FULL; 512c8b9416aS[email protected] } 513c8b9416aS[email protected] 51458de5610Smatthias.ringwald l2cap_channel_t * channel = l2cap_get_channel_for_local_cid(local_cid); 515b1d43497Smatthias.ringwald if (!channel) { 5169da54300S[email protected] log_error("l2cap_send_prepared no channel for cid 0x%02x", local_cid); 517b1d43497Smatthias.ringwald return -1; // TODO: define error 5186218e6f1Smatthias.ringwald } 5196218e6f1Smatthias.ringwald 520fc64f94aSMatthias Ringwald if (!hci_can_send_prepared_acl_packet_now(channel->con_handle)){ 5219da54300S[email protected] log_info("l2cap_send_prepared cid 0x%02x, cannot send", local_cid); 522a35252c8S[email protected] return BTSTACK_ACL_BUFFERS_FULL; 523a35252c8S[email protected] } 524a35252c8S[email protected] 525fc64f94aSMatthias Ringwald log_debug("l2cap_send_prepared cid 0x%02x, handle %u, 1 credit used", local_cid, channel->con_handle); 526b1d43497Smatthias.ringwald 527*85ddcd84SMatthias Ringwald int fcs_size = 0; 528*85ddcd84SMatthias Ringwald 529*85ddcd84SMatthias Ringwald #ifdef ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE 530*85ddcd84SMatthias Ringwald if (channel->mode == L2CAP_CHANNEL_MODE_ENHANCED_RETRANSMISSION){ 531*85ddcd84SMatthias Ringwald fcs_size = 2; 532*85ddcd84SMatthias Ringwald } 533*85ddcd84SMatthias Ringwald #endif 534*85ddcd84SMatthias Ringwald 535f511cefaSMatthias Ringwald // set non-flushable packet boundary flag if supported on Controller 536facf93fdS[email protected] uint8_t *acl_buffer = hci_get_outgoing_packet_buffer(); 537f511cefaSMatthias Ringwald uint8_t packet_boundary_flag = hci_non_flushable_packet_boundary_flag_supported() ? 0x00 : 0x02; 538*85ddcd84SMatthias Ringwald l2cap_setup_header(acl_buffer, channel->con_handle, packet_boundary_flag, channel->remote_cid, len + fcs_size); 539*85ddcd84SMatthias Ringwald 540*85ddcd84SMatthias Ringwald #ifdef ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE 541*85ddcd84SMatthias Ringwald if (channel->mode == L2CAP_CHANNEL_MODE_ENHANCED_RETRANSMISSION){ 542*85ddcd84SMatthias Ringwald // calculate FCS over l2cap data 543*85ddcd84SMatthias Ringwald uint16_t fcs = crc16_calc(acl_buffer + 4, 4 + len); 544*85ddcd84SMatthias Ringwald log_info("I-Frame: fcs 0x%04x", fcs); 545*85ddcd84SMatthias Ringwald little_endian_store_16(acl_buffer, 8 + len, fcs); 54658de5610Smatthias.ringwald } 547*85ddcd84SMatthias Ringwald #endif 548*85ddcd84SMatthias Ringwald 549*85ddcd84SMatthias Ringwald // send 550*85ddcd84SMatthias Ringwald return hci_send_acl_packet_buffer(len+8+fcs_size); 551*85ddcd84SMatthias Ringwald } 552*85ddcd84SMatthias Ringwald 553*85ddcd84SMatthias Ringwald #ifdef ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE 554*85ddcd84SMatthias 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){ 555*85ddcd84SMatthias Ringwald return (((uint16_t) sar) << 14) | (req_seq << 8) | (final << 7) | (tx_seq << 1) | 0; 556*85ddcd84SMatthias Ringwald } 557*85ddcd84SMatthias Ringwald #if 0 558*85ddcd84SMatthias 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){ 559*85ddcd84SMatthias Ringwald return (((uint16_t) sar) << 14) | (req_seq << 8) | (final << 7) | 1; 560*85ddcd84SMatthias Ringwald } 561*85ddcd84SMatthias Ringwald #endif 562*85ddcd84SMatthias Ringwald static int l2cap_next_ertm_seq_nr(int seq_nr){ 563*85ddcd84SMatthias Ringwald return (seq_nr + 1) & 0x3f; 564*85ddcd84SMatthias Ringwald } 565*85ddcd84SMatthias Ringwald #endif 56658de5610Smatthias.ringwald 567f511cefaSMatthias Ringwald // assumption - only on Classic connections 568ce8f182eSMatthias Ringwald int l2cap_send(uint16_t local_cid, uint8_t *data, uint16_t len){ 569b1d43497Smatthias.ringwald 570a35252c8S[email protected] l2cap_channel_t * channel = l2cap_get_channel_for_local_cid(local_cid); 571a35252c8S[email protected] if (!channel) { 572ce8f182eSMatthias Ringwald log_error("l2cap_send no channel for cid 0x%02x", local_cid); 573a35252c8S[email protected] return -1; // TODO: define error 574a35252c8S[email protected] } 575a35252c8S[email protected] 576f0efaa57S[email protected] if (len > channel->remote_mtu){ 577ce8f182eSMatthias Ringwald log_error("l2cap_send cid 0x%02x, data length exceeds remote MTU.", local_cid); 578f0efaa57S[email protected] return L2CAP_DATA_LEN_EXCEEDS_REMOTE_MTU; 579f0efaa57S[email protected] } 580f0efaa57S[email protected] 581fc64f94aSMatthias Ringwald if (!hci_can_send_acl_packet_now(channel->con_handle)){ 582ce8f182eSMatthias Ringwald log_info("l2cap_send cid 0x%02x, cannot send", local_cid); 583b1d43497Smatthias.ringwald return BTSTACK_ACL_BUFFERS_FULL; 584b1d43497Smatthias.ringwald } 585b1d43497Smatthias.ringwald 5862a373862S[email protected] hci_reserve_packet_buffer(); 587facf93fdS[email protected] uint8_t *acl_buffer = hci_get_outgoing_packet_buffer(); 588b1d43497Smatthias.ringwald 589*85ddcd84SMatthias Ringwald int control_size = 0; 590*85ddcd84SMatthias Ringwald #ifdef ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE 591*85ddcd84SMatthias Ringwald // hack to send i-frames 592*85ddcd84SMatthias Ringwald if (channel->mode == L2CAP_CHANNEL_MODE_ENHANCED_RETRANSMISSION){ 593*85ddcd84SMatthias Ringwald uint16_t control = l2cap_encanced_control_field_for_information_frame(channel->next_tx_seq, 0, 0, L2CAP_SEGMENTATION_AND_REASSEMBLY_UNSEGMENTED_L2CAP_SDU); 594*85ddcd84SMatthias Ringwald log_info("I-Frame: control 0x%04x", control); 595*85ddcd84SMatthias Ringwald little_endian_store_16(acl_buffer, 8, control); 596*85ddcd84SMatthias Ringwald channel->next_tx_seq = l2cap_next_ertm_seq_nr(channel->next_tx_seq); 597*85ddcd84SMatthias Ringwald control_size = 2; 598*85ddcd84SMatthias Ringwald } 599*85ddcd84SMatthias Ringwald #endif 600b1d43497Smatthias.ringwald 601*85ddcd84SMatthias Ringwald memcpy(&acl_buffer[8+control_size], data, len); 602*85ddcd84SMatthias Ringwald 603*85ddcd84SMatthias Ringwald return l2cap_send_prepared(local_cid, len+control_size); 604b1d43497Smatthias.ringwald } 605b1d43497Smatthias.ringwald 606fc64f94aSMatthias Ringwald int l2cap_send_echo_request(hci_con_handle_t con_handle, uint8_t *data, uint16_t len){ 607fc64f94aSMatthias Ringwald return l2cap_send_signaling_packet(con_handle, ECHO_REQUEST, 0x77, len, data); 6080e37e417S[email protected] } 6090e37e417S[email protected] 61028ca2b46S[email protected] static inline void channelStateVarSetFlag(l2cap_channel_t *channel, L2CAP_CHANNEL_STATE_VAR flag){ 61128ca2b46S[email protected] channel->state_var = (L2CAP_CHANNEL_STATE_VAR) (channel->state_var | flag); 61228ca2b46S[email protected] } 61328ca2b46S[email protected] 61428ca2b46S[email protected] static inline void channelStateVarClearFlag(l2cap_channel_t *channel, L2CAP_CHANNEL_STATE_VAR flag){ 61528ca2b46S[email protected] channel->state_var = (L2CAP_CHANNEL_STATE_VAR) (channel->state_var & ~flag); 61628ca2b46S[email protected] } 61709e9d05bSMatthias Ringwald #endif 61828ca2b46S[email protected] 61928ca2b46S[email protected] 62009e9d05bSMatthias Ringwald #ifdef ENABLE_BLE 62109e9d05bSMatthias Ringwald static int l2cap_send_le_signaling_packet(hci_con_handle_t handle, L2CAP_SIGNALING_COMMANDS cmd, uint8_t identifier, ...){ 62209e9d05bSMatthias Ringwald 62309e9d05bSMatthias Ringwald if (!hci_can_send_acl_packet_now(handle)){ 62409e9d05bSMatthias Ringwald log_info("l2cap_send_le_signaling_packet, cannot send"); 62509e9d05bSMatthias Ringwald return BTSTACK_ACL_BUFFERS_FULL; 62609e9d05bSMatthias Ringwald } 62709e9d05bSMatthias Ringwald 62809e9d05bSMatthias Ringwald // log_info("l2cap_send_le_signaling_packet type %u", cmd); 62909e9d05bSMatthias Ringwald hci_reserve_packet_buffer(); 63009e9d05bSMatthias Ringwald uint8_t *acl_buffer = hci_get_outgoing_packet_buffer(); 63109e9d05bSMatthias Ringwald va_list argptr; 63209e9d05bSMatthias Ringwald va_start(argptr, identifier); 63309e9d05bSMatthias Ringwald uint16_t len = l2cap_create_signaling_le(acl_buffer, handle, cmd, identifier, argptr); 63409e9d05bSMatthias Ringwald va_end(argptr); 63509e9d05bSMatthias Ringwald // log_info("l2cap_send_le_signaling_packet con %u!", handle); 63609e9d05bSMatthias Ringwald return hci_send_acl_packet_buffer(len); 63709e9d05bSMatthias Ringwald } 63809e9d05bSMatthias Ringwald #endif 63909e9d05bSMatthias Ringwald 64009e9d05bSMatthias Ringwald uint16_t l2cap_max_mtu(void){ 64109e9d05bSMatthias Ringwald return HCI_ACL_PAYLOAD_SIZE - L2CAP_HEADER_SIZE; 64209e9d05bSMatthias Ringwald } 64309e9d05bSMatthias Ringwald 64409e9d05bSMatthias Ringwald uint16_t l2cap_max_le_mtu(void){ 64509e9d05bSMatthias Ringwald return l2cap_max_mtu(); 64609e9d05bSMatthias Ringwald } 647b1d43497Smatthias.ringwald 6486dca2a0cSMatthias Ringwald static uint16_t l2cap_setup_options(l2cap_channel_t * channel, uint8_t * config_options){ 6496dca2a0cSMatthias Ringwald int send_retransmission_and_flow_control_option = 0; 6506dca2a0cSMatthias Ringwald int options_size; 6516dca2a0cSMatthias Ringwald #ifdef ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE 6526dca2a0cSMatthias Ringwald if (channel->mode == L2CAP_CHANNEL_MODE_ENHANCED_RETRANSMISSION){ 6536dca2a0cSMatthias Ringwald send_retransmission_and_flow_control_option = 1; 6546dca2a0cSMatthias Ringwald } 6556dca2a0cSMatthias Ringwald #endif 6566dca2a0cSMatthias Ringwald if (send_retransmission_and_flow_control_option){ 6576dca2a0cSMatthias Ringwald #ifdef ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE 6586dca2a0cSMatthias Ringwald config_options[0] = 0x04; // RETRANSMISSION AND FLOW CONTROL OPTION 6596dca2a0cSMatthias Ringwald config_options[1] = 9; // length 6606dca2a0cSMatthias Ringwald config_options[2] = (uint8_t) channel->mode; 6616dca2a0cSMatthias Ringwald config_options[3] = 1; // TxWindows size 6626dca2a0cSMatthias Ringwald config_options[4] = 1; // max retransmit 6636dca2a0cSMatthias Ringwald little_endian_store_16( config_options, 5, 100); // Retransmission timeout: 100 ms 6646dca2a0cSMatthias Ringwald little_endian_store_16( config_options, 7, 300); // Monitor timeout: 300 ms 6656dca2a0cSMatthias Ringwald little_endian_store_16( config_options, 9, channel->local_mtu); // Max PDU size // TODO: use real MTU 6666dca2a0cSMatthias Ringwald options_size = 11; 6676dca2a0cSMatthias Ringwald #endif 6686dca2a0cSMatthias Ringwald } else { 6696dca2a0cSMatthias Ringwald config_options[0] = 1; // MTU 6706dca2a0cSMatthias Ringwald config_options[1] = 2; // len param 6716dca2a0cSMatthias Ringwald little_endian_store_16( (uint8_t*)&config_options, 2, channel->local_mtu); 6726dca2a0cSMatthias Ringwald options_size = 4; 6736dca2a0cSMatthias Ringwald } 6746dca2a0cSMatthias Ringwald return options_size; 6756dca2a0cSMatthias Ringwald } 6766dca2a0cSMatthias Ringwald 6771b9cb13dSMatthias Ringwald static uint32_t l2cap_extended_features_mask(void){ 6781b9cb13dSMatthias Ringwald // extended features request supported, features: fixed channels, unicast connectionless data reception 6791b9cb13dSMatthias Ringwald uint32_t features = 0x280; 6801b9cb13dSMatthias Ringwald #ifdef ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE 6811b9cb13dSMatthias Ringwald features |= 0x0008; 6821b9cb13dSMatthias Ringwald #endif 6831b9cb13dSMatthias Ringwald return features; 6841b9cb13dSMatthias Ringwald } 6851b9cb13dSMatthias Ringwald 6868158c421Smatthias.ringwald // MARK: L2CAP_RUN 6872cd0be45Smatthias.ringwald // process outstanding signaling tasks 6887f02f414SMatthias Ringwald static void l2cap_run(void){ 6892b83fb7dSmatthias.ringwald 69022c29ab4SMatthias Ringwald // log_info("l2cap_run: entered"); 69122c29ab4SMatthias Ringwald 6922b83fb7dSmatthias.ringwald // check pending signaling responses 6932b83fb7dSmatthias.ringwald while (signaling_responses_pending){ 6942b83fb7dSmatthias.ringwald 6952b83fb7dSmatthias.ringwald hci_con_handle_t handle = signaling_responses[0].handle; 696a35252c8S[email protected] 697a35252c8S[email protected] if (!hci_can_send_acl_packet_now(handle)) break; 698a35252c8S[email protected] 6992b83fb7dSmatthias.ringwald uint8_t sig_id = signaling_responses[0].sig_id; 700e74c5f58SMatthias Ringwald uint8_t response_code = signaling_responses[0].code; 7012b360848Smatthias.ringwald uint16_t infoType = signaling_responses[0].data; // INFORMATION_REQUEST 70263a7246aSmatthias.ringwald uint16_t result = signaling_responses[0].data; // CONNECTION_REQUEST, COMMAND_REJECT 703b3264428SMatthias Ringwald #ifdef ENABLE_CLASSIC 704b3264428SMatthias Ringwald uint16_t source_cid = signaling_responses[0].cid; // CONNECTION_REQUEST 705b3264428SMatthias Ringwald #endif 706f3963406SMatthias Ringwald UNUSED(infoType); 70709e9d05bSMatthias Ringwald 708f53da564S[email protected] // remove first item before sending (to avoid sending response mutliple times) 709f53da564S[email protected] signaling_responses_pending--; 710f53da564S[email protected] int i; 711f53da564S[email protected] for (i=0; i < signaling_responses_pending; i++){ 712f53da564S[email protected] memcpy(&signaling_responses[i], &signaling_responses[i+1], sizeof(l2cap_signaling_response_t)); 713f53da564S[email protected] } 714f53da564S[email protected] 715f53da564S[email protected] switch (response_code){ 71609e9d05bSMatthias Ringwald #ifdef ENABLE_CLASSIC 7172b360848Smatthias.ringwald case CONNECTION_REQUEST: 718e74c5f58SMatthias Ringwald l2cap_send_signaling_packet(handle, CONNECTION_RESPONSE, sig_id, source_cid, 0, result, 0); 7192bd8b7e7S[email protected] // also disconnect if result is 0x0003 - security blocked 7204d816277S[email protected] if (result == 0x0003){ 7212bd8b7e7S[email protected] hci_disconnect_security_block(handle); 7224d816277S[email protected] } 7232b360848Smatthias.ringwald break; 7242b83fb7dSmatthias.ringwald case ECHO_REQUEST: 7252b83fb7dSmatthias.ringwald l2cap_send_signaling_packet(handle, ECHO_RESPONSE, sig_id, 0, NULL); 7262b83fb7dSmatthias.ringwald break; 7272b83fb7dSmatthias.ringwald case INFORMATION_REQUEST: 7283b0484b3S[email protected] switch (infoType){ 7293b0484b3S[email protected] case 1: { // Connectionless MTU 7303b0484b3S[email protected] uint16_t connectionless_mtu = hci_max_acl_data_packet_length(); 7313b0484b3S[email protected] l2cap_send_signaling_packet(handle, INFORMATION_RESPONSE, sig_id, infoType, 0, sizeof(connectionless_mtu), &connectionless_mtu); 7323b0484b3S[email protected] } 733202c8a4cSMatthias Ringwald break; 7343b0484b3S[email protected] case 2: { // Extended Features Supported 7351b9cb13dSMatthias Ringwald uint32_t features = l2cap_extended_features_mask(); 7363b0484b3S[email protected] l2cap_send_signaling_packet(handle, INFORMATION_RESPONSE, sig_id, infoType, 0, sizeof(features), &features); 7373b0484b3S[email protected] } 738202c8a4cSMatthias Ringwald break; 7393b0484b3S[email protected] case 3: { // Fixed Channels Supported 7403b0484b3S[email protected] uint8_t map[8]; 7413b0484b3S[email protected] memset(map, 0, 8); 742288636a2SMatthias Ringwald map[0] = 0x06; // L2CAP Signaling Channel (0x02) + Connectionless reception (0x04) 7433b0484b3S[email protected] l2cap_send_signaling_packet(handle, INFORMATION_RESPONSE, sig_id, infoType, 0, sizeof(map), &map); 7443b0484b3S[email protected] } 745202c8a4cSMatthias Ringwald break; 7463b0484b3S[email protected] default: 7472b83fb7dSmatthias.ringwald // all other types are not supported 7482b83fb7dSmatthias.ringwald l2cap_send_signaling_packet(handle, INFORMATION_RESPONSE, sig_id, infoType, 1, 0, NULL); 7493b0484b3S[email protected] break; 7502b83fb7dSmatthias.ringwald } 7512b83fb7dSmatthias.ringwald break; 75263a7246aSmatthias.ringwald case COMMAND_REJECT: 7535ca8d57bS[email protected] l2cap_send_signaling_packet(handle, COMMAND_REJECT, sig_id, result, 0, NULL); 75463f0ac45SMatthias Ringwald break; 75509e9d05bSMatthias Ringwald #endif 756a9a4c409SMatthias Ringwald #ifdef ENABLE_BLE 75763f0ac45SMatthias Ringwald case LE_CREDIT_BASED_CONNECTION_REQUEST: 75863f0ac45SMatthias Ringwald l2cap_send_le_signaling_packet(handle, LE_CREDIT_BASED_CONNECTION_RESPONSE, sig_id, 0, 0, 0, 0, result); 75963f0ac45SMatthias Ringwald break; 76070efece1S[email protected] case COMMAND_REJECT_LE: 76170efece1S[email protected] l2cap_send_le_signaling_packet(handle, COMMAND_REJECT, sig_id, result, 0, NULL); 76263a7246aSmatthias.ringwald break; 76370efece1S[email protected] #endif 7642b83fb7dSmatthias.ringwald default: 7652b83fb7dSmatthias.ringwald // should not happen 7662b83fb7dSmatthias.ringwald break; 7672b83fb7dSmatthias.ringwald } 7682b83fb7dSmatthias.ringwald } 7692b83fb7dSmatthias.ringwald 770665d90f2SMatthias Ringwald btstack_linked_list_iterator_t it; 771f3963406SMatthias Ringwald UNUSED(it); 77209e9d05bSMatthias Ringwald 7731b9cb13dSMatthias Ringwald #ifdef ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE 7741b9cb13dSMatthias Ringwald // send l2cap information request if neccessary 7751b9cb13dSMatthias Ringwald hci_connections_get_iterator(&it); 7761b9cb13dSMatthias Ringwald while(btstack_linked_list_iterator_has_next(&it)){ 7771b9cb13dSMatthias Ringwald hci_connection_t * connection = (hci_connection_t *) btstack_linked_list_iterator_next(&it); 7781b9cb13dSMatthias Ringwald if (connection->l2cap_state.information_state == L2CAP_INFORMATION_STATE_W2_SEND_EXTENDED_FEATURE_REQUEST){ 7791b9cb13dSMatthias Ringwald connection->l2cap_state.information_state = L2CAP_INFORMATION_STATE_W4_EXTENDED_FEATURE_RESPONSE; 7801b9cb13dSMatthias Ringwald // send information request for extended features 7811b9cb13dSMatthias Ringwald uint8_t sig_id = l2cap_next_sig_id(); 7821b9cb13dSMatthias Ringwald uint8_t info_type = 2; 7831b9cb13dSMatthias Ringwald l2cap_send_signaling_packet(connection->con_handle, INFORMATION_REQUEST, sig_id, info_type); 7841b9cb13dSMatthias Ringwald return; 7851b9cb13dSMatthias Ringwald } 7861b9cb13dSMatthias Ringwald } 7871b9cb13dSMatthias Ringwald #endif 7881b9cb13dSMatthias Ringwald 78909e9d05bSMatthias Ringwald #ifdef ENABLE_CLASSIC 79043ec931dSMatthias Ringwald uint8_t config_options[10]; 791665d90f2SMatthias Ringwald btstack_linked_list_iterator_init(&it, &l2cap_channels); 792665d90f2SMatthias Ringwald while (btstack_linked_list_iterator_has_next(&it)){ 793baf94f06S[email protected] 794665d90f2SMatthias Ringwald l2cap_channel_t * channel = (l2cap_channel_t *) btstack_linked_list_iterator_next(&it); 79522c29ab4SMatthias Ringwald // log_info("l2cap_run: channel %p, state %u, var 0x%02x", channel, channel->state, channel->state_var); 7962cd0be45Smatthias.ringwald switch (channel->state){ 7972cd0be45Smatthias.ringwald 798df3354fcS[email protected] case L2CAP_STATE_WAIT_INCOMING_SECURITY_LEVEL_UPDATE: 799ad671560S[email protected] case L2CAP_STATE_WAIT_CLIENT_ACCEPT_OR_REJECT: 800fc64f94aSMatthias Ringwald if (!hci_can_send_acl_packet_now(channel->con_handle)) break; 801a00031e2S[email protected] if (channel->state_var & L2CAP_CHANNEL_STATE_VAR_SEND_CONN_RESP_PEND) { 802ad671560S[email protected] channelStateVarClearFlag(channel, L2CAP_CHANNEL_STATE_VAR_SEND_CONN_RESP_PEND); 803fc64f94aSMatthias Ringwald l2cap_send_signaling_packet(channel->con_handle, CONNECTION_RESPONSE, channel->remote_sig_id, channel->local_cid, channel->remote_cid, 1, 0); 804ad671560S[email protected] } 805ad671560S[email protected] break; 806ad671560S[email protected] 80702b22dc4Smatthias.ringwald case L2CAP_STATE_WILL_SEND_CREATE_CONNECTION: 808baf94f06S[email protected] if (!hci_can_send_command_packet_now()) break; 80964472d52Smatthias.ringwald // send connection request - set state first 81064472d52Smatthias.ringwald channel->state = L2CAP_STATE_WAIT_CONNECTION_COMPLETE; 81102b22dc4Smatthias.ringwald // BD_ADDR, Packet_Type, Page_Scan_Repetition_Mode, Reserved, Clock_Offset, Allow_Role_Switch 8128f8108aaSmatthias.ringwald hci_send_cmd(&hci_create_connection, channel->address, hci_usable_acl_packet_types(), 0, 0, 0, 1); 81302b22dc4Smatthias.ringwald break; 81402b22dc4Smatthias.ringwald 815e7ff783cSmatthias.ringwald case L2CAP_STATE_WILL_SEND_CONNECTION_RESPONSE_DECLINE: 816fc64f94aSMatthias Ringwald if (!hci_can_send_acl_packet_now(channel->con_handle)) break; 81722c29ab4SMatthias Ringwald channel->state = L2CAP_STATE_INVALID; 818fc64f94aSMatthias Ringwald l2cap_send_signaling_packet(channel->con_handle, CONNECTION_RESPONSE, channel->remote_sig_id, channel->local_cid, channel->remote_cid, channel->reason, 0); 819e7ff783cSmatthias.ringwald // discard channel - l2cap_finialize_channel_close without sending l2cap close event 8209dcb2fb2S[email protected] l2cap_stop_rtx(channel); 821665d90f2SMatthias Ringwald btstack_linked_list_iterator_remove(&it); 822d3a9df87Smatthias.ringwald btstack_memory_l2cap_channel_free(channel); 823e7ff783cSmatthias.ringwald break; 824e7ff783cSmatthias.ringwald 825552d92a1Smatthias.ringwald case L2CAP_STATE_WILL_SEND_CONNECTION_RESPONSE_ACCEPT: 826fc64f94aSMatthias Ringwald if (!hci_can_send_acl_packet_now(channel->con_handle)) break; 827fa8473a4Smatthias.ringwald channel->state = L2CAP_STATE_CONFIG; 82828ca2b46S[email protected] channelStateVarSetFlag(channel, L2CAP_CHANNEL_STATE_VAR_SEND_CONF_REQ); 829fc64f94aSMatthias Ringwald l2cap_send_signaling_packet(channel->con_handle, CONNECTION_RESPONSE, channel->remote_sig_id, channel->local_cid, channel->remote_cid, 0, 0); 830552d92a1Smatthias.ringwald break; 831552d92a1Smatthias.ringwald 8326fdcc387Smatthias.ringwald case L2CAP_STATE_WILL_SEND_CONNECTION_REQUEST: 833fc64f94aSMatthias Ringwald if (!hci_can_send_acl_packet_now(channel->con_handle)) break; 8346fdcc387Smatthias.ringwald // success, start l2cap handshake 835b1988dceSmatthias.ringwald channel->local_sig_id = l2cap_next_sig_id(); 8366fdcc387Smatthias.ringwald channel->state = L2CAP_STATE_WAIT_CONNECT_RSP; 837fc64f94aSMatthias Ringwald l2cap_send_signaling_packet( channel->con_handle, CONNECTION_REQUEST, channel->local_sig_id, channel->psm, channel->local_cid); 8385932bd7cS[email protected] l2cap_start_rtx(channel); 8396fdcc387Smatthias.ringwald break; 8406fdcc387Smatthias.ringwald 841fa8473a4Smatthias.ringwald case L2CAP_STATE_CONFIG: 842fc64f94aSMatthias Ringwald if (!hci_can_send_acl_packet_now(channel->con_handle)) break; 84373cf2b3dSmatthias.ringwald if (channel->state_var & L2CAP_CHANNEL_STATE_VAR_SEND_CONF_RSP){ 84463a7246aSmatthias.ringwald uint16_t flags = 0; 84528ca2b46S[email protected] channelStateVarClearFlag(channel, L2CAP_CHANNEL_STATE_VAR_SEND_CONF_RSP); 84663a7246aSmatthias.ringwald if (channel->state_var & L2CAP_CHANNEL_STATE_VAR_SEND_CONF_RSP_CONT) { 84763a7246aSmatthias.ringwald flags = 1; 84863a7246aSmatthias.ringwald } else { 84928ca2b46S[email protected] channelStateVarSetFlag(channel, L2CAP_CHANNEL_STATE_VAR_SENT_CONF_RSP); 85063a7246aSmatthias.ringwald } 85163a7246aSmatthias.ringwald if (channel->state_var & L2CAP_CHANNEL_STATE_VAR_SEND_CONF_RSP_INVALID){ 852fc64f94aSMatthias Ringwald l2cap_send_signaling_packet(channel->con_handle, CONFIGURE_RESPONSE, channel->remote_sig_id, channel->remote_cid, flags, L2CAP_CONF_RESULT_UNKNOWN_OPTIONS, 0, NULL); 85363a7246aSmatthias.ringwald } else if (channel->state_var & L2CAP_CHANNEL_STATE_VAR_SEND_CONF_RSP_MTU){ 8546dca2a0cSMatthias Ringwald uint16_t options_size = l2cap_setup_options(channel, config_options); 8556dca2a0cSMatthias Ringwald l2cap_send_signaling_packet(channel->con_handle, CONFIGURE_RESPONSE, channel->remote_sig_id, channel->remote_cid, flags, 0, options_size, &config_options); 85663a7246aSmatthias.ringwald channelStateVarClearFlag(channel,L2CAP_CHANNEL_STATE_VAR_SEND_CONF_RSP_MTU); 85763a7246aSmatthias.ringwald } else { 858fc64f94aSMatthias Ringwald l2cap_send_signaling_packet(channel->con_handle, CONFIGURE_RESPONSE, channel->remote_sig_id, channel->remote_cid, flags, 0, 0, NULL); 85963a7246aSmatthias.ringwald } 86063a7246aSmatthias.ringwald channelStateVarClearFlag(channel, L2CAP_CHANNEL_STATE_VAR_SEND_CONF_RSP_CONT); 861fa8473a4Smatthias.ringwald } 86273cf2b3dSmatthias.ringwald else if (channel->state_var & L2CAP_CHANNEL_STATE_VAR_SEND_CONF_REQ){ 86328ca2b46S[email protected] channelStateVarClearFlag(channel, L2CAP_CHANNEL_STATE_VAR_SEND_CONF_REQ); 86428ca2b46S[email protected] channelStateVarSetFlag(channel, L2CAP_CHANNEL_STATE_VAR_SENT_CONF_REQ); 865b1988dceSmatthias.ringwald channel->local_sig_id = l2cap_next_sig_id(); 8666dca2a0cSMatthias Ringwald uint16_t options_size = l2cap_setup_options(channel, config_options); 8676dca2a0cSMatthias Ringwald l2cap_send_signaling_packet(channel->con_handle, CONFIGURE_REQUEST, channel->local_sig_id, channel->remote_cid, 0, options_size, &config_options); 8685932bd7cS[email protected] l2cap_start_rtx(channel); 869fa8473a4Smatthias.ringwald } 870fa8473a4Smatthias.ringwald if (l2cap_channel_ready_for_open(channel)){ 871552d92a1Smatthias.ringwald channel->state = L2CAP_STATE_OPEN; 872552d92a1Smatthias.ringwald l2cap_emit_channel_opened(channel, 0); // success 873fa8473a4Smatthias.ringwald } 874552d92a1Smatthias.ringwald break; 875552d92a1Smatthias.ringwald 876e7ff783cSmatthias.ringwald case L2CAP_STATE_WILL_SEND_DISCONNECT_RESPONSE: 877fc64f94aSMatthias Ringwald if (!hci_can_send_acl_packet_now(channel->con_handle)) break; 87822c29ab4SMatthias Ringwald channel->state = L2CAP_STATE_INVALID; 879fc64f94aSMatthias Ringwald l2cap_send_signaling_packet( channel->con_handle, DISCONNECTION_RESPONSE, channel->remote_sig_id, channel->local_cid, channel->remote_cid); 8805932bd7cS[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 :) 881756102d3Smatthias.ringwald l2cap_finialize_channel_close(channel); // -- remove from list 882e7ff783cSmatthias.ringwald break; 883e7ff783cSmatthias.ringwald 884e7ff783cSmatthias.ringwald case L2CAP_STATE_WILL_SEND_DISCONNECT_REQUEST: 885fc64f94aSMatthias Ringwald if (!hci_can_send_acl_packet_now(channel->con_handle)) break; 886b1988dceSmatthias.ringwald channel->local_sig_id = l2cap_next_sig_id(); 8872cd0be45Smatthias.ringwald channel->state = L2CAP_STATE_WAIT_DISCONNECT; 888fc64f94aSMatthias Ringwald l2cap_send_signaling_packet( channel->con_handle, DISCONNECTION_REQUEST, channel->local_sig_id, channel->remote_cid, channel->local_cid); 8892cd0be45Smatthias.ringwald break; 8902cd0be45Smatthias.ringwald default: 8912cd0be45Smatthias.ringwald break; 8922cd0be45Smatthias.ringwald } 8932cd0be45Smatthias.ringwald } 89409e9d05bSMatthias Ringwald #endif 895da886c03S[email protected] 896cab29d48SMatthias Ringwald #ifdef ENABLE_LE_DATA_CHANNELS 897efedfb4cSMatthias Ringwald btstack_linked_list_iterator_init(&it, &l2cap_le_channels); 898efedfb4cSMatthias Ringwald while (btstack_linked_list_iterator_has_next(&it)){ 8997f107edaSMatthias Ringwald uint8_t * acl_buffer; 9007f107edaSMatthias Ringwald uint8_t * l2cap_payload; 9017f107edaSMatthias Ringwald uint16_t pos; 9027f107edaSMatthias Ringwald uint16_t payload_size; 903efedfb4cSMatthias Ringwald l2cap_channel_t * channel = (l2cap_channel_t *) btstack_linked_list_iterator_next(&it); 904efedfb4cSMatthias Ringwald // log_info("l2cap_run: channel %p, state %u, var 0x%02x", channel, channel->state, channel->state_var); 905efedfb4cSMatthias Ringwald switch (channel->state){ 9065cb87675SMatthias Ringwald case L2CAP_STATE_WILL_SEND_LE_CONNECTION_REQUEST: 9075cb87675SMatthias Ringwald if (!hci_can_send_acl_packet_now(channel->con_handle)) break; 9085cb87675SMatthias Ringwald channel->state = L2CAP_STATE_WAIT_LE_CONNECTION_RESPONSE; 9095cb87675SMatthias Ringwald // le psm, source cid, mtu, mps, initial credits 9101b8b8d05SMatthias Ringwald channel->local_sig_id = l2cap_next_sig_id(); 91163f0ac45SMatthias Ringwald channel->credits_incoming = channel->new_credits_incoming; 91263f0ac45SMatthias Ringwald channel->new_credits_incoming = 0; 91363f0ac45SMatthias 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, 23, channel->credits_incoming); 9145cb87675SMatthias Ringwald break; 91523017473SMatthias Ringwald case L2CAP_STATE_WILL_SEND_LE_CONNECTION_RESPONSE_ACCEPT: 91623017473SMatthias Ringwald if (!hci_can_send_acl_packet_now(channel->con_handle)) break; 91723017473SMatthias Ringwald // TODO: support larger MPS 91823017473SMatthias Ringwald channel->state = L2CAP_STATE_OPEN; 91963f0ac45SMatthias Ringwald channel->credits_incoming = channel->new_credits_incoming; 92063f0ac45SMatthias Ringwald channel->new_credits_incoming = 0; 92163f0ac45SMatthias Ringwald l2cap_send_le_signaling_packet(channel->con_handle, LE_CREDIT_BASED_CONNECTION_RESPONSE, channel->remote_sig_id, channel->local_cid, channel->local_mtu, 23, channel->credits_incoming, 0); 92264e11ca9SMatthias Ringwald // notify client 92344276248SMatthias Ringwald l2cap_emit_le_channel_opened(channel, 0); 92423017473SMatthias Ringwald break; 925e7d0c9aaSMatthias Ringwald case L2CAP_STATE_WILL_SEND_LE_CONNECTION_RESPONSE_DECLINE: 926e7d0c9aaSMatthias Ringwald if (!hci_can_send_acl_packet_now(channel->con_handle)) break; 927e7d0c9aaSMatthias Ringwald channel->state = L2CAP_STATE_INVALID; 92863f0ac45SMatthias Ringwald l2cap_send_le_signaling_packet(channel->con_handle, LE_CREDIT_BASED_CONNECTION_RESPONSE, channel->remote_sig_id, 0, 0, 0, 0, channel->reason); 929e7d0c9aaSMatthias Ringwald // discard channel - l2cap_finialize_channel_close without sending l2cap close event 930e7d0c9aaSMatthias Ringwald l2cap_stop_rtx(channel); 931e7d0c9aaSMatthias Ringwald btstack_linked_list_iterator_remove(&it); 932e7d0c9aaSMatthias Ringwald btstack_memory_l2cap_channel_free(channel); 933e7d0c9aaSMatthias Ringwald break; 9347f107edaSMatthias Ringwald case L2CAP_STATE_OPEN: 93585aeef60SMatthias Ringwald if (!hci_can_send_acl_packet_now(channel->con_handle)) break; 93685aeef60SMatthias Ringwald 93785aeef60SMatthias Ringwald // send credits 93885aeef60SMatthias Ringwald if (channel->new_credits_incoming){ 93985aeef60SMatthias Ringwald log_info("l2cap: sending %u credits", channel->new_credits_incoming); 94085aeef60SMatthias Ringwald channel->local_sig_id = l2cap_next_sig_id(); 94185aeef60SMatthias Ringwald uint16_t new_credits = channel->new_credits_incoming; 94285aeef60SMatthias Ringwald channel->new_credits_incoming = 0; 94385aeef60SMatthias Ringwald channel->credits_incoming += new_credits; 94485aeef60SMatthias Ringwald l2cap_send_le_signaling_packet(channel->con_handle, LE_FLOW_CONTROL_CREDIT, channel->local_sig_id, channel->remote_cid, new_credits); 94585aeef60SMatthias Ringwald break; 94685aeef60SMatthias Ringwald } 94785aeef60SMatthias Ringwald 94885aeef60SMatthias Ringwald // send data 9497f107edaSMatthias Ringwald if (!channel->send_sdu_buffer) break; 9507f107edaSMatthias Ringwald if (!channel->credits_outgoing) break; 95185aeef60SMatthias Ringwald 9527f107edaSMatthias Ringwald // send part of SDU 9537f107edaSMatthias Ringwald hci_reserve_packet_buffer(); 9547f107edaSMatthias Ringwald acl_buffer = hci_get_outgoing_packet_buffer(); 9557f107edaSMatthias Ringwald l2cap_payload = acl_buffer + 8; 9567f107edaSMatthias Ringwald pos = 0; 9577f107edaSMatthias Ringwald if (!channel->send_sdu_pos){ 9587f107edaSMatthias Ringwald // store SDU len 9597f107edaSMatthias Ringwald channel->send_sdu_pos += 2; 9607f107edaSMatthias Ringwald little_endian_store_16(l2cap_payload, pos, channel->send_sdu_len); 9617f107edaSMatthias Ringwald pos += 2; 9627f107edaSMatthias Ringwald } 9637f107edaSMatthias Ringwald payload_size = btstack_min(channel->send_sdu_len + 2 - channel->send_sdu_pos, channel->remote_mps - pos); 96485aeef60SMatthias Ringwald log_info("len %u, pos %u => payload %u, credits %u", channel->send_sdu_len, channel->send_sdu_pos, payload_size, channel->credits_outgoing); 9657f107edaSMatthias Ringwald memcpy(&l2cap_payload[pos], &channel->send_sdu_buffer[channel->send_sdu_pos-2], payload_size); // -2 for virtual SDU len 9667f107edaSMatthias Ringwald pos += payload_size; 9677f107edaSMatthias Ringwald channel->send_sdu_pos += payload_size; 968f511cefaSMatthias Ringwald l2cap_setup_header(acl_buffer, channel->con_handle, 0, channel->remote_cid, pos); 9697f107edaSMatthias Ringwald // done 9707f107edaSMatthias Ringwald 97185aeef60SMatthias Ringwald channel->credits_outgoing--; 9727f107edaSMatthias Ringwald 9737f107edaSMatthias Ringwald if (channel->send_sdu_pos >= channel->send_sdu_len + 2){ 9747f107edaSMatthias Ringwald channel->send_sdu_buffer = NULL; 97544276248SMatthias Ringwald // send done event 97644276248SMatthias Ringwald l2cap_emit_simple_event_with_cid(channel, L2CAP_EVENT_LE_PACKET_SENT); 97744276248SMatthias Ringwald // inform about can send now 97844276248SMatthias Ringwald l2cap_le_notify_channel_can_send(channel); 9797f107edaSMatthias Ringwald } 9807f107edaSMatthias Ringwald hci_send_acl_packet_buffer(8 + pos); 9817f107edaSMatthias Ringwald break; 982828a7f7aSMatthias Ringwald case L2CAP_STATE_WILL_SEND_DISCONNECT_REQUEST: 983828a7f7aSMatthias Ringwald if (!hci_can_send_acl_packet_now(channel->con_handle)) break; 984828a7f7aSMatthias Ringwald channel->local_sig_id = l2cap_next_sig_id(); 985828a7f7aSMatthias Ringwald channel->state = L2CAP_STATE_WAIT_DISCONNECT; 986828a7f7aSMatthias Ringwald l2cap_send_le_signaling_packet( channel->con_handle, DISCONNECTION_REQUEST, channel->local_sig_id, channel->remote_cid, channel->local_cid); 987828a7f7aSMatthias Ringwald break; 988828a7f7aSMatthias Ringwald case L2CAP_STATE_WILL_SEND_DISCONNECT_RESPONSE: 989828a7f7aSMatthias Ringwald if (!hci_can_send_acl_packet_now(channel->con_handle)) break; 990828a7f7aSMatthias Ringwald channel->state = L2CAP_STATE_INVALID; 991828a7f7aSMatthias Ringwald l2cap_send_le_signaling_packet( channel->con_handle, DISCONNECTION_RESPONSE, channel->remote_sig_id, channel->local_cid, channel->remote_cid); 992828a7f7aSMatthias Ringwald l2cap_le_finialize_channel_close(channel); // -- remove from list 993828a7f7aSMatthias Ringwald break; 994efedfb4cSMatthias Ringwald default: 995efedfb4cSMatthias Ringwald break; 996efedfb4cSMatthias Ringwald } 997efedfb4cSMatthias Ringwald } 99809e9d05bSMatthias Ringwald #endif 999efedfb4cSMatthias Ringwald 100009e9d05bSMatthias Ringwald #ifdef ENABLE_BLE 1001da886c03S[email protected] // send l2cap con paramter update if necessary 1002da886c03S[email protected] hci_connections_get_iterator(&it); 1003665d90f2SMatthias Ringwald while(btstack_linked_list_iterator_has_next(&it)){ 1004665d90f2SMatthias Ringwald hci_connection_t * connection = (hci_connection_t *) btstack_linked_list_iterator_next(&it); 10055d14fa8fSMatthias Ringwald if (connection->address_type != BD_ADDR_TYPE_LE_PUBLIC && connection->address_type != BD_ADDR_TYPE_LE_RANDOM) continue; 1006b68d7bc3SMatthias Ringwald if (!hci_can_send_acl_packet_now(connection->con_handle)) continue; 1007da886c03S[email protected] switch (connection->le_con_parameter_update_state){ 1008b68d7bc3SMatthias Ringwald case CON_PARAMETER_UPDATE_SEND_REQUEST: 1009b68d7bc3SMatthias Ringwald connection->le_con_parameter_update_state = CON_PARAMETER_UPDATE_NONE; 1010b68d7bc3SMatthias Ringwald l2cap_send_le_signaling_packet(connection->con_handle, CONNECTION_PARAMETER_UPDATE_REQUEST, connection->le_con_param_update_identifier, 1011b68d7bc3SMatthias Ringwald connection->le_conn_interval_min, connection->le_conn_interval_max, connection->le_conn_latency, connection->le_supervision_timeout); 1012b68d7bc3SMatthias Ringwald break; 1013da886c03S[email protected] case CON_PARAMETER_UPDATE_SEND_RESPONSE: 1014b68d7bc3SMatthias Ringwald connection->le_con_parameter_update_state = CON_PARAMETER_UPDATE_CHANGE_HCI_CON_PARAMETERS; 1015b68d7bc3SMatthias Ringwald l2cap_send_le_signaling_packet(connection->con_handle, CONNECTION_PARAMETER_UPDATE_RESPONSE, connection->le_con_param_update_identifier, 0); 1016da886c03S[email protected] break; 1017da886c03S[email protected] case CON_PARAMETER_UPDATE_DENY: 1018b68d7bc3SMatthias Ringwald connection->le_con_parameter_update_state = CON_PARAMETER_UPDATE_NONE; 1019b68d7bc3SMatthias Ringwald l2cap_send_le_signaling_packet(connection->con_handle, CONNECTION_PARAMETER_UPDATE_RESPONSE, connection->le_con_param_update_identifier, 1); 1020da886c03S[email protected] break; 1021da886c03S[email protected] default: 1022da886c03S[email protected] break; 1023da886c03S[email protected] } 1024da886c03S[email protected] } 10254d7157c3S[email protected] #endif 1026da886c03S[email protected] 102722c29ab4SMatthias Ringwald // log_info("l2cap_run: exit"); 10282cd0be45Smatthias.ringwald } 10292cd0be45Smatthias.ringwald 103009e9d05bSMatthias Ringwald #ifdef ENABLE_CLASSIC 1031fc64f94aSMatthias Ringwald static void l2cap_handle_connection_complete(hci_con_handle_t con_handle, l2cap_channel_t * channel){ 10322df5dadcS[email protected] if (channel->state == L2CAP_STATE_WAIT_CONNECTION_COMPLETE || channel->state == L2CAP_STATE_WILL_SEND_CREATE_CONNECTION) { 10335533f01eS[email protected] log_info("l2cap_handle_connection_complete expected state"); 10342df5dadcS[email protected] // success, start l2cap handshake 1035fc64f94aSMatthias Ringwald channel->con_handle = con_handle; 10362df5dadcS[email protected] // check remote SSP feature first 10372df5dadcS[email protected] channel->state = L2CAP_STATE_WAIT_REMOTE_SUPPORTED_FEATURES; 10382df5dadcS[email protected] } 10392df5dadcS[email protected] } 10402df5dadcS[email protected] 10411b9cb13dSMatthias Ringwald static void l2cap_ready_to_connect(l2cap_channel_t * channel){ 10421b9cb13dSMatthias Ringwald 10431b9cb13dSMatthias Ringwald 10441b9cb13dSMatthias Ringwald #ifdef ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE 10451b9cb13dSMatthias Ringwald // TODO: we assume outgoing connection 10461b9cb13dSMatthias Ringwald if (channel->mode == L2CAP_CHANNEL_MODE_ENHANCED_RETRANSMISSION){ 10471b9cb13dSMatthias Ringwald // get hci_connection 10481b9cb13dSMatthias Ringwald hci_connection_t * connection = hci_connection_for_handle(channel->con_handle); 10491b9cb13dSMatthias Ringwald if (connection->l2cap_state.information_state == L2CAP_INFORMATION_STATE_IDLE){ 10501b9cb13dSMatthias Ringwald connection->l2cap_state.information_state = L2CAP_INFORMATION_STATE_W2_SEND_EXTENDED_FEATURE_REQUEST; 10511b9cb13dSMatthias Ringwald channel->state = L2CAP_STATE_WAIT_OUTGOING_EXTENDED_FEATURES; 10521b9cb13dSMatthias Ringwald return; 10531b9cb13dSMatthias Ringwald } 10541b9cb13dSMatthias Ringwald } 10551b9cb13dSMatthias Ringwald #endif 10561b9cb13dSMatthias Ringwald 10571b9cb13dSMatthias Ringwald // fine, go ahead 10581b9cb13dSMatthias Ringwald channel->state = L2CAP_STATE_WILL_SEND_CONNECTION_REQUEST; 10591b9cb13dSMatthias Ringwald } 10601b9cb13dSMatthias Ringwald 10612df5dadcS[email protected] static void l2cap_handle_remote_supported_features_received(l2cap_channel_t * channel){ 10622df5dadcS[email protected] if (channel->state != L2CAP_STATE_WAIT_REMOTE_SUPPORTED_FEATURES) return; 10632df5dadcS[email protected] 10642df5dadcS[email protected] // we have been waiting for remote supported features, if both support SSP, 1065ac301f95S[email protected] log_info("l2cap received remote supported features, sec_level_0_allowed for psm %u = %u", channel->psm, l2cap_security_level_0_allowed_for_PSM(channel->psm)); 1066fc64f94aSMatthias Ringwald if (gap_ssp_supported_on_both_sides(channel->con_handle) && !l2cap_security_level_0_allowed_for_PSM(channel->psm)){ 10672df5dadcS[email protected] // request security level 2 10682df5dadcS[email protected] channel->state = L2CAP_STATE_WAIT_OUTGOING_SECURITY_LEVEL_UPDATE; 1069fc64f94aSMatthias Ringwald gap_request_security_level(channel->con_handle, LEVEL_2); 10702df5dadcS[email protected] return; 10712df5dadcS[email protected] } 10721b9cb13dSMatthias Ringwald 10731b9cb13dSMatthias Ringwald l2cap_ready_to_connect(channel); 10742df5dadcS[email protected] } 107509e9d05bSMatthias Ringwald #endif 10762df5dadcS[email protected] 107709e9d05bSMatthias Ringwald #ifdef L2CAP_USES_CHANNELS 1078da144af5SMatthias Ringwald static l2cap_channel_t * l2cap_create_channel_entry(btstack_packet_handler_t packet_handler, bd_addr_t address, bd_addr_type_t address_type, 1079da144af5SMatthias Ringwald uint16_t psm, uint16_t local_mtu, gap_security_level_t security_level){ 1080da144af5SMatthias Ringwald 1081da144af5SMatthias Ringwald l2cap_channel_t * channel = btstack_memory_l2cap_channel_get(); 1082da144af5SMatthias Ringwald if (!channel) { 1083da144af5SMatthias Ringwald return NULL; 1084da144af5SMatthias Ringwald } 1085da144af5SMatthias Ringwald 1086da144af5SMatthias Ringwald // Init memory (make valgrind happy) 1087da144af5SMatthias Ringwald memset(channel, 0, sizeof(l2cap_channel_t)); 1088da144af5SMatthias Ringwald 1089da144af5SMatthias Ringwald // fill in 1090da144af5SMatthias Ringwald channel->packet_handler = packet_handler; 1091da144af5SMatthias Ringwald bd_addr_copy(channel->address, address); 1092da144af5SMatthias Ringwald channel->address_type = address_type; 1093da144af5SMatthias Ringwald channel->psm = psm; 1094da144af5SMatthias Ringwald channel->local_mtu = local_mtu; 1095da144af5SMatthias Ringwald channel->remote_mtu = L2CAP_MINIMAL_MTU; 1096da144af5SMatthias Ringwald channel->required_security_level = security_level; 1097da144af5SMatthias Ringwald 1098da144af5SMatthias Ringwald // 1099da144af5SMatthias Ringwald channel->local_cid = l2cap_next_local_cid(); 1100da144af5SMatthias Ringwald channel->con_handle = 0; 1101da144af5SMatthias Ringwald 1102da144af5SMatthias Ringwald // set initial state 1103da144af5SMatthias Ringwald channel->state = L2CAP_STATE_WILL_SEND_CREATE_CONNECTION; 1104da144af5SMatthias Ringwald channel->state_var = L2CAP_CHANNEL_STATE_VAR_NONE; 1105da144af5SMatthias Ringwald channel->remote_sig_id = L2CAP_SIG_ID_INVALID; 1106da144af5SMatthias Ringwald channel->local_sig_id = L2CAP_SIG_ID_INVALID; 1107da144af5SMatthias Ringwald return channel; 1108da144af5SMatthias Ringwald } 110909e9d05bSMatthias Ringwald #endif 111009e9d05bSMatthias Ringwald 111109e9d05bSMatthias Ringwald #ifdef ENABLE_CLASSIC 1112da144af5SMatthias Ringwald 11139077cb15SMatthias Ringwald /** 11149077cb15SMatthias Ringwald * @brief Creates L2CAP channel to the PSM of a remote device with baseband address. A new baseband connection will be initiated if necessary. 11159077cb15SMatthias Ringwald * @param packet_handler 11169077cb15SMatthias Ringwald * @param address 11179077cb15SMatthias Ringwald * @param psm 11189077cb15SMatthias Ringwald * @param mtu 11199077cb15SMatthias Ringwald * @param local_cid 11209077cb15SMatthias Ringwald */ 11219077cb15SMatthias Ringwald 11229d139fbaSMatthias 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){ 11239d139fbaSMatthias Ringwald // limit MTU to the size of our outtgoing HCI buffer 11249d139fbaSMatthias Ringwald uint16_t local_mtu = btstack_min(mtu, l2cap_max_mtu()); 1125da144af5SMatthias Ringwald 11269d139fbaSMatthias Ringwald log_info("L2CAP_CREATE_CHANNEL addr %s psm 0x%x mtu %u -> local mtu %u", bd_addr_to_str(address), psm, mtu, local_mtu); 1127da144af5SMatthias Ringwald 1128da144af5SMatthias Ringwald l2cap_channel_t * channel = l2cap_create_channel_entry(channel_packet_handler, address, BD_ADDR_TYPE_CLASSIC, psm, local_mtu, LEVEL_0); 1129fc64f94aSMatthias Ringwald if (!channel) { 11309077cb15SMatthias Ringwald return BTSTACK_MEMORY_ALLOC_FAILED; 11319077cb15SMatthias Ringwald } 11329077cb15SMatthias Ringwald 11331b9cb13dSMatthias Ringwald #ifdef ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE 11341b9cb13dSMatthias Ringwald channel->mode = L2CAP_CHANNEL_MODE_BASIC; 11351b9cb13dSMatthias Ringwald #endif 11361b9cb13dSMatthias Ringwald 11379077cb15SMatthias Ringwald // add to connections list 1138fc64f94aSMatthias Ringwald btstack_linked_list_add(&l2cap_channels, (btstack_linked_item_t *) channel); 11399077cb15SMatthias Ringwald 11409077cb15SMatthias Ringwald // store local_cid 11419077cb15SMatthias Ringwald if (out_local_cid){ 1142fc64f94aSMatthias Ringwald *out_local_cid = channel->local_cid; 11439077cb15SMatthias Ringwald } 11449077cb15SMatthias Ringwald 11459077cb15SMatthias Ringwald // check if hci connection is already usable 11469077cb15SMatthias Ringwald hci_connection_t * conn = hci_connection_for_bd_addr_and_type(address, BD_ADDR_TYPE_CLASSIC); 11479077cb15SMatthias Ringwald if (conn){ 1148add0254bSMatthias Ringwald log_info("l2cap_create_channel, hci connection already exists"); 1149fc64f94aSMatthias Ringwald l2cap_handle_connection_complete(conn->con_handle, channel); 11509077cb15SMatthias Ringwald // check if remote supported fearures are already received 11519077cb15SMatthias Ringwald if (conn->bonding_flags & BONDING_RECEIVED_REMOTE_FEATURES) { 1152fc64f94aSMatthias Ringwald l2cap_handle_remote_supported_features_received(channel); 11539077cb15SMatthias Ringwald } 11549077cb15SMatthias Ringwald } 11559077cb15SMatthias Ringwald 11569077cb15SMatthias Ringwald l2cap_run(); 11579077cb15SMatthias Ringwald 11589077cb15SMatthias Ringwald return 0; 11599077cb15SMatthias Ringwald } 11609077cb15SMatthias Ringwald 11611b9cb13dSMatthias Ringwald #ifdef ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE 116245caebe5SMatthias Ringwald uint8_t l2cap_create_ertm_channel(btstack_packet_handler_t channel_packet_handler, bd_addr_t address, uint16_t psm, uint16_t mtu, int ertm_mandatory, uint16_t * out_local_cid){ 11631b9cb13dSMatthias Ringwald // limit MTU to the size of our outtgoing HCI buffer 11641b9cb13dSMatthias Ringwald uint16_t local_mtu = btstack_min(mtu, l2cap_max_mtu()); 11651b9cb13dSMatthias Ringwald 11661b9cb13dSMatthias Ringwald log_info("L2CAP_CREATE_CHANNEL addr %s psm 0x%x mtu %u -> local mtu %u", bd_addr_to_str(address), psm, mtu, local_mtu); 11671b9cb13dSMatthias Ringwald 11681b9cb13dSMatthias Ringwald l2cap_channel_t * channel = l2cap_create_channel_entry(channel_packet_handler, address, BD_ADDR_TYPE_CLASSIC, psm, local_mtu, LEVEL_0); 11691b9cb13dSMatthias Ringwald if (!channel) { 11701b9cb13dSMatthias Ringwald return BTSTACK_MEMORY_ALLOC_FAILED; 11711b9cb13dSMatthias Ringwald } 11721b9cb13dSMatthias Ringwald 11731b9cb13dSMatthias Ringwald channel->mode = L2CAP_CHANNEL_MODE_ENHANCED_RETRANSMISSION; 117445caebe5SMatthias Ringwald channel->ertm_mandatory = ertm_mandatory; 11751b9cb13dSMatthias Ringwald 11761b9cb13dSMatthias Ringwald // add to connections list 11771b9cb13dSMatthias Ringwald btstack_linked_list_add(&l2cap_channels, (btstack_linked_item_t *) channel); 11781b9cb13dSMatthias Ringwald 11791b9cb13dSMatthias Ringwald // store local_cid 11801b9cb13dSMatthias Ringwald if (out_local_cid){ 11811b9cb13dSMatthias Ringwald *out_local_cid = channel->local_cid; 11821b9cb13dSMatthias Ringwald } 11831b9cb13dSMatthias Ringwald 11841b9cb13dSMatthias Ringwald // check if hci connection is already usable 11851b9cb13dSMatthias Ringwald hci_connection_t * conn = hci_connection_for_bd_addr_and_type(address, BD_ADDR_TYPE_CLASSIC); 11861b9cb13dSMatthias Ringwald if (conn){ 11871b9cb13dSMatthias Ringwald log_info("l2cap_create_channel, hci connection already exists"); 11881b9cb13dSMatthias Ringwald l2cap_handle_connection_complete(conn->con_handle, channel); 11891b9cb13dSMatthias Ringwald // check if remote supported fearures are already received 11901b9cb13dSMatthias Ringwald if (conn->bonding_flags & BONDING_RECEIVED_REMOTE_FEATURES) { 11911b9cb13dSMatthias Ringwald l2cap_handle_remote_supported_features_received(channel); 11921b9cb13dSMatthias Ringwald } 11931b9cb13dSMatthias Ringwald } 11941b9cb13dSMatthias Ringwald 11951b9cb13dSMatthias Ringwald l2cap_run(); 11961b9cb13dSMatthias Ringwald 11971b9cb13dSMatthias Ringwald return 0; 11981b9cb13dSMatthias Ringwald } 11991b9cb13dSMatthias Ringwald #endif 12001b9cb13dSMatthias Ringwald 1201ce8f182eSMatthias Ringwald void 1202ce8f182eSMatthias Ringwald l2cap_disconnect(uint16_t local_cid, uint8_t reason){ 1203e0abb8e7S[email protected] log_info("L2CAP_DISCONNECT local_cid 0x%x reason 0x%x", local_cid, reason); 1204b35f641cSmatthias.ringwald // find channel for local_cid 1205b35f641cSmatthias.ringwald l2cap_channel_t * channel = l2cap_get_channel_for_local_cid(local_cid); 1206f62db1e3Smatthias.ringwald if (channel) { 1207e7ff783cSmatthias.ringwald channel->state = L2CAP_STATE_WILL_SEND_DISCONNECT_REQUEST; 1208f62db1e3Smatthias.ringwald } 12092cd0be45Smatthias.ringwald // process 12102cd0be45Smatthias.ringwald l2cap_run(); 121143625864Smatthias.ringwald } 12121e6aba47Smatthias.ringwald 1213afde0c52Smatthias.ringwald static void l2cap_handle_connection_failed_for_addr(bd_addr_t address, uint8_t status){ 1214665d90f2SMatthias Ringwald btstack_linked_list_iterator_t it; 1215665d90f2SMatthias Ringwald btstack_linked_list_iterator_init(&it, &l2cap_channels); 1216665d90f2SMatthias Ringwald while (btstack_linked_list_iterator_has_next(&it)){ 1217665d90f2SMatthias Ringwald l2cap_channel_t * channel = (l2cap_channel_t *) btstack_linked_list_iterator_next(&it); 1218058e3d6bSMatthias Ringwald if ( bd_addr_cmp( channel->address, address) != 0) continue; 1219c22aecc9S[email protected] // channel for this address found 1220c22aecc9S[email protected] switch (channel->state){ 1221c22aecc9S[email protected] case L2CAP_STATE_WAIT_CONNECTION_COMPLETE: 1222c22aecc9S[email protected] case L2CAP_STATE_WILL_SEND_CREATE_CONNECTION: 1223afde0c52Smatthias.ringwald // failure, forward error code 1224afde0c52Smatthias.ringwald l2cap_emit_channel_opened(channel, status); 1225afde0c52Smatthias.ringwald // discard channel 12269dcb2fb2S[email protected] l2cap_stop_rtx(channel); 1227665d90f2SMatthias Ringwald btstack_linked_list_iterator_remove(&it); 1228d3a9df87Smatthias.ringwald btstack_memory_l2cap_channel_free(channel); 1229c22aecc9S[email protected] break; 1230c22aecc9S[email protected] default: 1231c22aecc9S[email protected] break; 1232afde0c52Smatthias.ringwald } 1233afde0c52Smatthias.ringwald } 1234afde0c52Smatthias.ringwald } 1235afde0c52Smatthias.ringwald 1236afde0c52Smatthias.ringwald static void l2cap_handle_connection_success_for_addr(bd_addr_t address, hci_con_handle_t handle){ 1237665d90f2SMatthias Ringwald btstack_linked_list_iterator_t it; 1238665d90f2SMatthias Ringwald btstack_linked_list_iterator_init(&it, &l2cap_channels); 1239665d90f2SMatthias Ringwald while (btstack_linked_list_iterator_has_next(&it)){ 1240665d90f2SMatthias Ringwald l2cap_channel_t * channel = (l2cap_channel_t *) btstack_linked_list_iterator_next(&it); 1241058e3d6bSMatthias Ringwald if ( ! bd_addr_cmp( channel->address, address) ){ 12422df5dadcS[email protected] l2cap_handle_connection_complete(handle, channel); 1243afde0c52Smatthias.ringwald } 1244afde0c52Smatthias.ringwald } 12456fdcc387Smatthias.ringwald // process 12466fdcc387Smatthias.ringwald l2cap_run(); 1247afde0c52Smatthias.ringwald } 124809e9d05bSMatthias Ringwald #endif 1249b448a0e7Smatthias.ringwald 125033c40538SMatthias Ringwald static void l2cap_notify_channel_can_send(void){ 125109e9d05bSMatthias Ringwald 125209e9d05bSMatthias Ringwald #ifdef ENABLE_CLASSIC 125333c40538SMatthias Ringwald btstack_linked_list_iterator_t it; 125433c40538SMatthias Ringwald btstack_linked_list_iterator_init(&it, &l2cap_channels); 125533c40538SMatthias Ringwald while (btstack_linked_list_iterator_has_next(&it)){ 125633c40538SMatthias Ringwald l2cap_channel_t * channel = (l2cap_channel_t *) btstack_linked_list_iterator_next(&it); 125733c40538SMatthias Ringwald if (!channel->waiting_for_can_send_now) continue; 1258fc64f94aSMatthias Ringwald if (!hci_can_send_acl_packet_now(channel->con_handle)) continue; 125933c40538SMatthias Ringwald channel->waiting_for_can_send_now = 0; 126034e7e577SMatthias Ringwald l2cap_emit_can_send_now(channel->packet_handler, channel->local_cid); 126133c40538SMatthias Ringwald } 126209e9d05bSMatthias Ringwald #endif 126344276248SMatthias Ringwald 12642125de09SMatthias Ringwald int i; 12652125de09SMatthias Ringwald for (i=0;i<L2CAP_FIXED_CHANNEL_TABLE_SIZE;i++){ 1266773c4106SMatthias Ringwald if (!fixed_channels[i].callback) continue; 12672125de09SMatthias Ringwald if (!fixed_channels[i].waiting_for_can_send_now) continue; 126835454696SMatthias Ringwald int can_send = 0; 126934e7e577SMatthias Ringwald if (l2cap_fixed_channel_table_index_is_le(i)){ 127035454696SMatthias Ringwald #ifdef ENABLE_BLE 127134e7e577SMatthias Ringwald can_send = hci_can_send_acl_le_packet_now(); 127235454696SMatthias Ringwald #endif 127334e7e577SMatthias Ringwald } else { 127435454696SMatthias Ringwald #ifdef ENABLE_CLASSIC 127534e7e577SMatthias Ringwald can_send = hci_can_send_acl_classic_packet_now(); 127635454696SMatthias Ringwald #endif 127734e7e577SMatthias Ringwald } 127834e7e577SMatthias Ringwald if (!can_send) continue; 127934e7e577SMatthias Ringwald fixed_channels[i].waiting_for_can_send_now = 0; 128034e7e577SMatthias Ringwald l2cap_emit_can_send_now(fixed_channels[i].callback, l2cap_fixed_channel_table_channel_id_for_index(i)); 12812125de09SMatthias Ringwald } 128233c40538SMatthias Ringwald } 128333c40538SMatthias Ringwald 1284d9a7306aSMatthias Ringwald static void l2cap_hci_event_handler(uint8_t packet_type, uint16_t cid, uint8_t *packet, uint16_t size){ 1285afde0c52Smatthias.ringwald 12869ec2630cSMatthias Ringwald UNUSED(packet_type); 12879ec2630cSMatthias Ringwald UNUSED(cid); 12889ec2630cSMatthias Ringwald UNUSED(size); 12899ec2630cSMatthias Ringwald 1290afde0c52Smatthias.ringwald bd_addr_t address; 1291afde0c52Smatthias.ringwald hci_con_handle_t handle; 12922d00edd4Smatthias.ringwald int hci_con_used; 129309e9d05bSMatthias Ringwald btstack_linked_list_iterator_t it; 129409e9d05bSMatthias Ringwald 129509e9d05bSMatthias Ringwald // avoid unused warnings 1296f3963406SMatthias Ringwald UNUSED(address); 1297f3963406SMatthias Ringwald UNUSED(hci_con_used); 1298f3963406SMatthias Ringwald UNUSED(it); 1299f22209dfSMatthias Ringwald UNUSED(handle); 1300afde0c52Smatthias.ringwald 13010e2df43fSMatthias Ringwald switch(hci_event_packet_get_type(packet)){ 1302afde0c52Smatthias.ringwald 130309e9d05bSMatthias Ringwald // Notify channel packet handler if they can send now 130409e9d05bSMatthias Ringwald case HCI_EVENT_TRANSPORT_PACKET_SENT: 130509e9d05bSMatthias Ringwald case HCI_EVENT_NUMBER_OF_COMPLETED_PACKETS: 130609e9d05bSMatthias Ringwald l2cap_run(); // try sending signaling packets first 130709e9d05bSMatthias Ringwald l2cap_notify_channel_can_send(); 130809e9d05bSMatthias Ringwald break; 130909e9d05bSMatthias Ringwald 131009e9d05bSMatthias Ringwald case HCI_EVENT_COMMAND_STATUS: 131109e9d05bSMatthias Ringwald l2cap_run(); // try sending signaling packets first 131209e9d05bSMatthias Ringwald break; 131309e9d05bSMatthias Ringwald 131409e9d05bSMatthias Ringwald #ifdef ENABLE_CLASSIC 1315afde0c52Smatthias.ringwald // handle connection complete events 1316afde0c52Smatthias.ringwald case HCI_EVENT_CONNECTION_COMPLETE: 1317724d70a2SMatthias Ringwald reverse_bd_addr(&packet[5], address); 1318afde0c52Smatthias.ringwald if (packet[2] == 0){ 1319f8fbdce0SMatthias Ringwald handle = little_endian_read_16(packet, 3); 1320afde0c52Smatthias.ringwald l2cap_handle_connection_success_for_addr(address, handle); 1321afde0c52Smatthias.ringwald } else { 1322afde0c52Smatthias.ringwald l2cap_handle_connection_failed_for_addr(address, packet[2]); 1323afde0c52Smatthias.ringwald } 1324afde0c52Smatthias.ringwald break; 1325afde0c52Smatthias.ringwald 1326afde0c52Smatthias.ringwald // handle successful create connection cancel command 1327afde0c52Smatthias.ringwald case HCI_EVENT_COMMAND_COMPLETE: 1328073bd0faSMatthias Ringwald if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_create_connection_cancel)) { 1329afde0c52Smatthias.ringwald if (packet[5] == 0){ 1330724d70a2SMatthias Ringwald reverse_bd_addr(&packet[6], address); 1331afde0c52Smatthias.ringwald // CONNECTION TERMINATED BY LOCAL HOST (0X16) 1332afde0c52Smatthias.ringwald l2cap_handle_connection_failed_for_addr(address, 0x16); 133303cfbabcSmatthias.ringwald } 13341e6aba47Smatthias.ringwald } 133539d59809Smatthias.ringwald l2cap_run(); // try sending signaling packets first 133639d59809Smatthias.ringwald break; 133709e9d05bSMatthias Ringwald #endif 133827a923d0Smatthias.ringwald 13391e6aba47Smatthias.ringwald // handle disconnection complete events 1340afde0c52Smatthias.ringwald case HCI_EVENT_DISCONNECTION_COMPLETE: 1341c22aecc9S[email protected] // send l2cap disconnect events for all channels on this handle and free them 134209e9d05bSMatthias Ringwald #ifdef ENABLE_CLASSIC 1343d0662982SMatthias Ringwald handle = little_endian_read_16(packet, 3); 1344665d90f2SMatthias Ringwald btstack_linked_list_iterator_init(&it, &l2cap_channels); 1345665d90f2SMatthias Ringwald while (btstack_linked_list_iterator_has_next(&it)){ 1346665d90f2SMatthias Ringwald l2cap_channel_t * channel = (l2cap_channel_t *) btstack_linked_list_iterator_next(&it); 1347fc64f94aSMatthias Ringwald if (channel->con_handle != handle) continue; 134815ec09bbSmatthias.ringwald l2cap_emit_channel_closed(channel); 13499dcb2fb2S[email protected] l2cap_stop_rtx(channel); 1350665d90f2SMatthias Ringwald btstack_linked_list_iterator_remove(&it); 1351d3a9df87Smatthias.ringwald btstack_memory_l2cap_channel_free(channel); 135227a923d0Smatthias.ringwald } 135309e9d05bSMatthias Ringwald #endif 1354a3dc965aSMatthias Ringwald #ifdef ENABLE_LE_DATA_CHANNELS 1355d0662982SMatthias Ringwald handle = little_endian_read_16(packet, 3); 1356991fea48SMatthias Ringwald btstack_linked_list_iterator_init(&it, &l2cap_le_channels); 1357991fea48SMatthias Ringwald while (btstack_linked_list_iterator_has_next(&it)){ 1358991fea48SMatthias Ringwald l2cap_channel_t * channel = (l2cap_channel_t *) btstack_linked_list_iterator_next(&it); 1359991fea48SMatthias Ringwald if (channel->con_handle != handle) continue; 1360991fea48SMatthias Ringwald l2cap_emit_channel_closed(channel); 1361991fea48SMatthias Ringwald btstack_linked_list_iterator_remove(&it); 1362991fea48SMatthias Ringwald btstack_memory_l2cap_channel_free(channel); 1363991fea48SMatthias Ringwald } 1364991fea48SMatthias Ringwald #endif 1365afde0c52Smatthias.ringwald break; 1366fcadd0caSmatthias.ringwald 1367ee091cf1Smatthias.ringwald // HCI Connection Timeouts 136809e9d05bSMatthias Ringwald #ifdef ENABLE_CLASSIC 1369afde0c52Smatthias.ringwald case L2CAP_EVENT_TIMEOUT_CHECK: 1370f8fbdce0SMatthias Ringwald handle = little_endian_read_16(packet, 2); 1371bd04d84aSMatthias Ringwald if (gap_get_connection_type(handle) != GAP_CONNECTION_ACL) break; 137280ca58a0Smatthias.ringwald if (hci_authentication_active_for_handle(handle)) break; 13732d00edd4Smatthias.ringwald hci_con_used = 0; 1374665d90f2SMatthias Ringwald btstack_linked_list_iterator_init(&it, &l2cap_channels); 1375665d90f2SMatthias Ringwald while (btstack_linked_list_iterator_has_next(&it)){ 1376665d90f2SMatthias Ringwald l2cap_channel_t * channel = (l2cap_channel_t *) btstack_linked_list_iterator_next(&it); 1377fc64f94aSMatthias Ringwald if (channel->con_handle != handle) continue; 13782d00edd4Smatthias.ringwald hci_con_used = 1; 1379c22aecc9S[email protected] break; 1380ee091cf1Smatthias.ringwald } 13812d00edd4Smatthias.ringwald if (hci_con_used) break; 1382d94d3cafS[email protected] if (!hci_can_send_command_packet_now()) break; 13839edc8742Smatthias.ringwald hci_send_cmd(&hci_disconnect, handle, 0x13); // remote closed connection 1384afde0c52Smatthias.ringwald break; 1385ee091cf1Smatthias.ringwald 1386df3354fcS[email protected] case HCI_EVENT_READ_REMOTE_SUPPORTED_FEATURES_COMPLETE: 1387f8fbdce0SMatthias Ringwald handle = little_endian_read_16(packet, 3); 1388665d90f2SMatthias Ringwald btstack_linked_list_iterator_init(&it, &l2cap_channels); 1389665d90f2SMatthias Ringwald while (btstack_linked_list_iterator_has_next(&it)){ 1390665d90f2SMatthias Ringwald l2cap_channel_t * channel = (l2cap_channel_t *) btstack_linked_list_iterator_next(&it); 1391fc64f94aSMatthias Ringwald if (channel->con_handle != handle) continue; 13922df5dadcS[email protected] l2cap_handle_remote_supported_features_received(channel); 1393df3354fcS[email protected] break; 1394df3354fcS[email protected] } 1395c22aecc9S[email protected] break; 1396df3354fcS[email protected] 13975611a760SMatthias Ringwald case GAP_EVENT_SECURITY_LEVEL: 1398f8fbdce0SMatthias Ringwald handle = little_endian_read_16(packet, 2); 1399bd63148eS[email protected] log_info("l2cap - security level update"); 1400665d90f2SMatthias Ringwald btstack_linked_list_iterator_init(&it, &l2cap_channels); 1401665d90f2SMatthias Ringwald while (btstack_linked_list_iterator_has_next(&it)){ 1402665d90f2SMatthias Ringwald l2cap_channel_t * channel = (l2cap_channel_t *) btstack_linked_list_iterator_next(&it); 1403fc64f94aSMatthias Ringwald if (channel->con_handle != handle) continue; 14045533f01eS[email protected] 1405bd63148eS[email protected] log_info("l2cap - state %u", channel->state); 1406bd63148eS[email protected] 1407e569dfd9SMatthias Ringwald gap_security_level_t actual_level = (gap_security_level_t) packet[4]; 14085533f01eS[email protected] gap_security_level_t required_level = channel->required_security_level; 14095533f01eS[email protected] 1410df3354fcS[email protected] switch (channel->state){ 1411df3354fcS[email protected] case L2CAP_STATE_WAIT_INCOMING_SECURITY_LEVEL_UPDATE: 14125533f01eS[email protected] if (actual_level >= required_level){ 1413f85a9399S[email protected] channel->state = L2CAP_STATE_WAIT_CLIENT_ACCEPT_OR_REJECT; 141444276248SMatthias Ringwald l2cap_emit_incoming_connection(channel); 14151eb2563eS[email protected] } else { 1416775ecc36SMatthias Ringwald channel->reason = 0x0003; // security block 14171eb2563eS[email protected] channel->state = L2CAP_STATE_WILL_SEND_CONNECTION_RESPONSE_DECLINE; 14181eb2563eS[email protected] } 1419df3354fcS[email protected] break; 1420df3354fcS[email protected] 1421df3354fcS[email protected] case L2CAP_STATE_WAIT_OUTGOING_SECURITY_LEVEL_UPDATE: 14225533f01eS[email protected] if (actual_level >= required_level){ 14231b9cb13dSMatthias Ringwald l2cap_ready_to_connect(channel); 1424df3354fcS[email protected] } else { 1425df3354fcS[email protected] // disconnnect, authentication not good enough 1426df3354fcS[email protected] hci_disconnect_security_block(handle); 1427df3354fcS[email protected] } 1428df3354fcS[email protected] break; 1429df3354fcS[email protected] 1430df3354fcS[email protected] default: 1431df3354fcS[email protected] break; 1432df3354fcS[email protected] } 1433f85a9399S[email protected] } 1434f85a9399S[email protected] break; 143509e9d05bSMatthias Ringwald #endif 1436f85a9399S[email protected] 1437afde0c52Smatthias.ringwald default: 1438afde0c52Smatthias.ringwald break; 1439afde0c52Smatthias.ringwald } 1440afde0c52Smatthias.ringwald 1441bd63148eS[email protected] l2cap_run(); 14421e6aba47Smatthias.ringwald } 14431e6aba47Smatthias.ringwald 1444e74c5f58SMatthias 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){ 14454cf56b4aSmatthias.ringwald // Vol 3, Part A, 4.3: "The DCID and SCID fields shall be ignored when the result field indi- cates the connection was refused." 14462b360848Smatthias.ringwald if (signaling_responses_pending < NR_PENDING_SIGNALING_RESPONSES) { 14472b360848Smatthias.ringwald signaling_responses[signaling_responses_pending].handle = handle; 14482b360848Smatthias.ringwald signaling_responses[signaling_responses_pending].code = code; 14492b360848Smatthias.ringwald signaling_responses[signaling_responses_pending].sig_id = sig_id; 1450e74c5f58SMatthias Ringwald signaling_responses[signaling_responses_pending].cid = cid; 14512b360848Smatthias.ringwald signaling_responses[signaling_responses_pending].data = data; 14522b360848Smatthias.ringwald signaling_responses_pending++; 14532b360848Smatthias.ringwald l2cap_run(); 14542b360848Smatthias.ringwald } 14552b360848Smatthias.ringwald } 14562b360848Smatthias.ringwald 145709e9d05bSMatthias Ringwald #ifdef ENABLE_CLASSIC 145809e9d05bSMatthias Ringwald static void l2cap_handle_disconnect_request(l2cap_channel_t *channel, uint16_t identifier){ 145909e9d05bSMatthias Ringwald channel->remote_sig_id = identifier; 146009e9d05bSMatthias Ringwald channel->state = L2CAP_STATE_WILL_SEND_DISCONNECT_RESPONSE; 146109e9d05bSMatthias Ringwald l2cap_run(); 146209e9d05bSMatthias Ringwald } 146309e9d05bSMatthias Ringwald 1464b35f641cSmatthias.ringwald static void l2cap_handle_connection_request(hci_con_handle_t handle, uint8_t sig_id, uint16_t psm, uint16_t source_cid){ 1465645658c9Smatthias.ringwald 14669da54300S[email protected] // log_info("l2cap_handle_connection_request for handle %u, psm %u cid 0x%02x", handle, psm, source_cid); 1467645658c9Smatthias.ringwald l2cap_service_t *service = l2cap_get_service(psm); 1468645658c9Smatthias.ringwald if (!service) { 1469645658c9Smatthias.ringwald // 0x0002 PSM not supported 1470e74c5f58SMatthias Ringwald l2cap_register_signaling_response(handle, CONNECTION_REQUEST, sig_id, source_cid, 0x0002); 1471645658c9Smatthias.ringwald return; 1472645658c9Smatthias.ringwald } 1473645658c9Smatthias.ringwald 14745061f3afS[email protected] hci_connection_t * hci_connection = hci_connection_for_handle( handle ); 1475645658c9Smatthias.ringwald if (!hci_connection) { 14762b360848Smatthias.ringwald // 14779da54300S[email protected] log_error("no hci_connection for handle %u", handle); 1478645658c9Smatthias.ringwald return; 1479645658c9Smatthias.ringwald } 14802bd8b7e7S[email protected] 1481645658c9Smatthias.ringwald // alloc structure 14829da54300S[email protected] // log_info("l2cap_handle_connection_request register channel"); 1483da144af5SMatthias Ringwald l2cap_channel_t * channel = l2cap_create_channel_entry(service->packet_handler, hci_connection->address, BD_ADDR_TYPE_CLASSIC, 1484da144af5SMatthias Ringwald psm, service->mtu, service->required_security_level); 14852b360848Smatthias.ringwald if (!channel){ 14862b360848Smatthias.ringwald // 0x0004 No resources available 1487e74c5f58SMatthias Ringwald l2cap_register_signaling_response(handle, CONNECTION_REQUEST, sig_id, source_cid, 0x0004); 14882b360848Smatthias.ringwald return; 14892b360848Smatthias.ringwald } 1490da144af5SMatthias Ringwald 1491fc64f94aSMatthias Ringwald channel->con_handle = handle; 1492b35f641cSmatthias.ringwald channel->remote_cid = source_cid; 1493b1988dceSmatthias.ringwald channel->remote_sig_id = sig_id; 1494645658c9Smatthias.ringwald 1495f53da564S[email protected] // limit local mtu to max acl packet length - l2cap header 14962985cb84Smatthias.ringwald if (channel->local_mtu > l2cap_max_mtu()) { 14972985cb84Smatthias.ringwald channel->local_mtu = l2cap_max_mtu(); 14989775e25bSmatthias.ringwald } 14999775e25bSmatthias.ringwald 1500645658c9Smatthias.ringwald // set initial state 1501df3354fcS[email protected] channel->state = L2CAP_STATE_WAIT_INCOMING_SECURITY_LEVEL_UPDATE; 1502a24785d0SMatthias Ringwald channel->state_var = (L2CAP_CHANNEL_STATE_VAR) (L2CAP_CHANNEL_STATE_VAR_SEND_CONN_RESP_PEND | L2CAP_CHANNEL_STATE_VAR_INCOMING); 1503e405ae81Smatthias.ringwald 1504645658c9Smatthias.ringwald // add to connections list 1505665d90f2SMatthias Ringwald btstack_linked_list_add(&l2cap_channels, (btstack_linked_item_t *) channel); 1506645658c9Smatthias.ringwald 1507f85a9399S[email protected] // assert security requirements 15081eb2563eS[email protected] gap_request_security_level(handle, channel->required_security_level); 1509e405ae81Smatthias.ringwald } 1510645658c9Smatthias.ringwald 1511ce8f182eSMatthias Ringwald void l2cap_accept_connection(uint16_t local_cid){ 1512e0abb8e7S[email protected] log_info("L2CAP_ACCEPT_CONNECTION local_cid 0x%x", local_cid); 1513b35f641cSmatthias.ringwald l2cap_channel_t * channel = l2cap_get_channel_for_local_cid(local_cid); 1514e405ae81Smatthias.ringwald if (!channel) { 1515ce8f182eSMatthias Ringwald log_error("l2cap_accept_connection called but local_cid 0x%x not found", local_cid); 1516e405ae81Smatthias.ringwald return; 1517e405ae81Smatthias.ringwald } 1518e405ae81Smatthias.ringwald 151943ec931dSMatthias Ringwald #ifdef ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE 152043ec931dSMatthias Ringwald // configure L2CAP Basic mode 152143ec931dSMatthias Ringwald channel->mode = L2CAP_CHANNEL_MODE_BASIC; 152243ec931dSMatthias Ringwald #endif 152343ec931dSMatthias Ringwald 1524552d92a1Smatthias.ringwald channel->state = L2CAP_STATE_WILL_SEND_CONNECTION_RESPONSE_ACCEPT; 1525e405ae81Smatthias.ringwald 1526552d92a1Smatthias.ringwald // process 1527552d92a1Smatthias.ringwald l2cap_run(); 1528e405ae81Smatthias.ringwald } 1529645658c9Smatthias.ringwald 153043ec931dSMatthias Ringwald 153143ec931dSMatthias Ringwald #ifdef ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE 153245caebe5SMatthias Ringwald void l2cap_accept_ertm_connection(uint16_t local_cid, int ertm_mandatory){ 153343ec931dSMatthias Ringwald log_info("L2CAP_ACCEPT_ERTM_CONNECTION local_cid 0x%x", local_cid); 153443ec931dSMatthias Ringwald l2cap_channel_t * channel = l2cap_get_channel_for_local_cid(local_cid); 153543ec931dSMatthias Ringwald if (!channel) { 153643ec931dSMatthias Ringwald log_error("l2cap_accept_connection called but local_cid 0x%x not found", local_cid); 153743ec931dSMatthias Ringwald return; 153843ec931dSMatthias Ringwald } 153943ec931dSMatthias Ringwald 154043ec931dSMatthias Ringwald // configure L2CAP ERTM 154143ec931dSMatthias Ringwald channel->mode = L2CAP_CHANNEL_MODE_ENHANCED_RETRANSMISSION; 154245caebe5SMatthias Ringwald channel->ertm_mandatory = ertm_mandatory; 154343ec931dSMatthias Ringwald 154443ec931dSMatthias Ringwald channel->state = L2CAP_STATE_WILL_SEND_CONNECTION_RESPONSE_ACCEPT; 154543ec931dSMatthias Ringwald 154643ec931dSMatthias Ringwald // process 154743ec931dSMatthias Ringwald l2cap_run(); 154843ec931dSMatthias Ringwald } 154943ec931dSMatthias Ringwald #endif 155043ec931dSMatthias Ringwald 155143ec931dSMatthias Ringwald 15527ef6a7bbSMatthias Ringwald void l2cap_decline_connection(uint16_t local_cid){ 15537ef6a7bbSMatthias Ringwald log_info("L2CAP_DECLINE_CONNECTION local_cid 0x%x", local_cid); 1554b35f641cSmatthias.ringwald l2cap_channel_t * channel = l2cap_get_channel_for_local_cid( local_cid); 1555e405ae81Smatthias.ringwald if (!channel) { 1556ce8f182eSMatthias Ringwald log_error( "l2cap_decline_connection called but local_cid 0x%x not found", local_cid); 1557e405ae81Smatthias.ringwald return; 1558e405ae81Smatthias.ringwald } 1559e7ff783cSmatthias.ringwald channel->state = L2CAP_STATE_WILL_SEND_CONNECTION_RESPONSE_DECLINE; 15607ef6a7bbSMatthias Ringwald channel->reason = 0x04; // no resources available 1561e7ff783cSmatthias.ringwald l2cap_run(); 1562645658c9Smatthias.ringwald } 1563645658c9Smatthias.ringwald 15647f02f414SMatthias Ringwald static void l2cap_signaling_handle_configure_request(l2cap_channel_t *channel, uint8_t *command){ 1565b1988dceSmatthias.ringwald 1566b1988dceSmatthias.ringwald channel->remote_sig_id = command[L2CAP_SIGNALING_COMMAND_SIGID_OFFSET]; 1567b1988dceSmatthias.ringwald 1568f8fbdce0SMatthias Ringwald uint16_t flags = little_endian_read_16(command, 6); 156963a7246aSmatthias.ringwald if (flags & 1) { 157063a7246aSmatthias.ringwald channelStateVarSetFlag(channel, L2CAP_CHANNEL_STATE_VAR_SEND_CONF_RSP_CONT); 157163a7246aSmatthias.ringwald } 157263a7246aSmatthias.ringwald 15732784b77dSmatthias.ringwald // accept the other's configuration options 1574f8fbdce0SMatthias Ringwald uint16_t end_pos = 4 + little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_LENGTH_OFFSET); 15753de7c0caSmatthias.ringwald uint16_t pos = 8; 15763de7c0caSmatthias.ringwald while (pos < end_pos){ 157763a7246aSmatthias.ringwald uint8_t option_hint = command[pos] >> 7; 157863a7246aSmatthias.ringwald uint8_t option_type = command[pos] & 0x7f; 157963a7246aSmatthias.ringwald log_info("l2cap cid %u, hint %u, type %u", channel->local_cid, option_hint, option_type); 158063a7246aSmatthias.ringwald pos++; 15811dc511deSmatthias.ringwald uint8_t length = command[pos++]; 15821dc511deSmatthias.ringwald // MTU { type(8): 1, len(8):2, MTU(16) } 158363a7246aSmatthias.ringwald if (option_type == 1 && length == 2){ 1584f8fbdce0SMatthias Ringwald channel->remote_mtu = little_endian_read_16(command, pos); 15859d139fbaSMatthias Ringwald if (channel->remote_mtu > l2cap_max_mtu()){ 15869d139fbaSMatthias Ringwald log_info("Remote MTU %u larger than outgoing buffer, only using MTU = %u", channel->remote_mtu, l2cap_max_mtu()); 15879d139fbaSMatthias Ringwald channel->remote_mtu = l2cap_max_mtu(); 15889d139fbaSMatthias Ringwald } 158963a7246aSmatthias.ringwald channelStateVarSetFlag(channel, L2CAP_CHANNEL_STATE_VAR_SEND_CONF_RSP_MTU); 159063a7246aSmatthias.ringwald } 15910fe7a9d0S[email protected] // Flush timeout { type(8):2, len(8): 2, Flush Timeout(16)} 15920fe7a9d0S[email protected] if (option_type == 2 && length == 2){ 1593f8fbdce0SMatthias Ringwald channel->flush_timeout = little_endian_read_16(command, pos); 15940fe7a9d0S[email protected] } 1595f2fa388dSMatthias Ringwald 15966dca2a0cSMatthias Ringwald #ifdef ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE 15976dca2a0cSMatthias Ringwald // Retransmission and Flow Control Option 15986dca2a0cSMatthias Ringwald if (option_type == 4 && length == 9){ 15993232a1c6SMatthias Ringwald if (channel->mode == L2CAP_CHANNEL_MODE_ENHANCED_RETRANSMISSION && channel->ertm_mandatory){ 16003232a1c6SMatthias Ringwald // ertm mandatory, but remote doens't offer ERTM -> disconnect 16013232a1c6SMatthias Ringwald l2cap_channel_mode_t mode = (l2cap_channel_mode_t) command[pos]; 16023232a1c6SMatthias Ringwald if (mode != L2CAP_CHANNEL_MODE_ENHANCED_RETRANSMISSION){ 16033232a1c6SMatthias Ringwald channel->state = L2CAP_STATE_WILL_SEND_DISCONNECT_REQUEST; 16043232a1c6SMatthias Ringwald } 16053232a1c6SMatthias Ringwald } else { 16066dca2a0cSMatthias Ringwald // TODO store and evaluate configuration 16076dca2a0cSMatthias Ringwald channelStateVarSetFlag(channel, L2CAP_CHANNEL_STATE_VAR_SEND_CONF_RSP_MTU); 16086dca2a0cSMatthias Ringwald } 16093232a1c6SMatthias Ringwald } 16106dca2a0cSMatthias Ringwald #endif 161163a7246aSmatthias.ringwald // check for unknown options 161263a7246aSmatthias.ringwald if (option_hint == 0 && (option_type == 0 || option_type >= 0x07)){ 1613c177a91cS[email protected] log_info("l2cap cid %u, unknown options", channel->local_cid); 161463a7246aSmatthias.ringwald channelStateVarSetFlag(channel, L2CAP_CHANNEL_STATE_VAR_SEND_CONF_RSP_INVALID); 16151dc511deSmatthias.ringwald } 16161dc511deSmatthias.ringwald pos += length; 16171dc511deSmatthias.ringwald } 16182784b77dSmatthias.ringwald } 16192784b77dSmatthias.ringwald 1620f2fa388dSMatthias Ringwald static void l2cap_signaling_handle_configure_response(l2cap_channel_t *channel, uint8_t result, uint8_t *command){ 1621f2fa388dSMatthias Ringwald log_info("l2cap_signaling_handle_configure_response"); 16223232a1c6SMatthias Ringwald #ifdef ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE 16233232a1c6SMatthias Ringwald uint16_t end_pos = 4 + little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_LENGTH_OFFSET); 1624f2fa388dSMatthias Ringwald uint16_t pos = 10; 16253232a1c6SMatthias Ringwald while (pos < end_pos){ 16263232a1c6SMatthias Ringwald uint8_t option_hint = command[pos] >> 7; 16273232a1c6SMatthias Ringwald uint8_t option_type = command[pos] & 0x7f; 16283232a1c6SMatthias Ringwald log_info("l2cap cid %u, hint %u, type %u", channel->local_cid, option_hint, option_type); 16293232a1c6SMatthias Ringwald pos++; 16303232a1c6SMatthias Ringwald uint8_t length = command[pos++]; 16313232a1c6SMatthias Ringwald 16323232a1c6SMatthias Ringwald // Retransmission and Flow Control Option 16333232a1c6SMatthias Ringwald if (option_type == 4 && length == 9){ 1634f2fa388dSMatthias Ringwald if (channel->mode == L2CAP_CHANNEL_MODE_ENHANCED_RETRANSMISSION){ 1635f2fa388dSMatthias Ringwald if (channel->ertm_mandatory){ 1636f2fa388dSMatthias Ringwald // 1637f2fa388dSMatthias Ringwald } else { 1638f2fa388dSMatthias Ringwald // On 'Reject - Unacceptable Parameters', fall back to BASIC mode 1639f2fa388dSMatthias Ringwald if (result == 1){ 1640f2fa388dSMatthias Ringwald channel->mode = L2CAP_CHANNEL_MODE_BASIC; 16413232a1c6SMatthias Ringwald } 16423232a1c6SMatthias Ringwald } 16433232a1c6SMatthias Ringwald } 1644f2fa388dSMatthias Ringwald } 16453232a1c6SMatthias Ringwald 16463232a1c6SMatthias Ringwald // check for unknown options 16473232a1c6SMatthias Ringwald if (option_hint == 0 && (option_type == 0 || option_type >= 0x07)){ 16483232a1c6SMatthias Ringwald log_info("l2cap cid %u, unknown options", channel->local_cid); 16493232a1c6SMatthias Ringwald channelStateVarSetFlag(channel, L2CAP_CHANNEL_STATE_VAR_SEND_CONF_RSP_INVALID); 16503232a1c6SMatthias Ringwald } 16513232a1c6SMatthias Ringwald 16523232a1c6SMatthias Ringwald pos += length; 16533232a1c6SMatthias Ringwald } 16543232a1c6SMatthias Ringwald #endif 16553232a1c6SMatthias Ringwald } 16563232a1c6SMatthias Ringwald 1657fa8473a4Smatthias.ringwald static int l2cap_channel_ready_for_open(l2cap_channel_t *channel){ 16589da54300S[email protected] // log_info("l2cap_channel_ready_for_open 0x%02x", channel->state_var); 165973cf2b3dSmatthias.ringwald if ((channel->state_var & L2CAP_CHANNEL_STATE_VAR_RCVD_CONF_RSP) == 0) return 0; 166073cf2b3dSmatthias.ringwald if ((channel->state_var & L2CAP_CHANNEL_STATE_VAR_SENT_CONF_RSP) == 0) return 0; 1661019f9b43SMatthias Ringwald // addition check that fixes re-entrance issue causing l2cap event channel opened twice 1662019f9b43SMatthias Ringwald if (channel->state == L2CAP_STATE_OPEN) return 0; 1663fa8473a4Smatthias.ringwald return 1; 1664fa8473a4Smatthias.ringwald } 1665fa8473a4Smatthias.ringwald 1666fa8473a4Smatthias.ringwald 16677f02f414SMatthias Ringwald static void l2cap_signaling_handler_channel(l2cap_channel_t *channel, uint8_t *command){ 16681e6aba47Smatthias.ringwald 166900d93d79Smatthias.ringwald uint8_t code = command[L2CAP_SIGNALING_COMMAND_CODE_OFFSET]; 167000d93d79Smatthias.ringwald uint8_t identifier = command[L2CAP_SIGNALING_COMMAND_SIGID_OFFSET]; 167138e5900eSmatthias.ringwald uint16_t result = 0; 16721e6aba47Smatthias.ringwald 16739da54300S[email protected] log_info("L2CAP signaling handler code %u, state %u", code, channel->state); 1674b35f641cSmatthias.ringwald 16759a011532Smatthias.ringwald // handle DISCONNECT REQUESTS seperately 16769a011532Smatthias.ringwald if (code == DISCONNECTION_REQUEST){ 16779a011532Smatthias.ringwald switch (channel->state){ 1678fa8473a4Smatthias.ringwald case L2CAP_STATE_CONFIG: 16799a011532Smatthias.ringwald case L2CAP_STATE_OPEN: 16802b83fb7dSmatthias.ringwald case L2CAP_STATE_WILL_SEND_DISCONNECT_REQUEST: 16819a011532Smatthias.ringwald case L2CAP_STATE_WAIT_DISCONNECT: 16829a011532Smatthias.ringwald l2cap_handle_disconnect_request(channel, identifier); 16839a011532Smatthias.ringwald break; 16849a011532Smatthias.ringwald 16859a011532Smatthias.ringwald default: 16869a011532Smatthias.ringwald // ignore in other states 16879a011532Smatthias.ringwald break; 16889a011532Smatthias.ringwald } 16899a011532Smatthias.ringwald return; 16909a011532Smatthias.ringwald } 16919a011532Smatthias.ringwald 169256081214Smatthias.ringwald // @STATEMACHINE(l2cap) 16931e6aba47Smatthias.ringwald switch (channel->state) { 16941e6aba47Smatthias.ringwald 16951e6aba47Smatthias.ringwald case L2CAP_STATE_WAIT_CONNECT_RSP: 16961e6aba47Smatthias.ringwald switch (code){ 16971e6aba47Smatthias.ringwald case CONNECTION_RESPONSE: 16985932bd7cS[email protected] l2cap_stop_rtx(channel); 1699f8fbdce0SMatthias Ringwald result = little_endian_read_16 (command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET+4); 170038e5900eSmatthias.ringwald switch (result) { 170138e5900eSmatthias.ringwald case 0: 1702169f8b28Smatthias.ringwald // successful connection 1703f8fbdce0SMatthias Ringwald channel->remote_cid = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET); 1704fa8473a4Smatthias.ringwald channel->state = L2CAP_STATE_CONFIG; 170528ca2b46S[email protected] channelStateVarSetFlag(channel, L2CAP_CHANNEL_STATE_VAR_SEND_CONF_REQ); 170638e5900eSmatthias.ringwald break; 170738e5900eSmatthias.ringwald case 1: 17085932bd7cS[email protected] // connection pending. get some coffee, but start the ERTX 17095932bd7cS[email protected] l2cap_start_ertx(channel); 171038e5900eSmatthias.ringwald break; 171138e5900eSmatthias.ringwald default: 1712eb920dbeSmatthias.ringwald // channel closed 1713eb920dbeSmatthias.ringwald channel->state = L2CAP_STATE_CLOSED; 1714f32b992eSmatthias.ringwald // map l2cap connection response result to BTstack status enumeration 171538e5900eSmatthias.ringwald l2cap_emit_channel_opened(channel, L2CAP_CONNECTION_RESPONSE_RESULT_SUCCESSFUL + result); 1716eb920dbeSmatthias.ringwald 1717eb920dbeSmatthias.ringwald // drop link key if security block 1718eb920dbeSmatthias.ringwald if (L2CAP_CONNECTION_RESPONSE_RESULT_SUCCESSFUL + result == L2CAP_CONNECTION_RESPONSE_RESULT_REFUSED_SECURITY){ 171915a95bd5SMatthias Ringwald gap_drop_link_key_for_bd_addr(channel->address); 1720eb920dbeSmatthias.ringwald } 1721eb920dbeSmatthias.ringwald 1722eb920dbeSmatthias.ringwald // discard channel 1723665d90f2SMatthias Ringwald btstack_linked_list_remove(&l2cap_channels, (btstack_linked_item_t *) channel); 1724d3a9df87Smatthias.ringwald btstack_memory_l2cap_channel_free(channel); 172538e5900eSmatthias.ringwald break; 17261e6aba47Smatthias.ringwald } 17271e6aba47Smatthias.ringwald break; 172838e5900eSmatthias.ringwald 172938e5900eSmatthias.ringwald default: 17301e6aba47Smatthias.ringwald //@TODO: implement other signaling packets 173138e5900eSmatthias.ringwald break; 17321e6aba47Smatthias.ringwald } 17331e6aba47Smatthias.ringwald break; 17341e6aba47Smatthias.ringwald 1735fa8473a4Smatthias.ringwald case L2CAP_STATE_CONFIG: 1736f8fbdce0SMatthias Ringwald result = little_endian_read_16 (command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET+4); 1737ae280e73Smatthias.ringwald switch (code) { 1738ae280e73Smatthias.ringwald case CONFIGURE_REQUEST: 173928ca2b46S[email protected] channelStateVarSetFlag(channel, L2CAP_CHANNEL_STATE_VAR_SEND_CONF_RSP); 1740ae280e73Smatthias.ringwald l2cap_signaling_handle_configure_request(channel, command); 174163a7246aSmatthias.ringwald if (!(channel->state_var & L2CAP_CHANNEL_STATE_VAR_SEND_CONF_RSP_CONT)){ 174263a7246aSmatthias.ringwald // only done if continuation not set 174363a7246aSmatthias.ringwald channelStateVarSetFlag(channel, L2CAP_CHANNEL_STATE_VAR_RCVD_CONF_REQ); 174463a7246aSmatthias.ringwald } 1745ae280e73Smatthias.ringwald break; 17461e6aba47Smatthias.ringwald case CONFIGURE_RESPONSE: 17475932bd7cS[email protected] l2cap_stop_rtx(channel); 1748f2fa388dSMatthias Ringwald l2cap_signaling_handle_configure_response(channel, result, command); 17495932bd7cS[email protected] switch (result){ 17505932bd7cS[email protected] case 0: // success 17515932bd7cS[email protected] channelStateVarSetFlag(channel, L2CAP_CHANNEL_STATE_VAR_RCVD_CONF_RSP); 17525932bd7cS[email protected] break; 17535932bd7cS[email protected] case 4: // pending 17545932bd7cS[email protected] l2cap_start_ertx(channel); 17555932bd7cS[email protected] break; 17565932bd7cS[email protected] default: 1757a32d6a03SMatthias Ringwald #ifdef ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE 1758a32d6a03SMatthias Ringwald if (channel->mode == L2CAP_CHANNEL_MODE_ENHANCED_RETRANSMISSION && channel->ertm_mandatory){ 1759a32d6a03SMatthias Ringwald // remote does not offer ertm but it's required 1760a32d6a03SMatthias Ringwald channel->state = L2CAP_STATE_WILL_SEND_DISCONNECT_REQUEST; 1761a32d6a03SMatthias Ringwald break; 1762a32d6a03SMatthias Ringwald } 1763a32d6a03SMatthias Ringwald #endif 1764fe9d8984S[email protected] // retry on negative result 1765fe9d8984S[email protected] channelStateVarSetFlag(channel, L2CAP_CHANNEL_STATE_VAR_SEND_CONF_REQ); 1766fe9d8984S[email protected] break; 1767fe9d8984S[email protected] } 17685a67bd4aSmatthias.ringwald break; 17695a67bd4aSmatthias.ringwald default: 17705a67bd4aSmatthias.ringwald break; 17711e6aba47Smatthias.ringwald } 1772fa8473a4Smatthias.ringwald if (l2cap_channel_ready_for_open(channel)){ 1773fa8473a4Smatthias.ringwald // for open: 17745a67bd4aSmatthias.ringwald channel->state = L2CAP_STATE_OPEN; 1775fa8473a4Smatthias.ringwald l2cap_emit_channel_opened(channel, 0); 1776c8e4258aSmatthias.ringwald } 1777c8e4258aSmatthias.ringwald break; 1778f62db1e3Smatthias.ringwald 1779f62db1e3Smatthias.ringwald case L2CAP_STATE_WAIT_DISCONNECT: 1780f62db1e3Smatthias.ringwald switch (code) { 1781f62db1e3Smatthias.ringwald case DISCONNECTION_RESPONSE: 178227a923d0Smatthias.ringwald l2cap_finialize_channel_close(channel); 178327a923d0Smatthias.ringwald break; 17845a67bd4aSmatthias.ringwald default: 17855a67bd4aSmatthias.ringwald //@TODO: implement other signaling packets 17865a67bd4aSmatthias.ringwald break; 178727a923d0Smatthias.ringwald } 178827a923d0Smatthias.ringwald break; 178984836b65Smatthias.ringwald 179084836b65Smatthias.ringwald case L2CAP_STATE_CLOSED: 179184836b65Smatthias.ringwald // @TODO handle incoming requests 179284836b65Smatthias.ringwald break; 179384836b65Smatthias.ringwald 179484836b65Smatthias.ringwald case L2CAP_STATE_OPEN: 179584836b65Smatthias.ringwald //@TODO: implement other signaling packets, e.g. re-configure 179684836b65Smatthias.ringwald break; 179710642e45Smatthias.ringwald default: 179810642e45Smatthias.ringwald break; 179927a923d0Smatthias.ringwald } 18009da54300S[email protected] // log_info("new state %u", channel->state); 180127a923d0Smatthias.ringwald } 180227a923d0Smatthias.ringwald 180300d93d79Smatthias.ringwald 18047f02f414SMatthias Ringwald static void l2cap_signaling_handler_dispatch( hci_con_handle_t handle, uint8_t * command){ 180500d93d79Smatthias.ringwald 18061b9cb13dSMatthias Ringwald btstack_linked_list_iterator_t it; 18071b9cb13dSMatthias Ringwald 180800d93d79Smatthias.ringwald // get code, signalind identifier and command len 180900d93d79Smatthias.ringwald uint8_t code = command[L2CAP_SIGNALING_COMMAND_CODE_OFFSET]; 181000d93d79Smatthias.ringwald uint8_t sig_id = command[L2CAP_SIGNALING_COMMAND_SIGID_OFFSET]; 181100d93d79Smatthias.ringwald 18121b9cb13dSMatthias Ringwald // not for a particular channel, and not CONNECTION_REQUEST, ECHO_[REQUEST|RESPONSE], INFORMATION_RESPONSE 18131b9cb13dSMatthias Ringwald if (code < 1 || code == ECHO_RESPONSE || code > INFORMATION_RESPONSE){ 1814e74c5f58SMatthias Ringwald l2cap_register_signaling_response(handle, COMMAND_REJECT, sig_id, 0, L2CAP_REJ_CMD_UNKNOWN); 181500d93d79Smatthias.ringwald return; 181600d93d79Smatthias.ringwald } 181700d93d79Smatthias.ringwald 181800d93d79Smatthias.ringwald // general commands without an assigned channel 181900d93d79Smatthias.ringwald switch(code) { 182000d93d79Smatthias.ringwald 182100d93d79Smatthias.ringwald case CONNECTION_REQUEST: { 1822f8fbdce0SMatthias Ringwald uint16_t psm = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET); 1823f8fbdce0SMatthias Ringwald uint16_t source_cid = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET+2); 182400d93d79Smatthias.ringwald l2cap_handle_connection_request(handle, sig_id, psm, source_cid); 18252b83fb7dSmatthias.ringwald return; 182600d93d79Smatthias.ringwald } 182700d93d79Smatthias.ringwald 18282b360848Smatthias.ringwald case ECHO_REQUEST: 1829e74c5f58SMatthias Ringwald l2cap_register_signaling_response(handle, code, sig_id, 0, 0); 18302b83fb7dSmatthias.ringwald return; 183100d93d79Smatthias.ringwald 183200d93d79Smatthias.ringwald case INFORMATION_REQUEST: { 1833f8fbdce0SMatthias Ringwald uint16_t infoType = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET); 1834e74c5f58SMatthias Ringwald l2cap_register_signaling_response(handle, code, sig_id, 0, infoType); 18352b83fb7dSmatthias.ringwald return; 183600d93d79Smatthias.ringwald } 183700d93d79Smatthias.ringwald 18381b9cb13dSMatthias Ringwald #ifdef ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE 18391b9cb13dSMatthias Ringwald case INFORMATION_RESPONSE: { 18401b9cb13dSMatthias Ringwald hci_connection_t * connection = hci_connection_for_handle(handle); 18411b9cb13dSMatthias Ringwald if (!connection) return; 18421b9cb13dSMatthias Ringwald uint16_t info_type = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET); 18431b9cb13dSMatthias Ringwald uint16_t result = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET+2); 18441b9cb13dSMatthias Ringwald if (result != 0) return; 1845543b84e4SMatthias Ringwald if (info_type != 0x02) return; 18461b9cb13dSMatthias Ringwald connection->l2cap_state.information_state = L2CAP_INFORMATION_STATE_DONE; 18471b9cb13dSMatthias Ringwald connection->l2cap_state.extended_feature_mask = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET+4); 1848543b84e4SMatthias Ringwald log_info("extended features mask 0x%02x", connection->l2cap_state.extended_feature_mask); 18491b9cb13dSMatthias Ringwald // trigger connection request 18501b9cb13dSMatthias Ringwald btstack_linked_list_iterator_init(&it, &l2cap_channels); 18511b9cb13dSMatthias Ringwald while (btstack_linked_list_iterator_has_next(&it)){ 18521b9cb13dSMatthias Ringwald l2cap_channel_t * channel = (l2cap_channel_t *) btstack_linked_list_iterator_next(&it); 1853543b84e4SMatthias Ringwald if (channel->con_handle != handle) continue; 1854543b84e4SMatthias Ringwald // bail if ERTM was requested but is not supported 1855543b84e4SMatthias Ringwald if ((channel->mode == L2CAP_CHANNEL_MODE_ENHANCED_RETRANSMISSION) && ((connection->l2cap_state.extended_feature_mask & 0x08) == 0)){ 1856f073f086SMatthias Ringwald if (channel->ertm_mandatory){ 1857543b84e4SMatthias Ringwald // channel closed 1858543b84e4SMatthias Ringwald channel->state = L2CAP_STATE_CLOSED; 1859543b84e4SMatthias Ringwald // map l2cap connection response result to BTstack status enumeration 1860543b84e4SMatthias Ringwald l2cap_emit_channel_opened(channel, L2CAP_CONNECTION_RESPONSE_RESULT_ERTM_NOT_SUPPORTD); 1861543b84e4SMatthias Ringwald // discard channel 1862543b84e4SMatthias Ringwald btstack_linked_list_remove(&l2cap_channels, (btstack_linked_item_t *) channel); 1863543b84e4SMatthias Ringwald btstack_memory_l2cap_channel_free(channel); 1864543b84e4SMatthias Ringwald continue; 1865f073f086SMatthias Ringwald } else { 1866f073f086SMatthias Ringwald // fallback to Basic mode 1867f073f086SMatthias Ringwald channel->mode = L2CAP_CHANNEL_MODE_BASIC; 1868f073f086SMatthias Ringwald } 1869543b84e4SMatthias Ringwald } 1870543b84e4SMatthias Ringwald // start connecting 18711b9cb13dSMatthias Ringwald if (channel->state == L2CAP_STATE_WAIT_OUTGOING_EXTENDED_FEATURES){ 18721b9cb13dSMatthias Ringwald channel->state = L2CAP_STATE_WILL_SEND_CONNECTION_REQUEST; 18731b9cb13dSMatthias Ringwald } 18741b9cb13dSMatthias Ringwald } 18751b9cb13dSMatthias Ringwald return; 18761b9cb13dSMatthias Ringwald } 18771b9cb13dSMatthias Ringwald #endif 18781b9cb13dSMatthias Ringwald 187900d93d79Smatthias.ringwald default: 188000d93d79Smatthias.ringwald break; 188100d93d79Smatthias.ringwald } 188200d93d79Smatthias.ringwald 188300d93d79Smatthias.ringwald 188400d93d79Smatthias.ringwald // Get potential destination CID 1885f8fbdce0SMatthias Ringwald uint16_t dest_cid = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET); 188600d93d79Smatthias.ringwald 188700d93d79Smatthias.ringwald // Find channel for this sig_id and connection handle 1888665d90f2SMatthias Ringwald btstack_linked_list_iterator_init(&it, &l2cap_channels); 1889665d90f2SMatthias Ringwald while (btstack_linked_list_iterator_has_next(&it)){ 1890665d90f2SMatthias Ringwald l2cap_channel_t * channel = (l2cap_channel_t *) btstack_linked_list_iterator_next(&it); 1891fc64f94aSMatthias Ringwald if (channel->con_handle != handle) continue; 189200d93d79Smatthias.ringwald if (code & 1) { 1893b1988dceSmatthias.ringwald // match odd commands (responses) by previous signaling identifier 1894b1988dceSmatthias.ringwald if (channel->local_sig_id == sig_id) { 189500d93d79Smatthias.ringwald l2cap_signaling_handler_channel(channel, command); 18964e32727eSmatthias.ringwald break; 189700d93d79Smatthias.ringwald } 189800d93d79Smatthias.ringwald } else { 1899b1988dceSmatthias.ringwald // match even commands (requests) by local channel id 190000d93d79Smatthias.ringwald if (channel->local_cid == dest_cid) { 190100d93d79Smatthias.ringwald l2cap_signaling_handler_channel(channel, command); 19024e32727eSmatthias.ringwald break; 190300d93d79Smatthias.ringwald } 190400d93d79Smatthias.ringwald } 190500d93d79Smatthias.ringwald } 190600d93d79Smatthias.ringwald } 190709e9d05bSMatthias Ringwald #endif 190800d93d79Smatthias.ringwald 1909e7d0c9aaSMatthias Ringwald #ifdef ENABLE_BLE 191009e9d05bSMatthias Ringwald 191109e9d05bSMatthias Ringwald static void l2cap_emit_connection_parameter_update_response(hci_con_handle_t con_handle, uint16_t result){ 191209e9d05bSMatthias Ringwald uint8_t event[6]; 191309e9d05bSMatthias Ringwald event[0] = L2CAP_EVENT_CONNECTION_PARAMETER_UPDATE_RESPONSE; 191409e9d05bSMatthias Ringwald event[1] = 4; 191509e9d05bSMatthias Ringwald little_endian_store_16(event, 2, con_handle); 191609e9d05bSMatthias Ringwald little_endian_store_16(event, 4, result); 191709e9d05bSMatthias Ringwald hci_dump_packet( HCI_EVENT_PACKET, 0, event, sizeof(event)); 191809e9d05bSMatthias Ringwald if (!l2cap_event_packet_handler) return; 191909e9d05bSMatthias Ringwald (*l2cap_event_packet_handler)(HCI_EVENT_PACKET, 0, event, sizeof(event)); 192009e9d05bSMatthias Ringwald } 192109e9d05bSMatthias Ringwald 1922c48b2a2cSMatthias Ringwald // @returns valid 1923c48b2a2cSMatthias Ringwald static int l2cap_le_signaling_handler_dispatch(hci_con_handle_t handle, uint8_t * command, uint8_t sig_id){ 1924e7d0c9aaSMatthias Ringwald hci_connection_t * connection; 1925c48b2a2cSMatthias Ringwald uint16_t result; 1926c48b2a2cSMatthias Ringwald uint8_t event[10]; 192783fd9c76SMatthias Ringwald 1928cab29d48SMatthias Ringwald #ifdef ENABLE_LE_DATA_CHANNELS 1929a3dc965aSMatthias Ringwald btstack_linked_list_iterator_t it; 1930a3dc965aSMatthias Ringwald l2cap_channel_t * channel; 1931a3dc965aSMatthias Ringwald uint16_t local_cid; 193283fd9c76SMatthias Ringwald uint16_t le_psm; 193363f0ac45SMatthias Ringwald uint16_t new_credits; 193463f0ac45SMatthias Ringwald uint16_t credits_before; 1935e7d0c9aaSMatthias Ringwald l2cap_service_t * service; 193611cae19eSMilanka Ringwald uint16_t source_cid; 193783fd9c76SMatthias Ringwald #endif 193800d93d79Smatthias.ringwald 19391b8b8d05SMatthias Ringwald uint8_t code = command[L2CAP_SIGNALING_COMMAND_CODE_OFFSET]; 194023017473SMatthias Ringwald log_info("l2cap_le_signaling_handler_dispatch: command 0x%02x, sig id %u", code, sig_id); 19411b8b8d05SMatthias Ringwald 19421b8b8d05SMatthias Ringwald switch (code){ 194300d93d79Smatthias.ringwald 1944c48b2a2cSMatthias Ringwald case CONNECTION_PARAMETER_UPDATE_RESPONSE: 1945c48b2a2cSMatthias Ringwald result = little_endian_read_16(command, 4); 1946ccf076adS[email protected] l2cap_emit_connection_parameter_update_response(handle, result); 1947ccf076adS[email protected] break; 1948da886c03S[email protected] 1949c48b2a2cSMatthias Ringwald case CONNECTION_PARAMETER_UPDATE_REQUEST: 1950e7d0c9aaSMatthias Ringwald connection = hci_connection_for_handle(handle); 1951da886c03S[email protected] if (connection){ 19526d91fb6cSMatthias Ringwald if (connection->role != HCI_ROLE_MASTER){ 19536d91fb6cSMatthias Ringwald // reject command without notifying upper layer when not in master role 1954c48b2a2cSMatthias Ringwald return 0; 19556d91fb6cSMatthias Ringwald } 1956da886c03S[email protected] int update_parameter = 1; 1957a4c06b28SMatthias Ringwald le_connection_parameter_range_t existing_range; 19584ced4e8cSMatthias Ringwald gap_get_connection_parameter_range(&existing_range); 1959c48b2a2cSMatthias Ringwald uint16_t le_conn_interval_min = little_endian_read_16(command,8); 1960c48b2a2cSMatthias Ringwald uint16_t le_conn_interval_max = little_endian_read_16(command,10); 1961c48b2a2cSMatthias Ringwald uint16_t le_conn_latency = little_endian_read_16(command,12); 1962c48b2a2cSMatthias Ringwald uint16_t le_supervision_timeout = little_endian_read_16(command,14); 1963da886c03S[email protected] 1964da886c03S[email protected] if (le_conn_interval_min < existing_range.le_conn_interval_min) update_parameter = 0; 1965da886c03S[email protected] if (le_conn_interval_max > existing_range.le_conn_interval_max) update_parameter = 0; 1966da886c03S[email protected] 1967da886c03S[email protected] if (le_conn_latency < existing_range.le_conn_latency_min) update_parameter = 0; 1968da886c03S[email protected] if (le_conn_latency > existing_range.le_conn_latency_max) update_parameter = 0; 1969da886c03S[email protected] 1970da886c03S[email protected] if (le_supervision_timeout < existing_range.le_supervision_timeout_min) update_parameter = 0; 1971da886c03S[email protected] if (le_supervision_timeout > existing_range.le_supervision_timeout_max) update_parameter = 0; 1972da886c03S[email protected] 1973da886c03S[email protected] if (update_parameter){ 1974da886c03S[email protected] connection->le_con_parameter_update_state = CON_PARAMETER_UPDATE_SEND_RESPONSE; 1975da886c03S[email protected] connection->le_conn_interval_min = le_conn_interval_min; 1976da886c03S[email protected] connection->le_conn_interval_max = le_conn_interval_max; 1977da886c03S[email protected] connection->le_conn_latency = le_conn_latency; 1978da886c03S[email protected] connection->le_supervision_timeout = le_supervision_timeout; 1979da886c03S[email protected] } else { 1980da886c03S[email protected] connection->le_con_parameter_update_state = CON_PARAMETER_UPDATE_DENY; 1981da886c03S[email protected] } 1982c48b2a2cSMatthias Ringwald connection->le_con_param_update_identifier = sig_id; 1983da886c03S[email protected] } 1984da886c03S[email protected] 198533c40538SMatthias Ringwald if (!l2cap_event_packet_handler) break; 1986c48b2a2cSMatthias Ringwald 1987c48b2a2cSMatthias Ringwald event[0] = L2CAP_EVENT_CONNECTION_PARAMETER_UPDATE_REQUEST; 1988c48b2a2cSMatthias Ringwald event[1] = 8; 1989c48b2a2cSMatthias Ringwald memcpy(&event[2], &command[4], 8); 1990c48b2a2cSMatthias Ringwald hci_dump_packet( HCI_EVENT_PACKET, 0, event, sizeof(event)); 199133c40538SMatthias Ringwald (*l2cap_event_packet_handler)( HCI_EVENT_PACKET, 0, event, sizeof(event)); 1992ccf076adS[email protected] break; 1993c48b2a2cSMatthias Ringwald 1994a3dc965aSMatthias Ringwald #ifdef ENABLE_LE_DATA_CHANNELS 1995a3dc965aSMatthias Ringwald 199663f0ac45SMatthias Ringwald case COMMAND_REJECT: 199763f0ac45SMatthias Ringwald // Find channel for this sig_id and connection handle 199863f0ac45SMatthias Ringwald channel = NULL; 199963f0ac45SMatthias Ringwald btstack_linked_list_iterator_init(&it, &l2cap_le_channels); 200063f0ac45SMatthias Ringwald while (btstack_linked_list_iterator_has_next(&it)){ 200163f0ac45SMatthias Ringwald l2cap_channel_t * a_channel = (l2cap_channel_t *) btstack_linked_list_iterator_next(&it); 200263f0ac45SMatthias Ringwald if (a_channel->con_handle != handle) continue; 200363f0ac45SMatthias Ringwald if (a_channel->local_sig_id != sig_id) continue; 200463f0ac45SMatthias Ringwald channel = a_channel; 200563f0ac45SMatthias Ringwald break; 200663f0ac45SMatthias Ringwald } 200763f0ac45SMatthias Ringwald if (!channel) break; 200863f0ac45SMatthias Ringwald 200963f0ac45SMatthias Ringwald // if received while waiting for le connection response, assume legacy device 201063f0ac45SMatthias Ringwald if (channel->state == L2CAP_STATE_WAIT_LE_CONNECTION_RESPONSE){ 201163f0ac45SMatthias Ringwald channel->state = L2CAP_STATE_CLOSED; 201263f0ac45SMatthias Ringwald // no official value for this, use: Connection refused – LE_PSM not supported - 0x0002 201344276248SMatthias Ringwald l2cap_emit_le_channel_opened(channel, 0x0002); 201463f0ac45SMatthias Ringwald 201563f0ac45SMatthias Ringwald // discard channel 201663f0ac45SMatthias Ringwald btstack_linked_list_remove(&l2cap_le_channels, (btstack_linked_item_t *) channel); 201763f0ac45SMatthias Ringwald btstack_memory_l2cap_channel_free(channel); 201863f0ac45SMatthias Ringwald break; 201963f0ac45SMatthias Ringwald } 202063f0ac45SMatthias Ringwald break; 202163f0ac45SMatthias Ringwald 2022e7d0c9aaSMatthias Ringwald case LE_CREDIT_BASED_CONNECTION_REQUEST: 2023e7d0c9aaSMatthias Ringwald 2024e7d0c9aaSMatthias Ringwald // get hci connection, bail if not found (must not happen) 2025e7d0c9aaSMatthias Ringwald connection = hci_connection_for_handle(handle); 2026e7d0c9aaSMatthias Ringwald if (!connection) return 0; 2027e7d0c9aaSMatthias Ringwald 2028e7d0c9aaSMatthias Ringwald // check if service registered 2029e7d0c9aaSMatthias Ringwald le_psm = little_endian_read_16(command, 4); 2030e7d0c9aaSMatthias Ringwald service = l2cap_le_get_service(le_psm); 203111cae19eSMilanka Ringwald source_cid = little_endian_read_16(command, 6); 2032e7d0c9aaSMatthias Ringwald 2033e7d0c9aaSMatthias Ringwald if (service){ 2034e7d0c9aaSMatthias Ringwald if (source_cid < 0x40){ 2035e7d0c9aaSMatthias Ringwald // 0x0009 Connection refused - Invalid Source CID 2036e74c5f58SMatthias Ringwald l2cap_register_signaling_response(handle, LE_CREDIT_BASED_CONNECTION_REQUEST, sig_id, source_cid, 0x0009); 2037e7d0c9aaSMatthias Ringwald return 1; 2038e7d0c9aaSMatthias Ringwald } 2039e7d0c9aaSMatthias Ringwald 2040e7d0c9aaSMatthias Ringwald // go through list of channels for this ACL connection and check if we get a match 2041e7d0c9aaSMatthias Ringwald btstack_linked_list_iterator_init(&it, &l2cap_le_channels); 2042e7d0c9aaSMatthias Ringwald while (btstack_linked_list_iterator_has_next(&it)){ 20431b8b8d05SMatthias Ringwald l2cap_channel_t * a_channel = (l2cap_channel_t *) btstack_linked_list_iterator_next(&it); 20441b8b8d05SMatthias Ringwald if (a_channel->con_handle != handle) continue; 20451b8b8d05SMatthias Ringwald if (a_channel->remote_cid != source_cid) continue; 2046e7d0c9aaSMatthias Ringwald // 0x000a Connection refused - Source CID already allocated 2047e74c5f58SMatthias Ringwald l2cap_register_signaling_response(handle, LE_CREDIT_BASED_CONNECTION_REQUEST, sig_id, source_cid, 0x000a); 2048e7d0c9aaSMatthias Ringwald return 1; 2049e7d0c9aaSMatthias Ringwald } 2050e7d0c9aaSMatthias Ringwald 205183fd9c76SMatthias Ringwald // security: check encryption 205283fd9c76SMatthias Ringwald if (service->required_security_level >= LEVEL_2){ 205383fd9c76SMatthias Ringwald if (sm_encryption_key_size(handle) == 0){ 205483fd9c76SMatthias Ringwald // 0x0008 Connection refused - insufficient encryption 2055e74c5f58SMatthias Ringwald l2cap_register_signaling_response(handle, LE_CREDIT_BASED_CONNECTION_REQUEST, sig_id, source_cid, 0x0008); 205683fd9c76SMatthias Ringwald return 1; 205783fd9c76SMatthias Ringwald } 205883fd9c76SMatthias Ringwald // anything less than 16 byte key size is insufficient 205983fd9c76SMatthias Ringwald if (sm_encryption_key_size(handle) < 16){ 206083fd9c76SMatthias Ringwald // 0x0007 Connection refused – insufficient encryption key size 2061e74c5f58SMatthias Ringwald l2cap_register_signaling_response(handle, LE_CREDIT_BASED_CONNECTION_REQUEST, sig_id, source_cid, 0x0007); 206283fd9c76SMatthias Ringwald return 1; 206383fd9c76SMatthias Ringwald } 206483fd9c76SMatthias Ringwald } 206583fd9c76SMatthias Ringwald 206683fd9c76SMatthias Ringwald // security: check authencation 206783fd9c76SMatthias Ringwald if (service->required_security_level >= LEVEL_3){ 206883fd9c76SMatthias Ringwald if (!sm_authenticated(handle)){ 206983fd9c76SMatthias Ringwald // 0x0005 Connection refused – insufficient authentication 2070e74c5f58SMatthias Ringwald l2cap_register_signaling_response(handle, LE_CREDIT_BASED_CONNECTION_REQUEST, sig_id, source_cid, 0x0005); 207183fd9c76SMatthias Ringwald return 1; 207283fd9c76SMatthias Ringwald } 207383fd9c76SMatthias Ringwald } 207483fd9c76SMatthias Ringwald 207583fd9c76SMatthias Ringwald // security: check authorization 207683fd9c76SMatthias Ringwald if (service->required_security_level >= LEVEL_4){ 207783fd9c76SMatthias Ringwald if (sm_authorization_state(handle) != AUTHORIZATION_GRANTED){ 207883fd9c76SMatthias Ringwald // 0x0006 Connection refused – insufficient authorization 2079e74c5f58SMatthias Ringwald l2cap_register_signaling_response(handle, LE_CREDIT_BASED_CONNECTION_REQUEST, sig_id, source_cid, 0x0006); 208083fd9c76SMatthias Ringwald return 1; 208183fd9c76SMatthias Ringwald } 208283fd9c76SMatthias Ringwald } 2083e7d0c9aaSMatthias Ringwald 2084e7d0c9aaSMatthias Ringwald // allocate channel 20851b8b8d05SMatthias Ringwald channel = l2cap_create_channel_entry(service->packet_handler, connection->address, 2086e7d0c9aaSMatthias Ringwald BD_ADDR_TYPE_LE_RANDOM, le_psm, service->mtu, service->required_security_level); 2087e7d0c9aaSMatthias Ringwald if (!channel){ 2088e7d0c9aaSMatthias Ringwald // 0x0004 Connection refused – no resources available 2089e74c5f58SMatthias Ringwald l2cap_register_signaling_response(handle, LE_CREDIT_BASED_CONNECTION_REQUEST, sig_id, source_cid, 0x0004); 2090e7d0c9aaSMatthias Ringwald return 1; 2091e7d0c9aaSMatthias Ringwald } 2092e7d0c9aaSMatthias Ringwald 2093e7d0c9aaSMatthias Ringwald channel->con_handle = handle; 2094e7d0c9aaSMatthias Ringwald channel->remote_cid = source_cid; 2095e7d0c9aaSMatthias Ringwald channel->remote_sig_id = sig_id; 20967f107edaSMatthias Ringwald channel->remote_mtu = little_endian_read_16(command, 8); 20977f107edaSMatthias Ringwald channel->remote_mps = little_endian_read_16(command, 10); 20987f107edaSMatthias Ringwald channel->credits_outgoing = little_endian_read_16(command, 12); 2099e7d0c9aaSMatthias Ringwald 2100e7d0c9aaSMatthias Ringwald // set initial state 2101e7d0c9aaSMatthias Ringwald channel->state = L2CAP_STATE_WAIT_CLIENT_ACCEPT_OR_REJECT; 2102c99bb618SMatthias Ringwald channel->state_var |= L2CAP_CHANNEL_STATE_VAR_INCOMING; 2103e7d0c9aaSMatthias Ringwald 2104e7d0c9aaSMatthias Ringwald // add to connections list 2105e7d0c9aaSMatthias Ringwald btstack_linked_list_add(&l2cap_le_channels, (btstack_linked_item_t *) channel); 2106e7d0c9aaSMatthias Ringwald 2107e7d0c9aaSMatthias Ringwald // post connection request event 210844276248SMatthias Ringwald l2cap_emit_le_incoming_connection(channel); 2109e7d0c9aaSMatthias Ringwald 2110e7d0c9aaSMatthias Ringwald } else { 2111e7d0c9aaSMatthias Ringwald // Connection refused – LE_PSM not supported 2112e74c5f58SMatthias Ringwald l2cap_register_signaling_response(handle, LE_CREDIT_BASED_CONNECTION_REQUEST, sig_id, source_cid, 0x0002); 2113e7d0c9aaSMatthias Ringwald } 2114e7d0c9aaSMatthias Ringwald break; 21151b8b8d05SMatthias Ringwald 21161b8b8d05SMatthias Ringwald case LE_CREDIT_BASED_CONNECTION_RESPONSE: 21171b8b8d05SMatthias Ringwald // Find channel for this sig_id and connection handle 21181b8b8d05SMatthias Ringwald channel = NULL; 21191b8b8d05SMatthias Ringwald btstack_linked_list_iterator_init(&it, &l2cap_le_channels); 21201b8b8d05SMatthias Ringwald while (btstack_linked_list_iterator_has_next(&it)){ 21211b8b8d05SMatthias Ringwald l2cap_channel_t * a_channel = (l2cap_channel_t *) btstack_linked_list_iterator_next(&it); 21221b8b8d05SMatthias Ringwald if (a_channel->con_handle != handle) continue; 21231b8b8d05SMatthias Ringwald if (a_channel->local_sig_id != sig_id) continue; 21241b8b8d05SMatthias Ringwald channel = a_channel; 21251b8b8d05SMatthias Ringwald break; 21261b8b8d05SMatthias Ringwald } 21271b8b8d05SMatthias Ringwald if (!channel) break; 21281b8b8d05SMatthias Ringwald 21291b8b8d05SMatthias Ringwald // cid + 0 21301b8b8d05SMatthias Ringwald result = little_endian_read_16 (command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET+8); 21311b8b8d05SMatthias Ringwald if (result){ 21321b8b8d05SMatthias Ringwald channel->state = L2CAP_STATE_CLOSED; 21331b8b8d05SMatthias Ringwald // map l2cap connection response result to BTstack status enumeration 213444276248SMatthias Ringwald l2cap_emit_le_channel_opened(channel, result); 21351b8b8d05SMatthias Ringwald 21361b8b8d05SMatthias Ringwald // discard channel 213763f0ac45SMatthias Ringwald btstack_linked_list_remove(&l2cap_le_channels, (btstack_linked_item_t *) channel); 21381b8b8d05SMatthias Ringwald btstack_memory_l2cap_channel_free(channel); 21391b8b8d05SMatthias Ringwald break; 21401b8b8d05SMatthias Ringwald } 21411b8b8d05SMatthias Ringwald 21421b8b8d05SMatthias Ringwald // success 21431b8b8d05SMatthias Ringwald channel->remote_cid = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET + 0); 21441b8b8d05SMatthias Ringwald channel->remote_mtu = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET + 2); 21451b8b8d05SMatthias Ringwald channel->remote_mps = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET + 4); 21461b8b8d05SMatthias Ringwald channel->credits_outgoing = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET + 6); 21471b8b8d05SMatthias Ringwald channel->state = L2CAP_STATE_OPEN; 214844276248SMatthias Ringwald l2cap_emit_le_channel_opened(channel, result); 21491b8b8d05SMatthias Ringwald break; 21501b8b8d05SMatthias Ringwald 215185aeef60SMatthias Ringwald case LE_FLOW_CONTROL_CREDIT: 215285aeef60SMatthias Ringwald // find channel 215385aeef60SMatthias Ringwald local_cid = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET + 0); 215485aeef60SMatthias Ringwald channel = l2cap_le_get_channel_for_local_cid(local_cid); 215563f0ac45SMatthias Ringwald if (!channel) { 215663f0ac45SMatthias Ringwald log_error("l2cap: no channel for cid 0x%02x", local_cid); 215763f0ac45SMatthias Ringwald break; 215863f0ac45SMatthias Ringwald } 215963f0ac45SMatthias Ringwald new_credits = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET + 2); 216063f0ac45SMatthias Ringwald credits_before = channel->credits_outgoing; 216163f0ac45SMatthias Ringwald channel->credits_outgoing += new_credits; 216263f0ac45SMatthias Ringwald // check for credit overrun 216363f0ac45SMatthias Ringwald if (credits_before > channel->credits_outgoing){ 216463f0ac45SMatthias Ringwald log_error("l2cap: new credits caused overrrun for cid 0x%02x, disconnecting", local_cid); 216563f0ac45SMatthias Ringwald channel->state = L2CAP_STATE_WILL_SEND_DISCONNECT_REQUEST; 216663f0ac45SMatthias Ringwald break; 216763f0ac45SMatthias Ringwald } 216863f0ac45SMatthias Ringwald log_info("l2cap: %u credits for 0x%02x, now %u", new_credits, local_cid, channel->credits_outgoing); 216985aeef60SMatthias Ringwald break; 217085aeef60SMatthias Ringwald 2171828a7f7aSMatthias Ringwald case DISCONNECTION_REQUEST: 2172828a7f7aSMatthias Ringwald // find channel 2173828a7f7aSMatthias Ringwald local_cid = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET + 0); 2174828a7f7aSMatthias Ringwald channel = l2cap_le_get_channel_for_local_cid(local_cid); 217563f34e00SMatthias Ringwald if (!channel) { 217663f34e00SMatthias Ringwald log_error("l2cap: no channel for cid 0x%02x", local_cid); 217763f34e00SMatthias Ringwald break; 217863f34e00SMatthias Ringwald } 2179828a7f7aSMatthias Ringwald channel->remote_sig_id = sig_id; 2180828a7f7aSMatthias Ringwald channel->state = L2CAP_STATE_WILL_SEND_DISCONNECT_RESPONSE; 2181828a7f7aSMatthias Ringwald break; 2182828a7f7aSMatthias Ringwald 2183a3dc965aSMatthias Ringwald #endif 2184a3dc965aSMatthias Ringwald 218563f0ac45SMatthias Ringwald case DISCONNECTION_RESPONSE: 218663f0ac45SMatthias Ringwald break; 218763f0ac45SMatthias Ringwald 2188c48b2a2cSMatthias Ringwald default: 2189c48b2a2cSMatthias Ringwald // command unknown -> reject command 2190c48b2a2cSMatthias Ringwald return 0; 2191ccf076adS[email protected] } 2192c48b2a2cSMatthias Ringwald return 1; 2193c48b2a2cSMatthias Ringwald } 2194e7d0c9aaSMatthias Ringwald #endif 2195c48b2a2cSMatthias Ringwald 2196c48b2a2cSMatthias Ringwald static void l2cap_acl_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size ){ 21979ec2630cSMatthias Ringwald UNUSED(packet_type); 21989ec2630cSMatthias Ringwald UNUSED(channel); 2199c48b2a2cSMatthias Ringwald 220009e9d05bSMatthias Ringwald l2cap_channel_t * l2cap_channel; 2201f3963406SMatthias Ringwald UNUSED(l2cap_channel); 220209e9d05bSMatthias Ringwald 2203c48b2a2cSMatthias Ringwald // Get Channel ID 2204c48b2a2cSMatthias Ringwald uint16_t channel_id = READ_L2CAP_CHANNEL_ID(packet); 2205c48b2a2cSMatthias Ringwald hci_con_handle_t handle = READ_ACL_CONNECTION_HANDLE(packet); 2206c48b2a2cSMatthias Ringwald 2207c48b2a2cSMatthias Ringwald switch (channel_id) { 2208c48b2a2cSMatthias Ringwald 220909e9d05bSMatthias Ringwald #ifdef ENABLE_CLASSIC 2210c48b2a2cSMatthias Ringwald case L2CAP_CID_SIGNALING: { 2211c48b2a2cSMatthias Ringwald uint16_t command_offset = 8; 2212c48b2a2cSMatthias Ringwald while (command_offset < size) { 2213c48b2a2cSMatthias Ringwald // handle signaling commands 2214c48b2a2cSMatthias Ringwald l2cap_signaling_handler_dispatch(handle, &packet[command_offset]); 2215c48b2a2cSMatthias Ringwald 2216c48b2a2cSMatthias Ringwald // increment command_offset 2217c48b2a2cSMatthias Ringwald command_offset += L2CAP_SIGNALING_COMMAND_DATA_OFFSET + little_endian_read_16(packet, command_offset + L2CAP_SIGNALING_COMMAND_LENGTH_OFFSET); 2218c48b2a2cSMatthias Ringwald } 2219c48b2a2cSMatthias Ringwald break; 2220c48b2a2cSMatthias Ringwald } 222109e9d05bSMatthias Ringwald #endif 2222c48b2a2cSMatthias Ringwald 2223e7d0c9aaSMatthias Ringwald #ifdef ENABLE_BLE 2224e7d0c9aaSMatthias Ringwald case L2CAP_CID_SIGNALING_LE: { 2225e7d0c9aaSMatthias Ringwald uint16_t sig_id = packet[COMPLETE_L2CAP_HEADER + 1]; 2226e7d0c9aaSMatthias Ringwald int valid = l2cap_le_signaling_handler_dispatch(handle, &packet[COMPLETE_L2CAP_HEADER], sig_id); 2227c48b2a2cSMatthias Ringwald if (!valid){ 2228e74c5f58SMatthias Ringwald l2cap_register_signaling_response(handle, COMMAND_REJECT_LE, sig_id, 0, L2CAP_REJ_CMD_UNKNOWN); 2229ccf076adS[email protected] } 2230ccf076adS[email protected] break; 2231e7d0c9aaSMatthias Ringwald } 2232e7d0c9aaSMatthias Ringwald #endif 2233c48b2a2cSMatthias Ringwald 2234c48b2a2cSMatthias Ringwald case L2CAP_CID_ATTRIBUTE_PROTOCOL: 2235c48b2a2cSMatthias Ringwald if (fixed_channels[L2CAP_FIXED_CHANNEL_TABLE_INDEX_ATTRIBUTE_PROTOCOL].callback) { 2236c48b2a2cSMatthias Ringwald (*fixed_channels[L2CAP_FIXED_CHANNEL_TABLE_INDEX_ATTRIBUTE_PROTOCOL].callback)(ATT_DATA_PACKET, handle, &packet[COMPLETE_L2CAP_HEADER], size-COMPLETE_L2CAP_HEADER); 2237ccf076adS[email protected] } 2238c48b2a2cSMatthias Ringwald break; 2239c48b2a2cSMatthias Ringwald 2240c48b2a2cSMatthias Ringwald case L2CAP_CID_SECURITY_MANAGER_PROTOCOL: 2241c48b2a2cSMatthias Ringwald if (fixed_channels[L2CAP_FIXED_CHANNEL_TABLE_INDEX_SECURITY_MANAGER_PROTOCOL].callback) { 2242c48b2a2cSMatthias Ringwald (*fixed_channels[L2CAP_FIXED_CHANNEL_TABLE_INDEX_SECURITY_MANAGER_PROTOCOL].callback)(SM_DATA_PACKET, handle, &packet[COMPLETE_L2CAP_HEADER], size-COMPLETE_L2CAP_HEADER); 2243c48b2a2cSMatthias Ringwald } 2244c48b2a2cSMatthias Ringwald break; 2245c48b2a2cSMatthias Ringwald 2246c48b2a2cSMatthias Ringwald case L2CAP_CID_CONNECTIONLESS_CHANNEL: 2247c48b2a2cSMatthias Ringwald if (fixed_channels[L2CAP_FIXED_CHANNEL_TABLE_INDEX_CONNECTIONLESS_CHANNEL].callback) { 2248c48b2a2cSMatthias Ringwald (*fixed_channels[L2CAP_FIXED_CHANNEL_TABLE_INDEX_CONNECTIONLESS_CHANNEL].callback)(UCD_DATA_PACKET, handle, &packet[COMPLETE_L2CAP_HEADER], size-COMPLETE_L2CAP_HEADER); 2249c48b2a2cSMatthias Ringwald } 2250c48b2a2cSMatthias Ringwald break; 22511bbc0b23S[email protected] 225209e9d05bSMatthias Ringwald default: 225309e9d05bSMatthias Ringwald #ifdef ENABLE_CLASSIC 225400d93d79Smatthias.ringwald // Find channel for this channel_id and connection handle 225564e11ca9SMatthias Ringwald l2cap_channel = l2cap_get_channel_for_local_cid(channel_id); 2256d1fd2a88SMatthias Ringwald if (l2cap_channel) { 22573d50b4baSMatthias Ringwald l2cap_dispatch_to_channel(l2cap_channel, L2CAP_DATA_PACKET, &packet[COMPLETE_L2CAP_HEADER], size-COMPLETE_L2CAP_HEADER); 225800d93d79Smatthias.ringwald } 225909e9d05bSMatthias Ringwald #endif 2260a3dc965aSMatthias Ringwald #ifdef ENABLE_LE_DATA_CHANNELS 226164e11ca9SMatthias Ringwald l2cap_channel = l2cap_le_get_channel_for_local_cid(channel_id); 226264e11ca9SMatthias Ringwald if (l2cap_channel) { 226385aeef60SMatthias Ringwald // credit counting 226485aeef60SMatthias Ringwald if (l2cap_channel->credits_incoming == 0){ 226585aeef60SMatthias Ringwald log_error("LE Data Channel packet received but no incoming credits"); 226685aeef60SMatthias Ringwald l2cap_channel->state = L2CAP_STATE_WILL_SEND_DISCONNECT_REQUEST; 226785aeef60SMatthias Ringwald break; 226885aeef60SMatthias Ringwald } 226985aeef60SMatthias Ringwald l2cap_channel->credits_incoming--; 227085aeef60SMatthias Ringwald 227185aeef60SMatthias Ringwald // automatic credits 227285aeef60SMatthias Ringwald if (l2cap_channel->credits_incoming < L2CAP_LE_DATA_CHANNELS_AUTOMATIC_CREDITS_WATERMARK && l2cap_channel->automatic_credits){ 227385aeef60SMatthias Ringwald l2cap_channel->new_credits_incoming = L2CAP_LE_DATA_CHANNELS_AUTOMATIC_CREDITS_INCREMENT; 227485aeef60SMatthias Ringwald } 227585aeef60SMatthias Ringwald 2276cd529728SMatthias Ringwald // first fragment 2277cd529728SMatthias Ringwald uint16_t pos = 0; 2278cd529728SMatthias Ringwald if (!l2cap_channel->receive_sdu_len){ 2279cd529728SMatthias Ringwald l2cap_channel->receive_sdu_len = little_endian_read_16(packet, COMPLETE_L2CAP_HEADER); 2280cd529728SMatthias Ringwald l2cap_channel->receive_sdu_pos = 0; 2281cd529728SMatthias Ringwald pos += 2; 2282cd529728SMatthias Ringwald size -= 2; 2283cd529728SMatthias Ringwald } 2284cd529728SMatthias Ringwald memcpy(&l2cap_channel->receive_sdu_buffer[l2cap_channel->receive_sdu_pos], &packet[COMPLETE_L2CAP_HEADER+pos], size-COMPLETE_L2CAP_HEADER); 2285cd529728SMatthias Ringwald l2cap_channel->receive_sdu_pos += size - COMPLETE_L2CAP_HEADER; 2286cd529728SMatthias Ringwald // done? 228763f0ac45SMatthias Ringwald log_info("le packet pos %u, len %u", l2cap_channel->receive_sdu_pos, l2cap_channel->receive_sdu_len); 2288cd529728SMatthias Ringwald if (l2cap_channel->receive_sdu_pos >= l2cap_channel->receive_sdu_len){ 2289cd529728SMatthias Ringwald l2cap_dispatch_to_channel(l2cap_channel, L2CAP_DATA_PACKET, l2cap_channel->receive_sdu_buffer, l2cap_channel->receive_sdu_len); 2290cd529728SMatthias Ringwald l2cap_channel->receive_sdu_len = 0; 2291cd529728SMatthias Ringwald } 229263f0ac45SMatthias Ringwald } else { 229363f0ac45SMatthias Ringwald log_error("LE Data Channel packet received but no channel found for cid 0x%02x", channel_id); 229464e11ca9SMatthias Ringwald } 229564e11ca9SMatthias Ringwald #endif 22965652b5ffS[email protected] break; 22975652b5ffS[email protected] } 229800d93d79Smatthias.ringwald 22991eb2563eS[email protected] l2cap_run(); 23002718e2e7Smatthias.ringwald } 230100d93d79Smatthias.ringwald 230209e9d05bSMatthias Ringwald // Bluetooth 4.0 - allows to register handler for Attribute Protocol and Security Manager Protocol 230309e9d05bSMatthias Ringwald void l2cap_register_fixed_channel(btstack_packet_handler_t the_packet_handler, uint16_t channel_id) { 230409e9d05bSMatthias Ringwald int index = l2cap_fixed_channel_table_index_for_channel_id(channel_id); 230509e9d05bSMatthias Ringwald if (index < 0) return; 230609e9d05bSMatthias Ringwald fixed_channels[index].callback = the_packet_handler; 230709e9d05bSMatthias Ringwald } 230809e9d05bSMatthias Ringwald 230909e9d05bSMatthias Ringwald #ifdef ENABLE_CLASSIC 231015ec09bbSmatthias.ringwald // finalize closed channel - l2cap_handle_disconnect_request & DISCONNECTION_RESPONSE 231127a923d0Smatthias.ringwald void l2cap_finialize_channel_close(l2cap_channel_t * channel){ 2312f62db1e3Smatthias.ringwald channel->state = L2CAP_STATE_CLOSED; 2313f62db1e3Smatthias.ringwald l2cap_emit_channel_closed(channel); 2314f62db1e3Smatthias.ringwald // discard channel 23159dcb2fb2S[email protected] l2cap_stop_rtx(channel); 2316665d90f2SMatthias Ringwald btstack_linked_list_remove(&l2cap_channels, (btstack_linked_item_t *) channel); 2317d3a9df87Smatthias.ringwald btstack_memory_l2cap_channel_free(channel); 2318c8e4258aSmatthias.ringwald } 23191e6aba47Smatthias.ringwald 23208f2a52f4SMatthias Ringwald static l2cap_service_t * l2cap_get_service_internal(btstack_linked_list_t * services, uint16_t psm){ 2321665d90f2SMatthias Ringwald btstack_linked_list_iterator_t it; 2322665d90f2SMatthias Ringwald btstack_linked_list_iterator_init(&it, services); 2323665d90f2SMatthias Ringwald while (btstack_linked_list_iterator_has_next(&it)){ 2324665d90f2SMatthias Ringwald l2cap_service_t * service = (l2cap_service_t *) btstack_linked_list_iterator_next(&it); 23259d9bbc01Smatthias.ringwald if ( service->psm == psm){ 23269d9bbc01Smatthias.ringwald return service; 23279d9bbc01Smatthias.ringwald }; 23289d9bbc01Smatthias.ringwald } 23299d9bbc01Smatthias.ringwald return NULL; 23309d9bbc01Smatthias.ringwald } 23319d9bbc01Smatthias.ringwald 23327192e786SMatthias Ringwald static inline l2cap_service_t * l2cap_get_service(uint16_t psm){ 23337192e786SMatthias Ringwald return l2cap_get_service_internal(&l2cap_services, psm); 23347192e786SMatthias Ringwald } 23357192e786SMatthias Ringwald 2336e0abb8e7S[email protected] 2337be2053a6SMatthias 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){ 2338be2053a6SMatthias Ringwald 2339be2053a6SMatthias Ringwald log_info("L2CAP_REGISTER_SERVICE psm 0x%x mtu %u", psm, mtu); 2340e0abb8e7S[email protected] 23414bb582b6Smatthias.ringwald // check for alread registered psm 23429d9bbc01Smatthias.ringwald l2cap_service_t *service = l2cap_get_service(psm); 2343277abc2cSmatthias.ringwald if (service) { 2344be2053a6SMatthias Ringwald log_error("l2cap_register_service: PSM %u already registered", psm); 2345be2053a6SMatthias Ringwald return L2CAP_SERVICE_ALREADY_REGISTERED; 2346277abc2cSmatthias.ringwald } 23479d9bbc01Smatthias.ringwald 23484bb582b6Smatthias.ringwald // alloc structure 2349bb69aaaeS[email protected] service = btstack_memory_l2cap_service_get(); 2350277abc2cSmatthias.ringwald if (!service) { 2351be2053a6SMatthias Ringwald log_error("l2cap_register_service: no memory for l2cap_service_t"); 2352be2053a6SMatthias Ringwald return BTSTACK_MEMORY_ALLOC_FAILED; 2353277abc2cSmatthias.ringwald } 23549d9bbc01Smatthias.ringwald 23559d9bbc01Smatthias.ringwald // fill in 23569d9bbc01Smatthias.ringwald service->psm = psm; 23579d9bbc01Smatthias.ringwald service->mtu = mtu; 235805ae8de3SMatthias Ringwald service->packet_handler = service_packet_handler; 2359df3354fcS[email protected] service->required_security_level = security_level; 23609d9bbc01Smatthias.ringwald 23619d9bbc01Smatthias.ringwald // add to services list 2362665d90f2SMatthias Ringwald btstack_linked_list_add(&l2cap_services, (btstack_linked_item_t *) service); 2363c0e866bfSmatthias.ringwald 2364c0e866bfSmatthias.ringwald // enable page scan 236515a95bd5SMatthias Ringwald gap_connectable_control(1); 23665842b6d9Smatthias.ringwald 2367be2053a6SMatthias Ringwald return 0; 23689d9bbc01Smatthias.ringwald } 23699d9bbc01Smatthias.ringwald 23707e8856ebSMatthias Ringwald uint8_t l2cap_unregister_service(uint16_t psm){ 2371e0abb8e7S[email protected] 2372e0abb8e7S[email protected] log_info("L2CAP_UNREGISTER_SERVICE psm 0x%x", psm); 2373e0abb8e7S[email protected] 23749d9bbc01Smatthias.ringwald l2cap_service_t *service = l2cap_get_service(psm); 23757e8856ebSMatthias Ringwald if (!service) return L2CAP_SERVICE_DOES_NOT_EXIST; 2376665d90f2SMatthias Ringwald btstack_linked_list_remove(&l2cap_services, (btstack_linked_item_t *) service); 2377d3a9df87Smatthias.ringwald btstack_memory_l2cap_service_free(service); 2378c0e866bfSmatthias.ringwald 2379c0e866bfSmatthias.ringwald // disable page scan when no services registered 23807e8856ebSMatthias Ringwald if (btstack_linked_list_empty(&l2cap_services)) { 238115a95bd5SMatthias Ringwald gap_connectable_control(0); 23829d9bbc01Smatthias.ringwald } 23837e8856ebSMatthias Ringwald return 0; 23847e8856ebSMatthias Ringwald } 238509e9d05bSMatthias Ringwald #endif 23869d9bbc01Smatthias.ringwald 23877192e786SMatthias Ringwald 2388cab29d48SMatthias Ringwald #ifdef ENABLE_LE_DATA_CHANNELS 238983fd9c76SMatthias Ringwald 239057be49d6SMatthias Ringwald static void l2cap_le_notify_channel_can_send(l2cap_channel_t *channel){ 239157be49d6SMatthias Ringwald if (!channel->waiting_for_can_send_now) return; 239257be49d6SMatthias Ringwald if (channel->send_sdu_buffer) return; 239357be49d6SMatthias Ringwald channel->waiting_for_can_send_now = 0; 239457be49d6SMatthias Ringwald log_info("L2CAP_EVENT_CHANNEL_LE_CAN_SEND_NOW local_cid 0x%x", channel->local_cid); 239557be49d6SMatthias Ringwald l2cap_emit_simple_event_with_cid(channel, L2CAP_EVENT_LE_CAN_SEND_NOW); 239657be49d6SMatthias Ringwald } 239757be49d6SMatthias Ringwald 239857be49d6SMatthias Ringwald // 1BH2222 239957be49d6SMatthias Ringwald static void l2cap_emit_le_incoming_connection(l2cap_channel_t *channel) { 240057be49d6SMatthias Ringwald log_info("L2CAP_EVENT_LE_INCOMING_CONNECTION addr_type %u, addr %s handle 0x%x psm 0x%x local_cid 0x%x remote_cid 0x%x, remote_mtu %u", 240157be49d6SMatthias Ringwald channel->address_type, bd_addr_to_str(channel->address), channel->con_handle, channel->psm, channel->local_cid, channel->remote_cid, channel->remote_mtu); 240257be49d6SMatthias Ringwald uint8_t event[19]; 240357be49d6SMatthias Ringwald event[0] = L2CAP_EVENT_LE_INCOMING_CONNECTION; 240457be49d6SMatthias Ringwald event[1] = sizeof(event) - 2; 240557be49d6SMatthias Ringwald event[2] = channel->address_type; 240657be49d6SMatthias Ringwald reverse_bd_addr(channel->address, &event[3]); 240757be49d6SMatthias Ringwald little_endian_store_16(event, 9, channel->con_handle); 240857be49d6SMatthias Ringwald little_endian_store_16(event, 11, channel->psm); 240957be49d6SMatthias Ringwald little_endian_store_16(event, 13, channel->local_cid); 241057be49d6SMatthias Ringwald little_endian_store_16(event, 15, channel->remote_cid); 241157be49d6SMatthias Ringwald little_endian_store_16(event, 17, channel->remote_mtu); 241257be49d6SMatthias Ringwald hci_dump_packet( HCI_EVENT_PACKET, 0, event, sizeof(event)); 241357be49d6SMatthias Ringwald l2cap_dispatch_to_channel(channel, HCI_EVENT_PACKET, event, sizeof(event)); 241457be49d6SMatthias Ringwald } 241557be49d6SMatthias Ringwald // 11BH22222 241657be49d6SMatthias Ringwald static void l2cap_emit_le_channel_opened(l2cap_channel_t *channel, uint8_t status) { 241757be49d6SMatthias Ringwald log_info("L2CAP_EVENT_LE_CHANNEL_OPENED 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", 241857be49d6SMatthias Ringwald status, channel->address_type, bd_addr_to_str(channel->address), channel->con_handle, channel->psm, 241957be49d6SMatthias Ringwald channel->local_cid, channel->remote_cid, channel->local_mtu, channel->remote_mtu); 2420c99bb618SMatthias Ringwald uint8_t event[23]; 242157be49d6SMatthias Ringwald event[0] = L2CAP_EVENT_LE_CHANNEL_OPENED; 242257be49d6SMatthias Ringwald event[1] = sizeof(event) - 2; 242357be49d6SMatthias Ringwald event[2] = status; 242457be49d6SMatthias Ringwald event[3] = channel->address_type; 242557be49d6SMatthias Ringwald reverse_bd_addr(channel->address, &event[4]); 242657be49d6SMatthias Ringwald little_endian_store_16(event, 10, channel->con_handle); 2427c99bb618SMatthias Ringwald event[12] = channel->state_var & L2CAP_CHANNEL_STATE_VAR_INCOMING ? 1 : 0; 2428c99bb618SMatthias Ringwald little_endian_store_16(event, 13, channel->psm); 2429c99bb618SMatthias Ringwald little_endian_store_16(event, 15, channel->local_cid); 2430c99bb618SMatthias Ringwald little_endian_store_16(event, 17, channel->remote_cid); 2431c99bb618SMatthias Ringwald little_endian_store_16(event, 19, channel->local_mtu); 2432c99bb618SMatthias Ringwald little_endian_store_16(event, 21, channel->remote_mtu); 243357be49d6SMatthias Ringwald hci_dump_packet( HCI_EVENT_PACKET, 0, event, sizeof(event)); 243457be49d6SMatthias Ringwald l2cap_dispatch_to_channel(channel, HCI_EVENT_PACKET, event, sizeof(event)); 243557be49d6SMatthias Ringwald } 243657be49d6SMatthias Ringwald 243757be49d6SMatthias Ringwald static l2cap_channel_t * l2cap_le_get_channel_for_local_cid(uint16_t local_cid){ 243857be49d6SMatthias Ringwald btstack_linked_list_iterator_t it; 243957be49d6SMatthias Ringwald btstack_linked_list_iterator_init(&it, &l2cap_le_channels); 244057be49d6SMatthias Ringwald while (btstack_linked_list_iterator_has_next(&it)){ 244157be49d6SMatthias Ringwald l2cap_channel_t * channel = (l2cap_channel_t *) btstack_linked_list_iterator_next(&it); 244257be49d6SMatthias Ringwald if ( channel->local_cid == local_cid) { 244357be49d6SMatthias Ringwald return channel; 244457be49d6SMatthias Ringwald } 244557be49d6SMatthias Ringwald } 244657be49d6SMatthias Ringwald return NULL; 244757be49d6SMatthias Ringwald } 244857be49d6SMatthias Ringwald 244957be49d6SMatthias Ringwald // finalize closed channel - l2cap_handle_disconnect_request & DISCONNECTION_RESPONSE 245057be49d6SMatthias Ringwald void l2cap_le_finialize_channel_close(l2cap_channel_t * channel){ 245157be49d6SMatthias Ringwald channel->state = L2CAP_STATE_CLOSED; 245257be49d6SMatthias Ringwald l2cap_emit_simple_event_with_cid(channel, L2CAP_EVENT_CHANNEL_CLOSED); 245357be49d6SMatthias Ringwald // discard channel 245457be49d6SMatthias Ringwald btstack_linked_list_remove(&l2cap_le_channels, (btstack_linked_item_t *) channel); 245557be49d6SMatthias Ringwald btstack_memory_l2cap_channel_free(channel); 245657be49d6SMatthias Ringwald } 245757be49d6SMatthias Ringwald 2458e7d0c9aaSMatthias Ringwald static inline l2cap_service_t * l2cap_le_get_service(uint16_t le_psm){ 2459e7d0c9aaSMatthias Ringwald return l2cap_get_service_internal(&l2cap_le_services, le_psm); 24607192e786SMatthias Ringwald } 2461efedfb4cSMatthias Ringwald 2462da144af5SMatthias Ringwald uint8_t l2cap_le_register_service(btstack_packet_handler_t packet_handler, uint16_t psm, gap_security_level_t security_level){ 24637192e786SMatthias Ringwald 2464da144af5SMatthias Ringwald log_info("L2CAP_LE_REGISTER_SERVICE psm 0x%x", psm); 24657192e786SMatthias Ringwald 24667192e786SMatthias Ringwald // check for alread registered psm 24677192e786SMatthias Ringwald l2cap_service_t *service = l2cap_le_get_service(psm); 24687192e786SMatthias Ringwald if (service) { 2469da144af5SMatthias Ringwald return L2CAP_SERVICE_ALREADY_REGISTERED; 24707192e786SMatthias Ringwald } 24717192e786SMatthias Ringwald 24727192e786SMatthias Ringwald // alloc structure 24737192e786SMatthias Ringwald service = btstack_memory_l2cap_service_get(); 24747192e786SMatthias Ringwald if (!service) { 24757192e786SMatthias Ringwald log_error("l2cap_register_service_internal: no memory for l2cap_service_t"); 2476da144af5SMatthias Ringwald return BTSTACK_MEMORY_ALLOC_FAILED; 24777192e786SMatthias Ringwald } 24787192e786SMatthias Ringwald 24797192e786SMatthias Ringwald // fill in 24807192e786SMatthias Ringwald service->psm = psm; 2481da144af5SMatthias Ringwald service->mtu = 0; 24827192e786SMatthias Ringwald service->packet_handler = packet_handler; 24837192e786SMatthias Ringwald service->required_security_level = security_level; 24847192e786SMatthias Ringwald 24857192e786SMatthias Ringwald // add to services list 2486665d90f2SMatthias Ringwald btstack_linked_list_add(&l2cap_le_services, (btstack_linked_item_t *) service); 24877192e786SMatthias Ringwald 24887192e786SMatthias Ringwald // done 2489da144af5SMatthias Ringwald return 0; 24907192e786SMatthias Ringwald } 24917192e786SMatthias Ringwald 2492da144af5SMatthias Ringwald uint8_t l2cap_le_unregister_service(uint16_t psm) { 24937192e786SMatthias Ringwald log_info("L2CAP_LE_UNREGISTER_SERVICE psm 0x%x", psm); 24947192e786SMatthias Ringwald l2cap_service_t *service = l2cap_le_get_service(psm); 24959367f9b0SMatthias Ringwald if (!service) return L2CAP_SERVICE_DOES_NOT_EXIST; 2496da144af5SMatthias Ringwald 2497665d90f2SMatthias Ringwald btstack_linked_list_remove(&l2cap_le_services, (btstack_linked_item_t *) service); 24987192e786SMatthias Ringwald btstack_memory_l2cap_service_free(service); 2499da144af5SMatthias Ringwald return 0; 25007192e786SMatthias Ringwald } 2501da144af5SMatthias Ringwald 2502da144af5SMatthias Ringwald uint8_t l2cap_le_accept_connection(uint16_t local_cid, uint8_t * receive_sdu_buffer, uint16_t mtu, uint16_t initial_credits){ 2503e7d0c9aaSMatthias Ringwald // get channel 2504e7d0c9aaSMatthias Ringwald l2cap_channel_t * channel = l2cap_le_get_channel_for_local_cid(local_cid); 2505e7d0c9aaSMatthias Ringwald if (!channel) return L2CAP_LOCAL_CID_DOES_NOT_EXIST; 2506e7d0c9aaSMatthias Ringwald 2507e7d0c9aaSMatthias Ringwald // validate state 2508e7d0c9aaSMatthias Ringwald if (channel->state != L2CAP_STATE_WAIT_CLIENT_ACCEPT_OR_REJECT){ 2509e7d0c9aaSMatthias Ringwald return ERROR_CODE_COMMAND_DISALLOWED; 2510e7d0c9aaSMatthias Ringwald } 2511e7d0c9aaSMatthias Ringwald 2512efedfb4cSMatthias Ringwald // set state accept connection 251323017473SMatthias Ringwald channel->state = L2CAP_STATE_WILL_SEND_LE_CONNECTION_RESPONSE_ACCEPT; 251423017473SMatthias Ringwald channel->receive_sdu_buffer = receive_sdu_buffer; 251523017473SMatthias Ringwald channel->local_mtu = mtu; 251685aeef60SMatthias Ringwald channel->new_credits_incoming = initial_credits; 251785aeef60SMatthias Ringwald channel->automatic_credits = initial_credits == L2CAP_LE_AUTOMATIC_CREDITS; 251885aeef60SMatthias Ringwald 251985aeef60SMatthias Ringwald // test 252063f0ac45SMatthias Ringwald // channel->new_credits_incoming = 1; 2521e7d0c9aaSMatthias Ringwald 2522e7d0c9aaSMatthias Ringwald // go 2523e7d0c9aaSMatthias Ringwald l2cap_run(); 2524da144af5SMatthias Ringwald return 0; 2525da144af5SMatthias Ringwald } 2526da144af5SMatthias Ringwald 2527da144af5SMatthias Ringwald /** 2528da144af5SMatthias Ringwald * @brief Deny incoming LE Data Channel connection due to resource constraints 2529da144af5SMatthias Ringwald * @param local_cid L2CAP LE Data Channel Identifier 2530da144af5SMatthias Ringwald */ 2531da144af5SMatthias Ringwald 2532da144af5SMatthias Ringwald uint8_t l2cap_le_decline_connection(uint16_t local_cid){ 2533e7d0c9aaSMatthias Ringwald // get channel 2534e7d0c9aaSMatthias Ringwald l2cap_channel_t * channel = l2cap_le_get_channel_for_local_cid(local_cid); 2535e7d0c9aaSMatthias Ringwald if (!channel) return L2CAP_LOCAL_CID_DOES_NOT_EXIST; 2536e7d0c9aaSMatthias Ringwald 2537e7d0c9aaSMatthias Ringwald // validate state 2538e7d0c9aaSMatthias Ringwald if (channel->state != L2CAP_STATE_WAIT_CLIENT_ACCEPT_OR_REJECT){ 2539e7d0c9aaSMatthias Ringwald return ERROR_CODE_COMMAND_DISALLOWED; 2540e7d0c9aaSMatthias Ringwald } 2541e7d0c9aaSMatthias Ringwald 2542efedfb4cSMatthias Ringwald // set state decline connection 2543e7d0c9aaSMatthias Ringwald channel->state = L2CAP_STATE_WILL_SEND_LE_CONNECTION_RESPONSE_DECLINE; 2544e7d0c9aaSMatthias Ringwald channel->reason = 0x04; // no resources available 2545e7d0c9aaSMatthias Ringwald l2cap_run(); 2546da144af5SMatthias Ringwald return 0; 2547da144af5SMatthias Ringwald } 2548da144af5SMatthias Ringwald 25497dafa750SMatthias Ringwald uint8_t l2cap_le_create_channel(btstack_packet_handler_t packet_handler, hci_con_handle_t con_handle, 2550da144af5SMatthias Ringwald uint16_t psm, uint8_t * receive_sdu_buffer, uint16_t mtu, uint16_t initial_credits, gap_security_level_t security_level, 2551efedfb4cSMatthias Ringwald uint16_t * out_local_cid) { 2552efedfb4cSMatthias Ringwald 25537dafa750SMatthias Ringwald log_info("L2CAP_LE_CREATE_CHANNEL handle 0x%04x psm 0x%x mtu %u", con_handle, psm, mtu); 2554da144af5SMatthias Ringwald 25557dafa750SMatthias Ringwald 25567dafa750SMatthias Ringwald hci_connection_t * connection = hci_connection_for_handle(con_handle); 25577dafa750SMatthias Ringwald if (!connection) { 25587dafa750SMatthias Ringwald log_error("no hci_connection for handle 0x%04x", con_handle); 25597dafa750SMatthias Ringwald return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 25607dafa750SMatthias Ringwald } 25617dafa750SMatthias Ringwald 25627dafa750SMatthias Ringwald l2cap_channel_t * channel = l2cap_create_channel_entry(packet_handler, connection->address, connection->address_type, psm, mtu, security_level); 2563da144af5SMatthias Ringwald if (!channel) { 2564da144af5SMatthias Ringwald return BTSTACK_MEMORY_ALLOC_FAILED; 2565da144af5SMatthias Ringwald } 2566e7d0c9aaSMatthias Ringwald log_info("l2cap_le_create_channel %p", channel); 2567da144af5SMatthias Ringwald 2568da144af5SMatthias Ringwald // store local_cid 2569da144af5SMatthias Ringwald if (out_local_cid){ 2570da144af5SMatthias Ringwald *out_local_cid = channel->local_cid; 2571da144af5SMatthias Ringwald } 2572da144af5SMatthias Ringwald 25737dafa750SMatthias Ringwald // provide buffer 25747dafa750SMatthias Ringwald channel->con_handle = con_handle; 2575cd529728SMatthias Ringwald channel->receive_sdu_buffer = receive_sdu_buffer; 25767dafa750SMatthias Ringwald channel->state = L2CAP_STATE_WILL_SEND_LE_CONNECTION_REQUEST; 257785aeef60SMatthias Ringwald channel->new_credits_incoming = initial_credits; 257885aeef60SMatthias Ringwald channel->automatic_credits = initial_credits == L2CAP_LE_AUTOMATIC_CREDITS; 257985aeef60SMatthias Ringwald 2580efedfb4cSMatthias Ringwald // add to connections list 2581efedfb4cSMatthias Ringwald btstack_linked_list_add(&l2cap_le_channels, (btstack_linked_item_t *) channel); 2582efedfb4cSMatthias Ringwald 25837dafa750SMatthias Ringwald // go 258463f0ac45SMatthias Ringwald l2cap_run(); 2585da144af5SMatthias Ringwald return 0; 2586da144af5SMatthias Ringwald } 2587da144af5SMatthias Ringwald 2588da144af5SMatthias Ringwald /** 2589da144af5SMatthias Ringwald * @brief Provide credtis for LE Data Channel 2590da144af5SMatthias Ringwald * @param local_cid L2CAP LE Data Channel Identifier 2591da144af5SMatthias Ringwald * @param credits Number additional credits for peer 2592da144af5SMatthias Ringwald */ 259364e11ca9SMatthias Ringwald uint8_t l2cap_le_provide_credits(uint16_t local_cid, uint16_t credits){ 259463f0ac45SMatthias Ringwald 259563f0ac45SMatthias Ringwald l2cap_channel_t * channel = l2cap_le_get_channel_for_local_cid(local_cid); 259663f0ac45SMatthias Ringwald if (!channel) { 259763f0ac45SMatthias Ringwald log_error("l2cap_le_provide_credits no channel for cid 0x%02x", local_cid); 259863f0ac45SMatthias Ringwald return L2CAP_LOCAL_CID_DOES_NOT_EXIST; 259963f0ac45SMatthias Ringwald } 260063f0ac45SMatthias Ringwald 2601efedfb4cSMatthias Ringwald // check state 260263f0ac45SMatthias Ringwald if (channel->state != L2CAP_STATE_OPEN){ 260363f0ac45SMatthias Ringwald log_error("l2cap_le_provide_credits but channel 0x%02x not open yet", local_cid); 260463f0ac45SMatthias Ringwald } 260563f0ac45SMatthias Ringwald 260663f0ac45SMatthias Ringwald // assert incoming credits + credits <= 0xffff 260763f0ac45SMatthias Ringwald uint32_t total_credits = channel->credits_incoming; 260863f0ac45SMatthias Ringwald total_credits += channel->new_credits_incoming; 260963f0ac45SMatthias Ringwald total_credits += credits; 261063f0ac45SMatthias Ringwald if (total_credits > 0xffff){ 261163f0ac45SMatthias Ringwald log_error("l2cap_le_provide_credits overrun: current %u, scheduled %u, additional %u", channel->credits_incoming, 261263f0ac45SMatthias Ringwald channel->new_credits_incoming, credits); 261363f0ac45SMatthias Ringwald } 261463f0ac45SMatthias Ringwald 2615efedfb4cSMatthias Ringwald // set credits_granted 261663f0ac45SMatthias Ringwald channel->new_credits_incoming += credits; 261763f0ac45SMatthias Ringwald 261863f0ac45SMatthias Ringwald // go 261963f0ac45SMatthias Ringwald l2cap_run(); 2620da144af5SMatthias Ringwald return 0; 2621da144af5SMatthias Ringwald } 2622da144af5SMatthias Ringwald 2623da144af5SMatthias Ringwald /** 2624da144af5SMatthias Ringwald * @brief Check if outgoing buffer is available and that there's space on the Bluetooth module 2625da144af5SMatthias Ringwald * @param local_cid L2CAP LE Data Channel Identifier 2626da144af5SMatthias Ringwald */ 262764e11ca9SMatthias Ringwald int l2cap_le_can_send_now(uint16_t local_cid){ 262844276248SMatthias Ringwald l2cap_channel_t * channel = l2cap_le_get_channel_for_local_cid(local_cid); 262944276248SMatthias Ringwald if (!channel) { 263044276248SMatthias Ringwald log_error("l2cap_le_provide_credits no channel for cid 0x%02x", local_cid); 2631da144af5SMatthias Ringwald return 0; 2632da144af5SMatthias Ringwald } 2633da144af5SMatthias Ringwald 263444276248SMatthias Ringwald // check state 263544276248SMatthias Ringwald if (channel->state != L2CAP_STATE_OPEN) return 0; 263644276248SMatthias Ringwald 263744276248SMatthias Ringwald // check queue 263844276248SMatthias Ringwald if (channel->send_sdu_buffer) return 0; 263944276248SMatthias Ringwald 264044276248SMatthias Ringwald // fine, go ahead 264144276248SMatthias Ringwald return 1; 264244276248SMatthias Ringwald } 264344276248SMatthias Ringwald 2644da144af5SMatthias Ringwald /** 2645da144af5SMatthias Ringwald * @brief Request emission of L2CAP_EVENT_CAN_SEND_NOW as soon as possible 2646da144af5SMatthias Ringwald * @note L2CAP_EVENT_CAN_SEND_NOW might be emitted during call to this function 2647da144af5SMatthias Ringwald * so packet handler should be ready to handle it 2648da144af5SMatthias Ringwald * @param local_cid L2CAP LE Data Channel Identifier 2649da144af5SMatthias Ringwald */ 265064e11ca9SMatthias Ringwald uint8_t l2cap_le_request_can_send_now_event(uint16_t local_cid){ 265144276248SMatthias Ringwald l2cap_channel_t * channel = l2cap_le_get_channel_for_local_cid(local_cid); 265244276248SMatthias Ringwald if (!channel) { 265344276248SMatthias Ringwald log_error("l2cap_le_request_can_send_now_event no channel for cid 0x%02x", local_cid); 265444276248SMatthias Ringwald return 0; 265544276248SMatthias Ringwald } 265644276248SMatthias Ringwald channel->waiting_for_can_send_now = 1; 265744276248SMatthias Ringwald l2cap_le_notify_channel_can_send(channel); 2658da144af5SMatthias Ringwald return 0; 2659da144af5SMatthias Ringwald } 2660da144af5SMatthias Ringwald 2661da144af5SMatthias Ringwald /** 2662da144af5SMatthias Ringwald * @brief Send data via LE Data Channel 2663da144af5SMatthias Ringwald * @note Since data larger then the maximum PDU needs to be segmented into multiple PDUs, data needs to stay valid until ... event 2664da144af5SMatthias Ringwald * @param local_cid L2CAP LE Data Channel Identifier 2665da144af5SMatthias Ringwald * @param data data to send 2666da144af5SMatthias Ringwald * @param size data size 2667da144af5SMatthias Ringwald */ 266864e11ca9SMatthias Ringwald uint8_t l2cap_le_send_data(uint16_t local_cid, uint8_t * data, uint16_t len){ 266964e11ca9SMatthias Ringwald 267064e11ca9SMatthias Ringwald l2cap_channel_t * channel = l2cap_le_get_channel_for_local_cid(local_cid); 267164e11ca9SMatthias Ringwald if (!channel) { 267264e11ca9SMatthias Ringwald log_error("l2cap_send no channel for cid 0x%02x", local_cid); 2673828a7f7aSMatthias Ringwald return L2CAP_LOCAL_CID_DOES_NOT_EXIST; 267464e11ca9SMatthias Ringwald } 267564e11ca9SMatthias Ringwald 267664e11ca9SMatthias Ringwald if (len > channel->remote_mtu){ 267764e11ca9SMatthias Ringwald log_error("l2cap_send cid 0x%02x, data length exceeds remote MTU.", local_cid); 267864e11ca9SMatthias Ringwald return L2CAP_DATA_LEN_EXCEEDS_REMOTE_MTU; 267964e11ca9SMatthias Ringwald } 268064e11ca9SMatthias Ringwald 26817f107edaSMatthias Ringwald if (channel->send_sdu_buffer){ 268264e11ca9SMatthias Ringwald log_info("l2cap_send cid 0x%02x, cannot send", local_cid); 268364e11ca9SMatthias Ringwald return BTSTACK_ACL_BUFFERS_FULL; 268464e11ca9SMatthias Ringwald } 268564e11ca9SMatthias Ringwald 26867f107edaSMatthias Ringwald channel->send_sdu_buffer = data; 26877f107edaSMatthias Ringwald channel->send_sdu_len = len; 26887f107edaSMatthias Ringwald channel->send_sdu_pos = 0; 268964e11ca9SMatthias Ringwald 26907f107edaSMatthias Ringwald l2cap_run(); 26917f107edaSMatthias Ringwald return 0; 2692da144af5SMatthias Ringwald } 2693da144af5SMatthias Ringwald 2694da144af5SMatthias Ringwald /** 2695da144af5SMatthias Ringwald * @brief Disconnect from LE Data Channel 2696da144af5SMatthias Ringwald * @param local_cid L2CAP LE Data Channel Identifier 2697da144af5SMatthias Ringwald */ 2698828a7f7aSMatthias Ringwald uint8_t l2cap_le_disconnect(uint16_t local_cid) 2699da144af5SMatthias Ringwald { 2700828a7f7aSMatthias Ringwald l2cap_channel_t * channel = l2cap_le_get_channel_for_local_cid(local_cid); 2701828a7f7aSMatthias Ringwald if (!channel) { 2702828a7f7aSMatthias Ringwald log_error("l2cap_send no channel for cid 0x%02x", local_cid); 2703828a7f7aSMatthias Ringwald return L2CAP_LOCAL_CID_DOES_NOT_EXIST; 2704828a7f7aSMatthias Ringwald } 2705828a7f7aSMatthias Ringwald 2706828a7f7aSMatthias Ringwald channel->state = L2CAP_STATE_WILL_SEND_DISCONNECT_REQUEST; 2707828a7f7aSMatthias Ringwald l2cap_run(); 2708da144af5SMatthias Ringwald return 0; 2709da144af5SMatthias Ringwald } 2710da144af5SMatthias Ringwald 27117f02f414SMatthias Ringwald #endif 2712