xref: /btstack/src/l2cap.c (revision 85ddcd849680017e6cb04e372017edc4ea3a957f)
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