xref: /btstack/src/classic/rfcomm.c (revision 724d70a2cfb8532b37f9246759b8f8a91d14356d)
13deb3ec6SMatthias Ringwald /*
23deb3ec6SMatthias Ringwald  * Copyright (C) 2014 BlueKitchen GmbH
33deb3ec6SMatthias Ringwald  *
43deb3ec6SMatthias Ringwald  * Redistribution and use in source and binary forms, with or without
53deb3ec6SMatthias Ringwald  * modification, are permitted provided that the following conditions
63deb3ec6SMatthias Ringwald  * are met:
73deb3ec6SMatthias Ringwald  *
83deb3ec6SMatthias Ringwald  * 1. Redistributions of source code must retain the above copyright
93deb3ec6SMatthias Ringwald  *    notice, this list of conditions and the following disclaimer.
103deb3ec6SMatthias Ringwald  * 2. Redistributions in binary form must reproduce the above copyright
113deb3ec6SMatthias Ringwald  *    notice, this list of conditions and the following disclaimer in the
123deb3ec6SMatthias Ringwald  *    documentation and/or other materials provided with the distribution.
133deb3ec6SMatthias Ringwald  * 3. Neither the name of the copyright holders nor the names of
143deb3ec6SMatthias Ringwald  *    contributors may be used to endorse or promote products derived
153deb3ec6SMatthias Ringwald  *    from this software without specific prior written permission.
163deb3ec6SMatthias Ringwald  * 4. Any redistribution, use, or modification is done solely for
173deb3ec6SMatthias Ringwald  *    personal benefit and not for any commercial purpose or for
183deb3ec6SMatthias Ringwald  *    monetary gain.
193deb3ec6SMatthias Ringwald  *
203deb3ec6SMatthias Ringwald  * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
213deb3ec6SMatthias Ringwald  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
223deb3ec6SMatthias Ringwald  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
233deb3ec6SMatthias Ringwald  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
243deb3ec6SMatthias Ringwald  * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
253deb3ec6SMatthias Ringwald  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
263deb3ec6SMatthias Ringwald  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
273deb3ec6SMatthias Ringwald  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
283deb3ec6SMatthias Ringwald  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
293deb3ec6SMatthias Ringwald  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
303deb3ec6SMatthias Ringwald  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
313deb3ec6SMatthias Ringwald  * SUCH DAMAGE.
323deb3ec6SMatthias Ringwald  *
333deb3ec6SMatthias Ringwald  * Please inquire about commercial licensing options at
343deb3ec6SMatthias Ringwald  * [email protected]
353deb3ec6SMatthias Ringwald  *
363deb3ec6SMatthias Ringwald  */
373deb3ec6SMatthias Ringwald 
383deb3ec6SMatthias Ringwald /*
393deb3ec6SMatthias Ringwald  *  rfcomm.c
403deb3ec6SMatthias Ringwald  */
413deb3ec6SMatthias Ringwald 
423deb3ec6SMatthias Ringwald #include <stdio.h>
433deb3ec6SMatthias Ringwald #include <stdlib.h>
443deb3ec6SMatthias Ringwald #include <string.h> // memcpy
453deb3ec6SMatthias Ringwald #include <stdint.h>
463deb3ec6SMatthias Ringwald 
4756042629SMatthias Ringwald #include "hci_cmd.h"
48eb886013SMatthias Ringwald #include "btstack_util.h"
493deb3ec6SMatthias Ringwald 
50eb886013SMatthias Ringwald #include "btstack_util.h"
513deb3ec6SMatthias Ringwald #include "btstack_memory.h"
523deb3ec6SMatthias Ringwald #include "hci.h"
533deb3ec6SMatthias Ringwald #include "hci_dump.h"
5416ece135SMatthias Ringwald #include "btstack_debug.h"
553edc84c5SMatthias Ringwald #include "classic/rfcomm.h"
563deb3ec6SMatthias Ringwald 
573deb3ec6SMatthias Ringwald // workaround for missing PRIxPTR on mspgcc (16/20-bit MCU)
583deb3ec6SMatthias Ringwald #ifndef PRIxPTR
593deb3ec6SMatthias Ringwald #if defined(__MSP430X__)  &&  defined(__MSP430X_LARGE__)
603deb3ec6SMatthias Ringwald #define PRIxPTR "lx"
613deb3ec6SMatthias Ringwald #else
623deb3ec6SMatthias Ringwald #define PRIxPTR "x"
633deb3ec6SMatthias Ringwald #endif
643deb3ec6SMatthias Ringwald #endif
653deb3ec6SMatthias Ringwald 
663deb3ec6SMatthias Ringwald #define RFCOMM_MULIPLEXER_TIMEOUT_MS 60000
673deb3ec6SMatthias Ringwald 
683deb3ec6SMatthias Ringwald #define RFCOMM_CREDITS 10
693deb3ec6SMatthias Ringwald 
703deb3ec6SMatthias Ringwald // FCS calc
713deb3ec6SMatthias Ringwald #define BT_RFCOMM_CODE_WORD         0xE0 // pol = x8+x2+x1+1
723deb3ec6SMatthias Ringwald #define BT_RFCOMM_CRC_CHECK_LEN     3
733deb3ec6SMatthias Ringwald #define BT_RFCOMM_UIHCRC_CHECK_LEN  2
743deb3ec6SMatthias Ringwald 
753deb3ec6SMatthias Ringwald #include "l2cap.h"
763deb3ec6SMatthias Ringwald 
773deb3ec6SMatthias Ringwald // global rfcomm data
783deb3ec6SMatthias Ringwald static uint16_t      rfcomm_client_cid_generator;  // used for client channel IDs
793deb3ec6SMatthias Ringwald 
803deb3ec6SMatthias Ringwald // linked lists for all
818f2a52f4SMatthias Ringwald static btstack_linked_list_t rfcomm_multiplexers = NULL;
828f2a52f4SMatthias Ringwald static btstack_linked_list_t rfcomm_channels = NULL;
838f2a52f4SMatthias Ringwald static btstack_linked_list_t rfcomm_services = NULL;
843deb3ec6SMatthias Ringwald 
853deb3ec6SMatthias Ringwald static gap_security_level_t rfcomm_security_level;
863deb3ec6SMatthias Ringwald 
87b31d33b2SMatthias Ringwald static int  rfcomm_channel_can_send(rfcomm_channel_t * channel);
88b31d33b2SMatthias Ringwald static int  rfcomm_channel_ready_for_open(rfcomm_channel_t *channel);
893deb3ec6SMatthias Ringwald static void rfcomm_channel_state_machine(rfcomm_channel_t *channel, rfcomm_channel_event_t *event);
903deb3ec6SMatthias Ringwald static void rfcomm_channel_state_machine_2(rfcomm_multiplexer_t * multiplexer, uint8_t dlci, rfcomm_channel_event_t *event);
91b31d33b2SMatthias Ringwald static void rfcomm_emit_can_send_now(rfcomm_channel_t *channel);
923deb3ec6SMatthias Ringwald static void rfcomm_multiplexer_state_machine(rfcomm_multiplexer_t * multiplexer, RFCOMM_MULTIPLEXER_EVENT event);
93b31d33b2SMatthias Ringwald static void rfcomm_run(void);
943deb3ec6SMatthias Ringwald 
953deb3ec6SMatthias Ringwald // MARK: RFCOMM CLIENT EVENTS
963deb3ec6SMatthias Ringwald 
973deb3ec6SMatthias Ringwald // data: event (8), len(8), address(48), channel (8), rfcomm_cid (16)
983deb3ec6SMatthias Ringwald static void rfcomm_emit_connection_request(rfcomm_channel_t *channel) {
993deb3ec6SMatthias Ringwald     log_info("RFCOMM_EVENT_INCOMING_CONNECTION addr %s channel #%u cid 0x%02x",
1003deb3ec6SMatthias Ringwald              bd_addr_to_str(channel->multiplexer->remote_addr), channel->dlci>>1, channel->rfcomm_cid);
1013deb3ec6SMatthias Ringwald     uint8_t event[11];
1023deb3ec6SMatthias Ringwald     event[0] = RFCOMM_EVENT_INCOMING_CONNECTION;
1033deb3ec6SMatthias Ringwald     event[1] = sizeof(event) - 2;
104*724d70a2SMatthias Ringwald     reverse_bd_addr(channel->multiplexer->remote_addr, &event[2]);
1053deb3ec6SMatthias Ringwald     event[8] = channel->dlci >> 1;
106f8fbdce0SMatthias Ringwald     little_endian_store_16(event, 9, channel->rfcomm_cid);
1073deb3ec6SMatthias Ringwald     hci_dump_packet(HCI_EVENT_PACKET, 0, event, sizeof(event));
108b31d33b2SMatthias Ringwald 	(channel->packet_handler)(HCI_EVENT_PACKET, 0, event, sizeof(event));
1093deb3ec6SMatthias Ringwald }
1103deb3ec6SMatthias Ringwald 
1113deb3ec6SMatthias Ringwald // API Change: BTstack-0.3.50x uses
1123deb3ec6SMatthias Ringwald // data: event(8), len(8), status (8), address (48), server channel(8), rfcomm_cid(16), max frame size(16)
1133deb3ec6SMatthias Ringwald // next Cydia release will use SVN version of this
1143deb3ec6SMatthias Ringwald // data: event(8), len(8), status (8), address (48), handle (16), server channel(8), rfcomm_cid(16), max frame size(16)
1153deb3ec6SMatthias Ringwald static void rfcomm_emit_channel_opened(rfcomm_channel_t *channel, uint8_t status) {
1163deb3ec6SMatthias Ringwald     log_info("RFCOMM_EVENT_OPEN_CHANNEL_COMPLETE status 0x%x addr %s handle 0x%x channel #%u cid 0x%02x mtu %u",
1173deb3ec6SMatthias Ringwald              status, bd_addr_to_str(channel->multiplexer->remote_addr), channel->multiplexer->con_handle,
1183deb3ec6SMatthias Ringwald              channel->dlci>>1, channel->rfcomm_cid, channel->max_frame_size);
1193deb3ec6SMatthias Ringwald     uint8_t event[16];
1203deb3ec6SMatthias Ringwald     uint8_t pos = 0;
1215d1e858fSMatthias Ringwald     event[pos++] = RFCOMM_EVENT_OPEN_CHANNEL_COMPLETE;  // 0
1225d1e858fSMatthias Ringwald     event[pos++] = sizeof(event) - 2;                   // 1
1235d1e858fSMatthias Ringwald     event[pos++] = status;                              // 2
124*724d70a2SMatthias Ringwald     reverse_bd_addr(channel->multiplexer->remote_addr, &event[pos]); pos += 6; // 3
125f8fbdce0SMatthias Ringwald     little_endian_store_16(event,  pos, channel->multiplexer->con_handle);   pos += 2; // 9
1265d1e858fSMatthias Ringwald 	event[pos++] = channel->dlci >> 1;                                      // 11
127f8fbdce0SMatthias Ringwald 	little_endian_store_16(event, pos, channel->rfcomm_cid); pos += 2;                 // 12 - channel ID
128f8fbdce0SMatthias Ringwald 	little_endian_store_16(event, pos, channel->max_frame_size); pos += 2;   // max frame size
1293deb3ec6SMatthias Ringwald     hci_dump_packet(HCI_EVENT_PACKET, 0, event, sizeof(event));
130b31d33b2SMatthias Ringwald 	(channel->packet_handler)(HCI_EVENT_PACKET, 0, event, pos);
131b31d33b2SMatthias Ringwald 
132b31d33b2SMatthias Ringwald     // if channel opened successfully, also send can send now if possible
133b31d33b2SMatthias Ringwald     if (status) return;
134b31d33b2SMatthias Ringwald     if (rfcomm_channel_can_send(channel)){
135b31d33b2SMatthias Ringwald         rfcomm_emit_can_send_now(channel);
136b31d33b2SMatthias Ringwald     } else {
137b31d33b2SMatthias Ringwald         channel->waiting_for_can_send_now = 1;
138b31d33b2SMatthias Ringwald     }
1393deb3ec6SMatthias Ringwald }
1403deb3ec6SMatthias Ringwald 
1413deb3ec6SMatthias Ringwald // data: event(8), len(8), rfcomm_cid(16)
1423deb3ec6SMatthias Ringwald static void rfcomm_emit_channel_closed(rfcomm_channel_t * channel) {
1433deb3ec6SMatthias Ringwald     log_info("RFCOMM_EVENT_CHANNEL_CLOSED cid 0x%02x", channel->rfcomm_cid);
1443deb3ec6SMatthias Ringwald     uint8_t event[4];
1453deb3ec6SMatthias Ringwald     event[0] = RFCOMM_EVENT_CHANNEL_CLOSED;
1463deb3ec6SMatthias Ringwald     event[1] = sizeof(event) - 2;
147f8fbdce0SMatthias Ringwald     little_endian_store_16(event, 2, channel->rfcomm_cid);
1483deb3ec6SMatthias Ringwald     hci_dump_packet(HCI_EVENT_PACKET, 0, event, sizeof(event));
149b31d33b2SMatthias Ringwald 	(channel->packet_handler)(HCI_EVENT_PACKET, 0, event, sizeof(event));
1503deb3ec6SMatthias Ringwald }
1513deb3ec6SMatthias Ringwald 
1523deb3ec6SMatthias Ringwald static void rfcomm_emit_remote_line_status(rfcomm_channel_t *channel, uint8_t line_status){
1533deb3ec6SMatthias Ringwald     log_info("RFCOMM_EVENT_REMOTE_LINE_STATUS cid 0x%02x c, line status 0x%x", channel->rfcomm_cid, line_status);
1543deb3ec6SMatthias Ringwald     uint8_t event[5];
1553deb3ec6SMatthias Ringwald     event[0] = RFCOMM_EVENT_REMOTE_LINE_STATUS;
1563deb3ec6SMatthias Ringwald     event[1] = sizeof(event) - 2;
157f8fbdce0SMatthias Ringwald     little_endian_store_16(event, 2, channel->rfcomm_cid);
1583deb3ec6SMatthias Ringwald     event[4] = line_status;
1593deb3ec6SMatthias Ringwald     hci_dump_packet( HCI_EVENT_PACKET, 0, event, sizeof(event));
160b31d33b2SMatthias Ringwald     (channel->packet_handler)(HCI_EVENT_PACKET, 0, event, sizeof(event));
1613deb3ec6SMatthias Ringwald }
1623deb3ec6SMatthias Ringwald 
1633deb3ec6SMatthias Ringwald static void rfcomm_emit_port_configuration(rfcomm_channel_t *channel){
1643deb3ec6SMatthias Ringwald     // notify client about new settings
1653deb3ec6SMatthias Ringwald     uint8_t event[2+sizeof(rfcomm_rpn_data_t)];
1663deb3ec6SMatthias Ringwald     event[0] = RFCOMM_EVENT_PORT_CONFIGURATION;
1673deb3ec6SMatthias Ringwald     event[1] = sizeof(rfcomm_rpn_data_t);
1683deb3ec6SMatthias Ringwald     memcpy(&event[2], (uint8_t*) &channel->rpn_data, sizeof(rfcomm_rpn_data_t));
1693deb3ec6SMatthias Ringwald     hci_dump_packet( HCI_EVENT_PACKET, 0, event, sizeof(event));
170b31d33b2SMatthias Ringwald     (channel->packet_handler)(HCI_EVENT_PACKET, channel->rfcomm_cid, event, sizeof(event));
171b31d33b2SMatthias Ringwald }
172b31d33b2SMatthias Ringwald 
173b31d33b2SMatthias Ringwald static void rfcomm_emit_can_send_now(rfcomm_channel_t *channel) {
174b31d33b2SMatthias Ringwald     log_info("RFCOMM_EVENT_CHANNEL_CAN_SEND_NOW local_cid 0x%x", channel->rfcomm_cid);
175b31d33b2SMatthias Ringwald     uint8_t event[4];
176b31d33b2SMatthias Ringwald     event[0] = RFCOMM_EVENT_CAN_SEND_NOW;
177b31d33b2SMatthias Ringwald     event[1] = sizeof(event) - 2;
178b31d33b2SMatthias Ringwald     little_endian_store_16(event, 2, channel->rfcomm_cid);
179b31d33b2SMatthias Ringwald     hci_dump_packet( HCI_EVENT_PACKET, 0, event, sizeof(event));
180b31d33b2SMatthias Ringwald     (channel->packet_handler)(HCI_EVENT_PACKET, channel->rfcomm_cid, event, sizeof(event));
1813deb3ec6SMatthias Ringwald }
1823deb3ec6SMatthias Ringwald 
1833deb3ec6SMatthias Ringwald // MARK RFCOMM RPN DATA HELPER
1843deb3ec6SMatthias Ringwald static void rfcomm_rpn_data_set_defaults(rfcomm_rpn_data_t * rpn_data){
1853deb3ec6SMatthias Ringwald         rpn_data->baud_rate = RPN_BAUD_9600;  /* 9600 bps */
1863deb3ec6SMatthias Ringwald         rpn_data->flags = 0x03;               /* 8-n-1 */
1873deb3ec6SMatthias Ringwald         rpn_data->flow_control = 0;           /* no flow control */
1883deb3ec6SMatthias Ringwald         rpn_data->xon  = 0xd1;                /* XON */
1893deb3ec6SMatthias Ringwald         rpn_data->xoff = 0xd3;                /* XOFF */
1903deb3ec6SMatthias Ringwald         rpn_data->parameter_mask_0 = 0x7f;    /* parameter mask, all values set */
1913deb3ec6SMatthias Ringwald         rpn_data->parameter_mask_1 = 0x3f;    /* parameter mask, all values set */
1923deb3ec6SMatthias Ringwald }
1933deb3ec6SMatthias Ringwald 
1943deb3ec6SMatthias Ringwald static void rfcomm_rpn_data_update(rfcomm_rpn_data_t * dest, rfcomm_rpn_data_t * src){
1953deb3ec6SMatthias Ringwald     if (src->parameter_mask_0 & RPN_PARAM_MASK_0_BAUD){
1963deb3ec6SMatthias Ringwald         dest->baud_rate = src->baud_rate;
1973deb3ec6SMatthias Ringwald     }
1983deb3ec6SMatthias Ringwald     if (src->parameter_mask_0 & RPN_PARAM_MASK_0_DATA_BITS){
1993deb3ec6SMatthias Ringwald         dest->flags = (dest->flags & 0xfc) | (src->flags & 0x03);
2003deb3ec6SMatthias Ringwald     }
2013deb3ec6SMatthias Ringwald     if (src->parameter_mask_0 & RPN_PARAM_MASK_0_STOP_BITS){
2023deb3ec6SMatthias Ringwald         dest->flags = (dest->flags & 0xfb) | (src->flags & 0x04);
2033deb3ec6SMatthias Ringwald     }
2043deb3ec6SMatthias Ringwald     if (src->parameter_mask_0 & RPN_PARAM_MASK_0_PARITY){
2053deb3ec6SMatthias Ringwald         dest->flags = (dest->flags & 0xf7) | (src->flags & 0x08);
2063deb3ec6SMatthias Ringwald     }
2073deb3ec6SMatthias Ringwald     if (src->parameter_mask_0 & RPN_PARAM_MASK_0_PARITY_TYPE){
2083deb3ec6SMatthias Ringwald         dest->flags = (dest->flags & 0xfc) | (src->flags & 0x30);
2093deb3ec6SMatthias Ringwald     }
2103deb3ec6SMatthias Ringwald     if (src->parameter_mask_0 & RPN_PARAM_MASK_0_XON_CHAR){
2113deb3ec6SMatthias Ringwald         dest->xon = src->xon;
2123deb3ec6SMatthias Ringwald     }
2133deb3ec6SMatthias Ringwald     if (src->parameter_mask_0 & RPN_PARAM_MASK_0_XOFF_CHAR){
2143deb3ec6SMatthias Ringwald         dest->xoff = src->xoff;
2153deb3ec6SMatthias Ringwald     }
2163deb3ec6SMatthias Ringwald     int i;
2173deb3ec6SMatthias Ringwald     for (i=0; i < 6 ; i++){
2183deb3ec6SMatthias Ringwald         uint8_t mask = 1 << i;
2193deb3ec6SMatthias Ringwald         if (src->parameter_mask_1 & mask){
2203deb3ec6SMatthias Ringwald             dest->flags = (dest->flags & ~mask) | (src->flags & mask);
2213deb3ec6SMatthias Ringwald         }
2223deb3ec6SMatthias Ringwald     }
2233deb3ec6SMatthias Ringwald     // always copy parameter mask, too. informative for client, needed for response
2243deb3ec6SMatthias Ringwald     dest->parameter_mask_0 = src->parameter_mask_0;
2253deb3ec6SMatthias Ringwald     dest->parameter_mask_1 = src->parameter_mask_1;
2263deb3ec6SMatthias Ringwald }
2273deb3ec6SMatthias Ringwald // MARK: RFCOMM MULTIPLEXER HELPER
2283deb3ec6SMatthias Ringwald 
2293deb3ec6SMatthias Ringwald static uint16_t rfcomm_max_frame_size_for_l2cap_mtu(uint16_t l2cap_mtu){
2303deb3ec6SMatthias Ringwald     // Assume RFCOMM header without credits and 2 byte (14 bit) length field
2313deb3ec6SMatthias Ringwald     uint16_t max_frame_size = l2cap_mtu - 5;
2323deb3ec6SMatthias Ringwald     log_info("rfcomm_max_frame_size_for_l2cap_mtu:  %u -> %u", l2cap_mtu, max_frame_size);
2333deb3ec6SMatthias Ringwald     return max_frame_size;
2343deb3ec6SMatthias Ringwald }
2353deb3ec6SMatthias Ringwald 
2363deb3ec6SMatthias Ringwald static void rfcomm_multiplexer_initialize(rfcomm_multiplexer_t *multiplexer){
2373deb3ec6SMatthias Ringwald 
2383deb3ec6SMatthias Ringwald     memset(multiplexer, 0, sizeof(rfcomm_multiplexer_t));
2393deb3ec6SMatthias Ringwald 
2403deb3ec6SMatthias Ringwald     multiplexer->state = RFCOMM_MULTIPLEXER_CLOSED;
2413deb3ec6SMatthias Ringwald     multiplexer->fcon = 1;
2423deb3ec6SMatthias Ringwald     multiplexer->send_dm_for_dlci = 0;
2433deb3ec6SMatthias Ringwald     multiplexer->max_frame_size = rfcomm_max_frame_size_for_l2cap_mtu(l2cap_max_mtu());
2443deb3ec6SMatthias Ringwald     multiplexer->test_data_len = 0;
2453deb3ec6SMatthias Ringwald     multiplexer->nsc_command = 0;
2463deb3ec6SMatthias Ringwald }
2473deb3ec6SMatthias Ringwald 
2483deb3ec6SMatthias Ringwald static rfcomm_multiplexer_t * rfcomm_multiplexer_create_for_addr(bd_addr_t addr){
2493deb3ec6SMatthias Ringwald 
2503deb3ec6SMatthias Ringwald     // alloc structure
2513deb3ec6SMatthias Ringwald     rfcomm_multiplexer_t * multiplexer = btstack_memory_rfcomm_multiplexer_get();
2523deb3ec6SMatthias Ringwald     if (!multiplexer) return NULL;
2533deb3ec6SMatthias Ringwald 
2543deb3ec6SMatthias Ringwald     // fill in
2553deb3ec6SMatthias Ringwald     rfcomm_multiplexer_initialize(multiplexer);
25673988a59SMatthias Ringwald     bd_addr_copy(multiplexer->remote_addr, addr);
2573deb3ec6SMatthias Ringwald 
2583deb3ec6SMatthias Ringwald     // add to services list
259665d90f2SMatthias Ringwald     btstack_linked_list_add(&rfcomm_multiplexers, (btstack_linked_item_t *) multiplexer);
2603deb3ec6SMatthias Ringwald 
2613deb3ec6SMatthias Ringwald     return multiplexer;
2623deb3ec6SMatthias Ringwald }
2633deb3ec6SMatthias Ringwald 
2643deb3ec6SMatthias Ringwald static rfcomm_multiplexer_t * rfcomm_multiplexer_for_addr(bd_addr_t addr){
265665d90f2SMatthias Ringwald     btstack_linked_item_t *it;
266665d90f2SMatthias Ringwald     for (it = (btstack_linked_item_t *) rfcomm_multiplexers; it ; it = it->next){
2673deb3ec6SMatthias Ringwald         rfcomm_multiplexer_t * multiplexer = ((rfcomm_multiplexer_t *) it);
268058e3d6bSMatthias Ringwald         if (bd_addr_cmp(addr, multiplexer->remote_addr) == 0) {
2693deb3ec6SMatthias Ringwald             return multiplexer;
2703deb3ec6SMatthias Ringwald         };
2713deb3ec6SMatthias Ringwald     }
2723deb3ec6SMatthias Ringwald     return NULL;
2733deb3ec6SMatthias Ringwald }
2743deb3ec6SMatthias Ringwald 
2753deb3ec6SMatthias Ringwald static rfcomm_multiplexer_t * rfcomm_multiplexer_for_l2cap_cid(uint16_t l2cap_cid) {
276665d90f2SMatthias Ringwald     btstack_linked_item_t *it;
277665d90f2SMatthias Ringwald     for (it = (btstack_linked_item_t *) rfcomm_multiplexers; it ; it = it->next){
2783deb3ec6SMatthias Ringwald         rfcomm_multiplexer_t * multiplexer = ((rfcomm_multiplexer_t *) it);
2793deb3ec6SMatthias Ringwald         if (multiplexer->l2cap_cid == l2cap_cid) {
2803deb3ec6SMatthias Ringwald             return multiplexer;
2813deb3ec6SMatthias Ringwald         };
2823deb3ec6SMatthias Ringwald     }
2833deb3ec6SMatthias Ringwald     return NULL;
2843deb3ec6SMatthias Ringwald }
2853deb3ec6SMatthias Ringwald 
2863deb3ec6SMatthias Ringwald static int rfcomm_multiplexer_has_channels(rfcomm_multiplexer_t * multiplexer){
287665d90f2SMatthias Ringwald     btstack_linked_item_t *it;
288665d90f2SMatthias Ringwald     for (it = (btstack_linked_item_t *) rfcomm_channels; it ; it = it->next){
2893deb3ec6SMatthias Ringwald         rfcomm_channel_t * channel = ((rfcomm_channel_t *) it);
2903deb3ec6SMatthias Ringwald         if (channel->multiplexer == multiplexer) {
2913deb3ec6SMatthias Ringwald             return 1;
2923deb3ec6SMatthias Ringwald         }
2933deb3ec6SMatthias Ringwald     }
2943deb3ec6SMatthias Ringwald     return 0;
2953deb3ec6SMatthias Ringwald }
2963deb3ec6SMatthias Ringwald 
2973deb3ec6SMatthias Ringwald // MARK: RFCOMM CHANNEL HELPER
2983deb3ec6SMatthias Ringwald 
2993deb3ec6SMatthias Ringwald static void rfcomm_dump_channels(void){
300665d90f2SMatthias Ringwald     btstack_linked_item_t * it;
3013deb3ec6SMatthias Ringwald     int channels = 0;
302665d90f2SMatthias Ringwald     for (it = (btstack_linked_item_t *) rfcomm_channels; it ; it = it->next){
3033deb3ec6SMatthias Ringwald         rfcomm_channel_t * channel = (rfcomm_channel_t *) it;
3043deb3ec6SMatthias Ringwald         log_info("Channel #%u: addr %p, state %u", channels, channel, channel->state);
3053deb3ec6SMatthias Ringwald         channels++;
3063deb3ec6SMatthias Ringwald     }
3073deb3ec6SMatthias Ringwald }
3083deb3ec6SMatthias Ringwald 
3093deb3ec6SMatthias Ringwald static void rfcomm_channel_initialize(rfcomm_channel_t *channel, rfcomm_multiplexer_t *multiplexer,
3103deb3ec6SMatthias Ringwald                                rfcomm_service_t *service, uint8_t server_channel){
3113deb3ec6SMatthias Ringwald 
3123deb3ec6SMatthias Ringwald     // don't use 0 as channel id
3133deb3ec6SMatthias Ringwald     if (rfcomm_client_cid_generator == 0) ++rfcomm_client_cid_generator;
3143deb3ec6SMatthias Ringwald 
3153deb3ec6SMatthias Ringwald     // setup channel
3163deb3ec6SMatthias Ringwald     memset(channel, 0, sizeof(rfcomm_channel_t));
3173deb3ec6SMatthias Ringwald 
318ccb8ddfbSMatthias Ringwald     // set defaults for port configuration (even for services)
319ccb8ddfbSMatthias Ringwald     rfcomm_rpn_data_set_defaults(&channel->rpn_data);
320ccb8ddfbSMatthias Ringwald 
3213deb3ec6SMatthias Ringwald     channel->state            = RFCOMM_CHANNEL_CLOSED;
3223deb3ec6SMatthias Ringwald     channel->state_var        = RFCOMM_CHANNEL_STATE_VAR_NONE;
3233deb3ec6SMatthias Ringwald 
3243deb3ec6SMatthias Ringwald     channel->multiplexer      = multiplexer;
3253deb3ec6SMatthias Ringwald     channel->rfcomm_cid       = rfcomm_client_cid_generator++;
3263deb3ec6SMatthias Ringwald     channel->max_frame_size   = multiplexer->max_frame_size;
3273deb3ec6SMatthias Ringwald 
3283deb3ec6SMatthias Ringwald     channel->credits_incoming = 0;
3293deb3ec6SMatthias Ringwald     channel->credits_outgoing = 0;
3303deb3ec6SMatthias Ringwald 
3313deb3ec6SMatthias Ringwald     // incoming flow control not active
3323deb3ec6SMatthias Ringwald     channel->new_credits_incoming  = RFCOMM_CREDITS;
3333deb3ec6SMatthias Ringwald     channel->incoming_flow_control = 0;
3343deb3ec6SMatthias Ringwald 
3353deb3ec6SMatthias Ringwald     channel->rls_line_status       = RFCOMM_RLS_STATUS_INVALID;
3363deb3ec6SMatthias Ringwald 
337ccb8ddfbSMatthias Ringwald     channel->service = service;
3383deb3ec6SMatthias Ringwald 	if (service) {
3393deb3ec6SMatthias Ringwald 		// incoming connection
3403deb3ec6SMatthias Ringwald     	channel->dlci = (server_channel << 1) |  multiplexer->outgoing;
3413deb3ec6SMatthias Ringwald         if (channel->max_frame_size > service->max_frame_size) {
3423deb3ec6SMatthias Ringwald             channel->max_frame_size = service->max_frame_size;
3433deb3ec6SMatthias Ringwald         }
3443deb3ec6SMatthias Ringwald         channel->incoming_flow_control = service->incoming_flow_control;
3453deb3ec6SMatthias Ringwald         channel->new_credits_incoming  = service->incoming_initial_credits;
346ccb8ddfbSMatthias Ringwald         channel->packet_handler        = service->packet_handler;
3473deb3ec6SMatthias Ringwald 	} else {
3483deb3ec6SMatthias Ringwald 		// outgoing connection
3493deb3ec6SMatthias Ringwald 		channel->dlci = (server_channel << 1) | (multiplexer->outgoing ^ 1);
3503deb3ec6SMatthias Ringwald 	}
3513deb3ec6SMatthias Ringwald }
3523deb3ec6SMatthias Ringwald 
3533deb3ec6SMatthias Ringwald // service == NULL -> outgoing channel
3543deb3ec6SMatthias Ringwald static rfcomm_channel_t * rfcomm_channel_create(rfcomm_multiplexer_t * multiplexer,
3553deb3ec6SMatthias Ringwald                                                 rfcomm_service_t * service, uint8_t server_channel){
3563deb3ec6SMatthias Ringwald 
3573deb3ec6SMatthias Ringwald     log_info("rfcomm_channel_create for service %p, channel %u --- list of channels:", service, server_channel);
3583deb3ec6SMatthias Ringwald     rfcomm_dump_channels();
3593deb3ec6SMatthias Ringwald 
3603deb3ec6SMatthias Ringwald     // alloc structure
3613deb3ec6SMatthias Ringwald     rfcomm_channel_t * channel = btstack_memory_rfcomm_channel_get();
3623deb3ec6SMatthias Ringwald     if (!channel) return NULL;
3633deb3ec6SMatthias Ringwald 
3643deb3ec6SMatthias Ringwald     // fill in
3653deb3ec6SMatthias Ringwald     rfcomm_channel_initialize(channel, multiplexer, service, server_channel);
3663deb3ec6SMatthias Ringwald 
3673deb3ec6SMatthias Ringwald     // add to services list
368665d90f2SMatthias Ringwald     btstack_linked_list_add(&rfcomm_channels, (btstack_linked_item_t *) channel);
3693deb3ec6SMatthias Ringwald 
3703deb3ec6SMatthias Ringwald     return channel;
3713deb3ec6SMatthias Ringwald }
3723deb3ec6SMatthias Ringwald 
373b31d33b2SMatthias Ringwald static void rfcomm_notify_channel_can_send(void){
374b31d33b2SMatthias Ringwald     btstack_linked_list_iterator_t it;
375b31d33b2SMatthias Ringwald     btstack_linked_list_iterator_init(&it, &rfcomm_channels);
376b31d33b2SMatthias Ringwald     while (btstack_linked_list_iterator_has_next(&it)){
377b31d33b2SMatthias Ringwald         rfcomm_channel_t * channel = (rfcomm_channel_t *) btstack_linked_list_iterator_next(&it);
378b31d33b2SMatthias Ringwald         if (!channel->waiting_for_can_send_now) continue; // didn't try to send yet
379b31d33b2SMatthias Ringwald         if (!rfcomm_channel_can_send(channel)) continue;  // or cannot yet either
380b31d33b2SMatthias Ringwald 
381b31d33b2SMatthias Ringwald         channel->waiting_for_can_send_now = 0;
382b31d33b2SMatthias Ringwald         rfcomm_emit_can_send_now(channel);
383b31d33b2SMatthias Ringwald     }
384b31d33b2SMatthias Ringwald }
385b31d33b2SMatthias Ringwald 
3863deb3ec6SMatthias Ringwald static rfcomm_channel_t * rfcomm_channel_for_rfcomm_cid(uint16_t rfcomm_cid){
387665d90f2SMatthias Ringwald     btstack_linked_item_t *it;
388665d90f2SMatthias Ringwald     for (it = (btstack_linked_item_t *) rfcomm_channels; it ; it = it->next){
3893deb3ec6SMatthias Ringwald         rfcomm_channel_t * channel = ((rfcomm_channel_t *) it);
3903deb3ec6SMatthias Ringwald         if (channel->rfcomm_cid == rfcomm_cid) {
3913deb3ec6SMatthias Ringwald             return channel;
3923deb3ec6SMatthias Ringwald         };
3933deb3ec6SMatthias Ringwald     }
3943deb3ec6SMatthias Ringwald     return NULL;
3953deb3ec6SMatthias Ringwald }
3963deb3ec6SMatthias Ringwald 
3973deb3ec6SMatthias Ringwald static rfcomm_channel_t * rfcomm_channel_for_multiplexer_and_dlci(rfcomm_multiplexer_t * multiplexer, uint8_t dlci){
398665d90f2SMatthias Ringwald     btstack_linked_item_t *it;
399665d90f2SMatthias Ringwald     for (it = (btstack_linked_item_t *) rfcomm_channels; it ; it = it->next){
4003deb3ec6SMatthias Ringwald         rfcomm_channel_t * channel = ((rfcomm_channel_t *) it);
4013deb3ec6SMatthias Ringwald         if (channel->dlci == dlci && channel->multiplexer == multiplexer) {
4023deb3ec6SMatthias Ringwald             return channel;
4033deb3ec6SMatthias Ringwald         };
4043deb3ec6SMatthias Ringwald     }
4053deb3ec6SMatthias Ringwald     return NULL;
4063deb3ec6SMatthias Ringwald }
4073deb3ec6SMatthias Ringwald 
4083deb3ec6SMatthias Ringwald static rfcomm_service_t * rfcomm_service_for_channel(uint8_t server_channel){
409665d90f2SMatthias Ringwald     btstack_linked_item_t *it;
410665d90f2SMatthias Ringwald     for (it = (btstack_linked_item_t *) rfcomm_services; it ; it = it->next){
4113deb3ec6SMatthias Ringwald         rfcomm_service_t * service = ((rfcomm_service_t *) it);
4123deb3ec6SMatthias Ringwald         if ( service->server_channel == server_channel){
4133deb3ec6SMatthias Ringwald             return service;
4143deb3ec6SMatthias Ringwald         };
4153deb3ec6SMatthias Ringwald     }
4163deb3ec6SMatthias Ringwald     return NULL;
4173deb3ec6SMatthias Ringwald }
4183deb3ec6SMatthias Ringwald 
4193deb3ec6SMatthias Ringwald // MARK: RFCOMM SEND
4203deb3ec6SMatthias Ringwald 
4213deb3ec6SMatthias Ringwald /**
4223deb3ec6SMatthias Ringwald  * @param credits - only used for RFCOMM flow control in UIH wiht P/F = 1
4233deb3ec6SMatthias Ringwald  */
4243deb3ec6SMatthias Ringwald static int rfcomm_send_packet_for_multiplexer(rfcomm_multiplexer_t *multiplexer, uint8_t address, uint8_t control, uint8_t credits, uint8_t *data, uint16_t len){
4253deb3ec6SMatthias Ringwald 
4263deb3ec6SMatthias Ringwald     if (!l2cap_can_send_packet_now(multiplexer->l2cap_cid)) return BTSTACK_ACL_BUFFERS_FULL;
4273deb3ec6SMatthias Ringwald 
4283deb3ec6SMatthias Ringwald     l2cap_reserve_packet_buffer();
4293deb3ec6SMatthias Ringwald     uint8_t * rfcomm_out_buffer = l2cap_get_outgoing_buffer();
4303deb3ec6SMatthias Ringwald 
4313deb3ec6SMatthias Ringwald 	uint16_t pos = 0;
4323deb3ec6SMatthias Ringwald 	uint8_t crc_fields = 3;
4333deb3ec6SMatthias Ringwald 
4343deb3ec6SMatthias Ringwald 	rfcomm_out_buffer[pos++] = address;
4353deb3ec6SMatthias Ringwald 	rfcomm_out_buffer[pos++] = control;
4363deb3ec6SMatthias Ringwald 
4373deb3ec6SMatthias Ringwald 	// length field can be 1 or 2 octets
4383deb3ec6SMatthias Ringwald 	if (len < 128){
4393deb3ec6SMatthias Ringwald 		rfcomm_out_buffer[pos++] = (len << 1)| 1;     // bits 0-6
4403deb3ec6SMatthias Ringwald 	} else {
4413deb3ec6SMatthias Ringwald 		rfcomm_out_buffer[pos++] = (len & 0x7f) << 1; // bits 0-6
4423deb3ec6SMatthias Ringwald 		rfcomm_out_buffer[pos++] = len >> 7;          // bits 7-14
4433deb3ec6SMatthias Ringwald 		crc_fields++;
4443deb3ec6SMatthias Ringwald 	}
4453deb3ec6SMatthias Ringwald 
4463deb3ec6SMatthias Ringwald 	// add credits for UIH frames when PF bit is set
4473deb3ec6SMatthias Ringwald 	if (control == BT_RFCOMM_UIH_PF){
4483deb3ec6SMatthias Ringwald 		rfcomm_out_buffer[pos++] = credits;
4493deb3ec6SMatthias Ringwald 	}
4503deb3ec6SMatthias Ringwald 
4513deb3ec6SMatthias Ringwald 	// copy actual data
4523deb3ec6SMatthias Ringwald 	if (len) {
4533deb3ec6SMatthias Ringwald 		memcpy(&rfcomm_out_buffer[pos], data, len);
4543deb3ec6SMatthias Ringwald 		pos += len;
4553deb3ec6SMatthias Ringwald 	}
4563deb3ec6SMatthias Ringwald 
4573deb3ec6SMatthias Ringwald 	// UIH frames only calc FCS over address + control (5.1.1)
4583deb3ec6SMatthias Ringwald 	if ((control & 0xef) == BT_RFCOMM_UIH){
4593deb3ec6SMatthias Ringwald 		crc_fields = 2;
4603deb3ec6SMatthias Ringwald 	}
4613deb3ec6SMatthias Ringwald 	rfcomm_out_buffer[pos++] =  crc8_calc(rfcomm_out_buffer, crc_fields); // calc fcs
4623deb3ec6SMatthias Ringwald 
4633deb3ec6SMatthias Ringwald     int err = l2cap_send_prepared(multiplexer->l2cap_cid, pos);
4643deb3ec6SMatthias Ringwald 
4653deb3ec6SMatthias Ringwald     return err;
4663deb3ec6SMatthias Ringwald }
4673deb3ec6SMatthias Ringwald 
4683deb3ec6SMatthias Ringwald // simplified version of rfcomm_send_packet_for_multiplexer for prepared rfcomm packet (UIH, 2 byte len, no credits)
4693deb3ec6SMatthias Ringwald static int rfcomm_send_uih_prepared(rfcomm_multiplexer_t *multiplexer, uint8_t dlci, uint16_t len){
4703deb3ec6SMatthias Ringwald 
4713deb3ec6SMatthias Ringwald     uint8_t address = (1 << 0) | (multiplexer->outgoing << 1) | (dlci << 2);
4723deb3ec6SMatthias Ringwald     uint8_t control = BT_RFCOMM_UIH;
4733deb3ec6SMatthias Ringwald 
4743deb3ec6SMatthias Ringwald     uint8_t * rfcomm_out_buffer = l2cap_get_outgoing_buffer();
4753deb3ec6SMatthias Ringwald 
4763deb3ec6SMatthias Ringwald     uint16_t pos = 0;
4773deb3ec6SMatthias Ringwald     rfcomm_out_buffer[pos++] = address;
4783deb3ec6SMatthias Ringwald     rfcomm_out_buffer[pos++] = control;
4793deb3ec6SMatthias Ringwald     rfcomm_out_buffer[pos++] = (len & 0x7f) << 1; // bits 0-6
4803deb3ec6SMatthias Ringwald     rfcomm_out_buffer[pos++] = len >> 7;          // bits 7-14
4813deb3ec6SMatthias Ringwald 
4823deb3ec6SMatthias Ringwald     // actual data is already in place
4833deb3ec6SMatthias Ringwald     pos += len;
4843deb3ec6SMatthias Ringwald 
4853deb3ec6SMatthias Ringwald     // UIH frames only calc FCS over address + control (5.1.1)
4863deb3ec6SMatthias Ringwald     rfcomm_out_buffer[pos++] =  crc8_calc(rfcomm_out_buffer, 2); // calc fcs
4873deb3ec6SMatthias Ringwald 
4883deb3ec6SMatthias Ringwald     int err = l2cap_send_prepared(multiplexer->l2cap_cid, pos);
4893deb3ec6SMatthias Ringwald 
4903deb3ec6SMatthias Ringwald     return err;
4913deb3ec6SMatthias Ringwald }
4923deb3ec6SMatthias Ringwald 
4933deb3ec6SMatthias Ringwald // C/R Flag in Address
4943deb3ec6SMatthias Ringwald // - terms: initiator = station that creates multiplexer with SABM
4953deb3ec6SMatthias Ringwald // - terms: responder = station that responds to multiplexer setup with UA
4963deb3ec6SMatthias Ringwald // "For SABM, UA, DM and DISC frames C/R bit is set according to Table 1 in GSM 07.10, section 5.2.1.2"
4973deb3ec6SMatthias Ringwald //    - command initiator = 1 /response responder = 1
4983deb3ec6SMatthias Ringwald //    - command responder = 0 /response initiator = 0
4993deb3ec6SMatthias Ringwald // "For UIH frames, the C/R bit is always set according to section 5.4.3.1 in GSM 07.10.
5003deb3ec6SMatthias Ringwald //  This applies independently of what is contained wthin the UIH frames, either data or control messages."
5013deb3ec6SMatthias Ringwald //    - c/r = 1 for frames by initiating station, 0 = for frames by responding station
5023deb3ec6SMatthias Ringwald 
5033deb3ec6SMatthias Ringwald // C/R Flag in Message
5043deb3ec6SMatthias Ringwald // "In the message level, the C/R bit in the command type field is set as stated in section 5.4.6.2 in GSM 07.10."
5053deb3ec6SMatthias Ringwald //   - If the C/R bit is set to 1 the message is a command
5063deb3ec6SMatthias Ringwald //   - if it is set to 0 the message is a response.
5073deb3ec6SMatthias Ringwald 
5083deb3ec6SMatthias Ringwald // temp/old messge construction
5093deb3ec6SMatthias Ringwald 
5103deb3ec6SMatthias Ringwald // new object oriented version
5113deb3ec6SMatthias Ringwald static int rfcomm_send_sabm(rfcomm_multiplexer_t *multiplexer, uint8_t dlci){
5123deb3ec6SMatthias Ringwald 	uint8_t address = (1 << 0) | (multiplexer->outgoing << 1) | (dlci << 2);   // command
5133deb3ec6SMatthias Ringwald     return rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_SABM, 0, NULL, 0);
5143deb3ec6SMatthias Ringwald }
5153deb3ec6SMatthias Ringwald 
5163deb3ec6SMatthias Ringwald static int rfcomm_send_disc(rfcomm_multiplexer_t *multiplexer, uint8_t dlci){
5173deb3ec6SMatthias Ringwald 	uint8_t address = (1 << 0) | (multiplexer->outgoing << 1) | (dlci << 2);  // command
5183deb3ec6SMatthias Ringwald     return rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_DISC, 0, NULL, 0);
5193deb3ec6SMatthias Ringwald }
5203deb3ec6SMatthias Ringwald 
5213deb3ec6SMatthias Ringwald static int rfcomm_send_ua(rfcomm_multiplexer_t *multiplexer, uint8_t dlci){
5223deb3ec6SMatthias Ringwald 	uint8_t address = (1 << 0) | ((multiplexer->outgoing ^ 1) << 1) | (dlci << 2); // response
5233deb3ec6SMatthias Ringwald     return rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_UA, 0, NULL, 0);
5243deb3ec6SMatthias Ringwald }
5253deb3ec6SMatthias Ringwald 
5263deb3ec6SMatthias Ringwald static int rfcomm_send_dm_pf(rfcomm_multiplexer_t *multiplexer, uint8_t dlci){
5273deb3ec6SMatthias Ringwald 	uint8_t address = (1 << 0) | ((multiplexer->outgoing ^ 1) << 1) | (dlci << 2); // response
5283deb3ec6SMatthias Ringwald     return rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_DM_PF, 0, NULL, 0);
5293deb3ec6SMatthias Ringwald }
5303deb3ec6SMatthias Ringwald 
5313deb3ec6SMatthias Ringwald static int rfcomm_send_uih_fc_rsp(rfcomm_multiplexer_t *multiplexer, uint8_t fcon) {
5323deb3ec6SMatthias Ringwald     uint8_t address = (1 << 0) | (multiplexer->outgoing<< 1);
5333deb3ec6SMatthias Ringwald     uint8_t payload[2];
5343deb3ec6SMatthias Ringwald     uint8_t pos = 0;
5353deb3ec6SMatthias Ringwald     payload[pos++] = fcon ? BT_RFCOMM_FCON_RSP : BT_RFCOMM_FCOFF_RSP;
5363deb3ec6SMatthias Ringwald     payload[pos++] = (0 << 1) | 1;  // len
5373deb3ec6SMatthias Ringwald     return rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_UIH, 0, (uint8_t *) payload, pos);
5383deb3ec6SMatthias Ringwald }
5393deb3ec6SMatthias Ringwald 
5403deb3ec6SMatthias Ringwald // static int rfcomm_send_uih_test_cmd(rfcomm_multiplexer_t *multiplexer, uint8_t * data, uint16_t len) {
5413deb3ec6SMatthias Ringwald //     uint8_t address = (1 << 0) | (multiplexer->outgoing << 1);
5423deb3ec6SMatthias Ringwald //     uint8_t payload[2+len];
5433deb3ec6SMatthias Ringwald //     uint8_t pos = 0;
5443deb3ec6SMatthias Ringwald //     payload[pos++] = BT_RFCOMM_TEST_CMD;
5453deb3ec6SMatthias Ringwald //     payload[pos++] = (len + 1) << 1 | 1;  // len
5463deb3ec6SMatthias Ringwald //     memcpy(&payload[pos], data, len);
5473deb3ec6SMatthias Ringwald //     pos += len;
5483deb3ec6SMatthias Ringwald //     return rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_UIH, 0, (uint8_t *) payload, pos);
5493deb3ec6SMatthias Ringwald // }
5503deb3ec6SMatthias Ringwald 
5513deb3ec6SMatthias Ringwald static int rfcomm_send_uih_test_rsp(rfcomm_multiplexer_t *multiplexer, uint8_t * data, uint16_t len) {
5523deb3ec6SMatthias Ringwald     uint8_t address = (1 << 0) | (multiplexer->outgoing << 1);
5533deb3ec6SMatthias Ringwald     uint8_t payload[2+RFCOMM_TEST_DATA_MAX_LEN];
5543deb3ec6SMatthias Ringwald     uint8_t pos = 0;
5553deb3ec6SMatthias Ringwald     payload[pos++] = BT_RFCOMM_TEST_RSP;
5563deb3ec6SMatthias Ringwald     if (len > RFCOMM_TEST_DATA_MAX_LEN) {
5573deb3ec6SMatthias Ringwald         len = RFCOMM_TEST_DATA_MAX_LEN;
5583deb3ec6SMatthias Ringwald     }
5593deb3ec6SMatthias Ringwald     payload[pos++] = (len << 1) | 1;  // len
5603deb3ec6SMatthias Ringwald     memcpy(&payload[pos], data, len);
5613deb3ec6SMatthias Ringwald     pos += len;
5623deb3ec6SMatthias Ringwald     return rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_UIH, 0, (uint8_t *) payload, pos);
5633deb3ec6SMatthias Ringwald }
5643deb3ec6SMatthias Ringwald 
5653deb3ec6SMatthias Ringwald static int rfcomm_send_uih_msc_cmd(rfcomm_multiplexer_t *multiplexer, uint8_t dlci, uint8_t signals) {
5663deb3ec6SMatthias Ringwald 	uint8_t address = (1 << 0) | (multiplexer->outgoing << 1);
5673deb3ec6SMatthias Ringwald 	uint8_t payload[4];
5683deb3ec6SMatthias Ringwald 	uint8_t pos = 0;
5693deb3ec6SMatthias Ringwald 	payload[pos++] = BT_RFCOMM_MSC_CMD;
5703deb3ec6SMatthias Ringwald 	payload[pos++] = (2 << 1) | 1;  // len
5713deb3ec6SMatthias Ringwald 	payload[pos++] = (1 << 0) | (1 << 1) | (dlci << 2); // CMD => C/R = 1
5723deb3ec6SMatthias Ringwald 	payload[pos++] = signals;
5733deb3ec6SMatthias Ringwald 	return rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_UIH, 0, (uint8_t *) payload, pos);
5743deb3ec6SMatthias Ringwald }
5753deb3ec6SMatthias Ringwald 
5763deb3ec6SMatthias Ringwald static int rfcomm_send_uih_msc_rsp(rfcomm_multiplexer_t *multiplexer, uint8_t dlci, uint8_t signals) {
5773deb3ec6SMatthias Ringwald 	uint8_t address = (1 << 0) | (multiplexer->outgoing<< 1);
5783deb3ec6SMatthias Ringwald 	uint8_t payload[4];
5793deb3ec6SMatthias Ringwald 	uint8_t pos = 0;
5803deb3ec6SMatthias Ringwald 	payload[pos++] = BT_RFCOMM_MSC_RSP;
5813deb3ec6SMatthias Ringwald 	payload[pos++] = (2 << 1) | 1;  // len
5823deb3ec6SMatthias Ringwald 	payload[pos++] = (1 << 0) | (1 << 1) | (dlci << 2); // CMD => C/R = 1
5833deb3ec6SMatthias Ringwald 	payload[pos++] = signals;
5843deb3ec6SMatthias Ringwald 	return rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_UIH, 0, (uint8_t *) payload, pos);
5853deb3ec6SMatthias Ringwald }
5863deb3ec6SMatthias Ringwald 
5873deb3ec6SMatthias Ringwald static int rfcomm_send_uih_nsc_rsp(rfcomm_multiplexer_t *multiplexer, uint8_t command) {
5883deb3ec6SMatthias Ringwald     uint8_t address = (1 << 0) | (multiplexer->outgoing<< 1);
5893deb3ec6SMatthias Ringwald     uint8_t payload[3];
5903deb3ec6SMatthias Ringwald     uint8_t pos = 0;
5913deb3ec6SMatthias Ringwald     payload[pos++] = BT_RFCOMM_NSC_RSP;
5923deb3ec6SMatthias Ringwald     payload[pos++] = (1 << 1) | 1;  // len
5933deb3ec6SMatthias Ringwald     payload[pos++] = command;
5943deb3ec6SMatthias Ringwald     return rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_UIH, 0, (uint8_t *) payload, pos);
5953deb3ec6SMatthias Ringwald }
5963deb3ec6SMatthias Ringwald 
5973deb3ec6SMatthias Ringwald static int rfcomm_send_uih_pn_command(rfcomm_multiplexer_t *multiplexer, uint8_t dlci, uint16_t max_frame_size){
5983deb3ec6SMatthias Ringwald 	uint8_t payload[10];
5993deb3ec6SMatthias Ringwald 	uint8_t address = (1 << 0) | (multiplexer->outgoing << 1);
6003deb3ec6SMatthias Ringwald 	uint8_t pos = 0;
6013deb3ec6SMatthias Ringwald 	payload[pos++] = BT_RFCOMM_PN_CMD;
6023deb3ec6SMatthias Ringwald 	payload[pos++] = (8 << 1) | 1;  // len
6033deb3ec6SMatthias Ringwald 	payload[pos++] = dlci;
6043deb3ec6SMatthias Ringwald 	payload[pos++] = 0xf0; // pre-defined for Bluetooth, see 5.5.3 of TS 07.10 Adaption for RFCOMM
6053deb3ec6SMatthias Ringwald 	payload[pos++] = 0; // priority
6063deb3ec6SMatthias Ringwald 	payload[pos++] = 0; // max 60 seconds ack
6073deb3ec6SMatthias Ringwald 	payload[pos++] = max_frame_size & 0xff; // max framesize low
6083deb3ec6SMatthias Ringwald 	payload[pos++] = max_frame_size >> 8;   // max framesize high
6093deb3ec6SMatthias Ringwald 	payload[pos++] = 0x00; // number of retransmissions
6103deb3ec6SMatthias Ringwald 	payload[pos++] = 0x00; // (unused error recovery window) initial number of credits
6113deb3ec6SMatthias Ringwald 	return rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_UIH, 0, (uint8_t *) payload, pos);
6123deb3ec6SMatthias Ringwald }
6133deb3ec6SMatthias Ringwald 
614d6549a6eSMatthias Ringwald // "The response may not change the DLCI, the priority, the convergence layer, or the timer value." rfcomm_tutorial.pdf
6153deb3ec6SMatthias Ringwald static int rfcomm_send_uih_pn_response(rfcomm_multiplexer_t *multiplexer, uint8_t dlci,
6163deb3ec6SMatthias Ringwald                                        uint8_t priority, uint16_t max_frame_size){
6173deb3ec6SMatthias Ringwald 	uint8_t payload[10];
6183deb3ec6SMatthias Ringwald 	uint8_t address = (1 << 0) | (multiplexer->outgoing << 1);
6193deb3ec6SMatthias Ringwald 	uint8_t pos = 0;
6203deb3ec6SMatthias Ringwald 	payload[pos++] = BT_RFCOMM_PN_RSP;
6213deb3ec6SMatthias Ringwald 	payload[pos++] = (8 << 1) | 1;  // len
6223deb3ec6SMatthias Ringwald 	payload[pos++] = dlci;
6233deb3ec6SMatthias Ringwald 	payload[pos++] = 0xe0; // pre defined for Bluetooth, see 5.5.3 of TS 07.10 Adaption for RFCOMM
6243deb3ec6SMatthias Ringwald 	payload[pos++] = priority; // priority
6253deb3ec6SMatthias Ringwald 	payload[pos++] = 0; // max 60 seconds ack
6263deb3ec6SMatthias Ringwald 	payload[pos++] = max_frame_size & 0xff; // max framesize low
6273deb3ec6SMatthias Ringwald 	payload[pos++] = max_frame_size >> 8;   // max framesize high
6283deb3ec6SMatthias Ringwald 	payload[pos++] = 0x00; // number of retransmissions
6293deb3ec6SMatthias Ringwald 	payload[pos++] = 0x00; // (unused error recovery window) initial number of credits
6303deb3ec6SMatthias Ringwald 	return rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_UIH, 0, (uint8_t *) payload, pos);
6313deb3ec6SMatthias Ringwald }
6323deb3ec6SMatthias Ringwald 
6333deb3ec6SMatthias Ringwald static int rfcomm_send_uih_rls_cmd(rfcomm_multiplexer_t *multiplexer, uint8_t dlci, uint8_t line_status) {
6343deb3ec6SMatthias Ringwald     uint8_t address = (1 << 0) | (multiplexer->outgoing << 1);
6353deb3ec6SMatthias Ringwald     uint8_t payload[4];
6363deb3ec6SMatthias Ringwald     uint8_t pos = 0;
6373deb3ec6SMatthias Ringwald     payload[pos++] = BT_RFCOMM_RLS_CMD;
6383deb3ec6SMatthias Ringwald     payload[pos++] = (2 << 1) | 1;  // len
6393deb3ec6SMatthias Ringwald     payload[pos++] = (1 << 0) | (1 << 1) | (dlci << 2); // CMD => C/R = 1
6403deb3ec6SMatthias Ringwald     payload[pos++] = line_status;
6413deb3ec6SMatthias Ringwald     return rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_UIH, 0, (uint8_t *) payload, pos);
6423deb3ec6SMatthias Ringwald }
6433deb3ec6SMatthias Ringwald 
6443deb3ec6SMatthias Ringwald static int rfcomm_send_uih_rls_rsp(rfcomm_multiplexer_t *multiplexer, uint8_t dlci, uint8_t line_status) {
6453deb3ec6SMatthias Ringwald     uint8_t address = (1 << 0) | (multiplexer->outgoing << 1);
6463deb3ec6SMatthias Ringwald     uint8_t payload[4];
6473deb3ec6SMatthias Ringwald     uint8_t pos = 0;
6483deb3ec6SMatthias Ringwald     payload[pos++] = BT_RFCOMM_RLS_RSP;
6493deb3ec6SMatthias Ringwald     payload[pos++] = (2 << 1) | 1;  // len
6503deb3ec6SMatthias Ringwald     payload[pos++] = (1 << 0) | (1 << 1) | (dlci << 2); // CMD => C/R = 1
6513deb3ec6SMatthias Ringwald     payload[pos++] = line_status;
6523deb3ec6SMatthias Ringwald     return rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_UIH, 0, (uint8_t *) payload, pos);
6533deb3ec6SMatthias Ringwald }
6543deb3ec6SMatthias Ringwald 
6553deb3ec6SMatthias Ringwald static int rfcomm_send_uih_rpn_cmd(rfcomm_multiplexer_t *multiplexer, uint8_t dlci, rfcomm_rpn_data_t *rpn_data) {
6563deb3ec6SMatthias Ringwald     uint8_t payload[10];
6573deb3ec6SMatthias Ringwald     uint8_t address = (1 << 0) | (multiplexer->outgoing << 1);
6583deb3ec6SMatthias Ringwald     uint8_t pos = 0;
6593deb3ec6SMatthias Ringwald     payload[pos++] = BT_RFCOMM_RPN_CMD;
6603deb3ec6SMatthias Ringwald     payload[pos++] = (8 << 1) | 1;  // len
6613deb3ec6SMatthias Ringwald     payload[pos++] = (1 << 0) | (1 << 1) | (dlci << 2); // CMD => C/R = 1
6623deb3ec6SMatthias Ringwald     payload[pos++] = rpn_data->baud_rate;
6633deb3ec6SMatthias Ringwald     payload[pos++] = rpn_data->flags;
6643deb3ec6SMatthias Ringwald     payload[pos++] = rpn_data->flow_control;
6653deb3ec6SMatthias Ringwald     payload[pos++] = rpn_data->xon;
6663deb3ec6SMatthias Ringwald     payload[pos++] = rpn_data->xoff;
6673deb3ec6SMatthias Ringwald     payload[pos++] = rpn_data->parameter_mask_0;
6683deb3ec6SMatthias Ringwald     payload[pos++] = rpn_data->parameter_mask_1;
6693deb3ec6SMatthias Ringwald     return rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_UIH, 0, (uint8_t *) payload, pos);
6703deb3ec6SMatthias Ringwald }
6713deb3ec6SMatthias Ringwald 
6723deb3ec6SMatthias Ringwald static int rfcomm_send_uih_rpn_req(rfcomm_multiplexer_t *multiplexer, uint8_t dlci) {
6733deb3ec6SMatthias Ringwald     uint8_t payload[3];
6743deb3ec6SMatthias Ringwald     uint8_t address = (1 << 0) | (multiplexer->outgoing << 1);
6753deb3ec6SMatthias Ringwald     uint8_t pos = 0;
6763deb3ec6SMatthias Ringwald     payload[pos++] = BT_RFCOMM_RPN_CMD;
6773deb3ec6SMatthias Ringwald     payload[pos++] = (1 << 1) | 1;  // len
6783deb3ec6SMatthias Ringwald     payload[pos++] = (1 << 0) | (1 << 1) | (dlci << 2); // CMD => C/R = 1
6793deb3ec6SMatthias Ringwald     return rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_UIH, 0, (uint8_t *) payload, pos);
6803deb3ec6SMatthias Ringwald }
6813deb3ec6SMatthias Ringwald 
6823deb3ec6SMatthias Ringwald static int rfcomm_send_uih_rpn_rsp(rfcomm_multiplexer_t *multiplexer, uint8_t dlci, rfcomm_rpn_data_t *rpn_data) {
6833deb3ec6SMatthias Ringwald 	uint8_t payload[10];
6843deb3ec6SMatthias Ringwald 	uint8_t address = (1 << 0) | (multiplexer->outgoing << 1);
6853deb3ec6SMatthias Ringwald 	uint8_t pos = 0;
6863deb3ec6SMatthias Ringwald 	payload[pos++] = BT_RFCOMM_RPN_RSP;
6873deb3ec6SMatthias Ringwald 	payload[pos++] = (8 << 1) | 1;  // len
6883deb3ec6SMatthias Ringwald 	payload[pos++] = (1 << 0) | (1 << 1) | (dlci << 2); // CMD => C/R = 1
6893deb3ec6SMatthias Ringwald 	payload[pos++] = rpn_data->baud_rate;
6903deb3ec6SMatthias Ringwald 	payload[pos++] = rpn_data->flags;
6913deb3ec6SMatthias Ringwald 	payload[pos++] = rpn_data->flow_control;
6923deb3ec6SMatthias Ringwald 	payload[pos++] = rpn_data->xon;
6933deb3ec6SMatthias Ringwald 	payload[pos++] = rpn_data->xoff;
6943deb3ec6SMatthias Ringwald 	payload[pos++] = rpn_data->parameter_mask_0;
6953deb3ec6SMatthias Ringwald 	payload[pos++] = rpn_data->parameter_mask_1;
6963deb3ec6SMatthias Ringwald 	return rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_UIH, 0, (uint8_t *) payload, pos);
6973deb3ec6SMatthias Ringwald }
6983deb3ec6SMatthias Ringwald 
6993deb3ec6SMatthias Ringwald static void rfcomm_send_uih_credits(rfcomm_multiplexer_t *multiplexer, uint8_t dlci,  uint8_t credits){
7003deb3ec6SMatthias Ringwald     uint8_t address = (1 << 0) | (multiplexer->outgoing << 1) |  (dlci << 2);
7013deb3ec6SMatthias Ringwald     rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_UIH_PF, credits, NULL, 0);
7023deb3ec6SMatthias Ringwald }
7033deb3ec6SMatthias Ringwald 
7043deb3ec6SMatthias Ringwald // MARK: RFCOMM MULTIPLEXER
7053deb3ec6SMatthias Ringwald static void rfcomm_multiplexer_stop_timer(rfcomm_multiplexer_t * multiplexer){
7063deb3ec6SMatthias Ringwald     if (multiplexer->timer_active) {
707528a4a3bSMatthias Ringwald         btstack_run_loop_remove_timer(&multiplexer->timer);
7083deb3ec6SMatthias Ringwald         multiplexer->timer_active = 0;
7093deb3ec6SMatthias Ringwald     }
7103deb3ec6SMatthias Ringwald }
7113deb3ec6SMatthias Ringwald static void rfcomm_multiplexer_free(rfcomm_multiplexer_t * multiplexer){
712665d90f2SMatthias Ringwald     btstack_linked_list_remove( &rfcomm_multiplexers, (btstack_linked_item_t *) multiplexer);
7133deb3ec6SMatthias Ringwald     btstack_memory_rfcomm_multiplexer_free(multiplexer);
7143deb3ec6SMatthias Ringwald }
7153deb3ec6SMatthias Ringwald 
7163deb3ec6SMatthias Ringwald static void rfcomm_multiplexer_finalize(rfcomm_multiplexer_t * multiplexer){
7173deb3ec6SMatthias Ringwald     // remove (potential) timer
7183deb3ec6SMatthias Ringwald     rfcomm_multiplexer_stop_timer(multiplexer);
7193deb3ec6SMatthias Ringwald 
7203deb3ec6SMatthias Ringwald     // close and remove all channels
721665d90f2SMatthias Ringwald     btstack_linked_item_t *it = (btstack_linked_item_t *) &rfcomm_channels;
7223deb3ec6SMatthias Ringwald     while (it->next){
7233deb3ec6SMatthias Ringwald         rfcomm_channel_t * channel = (rfcomm_channel_t *) it->next;
7243deb3ec6SMatthias Ringwald         if (channel->multiplexer == multiplexer) {
7253deb3ec6SMatthias Ringwald             // emit appropriate events
7263deb3ec6SMatthias Ringwald             if (channel->state == RFCOMM_CHANNEL_OPEN) {
7273deb3ec6SMatthias Ringwald                 rfcomm_emit_channel_closed(channel);
7283deb3ec6SMatthias Ringwald             } else {
7293deb3ec6SMatthias Ringwald                 rfcomm_emit_channel_opened(channel, RFCOMM_MULTIPLEXER_STOPPED);
7303deb3ec6SMatthias Ringwald             }
7313deb3ec6SMatthias Ringwald             // remove from list
7323deb3ec6SMatthias Ringwald             it->next = it->next->next;
7333deb3ec6SMatthias Ringwald             // free channel struct
7343deb3ec6SMatthias Ringwald             btstack_memory_rfcomm_channel_free(channel);
7353deb3ec6SMatthias Ringwald         } else {
7363deb3ec6SMatthias Ringwald             it = it->next;
7373deb3ec6SMatthias Ringwald         }
7383deb3ec6SMatthias Ringwald     }
7393deb3ec6SMatthias Ringwald 
7403deb3ec6SMatthias Ringwald     // remove mutliplexer
7413deb3ec6SMatthias Ringwald     rfcomm_multiplexer_free(multiplexer);
7423deb3ec6SMatthias Ringwald }
7433deb3ec6SMatthias Ringwald 
744ec820d77SMatthias Ringwald static void rfcomm_multiplexer_timer_handler(btstack_timer_source_t *timer){
745c5b64319SMatthias Ringwald     rfcomm_multiplexer_t * multiplexer = (rfcomm_multiplexer_t*) btstack_run_loop_get_timer_context(timer);
7463deb3ec6SMatthias Ringwald     if (rfcomm_multiplexer_has_channels(multiplexer)) return;
7473deb3ec6SMatthias Ringwald 
7483deb3ec6SMatthias Ringwald     log_info("rfcomm_multiplexer_timer_handler timeout: shutting down multiplexer! (no channels)");
7493deb3ec6SMatthias Ringwald     uint16_t l2cap_cid = multiplexer->l2cap_cid;
7503deb3ec6SMatthias Ringwald     rfcomm_multiplexer_finalize(multiplexer);
751ce8f182eSMatthias Ringwald     l2cap_disconnect(l2cap_cid, 0x13);
7523deb3ec6SMatthias Ringwald }
7533deb3ec6SMatthias Ringwald 
7543deb3ec6SMatthias Ringwald static void rfcomm_multiplexer_prepare_idle_timer(rfcomm_multiplexer_t * multiplexer){
7553deb3ec6SMatthias Ringwald     if (multiplexer->timer_active) {
756528a4a3bSMatthias Ringwald         btstack_run_loop_remove_timer(&multiplexer->timer);
7573deb3ec6SMatthias Ringwald         multiplexer->timer_active = 0;
7583deb3ec6SMatthias Ringwald     }
7593deb3ec6SMatthias Ringwald     if (rfcomm_multiplexer_has_channels(multiplexer)) return;
7603deb3ec6SMatthias Ringwald 
7613deb3ec6SMatthias Ringwald     // start idle timer for multiplexer timeout check as there are no rfcomm channels yet
762528a4a3bSMatthias Ringwald     btstack_run_loop_set_timer(&multiplexer->timer, RFCOMM_MULIPLEXER_TIMEOUT_MS);
76391a977e8SMatthias Ringwald     btstack_run_loop_set_timer_handler(&multiplexer->timer, rfcomm_multiplexer_timer_handler);
76491a977e8SMatthias Ringwald     btstack_run_loop_set_timer_context(&multiplexer->timer, multiplexer);
765528a4a3bSMatthias Ringwald     btstack_run_loop_add_timer(&multiplexer->timer);
7663deb3ec6SMatthias Ringwald     multiplexer->timer_active = 1;
7673deb3ec6SMatthias Ringwald }
7683deb3ec6SMatthias Ringwald 
7693deb3ec6SMatthias Ringwald static void rfcomm_multiplexer_opened(rfcomm_multiplexer_t *multiplexer){
7703deb3ec6SMatthias Ringwald     log_info("Multiplexer up and running");
7713deb3ec6SMatthias Ringwald     multiplexer->state = RFCOMM_MULTIPLEXER_OPEN;
7723deb3ec6SMatthias Ringwald 
7733deb3ec6SMatthias Ringwald     rfcomm_channel_event_t event = { CH_EVT_MULTIPLEXER_READY };
7743deb3ec6SMatthias Ringwald 
7753deb3ec6SMatthias Ringwald     // transition of channels that wait for multiplexer
776665d90f2SMatthias Ringwald     btstack_linked_item_t *it;
777665d90f2SMatthias Ringwald     for (it = (btstack_linked_item_t *) rfcomm_channels; it ; it = it->next){
7783deb3ec6SMatthias Ringwald         rfcomm_channel_t * channel = ((rfcomm_channel_t *) it);
7793deb3ec6SMatthias Ringwald         if (channel->multiplexer != multiplexer) continue;
7803deb3ec6SMatthias Ringwald         rfcomm_channel_state_machine(channel, &event);
7813deb3ec6SMatthias Ringwald     }
7823deb3ec6SMatthias Ringwald 
7833deb3ec6SMatthias Ringwald     rfcomm_run();
7843deb3ec6SMatthias Ringwald     rfcomm_multiplexer_prepare_idle_timer(multiplexer);
7853deb3ec6SMatthias Ringwald }
7863deb3ec6SMatthias Ringwald 
7873deb3ec6SMatthias Ringwald 
7883deb3ec6SMatthias Ringwald /**
7893deb3ec6SMatthias Ringwald  * @return handled packet
7903deb3ec6SMatthias Ringwald  */
7913deb3ec6SMatthias Ringwald static int rfcomm_multiplexer_hci_event_handler(uint8_t *packet, uint16_t size){
7923deb3ec6SMatthias Ringwald     bd_addr_t event_addr;
7933deb3ec6SMatthias Ringwald     uint16_t  psm;
7943deb3ec6SMatthias Ringwald     uint16_t l2cap_cid;
7953deb3ec6SMatthias Ringwald     hci_con_handle_t con_handle;
7963deb3ec6SMatthias Ringwald     rfcomm_multiplexer_t *multiplexer = NULL;
7973deb3ec6SMatthias Ringwald     uint8_t status;
7983deb3ec6SMatthias Ringwald 
7993deb3ec6SMatthias Ringwald     switch (packet[0]) {
8003deb3ec6SMatthias Ringwald 
8013deb3ec6SMatthias Ringwald         // accept incoming PSM_RFCOMM connection if no multiplexer exists yet
8023deb3ec6SMatthias Ringwald         case L2CAP_EVENT_INCOMING_CONNECTION:
8033deb3ec6SMatthias Ringwald             // data: event(8), len(8), address(48), handle (16),  psm (16), source cid(16) dest cid(16)
804*724d70a2SMatthias Ringwald             reverse_bd_addr(&packet[2], event_addr);
805f8fbdce0SMatthias Ringwald             con_handle = little_endian_read_16(packet,  8);
806f8fbdce0SMatthias Ringwald             psm        = little_endian_read_16(packet, 10);
807f8fbdce0SMatthias Ringwald             l2cap_cid  = little_endian_read_16(packet, 12);
8083deb3ec6SMatthias Ringwald 
8093deb3ec6SMatthias Ringwald             if (psm != PSM_RFCOMM) break;
8103deb3ec6SMatthias Ringwald 
8113deb3ec6SMatthias Ringwald             multiplexer = rfcomm_multiplexer_for_addr(event_addr);
8123deb3ec6SMatthias Ringwald 
8133deb3ec6SMatthias Ringwald             if (multiplexer) {
8143deb3ec6SMatthias Ringwald                 log_info("INCOMING_CONNECTION (l2cap_cid 0x%02x) for PSM_RFCOMM => decline - multiplexer already exists", l2cap_cid);
815ce8f182eSMatthias Ringwald                 l2cap_decline_connection(l2cap_cid,  0x04);    // no resources available
8163deb3ec6SMatthias Ringwald                 return 1;
8173deb3ec6SMatthias Ringwald             }
8183deb3ec6SMatthias Ringwald 
8193deb3ec6SMatthias Ringwald             // create and inititialize new multiplexer instance (incoming)
8203deb3ec6SMatthias Ringwald             multiplexer = rfcomm_multiplexer_create_for_addr(event_addr);
8213deb3ec6SMatthias Ringwald             if (!multiplexer){
8223deb3ec6SMatthias Ringwald                 log_info("INCOMING_CONNECTION (l2cap_cid 0x%02x) for PSM_RFCOMM => decline - no memory left", l2cap_cid);
823ce8f182eSMatthias Ringwald                 l2cap_decline_connection(l2cap_cid,  0x04);    // no resources available
8243deb3ec6SMatthias Ringwald                 return 1;
8253deb3ec6SMatthias Ringwald             }
8263deb3ec6SMatthias Ringwald 
8273deb3ec6SMatthias Ringwald             multiplexer->con_handle = con_handle;
8283deb3ec6SMatthias Ringwald             multiplexer->l2cap_cid = l2cap_cid;
8293deb3ec6SMatthias Ringwald             multiplexer->state = RFCOMM_MULTIPLEXER_W4_SABM_0;
8303deb3ec6SMatthias Ringwald 
8313deb3ec6SMatthias Ringwald             log_info("L2CAP_EVENT_INCOMING_CONNECTION (l2cap_cid 0x%02x) for PSM_RFCOMM => accept", l2cap_cid);
832ce8f182eSMatthias Ringwald             l2cap_accept_connection(l2cap_cid);
8333deb3ec6SMatthias Ringwald             return 1;
8343deb3ec6SMatthias Ringwald 
8353deb3ec6SMatthias Ringwald         // l2cap connection opened -> store l2cap_cid, remote_addr
8363deb3ec6SMatthias Ringwald         case L2CAP_EVENT_CHANNEL_OPENED:
8373deb3ec6SMatthias Ringwald 
838f8fbdce0SMatthias Ringwald             if (little_endian_read_16(packet, 11) != PSM_RFCOMM) break;
8393deb3ec6SMatthias Ringwald 
8403deb3ec6SMatthias Ringwald             status = packet[2];
8413deb3ec6SMatthias Ringwald             log_info("L2CAP_EVENT_CHANNEL_OPENED for PSM_RFCOMM, status %u", status);
8423deb3ec6SMatthias Ringwald 
8433deb3ec6SMatthias Ringwald             // get multiplexer for remote addr
844f8fbdce0SMatthias Ringwald             con_handle = little_endian_read_16(packet, 9);
845f8fbdce0SMatthias Ringwald             l2cap_cid = little_endian_read_16(packet, 13);
846*724d70a2SMatthias Ringwald             reverse_bd_addr(&packet[3], event_addr);
8473deb3ec6SMatthias Ringwald             multiplexer = rfcomm_multiplexer_for_addr(event_addr);
8483deb3ec6SMatthias Ringwald             if (!multiplexer) {
8493deb3ec6SMatthias Ringwald                 log_error("L2CAP_EVENT_CHANNEL_OPENED but no multiplexer prepared");
8503deb3ec6SMatthias Ringwald                 return 1;
8513deb3ec6SMatthias Ringwald             }
8523deb3ec6SMatthias Ringwald 
8533deb3ec6SMatthias Ringwald             // on l2cap open error discard everything
8543deb3ec6SMatthias Ringwald             if (status){
8553deb3ec6SMatthias Ringwald 
8563deb3ec6SMatthias Ringwald                 // remove (potential) timer
8573deb3ec6SMatthias Ringwald                 rfcomm_multiplexer_stop_timer(multiplexer);
8583deb3ec6SMatthias Ringwald 
8593deb3ec6SMatthias Ringwald                 // emit rfcomm_channel_opened with status and free channel
860665d90f2SMatthias Ringwald                 btstack_linked_item_t * it = (btstack_linked_item_t *) &rfcomm_channels;
8613deb3ec6SMatthias Ringwald                 while (it->next) {
8623deb3ec6SMatthias Ringwald                     rfcomm_channel_t * channel = (rfcomm_channel_t *) it->next;
8633deb3ec6SMatthias Ringwald                     if (channel->multiplexer == multiplexer){
8643deb3ec6SMatthias Ringwald                         rfcomm_emit_channel_opened(channel, status);
8653deb3ec6SMatthias Ringwald                         it->next = it->next->next;
8663deb3ec6SMatthias Ringwald                         btstack_memory_rfcomm_channel_free(channel);
8673deb3ec6SMatthias Ringwald                     } else {
8683deb3ec6SMatthias Ringwald                         it = it->next;
8693deb3ec6SMatthias Ringwald                     }
8703deb3ec6SMatthias Ringwald                 }
8713deb3ec6SMatthias Ringwald 
8723deb3ec6SMatthias Ringwald                 // free multiplexer
8733deb3ec6SMatthias Ringwald                 rfcomm_multiplexer_free(multiplexer);
8743deb3ec6SMatthias Ringwald                 return 1;
8753deb3ec6SMatthias Ringwald             }
8763deb3ec6SMatthias Ringwald 
8773deb3ec6SMatthias Ringwald             if (multiplexer->state == RFCOMM_MULTIPLEXER_W4_CONNECT) {
8783deb3ec6SMatthias Ringwald                 log_info("L2CAP_EVENT_CHANNEL_OPENED: outgoing connection");
8793deb3ec6SMatthias Ringwald                 // wrong remote addr
880058e3d6bSMatthias Ringwald                 if (bd_addr_cmp(event_addr, multiplexer->remote_addr)) break;
8813deb3ec6SMatthias Ringwald                 multiplexer->l2cap_cid = l2cap_cid;
8823deb3ec6SMatthias Ringwald                 multiplexer->con_handle = con_handle;
8833deb3ec6SMatthias Ringwald                 // send SABM #0
8843deb3ec6SMatthias Ringwald                 multiplexer->state = RFCOMM_MULTIPLEXER_SEND_SABM_0;
8853deb3ec6SMatthias Ringwald             } else { // multiplexer->state == RFCOMM_MULTIPLEXER_W4_SABM_0
8863deb3ec6SMatthias Ringwald 
8873deb3ec6SMatthias Ringwald                 // set max frame size based on l2cap MTU
888f8fbdce0SMatthias Ringwald                 multiplexer->max_frame_size = rfcomm_max_frame_size_for_l2cap_mtu(little_endian_read_16(packet, 17));
8893deb3ec6SMatthias Ringwald             }
8903deb3ec6SMatthias Ringwald             return 1;
8913deb3ec6SMatthias Ringwald 
8923deb3ec6SMatthias Ringwald             // l2cap disconnect -> state = RFCOMM_MULTIPLEXER_CLOSED;
8933deb3ec6SMatthias Ringwald 
894b31d33b2SMatthias Ringwald         // Notify channel packet handler if they can send now
895b31d33b2SMatthias Ringwald         case L2CAP_EVENT_CAN_SEND_NOW:
896b31d33b2SMatthias Ringwald             rfcomm_run();   // rfcomm signaling packets first
897b31d33b2SMatthias Ringwald             rfcomm_notify_channel_can_send();
8983deb3ec6SMatthias Ringwald             break;
8993deb3ec6SMatthias Ringwald 
9003deb3ec6SMatthias Ringwald         case L2CAP_EVENT_CHANNEL_CLOSED:
9013deb3ec6SMatthias Ringwald             // data: event (8), len(8), channel (16)
902f8fbdce0SMatthias Ringwald             l2cap_cid = little_endian_read_16(packet, 2);
9033deb3ec6SMatthias Ringwald             multiplexer = rfcomm_multiplexer_for_l2cap_cid(l2cap_cid);
9043deb3ec6SMatthias Ringwald             log_info("L2CAP_EVENT_CHANNEL_CLOSED cid 0x%0x, mult %p", l2cap_cid, multiplexer);
9053deb3ec6SMatthias Ringwald             if (!multiplexer) break;
9063deb3ec6SMatthias Ringwald             log_info("L2CAP_EVENT_CHANNEL_CLOSED state %u", multiplexer->state);
9073deb3ec6SMatthias Ringwald             switch (multiplexer->state) {
9083deb3ec6SMatthias Ringwald                 case RFCOMM_MULTIPLEXER_W4_CONNECT:
9093deb3ec6SMatthias Ringwald                 case RFCOMM_MULTIPLEXER_SEND_SABM_0:
9103deb3ec6SMatthias Ringwald                 case RFCOMM_MULTIPLEXER_W4_SABM_0:
9113deb3ec6SMatthias Ringwald                 case RFCOMM_MULTIPLEXER_SEND_UA_0:
9123deb3ec6SMatthias Ringwald                 case RFCOMM_MULTIPLEXER_W4_UA_0:
9133deb3ec6SMatthias Ringwald                 case RFCOMM_MULTIPLEXER_OPEN:
9143deb3ec6SMatthias Ringwald                     // don't call l2cap_disconnect as it's alreay closed
9153deb3ec6SMatthias Ringwald                     rfcomm_multiplexer_finalize(multiplexer);
9163deb3ec6SMatthias Ringwald                     return 1;
9173deb3ec6SMatthias Ringwald                 default:
9183deb3ec6SMatthias Ringwald                     break;
9193deb3ec6SMatthias Ringwald             }
9203deb3ec6SMatthias Ringwald             break;
9213deb3ec6SMatthias Ringwald         default:
9223deb3ec6SMatthias Ringwald             break;
9233deb3ec6SMatthias Ringwald     }
9243deb3ec6SMatthias Ringwald     return 0;
9253deb3ec6SMatthias Ringwald }
9263deb3ec6SMatthias Ringwald 
9273deb3ec6SMatthias Ringwald static int rfcomm_multiplexer_l2cap_packet_handler(uint16_t channel, uint8_t *packet, uint16_t size){
9283deb3ec6SMatthias Ringwald 
9293deb3ec6SMatthias Ringwald     // get or create a multiplexer for a certain device
9303deb3ec6SMatthias Ringwald     rfcomm_multiplexer_t *multiplexer = rfcomm_multiplexer_for_l2cap_cid(channel);
9313deb3ec6SMatthias Ringwald     if (!multiplexer) return 0;
9323deb3ec6SMatthias Ringwald 
9333deb3ec6SMatthias Ringwald     uint16_t l2cap_cid = multiplexer->l2cap_cid;
9343deb3ec6SMatthias Ringwald 
9353deb3ec6SMatthias Ringwald 	// but only care for multiplexer control channel
9363deb3ec6SMatthias Ringwald     uint8_t frame_dlci = packet[0] >> 2;
9373deb3ec6SMatthias Ringwald     if (frame_dlci) return 0;
9383deb3ec6SMatthias Ringwald     const uint8_t length_offset = (packet[2] & 1) ^ 1;  // to be used for pos >= 3
9393deb3ec6SMatthias Ringwald     const uint8_t credit_offset = ((packet[1] & BT_RFCOMM_UIH_PF) == BT_RFCOMM_UIH_PF) ? 1 : 0;   // credits for uih_pf frames
9403deb3ec6SMatthias Ringwald     const uint8_t payload_offset = 3 + length_offset + credit_offset;
9413deb3ec6SMatthias Ringwald     switch (packet[1]){
9423deb3ec6SMatthias Ringwald 
9433deb3ec6SMatthias Ringwald         case BT_RFCOMM_SABM:
9443deb3ec6SMatthias Ringwald             if (multiplexer->state == RFCOMM_MULTIPLEXER_W4_SABM_0){
9453deb3ec6SMatthias Ringwald                 log_info("Received SABM #0");
9463deb3ec6SMatthias Ringwald                 multiplexer->outgoing = 0;
9473deb3ec6SMatthias Ringwald                 multiplexer->state = RFCOMM_MULTIPLEXER_SEND_UA_0;
9483deb3ec6SMatthias Ringwald                 return 1;
9493deb3ec6SMatthias Ringwald             }
9503deb3ec6SMatthias Ringwald             break;
9513deb3ec6SMatthias Ringwald 
9523deb3ec6SMatthias Ringwald         case BT_RFCOMM_UA:
9533deb3ec6SMatthias Ringwald             if (multiplexer->state == RFCOMM_MULTIPLEXER_W4_UA_0) {
9543deb3ec6SMatthias Ringwald                 // UA #0 -> send UA #0, state = RFCOMM_MULTIPLEXER_OPEN
9553deb3ec6SMatthias Ringwald                 log_info("Received UA #0 ");
9563deb3ec6SMatthias Ringwald                 rfcomm_multiplexer_opened(multiplexer);
9573deb3ec6SMatthias Ringwald                 return 1;
9583deb3ec6SMatthias Ringwald             }
9593deb3ec6SMatthias Ringwald             break;
9603deb3ec6SMatthias Ringwald 
9613deb3ec6SMatthias Ringwald         case BT_RFCOMM_DISC:
9623deb3ec6SMatthias Ringwald             // DISC #0 -> send UA #0, close multiplexer
9633deb3ec6SMatthias Ringwald             log_info("Received DISC #0, (ougoing = %u)", multiplexer->outgoing);
9643deb3ec6SMatthias Ringwald             multiplexer->state = RFCOMM_MULTIPLEXER_SEND_UA_0_AND_DISC;
9653deb3ec6SMatthias Ringwald             return 1;
9663deb3ec6SMatthias Ringwald 
9673deb3ec6SMatthias Ringwald         case BT_RFCOMM_DM:
9683deb3ec6SMatthias Ringwald             // DM #0 - we shouldn't get this, just give up
9693deb3ec6SMatthias Ringwald             log_info("Received DM #0");
9703deb3ec6SMatthias Ringwald             log_info("-> Closing down multiplexer");
9713deb3ec6SMatthias Ringwald             rfcomm_multiplexer_finalize(multiplexer);
972ce8f182eSMatthias Ringwald             l2cap_disconnect(l2cap_cid, 0x13);
9733deb3ec6SMatthias Ringwald             return 1;
9743deb3ec6SMatthias Ringwald 
9753deb3ec6SMatthias Ringwald         case BT_RFCOMM_UIH:
9763deb3ec6SMatthias Ringwald             if (packet[payload_offset] == BT_RFCOMM_CLD_CMD){
9773deb3ec6SMatthias Ringwald                 // Multiplexer close down (CLD) -> close mutliplexer
9783deb3ec6SMatthias Ringwald                 log_info("Received Multiplexer close down command");
9793deb3ec6SMatthias Ringwald                 log_info("-> Closing down multiplexer");
9803deb3ec6SMatthias Ringwald                 rfcomm_multiplexer_finalize(multiplexer);
981ce8f182eSMatthias Ringwald                 l2cap_disconnect(l2cap_cid, 0x13);
9823deb3ec6SMatthias Ringwald                 return 1;
9833deb3ec6SMatthias Ringwald             }
9843deb3ec6SMatthias Ringwald             switch (packet[payload_offset]){
9853deb3ec6SMatthias Ringwald                 case BT_RFCOMM_CLD_CMD:
9863deb3ec6SMatthias Ringwald                      // Multiplexer close down (CLD) -> close mutliplexer
9873deb3ec6SMatthias Ringwald                     log_info("Received Multiplexer close down command");
9883deb3ec6SMatthias Ringwald                     log_info("-> Closing down multiplexer");
9893deb3ec6SMatthias Ringwald                     rfcomm_multiplexer_finalize(multiplexer);
990ce8f182eSMatthias Ringwald                     l2cap_disconnect(l2cap_cid, 0x13);
9913deb3ec6SMatthias Ringwald                     return 1;
9923deb3ec6SMatthias Ringwald 
9933deb3ec6SMatthias Ringwald                 case BT_RFCOMM_FCON_CMD:
9943deb3ec6SMatthias Ringwald                     multiplexer->fcon = 0x81;
9953deb3ec6SMatthias Ringwald                     break;
9963deb3ec6SMatthias Ringwald 
9973deb3ec6SMatthias Ringwald                 case BT_RFCOMM_FCOFF_CMD:
9983deb3ec6SMatthias Ringwald                     multiplexer->fcon = 0x80;
9993deb3ec6SMatthias Ringwald                     break;
10003deb3ec6SMatthias Ringwald 
10013deb3ec6SMatthias Ringwald                 case BT_RFCOMM_TEST_CMD: {
10023deb3ec6SMatthias Ringwald                     log_info("Received test command");
10033deb3ec6SMatthias Ringwald                     int len = packet[payload_offset+1] >> 1; // length < 125
10043deb3ec6SMatthias Ringwald                     if (len > RFCOMM_TEST_DATA_MAX_LEN){
10053deb3ec6SMatthias Ringwald                         len = RFCOMM_TEST_DATA_MAX_LEN;
10063deb3ec6SMatthias Ringwald                     }
10073deb3ec6SMatthias Ringwald                     multiplexer->test_data_len = len;
10083deb3ec6SMatthias Ringwald                     memcpy(multiplexer->test_data, &packet[payload_offset + 2], len);
10093deb3ec6SMatthias Ringwald                     return 1;
10103deb3ec6SMatthias Ringwald                 }
10113deb3ec6SMatthias Ringwald                 default:
10123deb3ec6SMatthias Ringwald                     break;
10133deb3ec6SMatthias Ringwald             }
10143deb3ec6SMatthias Ringwald             break;
10153deb3ec6SMatthias Ringwald 
10163deb3ec6SMatthias Ringwald         default:
10173deb3ec6SMatthias Ringwald             break;
10183deb3ec6SMatthias Ringwald 
10193deb3ec6SMatthias Ringwald     }
10203deb3ec6SMatthias Ringwald     return 0;
10213deb3ec6SMatthias Ringwald }
10223deb3ec6SMatthias Ringwald 
10233deb3ec6SMatthias Ringwald static void rfcomm_multiplexer_state_machine(rfcomm_multiplexer_t * multiplexer, RFCOMM_MULTIPLEXER_EVENT event){
10243deb3ec6SMatthias Ringwald 
10253deb3ec6SMatthias Ringwald     uint16_t l2cap_cid = multiplexer->l2cap_cid;
10263deb3ec6SMatthias Ringwald 
10273deb3ec6SMatthias Ringwald     // process stored DM responses
10283deb3ec6SMatthias Ringwald     if (multiplexer->send_dm_for_dlci){
10293deb3ec6SMatthias Ringwald         uint8_t dlci = multiplexer->send_dm_for_dlci;
10303deb3ec6SMatthias Ringwald         multiplexer->send_dm_for_dlci = 0;
10313deb3ec6SMatthias Ringwald         rfcomm_send_dm_pf(multiplexer, dlci);
10323deb3ec6SMatthias Ringwald         return;
10333deb3ec6SMatthias Ringwald     }
10343deb3ec6SMatthias Ringwald 
10353deb3ec6SMatthias Ringwald     if (multiplexer->nsc_command){
10363deb3ec6SMatthias Ringwald         uint8_t command = multiplexer->nsc_command;
10373deb3ec6SMatthias Ringwald         multiplexer->nsc_command = 0;
10383deb3ec6SMatthias Ringwald         rfcomm_send_uih_nsc_rsp(multiplexer, command);
10393deb3ec6SMatthias Ringwald         return;
10403deb3ec6SMatthias Ringwald     }
10413deb3ec6SMatthias Ringwald 
10423deb3ec6SMatthias Ringwald     if (multiplexer->fcon & 0x80){
10433deb3ec6SMatthias Ringwald         multiplexer->fcon &= 0x01;
10443deb3ec6SMatthias Ringwald         rfcomm_send_uih_fc_rsp(multiplexer, multiplexer->fcon);
10453deb3ec6SMatthias Ringwald         if (multiplexer->fcon == 0) return;
10463deb3ec6SMatthias Ringwald         // trigger client to send again after sending FCon Response
1047b31d33b2SMatthias Ringwald         rfcomm_notify_channel_can_send();
10483deb3ec6SMatthias Ringwald         return;
10493deb3ec6SMatthias Ringwald     }
10503deb3ec6SMatthias Ringwald 
10513deb3ec6SMatthias Ringwald     switch (multiplexer->state) {
10523deb3ec6SMatthias Ringwald         case RFCOMM_MULTIPLEXER_SEND_SABM_0:
10533deb3ec6SMatthias Ringwald             switch (event) {
10543deb3ec6SMatthias Ringwald                 case MULT_EV_READY_TO_SEND:
10553deb3ec6SMatthias Ringwald                     log_info("Sending SABM #0 - (multi 0x%p)", multiplexer);
10563deb3ec6SMatthias Ringwald                     multiplexer->state = RFCOMM_MULTIPLEXER_W4_UA_0;
10573deb3ec6SMatthias Ringwald                     rfcomm_send_sabm(multiplexer, 0);
10583deb3ec6SMatthias Ringwald                     break;
10593deb3ec6SMatthias Ringwald                 default:
10603deb3ec6SMatthias Ringwald                     break;
10613deb3ec6SMatthias Ringwald             }
10623deb3ec6SMatthias Ringwald             break;
10633deb3ec6SMatthias Ringwald         case RFCOMM_MULTIPLEXER_SEND_UA_0:
10643deb3ec6SMatthias Ringwald             switch (event) {
10653deb3ec6SMatthias Ringwald                 case MULT_EV_READY_TO_SEND:
10663deb3ec6SMatthias Ringwald                     log_info("Sending UA #0");
10673deb3ec6SMatthias Ringwald                     multiplexer->state = RFCOMM_MULTIPLEXER_OPEN;
10683deb3ec6SMatthias Ringwald                     rfcomm_send_ua(multiplexer, 0);
10693deb3ec6SMatthias Ringwald                     rfcomm_multiplexer_opened(multiplexer);
10703deb3ec6SMatthias Ringwald                     break;
10713deb3ec6SMatthias Ringwald                 default:
10723deb3ec6SMatthias Ringwald                     break;
10733deb3ec6SMatthias Ringwald             }
10743deb3ec6SMatthias Ringwald             break;
10753deb3ec6SMatthias Ringwald         case RFCOMM_MULTIPLEXER_SEND_UA_0_AND_DISC:
10763deb3ec6SMatthias Ringwald             switch (event) {
10773deb3ec6SMatthias Ringwald                 case MULT_EV_READY_TO_SEND:
10783deb3ec6SMatthias Ringwald                     // try to detect authentication errors: drop link key if multiplexer closed before first channel got opened
10793deb3ec6SMatthias Ringwald                     if (!multiplexer->at_least_one_connection){
10803deb3ec6SMatthias Ringwald                         log_info("TODO: no connections established - delete link key prophylactically");
10813deb3ec6SMatthias Ringwald                         // hci_send_cmd(&hci_delete_stored_link_key, multiplexer->remote_addr);
10823deb3ec6SMatthias Ringwald                     }
10833deb3ec6SMatthias Ringwald                     log_info("Sending UA #0");
10843deb3ec6SMatthias Ringwald                     log_info("Closing down multiplexer");
10853deb3ec6SMatthias Ringwald                     multiplexer->state = RFCOMM_MULTIPLEXER_CLOSED;
10863deb3ec6SMatthias Ringwald                     rfcomm_send_ua(multiplexer, 0);
10873deb3ec6SMatthias Ringwald                     rfcomm_multiplexer_finalize(multiplexer);
1088ce8f182eSMatthias Ringwald                     l2cap_disconnect(l2cap_cid, 0x13);
10893deb3ec6SMatthias Ringwald                 default:
10903deb3ec6SMatthias Ringwald                     break;
10913deb3ec6SMatthias Ringwald             }
10923deb3ec6SMatthias Ringwald             break;
10933deb3ec6SMatthias Ringwald         case RFCOMM_MULTIPLEXER_OPEN:
10943deb3ec6SMatthias Ringwald             switch (event) {
10953deb3ec6SMatthias Ringwald                 case MULT_EV_READY_TO_SEND:
10963deb3ec6SMatthias Ringwald                     // respond to test command
10973deb3ec6SMatthias Ringwald                     if (multiplexer->test_data_len){
10983deb3ec6SMatthias Ringwald                         int len = multiplexer->test_data_len;
10993deb3ec6SMatthias Ringwald                         log_info("Sending TEST Response with %u bytes", len);
11003deb3ec6SMatthias Ringwald                         multiplexer->test_data_len = 0;
11013deb3ec6SMatthias Ringwald                         rfcomm_send_uih_test_rsp(multiplexer, multiplexer->test_data, len);
11023deb3ec6SMatthias Ringwald                         return;
11033deb3ec6SMatthias Ringwald                     }
11043deb3ec6SMatthias Ringwald                     break;
11053deb3ec6SMatthias Ringwald                 default:
11063deb3ec6SMatthias Ringwald                     break;
11073deb3ec6SMatthias Ringwald             }
11083deb3ec6SMatthias Ringwald             break;
11093deb3ec6SMatthias Ringwald         default:
11103deb3ec6SMatthias Ringwald             break;
11113deb3ec6SMatthias Ringwald     }
11123deb3ec6SMatthias Ringwald }
11133deb3ec6SMatthias Ringwald 
11143deb3ec6SMatthias Ringwald // MARK: RFCOMM CHANNEL
11153deb3ec6SMatthias Ringwald 
11163deb3ec6SMatthias Ringwald static void rfcomm_channel_send_credits(rfcomm_channel_t *channel, uint8_t credits){
11173deb3ec6SMatthias Ringwald     rfcomm_send_uih_credits(channel->multiplexer, channel->dlci, credits);
11183deb3ec6SMatthias Ringwald     channel->credits_incoming += credits;
11193deb3ec6SMatthias Ringwald }
11203deb3ec6SMatthias Ringwald 
1121b31d33b2SMatthias Ringwald static int rfcomm_channel_can_send(rfcomm_channel_t * channel){
1122b31d33b2SMatthias Ringwald     if (!channel->credits_outgoing) return 0;
1123b31d33b2SMatthias Ringwald     if ((channel->multiplexer->fcon & 1) == 0) return 0;
1124b31d33b2SMatthias Ringwald     return l2cap_can_send_packet_now(channel->multiplexer->l2cap_cid);
1125b31d33b2SMatthias Ringwald }
1126b31d33b2SMatthias Ringwald 
11273deb3ec6SMatthias Ringwald static void rfcomm_channel_opened(rfcomm_channel_t *rfChannel){
11283deb3ec6SMatthias Ringwald 
11293deb3ec6SMatthias Ringwald     log_info("rfcomm_channel_opened!");
11303deb3ec6SMatthias Ringwald 
11313deb3ec6SMatthias Ringwald     rfChannel->state = RFCOMM_CHANNEL_OPEN;
11323deb3ec6SMatthias Ringwald     rfcomm_emit_channel_opened(rfChannel, 0);
11333deb3ec6SMatthias Ringwald     rfcomm_emit_port_configuration(rfChannel);
11343deb3ec6SMatthias Ringwald 
11353deb3ec6SMatthias Ringwald     // remove (potential) timer
11363deb3ec6SMatthias Ringwald     rfcomm_multiplexer_t *multiplexer = rfChannel->multiplexer;
11373deb3ec6SMatthias Ringwald     if (multiplexer->timer_active) {
1138528a4a3bSMatthias Ringwald         btstack_run_loop_remove_timer(&multiplexer->timer);
11393deb3ec6SMatthias Ringwald         multiplexer->timer_active = 0;
11403deb3ec6SMatthias Ringwald     }
11413deb3ec6SMatthias Ringwald     // hack for problem detecting authentication failure
11423deb3ec6SMatthias Ringwald     multiplexer->at_least_one_connection = 1;
11433deb3ec6SMatthias Ringwald 
11443deb3ec6SMatthias Ringwald     // start next connection request if pending
11453deb3ec6SMatthias Ringwald     rfcomm_run();
11463deb3ec6SMatthias Ringwald }
11473deb3ec6SMatthias Ringwald 
11483deb3ec6SMatthias Ringwald static void rfcomm_channel_packet_handler_uih(rfcomm_multiplexer_t *multiplexer, uint8_t * packet, uint16_t size){
11493deb3ec6SMatthias Ringwald     const uint8_t frame_dlci = packet[0] >> 2;
11503deb3ec6SMatthias Ringwald     const uint8_t length_offset = (packet[2] & 1) ^ 1;  // to be used for pos >= 3
11513deb3ec6SMatthias Ringwald     const uint8_t credit_offset = ((packet[1] & BT_RFCOMM_UIH_PF) == BT_RFCOMM_UIH_PF) ? 1 : 0;   // credits for uih_pf frames
11523deb3ec6SMatthias Ringwald     const uint8_t payload_offset = 3 + length_offset + credit_offset;
11533deb3ec6SMatthias Ringwald 
11543deb3ec6SMatthias Ringwald     rfcomm_channel_t * channel = rfcomm_channel_for_multiplexer_and_dlci(multiplexer, frame_dlci);
11553deb3ec6SMatthias Ringwald     if (!channel) return;
11563deb3ec6SMatthias Ringwald 
11573deb3ec6SMatthias Ringwald     // handle new outgoing credits
11583deb3ec6SMatthias Ringwald     if (packet[1] == BT_RFCOMM_UIH_PF) {
11593deb3ec6SMatthias Ringwald 
11603deb3ec6SMatthias Ringwald         // add them
11613deb3ec6SMatthias Ringwald         uint16_t new_credits = packet[3+length_offset];
11623deb3ec6SMatthias Ringwald         channel->credits_outgoing += new_credits;
11633deb3ec6SMatthias Ringwald         log_info( "RFCOMM data UIH_PF, new credits: %u, now %u", new_credits, channel->credits_outgoing);
11643deb3ec6SMatthias Ringwald 
11653deb3ec6SMatthias Ringwald         // notify channel statemachine
11663deb3ec6SMatthias Ringwald         rfcomm_channel_event_t channel_event = { CH_EVT_RCVD_CREDITS };
11673deb3ec6SMatthias Ringwald         rfcomm_channel_state_machine(channel, &channel_event);
11683deb3ec6SMatthias Ringwald     }
11693deb3ec6SMatthias Ringwald 
11703deb3ec6SMatthias Ringwald     // contains payload?
11713deb3ec6SMatthias Ringwald     if (size - 1 > payload_offset){
11723deb3ec6SMatthias Ringwald 
11733deb3ec6SMatthias Ringwald         // log_info( "RFCOMM data UIH_PF, size %u, channel %p", size-payload_offset-1, rfChannel->connection);
11743deb3ec6SMatthias Ringwald 
11753deb3ec6SMatthias Ringwald         // decrease incoming credit counter
11763deb3ec6SMatthias Ringwald         if (channel->credits_incoming > 0){
11773deb3ec6SMatthias Ringwald             channel->credits_incoming--;
11783deb3ec6SMatthias Ringwald         }
11793deb3ec6SMatthias Ringwald 
11803deb3ec6SMatthias Ringwald         // deliver payload
1181fc376368SMatthias Ringwald         (channel->packet_handler)(RFCOMM_DATA_PACKET, channel->rfcomm_cid,
11823deb3ec6SMatthias Ringwald                               &packet[payload_offset], size-payload_offset-1);
11833deb3ec6SMatthias Ringwald     }
11843deb3ec6SMatthias Ringwald 
11853deb3ec6SMatthias Ringwald     // automatically provide new credits to remote device, if no incoming flow control
11863deb3ec6SMatthias Ringwald     if (!channel->incoming_flow_control && channel->credits_incoming < 5){
11873deb3ec6SMatthias Ringwald         channel->new_credits_incoming =RFCOMM_CREDITS;
11883deb3ec6SMatthias Ringwald     }
11893deb3ec6SMatthias Ringwald }
11903deb3ec6SMatthias Ringwald 
11913deb3ec6SMatthias Ringwald static void rfcomm_channel_accept_pn(rfcomm_channel_t *channel, rfcomm_channel_event_pn_t *event){
11923deb3ec6SMatthias Ringwald     // priority of client request
11933deb3ec6SMatthias Ringwald     channel->pn_priority = event->priority;
11943deb3ec6SMatthias Ringwald 
11953deb3ec6SMatthias Ringwald     // new credits
11963deb3ec6SMatthias Ringwald     channel->credits_outgoing = event->credits_outgoing;
11973deb3ec6SMatthias Ringwald 
11983deb3ec6SMatthias Ringwald     // negotiate max frame size
11993deb3ec6SMatthias Ringwald     if (channel->max_frame_size > channel->multiplexer->max_frame_size) {
12003deb3ec6SMatthias Ringwald         channel->max_frame_size = channel->multiplexer->max_frame_size;
12013deb3ec6SMatthias Ringwald     }
12023deb3ec6SMatthias Ringwald     if (channel->max_frame_size > event->max_frame_size) {
12033deb3ec6SMatthias Ringwald         channel->max_frame_size = event->max_frame_size;
12043deb3ec6SMatthias Ringwald     }
12053deb3ec6SMatthias Ringwald 
12063deb3ec6SMatthias Ringwald }
12073deb3ec6SMatthias Ringwald 
12083deb3ec6SMatthias Ringwald static void rfcomm_channel_finalize(rfcomm_channel_t *channel){
12093deb3ec6SMatthias Ringwald 
12103deb3ec6SMatthias Ringwald     rfcomm_multiplexer_t *multiplexer = channel->multiplexer;
12113deb3ec6SMatthias Ringwald 
12123deb3ec6SMatthias Ringwald     // remove from list
1213665d90f2SMatthias Ringwald     btstack_linked_list_remove( &rfcomm_channels, (btstack_linked_item_t *) channel);
12143deb3ec6SMatthias Ringwald 
12153deb3ec6SMatthias Ringwald     // free channel
12163deb3ec6SMatthias Ringwald     btstack_memory_rfcomm_channel_free(channel);
12173deb3ec6SMatthias Ringwald 
12183deb3ec6SMatthias Ringwald     // update multiplexer timeout after channel was removed from list
12193deb3ec6SMatthias Ringwald     rfcomm_multiplexer_prepare_idle_timer(multiplexer);
12203deb3ec6SMatthias Ringwald }
12213deb3ec6SMatthias Ringwald 
12223deb3ec6SMatthias Ringwald static void rfcomm_channel_state_machine_2(rfcomm_multiplexer_t * multiplexer, uint8_t dlci, rfcomm_channel_event_t *event){
12233deb3ec6SMatthias Ringwald 
12243deb3ec6SMatthias Ringwald     // TODO: if client max frame size is smaller than RFCOMM_DEFAULT_SIZE, send PN
12253deb3ec6SMatthias Ringwald 
12263deb3ec6SMatthias Ringwald 
12273deb3ec6SMatthias Ringwald     // lookup existing channel
12283deb3ec6SMatthias Ringwald     rfcomm_channel_t * channel = rfcomm_channel_for_multiplexer_and_dlci(multiplexer, dlci);
12293deb3ec6SMatthias Ringwald 
12303deb3ec6SMatthias Ringwald     // log_info("rfcomm_channel_state_machine_2 lookup dlci #%u = 0x%08x - event %u", dlci, (int) channel, event->type);
12313deb3ec6SMatthias Ringwald 
12323deb3ec6SMatthias Ringwald     if (channel) {
12333deb3ec6SMatthias Ringwald         rfcomm_channel_state_machine(channel, event);
12343deb3ec6SMatthias Ringwald         return;
12353deb3ec6SMatthias Ringwald     }
12363deb3ec6SMatthias Ringwald 
12373deb3ec6SMatthias Ringwald     // service registered?
12383deb3ec6SMatthias Ringwald     rfcomm_service_t * service = rfcomm_service_for_channel(dlci >> 1);
12393deb3ec6SMatthias Ringwald     // log_info("rfcomm_channel_state_machine_2 service dlci #%u = 0x%08x", dlci, (int) service);
12403deb3ec6SMatthias Ringwald     if (!service) {
12413deb3ec6SMatthias Ringwald         // discard request by sending disconnected mode
12423deb3ec6SMatthias Ringwald         multiplexer->send_dm_for_dlci = dlci;
12433deb3ec6SMatthias Ringwald         return;
12443deb3ec6SMatthias Ringwald     }
12453deb3ec6SMatthias Ringwald 
12463deb3ec6SMatthias Ringwald     // create channel for some events
12473deb3ec6SMatthias Ringwald     switch (event->type) {
12483deb3ec6SMatthias Ringwald         case CH_EVT_RCVD_SABM:
12493deb3ec6SMatthias Ringwald         case CH_EVT_RCVD_PN:
12503deb3ec6SMatthias Ringwald         case CH_EVT_RCVD_RPN_REQ:
12513deb3ec6SMatthias Ringwald         case CH_EVT_RCVD_RPN_CMD:
12523deb3ec6SMatthias Ringwald             // setup incoming channel
12533deb3ec6SMatthias Ringwald             channel = rfcomm_channel_create(multiplexer, service, dlci >> 1);
12543deb3ec6SMatthias Ringwald             if (!channel){
12553deb3ec6SMatthias Ringwald                 // discard request by sending disconnected mode
12563deb3ec6SMatthias Ringwald                 multiplexer->send_dm_for_dlci = dlci;
12573deb3ec6SMatthias Ringwald             }
12583deb3ec6SMatthias Ringwald             break;
12593deb3ec6SMatthias Ringwald         default:
12603deb3ec6SMatthias Ringwald             break;
12613deb3ec6SMatthias Ringwald     }
12623deb3ec6SMatthias Ringwald 
12633deb3ec6SMatthias Ringwald     if (!channel) {
12643deb3ec6SMatthias Ringwald         // discard request by sending disconnected mode
12653deb3ec6SMatthias Ringwald         multiplexer->send_dm_for_dlci = dlci;
12663deb3ec6SMatthias Ringwald         return;
12673deb3ec6SMatthias Ringwald     }
12683deb3ec6SMatthias Ringwald     rfcomm_channel_state_machine(channel, event);
12693deb3ec6SMatthias Ringwald }
12703deb3ec6SMatthias Ringwald 
12713deb3ec6SMatthias Ringwald static void rfcomm_channel_packet_handler(rfcomm_multiplexer_t * multiplexer,  uint8_t *packet, uint16_t size){
12723deb3ec6SMatthias Ringwald 
12733deb3ec6SMatthias Ringwald     // rfcomm: (0) addr [76543 server channel] [2 direction: initiator uses 1] [1 C/R: CMD by initiator = 1] [0 EA=1]
12743deb3ec6SMatthias Ringwald     const uint8_t frame_dlci = packet[0] >> 2;
12753deb3ec6SMatthias Ringwald     uint8_t message_dlci; // used by commands in UIH(_PF) packets
12763deb3ec6SMatthias Ringwald 	uint8_t message_len;  //   "
12773deb3ec6SMatthias Ringwald 
12783deb3ec6SMatthias Ringwald     // rfcomm: (1) command/control
12793deb3ec6SMatthias Ringwald     // -- credits_offset = 1 if command == BT_RFCOMM_UIH_PF
12803deb3ec6SMatthias Ringwald     const uint8_t credit_offset = ((packet[1] & BT_RFCOMM_UIH_PF) == BT_RFCOMM_UIH_PF) ? 1 : 0;   // credits for uih_pf frames
12813deb3ec6SMatthias Ringwald     // rfcomm: (2) length. if bit 0 is cleared, 2 byte length is used. (little endian)
12823deb3ec6SMatthias Ringwald     const uint8_t length_offset = (packet[2] & 1) ^ 1;  // to be used for pos >= 3
12833deb3ec6SMatthias Ringwald     // rfcomm: (3+length_offset) credits if credits_offset == 1
12843deb3ec6SMatthias Ringwald     // rfcomm: (3+length_offest+credits_offset)
12853deb3ec6SMatthias Ringwald     const uint8_t payload_offset = 3 + length_offset + credit_offset;
12863deb3ec6SMatthias Ringwald 
12873deb3ec6SMatthias Ringwald     rfcomm_channel_event_t event;
12883deb3ec6SMatthias Ringwald     rfcomm_channel_event_pn_t event_pn;
12893deb3ec6SMatthias Ringwald     rfcomm_channel_event_rpn_t event_rpn;
12903deb3ec6SMatthias Ringwald     rfcomm_channel_event_msc_t event_msc;
12913deb3ec6SMatthias Ringwald 
12923deb3ec6SMatthias Ringwald     // switch by rfcomm message type
12933deb3ec6SMatthias Ringwald     switch(packet[1]) {
12943deb3ec6SMatthias Ringwald 
12953deb3ec6SMatthias Ringwald         case BT_RFCOMM_SABM:
12963deb3ec6SMatthias Ringwald             event.type = CH_EVT_RCVD_SABM;
12973deb3ec6SMatthias Ringwald             log_info("Received SABM #%u", frame_dlci);
12983deb3ec6SMatthias Ringwald             rfcomm_channel_state_machine_2(multiplexer, frame_dlci, &event);
12993deb3ec6SMatthias Ringwald             break;
13003deb3ec6SMatthias Ringwald 
13013deb3ec6SMatthias Ringwald         case BT_RFCOMM_UA:
13023deb3ec6SMatthias Ringwald             event.type = CH_EVT_RCVD_UA;
13033deb3ec6SMatthias Ringwald             log_info("Received UA #%u",frame_dlci);
13043deb3ec6SMatthias Ringwald             rfcomm_channel_state_machine_2(multiplexer, frame_dlci, &event);
13053deb3ec6SMatthias Ringwald             break;
13063deb3ec6SMatthias Ringwald 
13073deb3ec6SMatthias Ringwald         case BT_RFCOMM_DISC:
13083deb3ec6SMatthias Ringwald             event.type = CH_EVT_RCVD_DISC;
13093deb3ec6SMatthias Ringwald             rfcomm_channel_state_machine_2(multiplexer, frame_dlci, &event);
13103deb3ec6SMatthias Ringwald             break;
13113deb3ec6SMatthias Ringwald 
13123deb3ec6SMatthias Ringwald         case BT_RFCOMM_DM:
13133deb3ec6SMatthias Ringwald         case BT_RFCOMM_DM_PF:
13143deb3ec6SMatthias Ringwald             event.type = CH_EVT_RCVD_DM;
13153deb3ec6SMatthias Ringwald             rfcomm_channel_state_machine_2(multiplexer, frame_dlci, &event);
13163deb3ec6SMatthias Ringwald             break;
13173deb3ec6SMatthias Ringwald 
13183deb3ec6SMatthias Ringwald         case BT_RFCOMM_UIH_PF:
13193deb3ec6SMatthias Ringwald         case BT_RFCOMM_UIH:
13203deb3ec6SMatthias Ringwald 
13213deb3ec6SMatthias Ringwald             message_len  = packet[payload_offset+1] >> 1;
13223deb3ec6SMatthias Ringwald 
13233deb3ec6SMatthias Ringwald             switch (packet[payload_offset]) {
13243deb3ec6SMatthias Ringwald                 case BT_RFCOMM_PN_CMD:
13253deb3ec6SMatthias Ringwald                     message_dlci = packet[payload_offset+2];
13263deb3ec6SMatthias Ringwald                     event_pn.super.type = CH_EVT_RCVD_PN;
13273deb3ec6SMatthias Ringwald                     event_pn.priority = packet[payload_offset+4];
1328f8fbdce0SMatthias Ringwald                     event_pn.max_frame_size = little_endian_read_16(packet, payload_offset+6);
13293deb3ec6SMatthias Ringwald                     event_pn.credits_outgoing = packet[payload_offset+9];
13303deb3ec6SMatthias Ringwald                     log_info("Received UIH Parameter Negotiation Command for #%u, credits %u",
13313deb3ec6SMatthias Ringwald                         message_dlci, event_pn.credits_outgoing);
13323deb3ec6SMatthias Ringwald                     rfcomm_channel_state_machine_2(multiplexer, message_dlci, (rfcomm_channel_event_t*) &event_pn);
13333deb3ec6SMatthias Ringwald                     break;
13343deb3ec6SMatthias Ringwald 
13353deb3ec6SMatthias Ringwald                 case BT_RFCOMM_PN_RSP:
13363deb3ec6SMatthias Ringwald                     message_dlci = packet[payload_offset+2];
13373deb3ec6SMatthias Ringwald                     event_pn.super.type = CH_EVT_RCVD_PN_RSP;
13383deb3ec6SMatthias Ringwald                     event_pn.priority = packet[payload_offset+4];
1339f8fbdce0SMatthias Ringwald                     event_pn.max_frame_size = little_endian_read_16(packet, payload_offset+6);
13403deb3ec6SMatthias Ringwald                     event_pn.credits_outgoing = packet[payload_offset+9];
13413deb3ec6SMatthias Ringwald                     log_info("Received UIH Parameter Negotiation Response max frame %u, credits %u",
13423deb3ec6SMatthias Ringwald                             event_pn.max_frame_size, event_pn.credits_outgoing);
13433deb3ec6SMatthias Ringwald                     rfcomm_channel_state_machine_2(multiplexer, message_dlci, (rfcomm_channel_event_t*) &event_pn);
13443deb3ec6SMatthias Ringwald                     break;
13453deb3ec6SMatthias Ringwald 
13463deb3ec6SMatthias Ringwald                 case BT_RFCOMM_MSC_CMD:
13473deb3ec6SMatthias Ringwald                     message_dlci = packet[payload_offset+2] >> 2;
13483deb3ec6SMatthias Ringwald                     event_msc.super.type = CH_EVT_RCVD_MSC_CMD;
13493deb3ec6SMatthias Ringwald                     event_msc.modem_status = packet[payload_offset+3];
13503deb3ec6SMatthias Ringwald                     log_info("Received MSC CMD for #%u, ", message_dlci);
13513deb3ec6SMatthias Ringwald                     rfcomm_channel_state_machine_2(multiplexer, message_dlci, (rfcomm_channel_event_t*) &event_msc);
13523deb3ec6SMatthias Ringwald                     break;
13533deb3ec6SMatthias Ringwald 
13543deb3ec6SMatthias Ringwald                 case BT_RFCOMM_MSC_RSP:
13553deb3ec6SMatthias Ringwald                     message_dlci = packet[payload_offset+2] >> 2;
13563deb3ec6SMatthias Ringwald                     event.type = CH_EVT_RCVD_MSC_RSP;
13573deb3ec6SMatthias Ringwald                     log_info("Received MSC RSP for #%u", message_dlci);
13583deb3ec6SMatthias Ringwald                     rfcomm_channel_state_machine_2(multiplexer, message_dlci, &event);
13593deb3ec6SMatthias Ringwald                     break;
13603deb3ec6SMatthias Ringwald 
13613deb3ec6SMatthias Ringwald                 case BT_RFCOMM_RPN_CMD:
13623deb3ec6SMatthias Ringwald                     message_dlci = packet[payload_offset+2] >> 2;
13633deb3ec6SMatthias Ringwald                     switch (message_len){
13643deb3ec6SMatthias Ringwald                         case 1:
13653deb3ec6SMatthias Ringwald                             log_info("Received Remote Port Negotiation Request for #%u", message_dlci);
13663deb3ec6SMatthias Ringwald                             event.type = CH_EVT_RCVD_RPN_REQ;
13673deb3ec6SMatthias Ringwald                             rfcomm_channel_state_machine_2(multiplexer, message_dlci, &event);
13683deb3ec6SMatthias Ringwald                             break;
13693deb3ec6SMatthias Ringwald                         case 8:
13703deb3ec6SMatthias Ringwald                             log_info("Received Remote Port Negotiation Update for #%u", message_dlci);
13713deb3ec6SMatthias Ringwald                             event_rpn.super.type = CH_EVT_RCVD_RPN_CMD;
13723deb3ec6SMatthias Ringwald                             event_rpn.data = *(rfcomm_rpn_data_t*) &packet[payload_offset+3];
13733deb3ec6SMatthias Ringwald                             rfcomm_channel_state_machine_2(multiplexer, message_dlci, (rfcomm_channel_event_t*) &event_rpn);
13743deb3ec6SMatthias Ringwald                             break;
13753deb3ec6SMatthias Ringwald                         default:
13763deb3ec6SMatthias Ringwald                             break;
13773deb3ec6SMatthias Ringwald                     }
13783deb3ec6SMatthias Ringwald                     break;
13793deb3ec6SMatthias Ringwald 
13803deb3ec6SMatthias Ringwald                 case BT_RFCOMM_RPN_RSP:
13813deb3ec6SMatthias Ringwald                     log_info("Received RPN response");
13823deb3ec6SMatthias Ringwald                     break;
13833deb3ec6SMatthias Ringwald 
13843deb3ec6SMatthias Ringwald                 case BT_RFCOMM_RLS_CMD: {
13853deb3ec6SMatthias Ringwald                     log_info("Received RLS command");
13863deb3ec6SMatthias Ringwald                     message_dlci = packet[payload_offset+2] >> 2;
13873deb3ec6SMatthias Ringwald                     rfcomm_channel_event_rls_t event_rls;
13883deb3ec6SMatthias Ringwald                     event_rls.super.type = CH_EVT_RCVD_RLS_CMD;
13893deb3ec6SMatthias Ringwald                     event_rls.line_status = packet[payload_offset+3];
13903deb3ec6SMatthias Ringwald                     rfcomm_channel_state_machine_2(multiplexer, message_dlci, (rfcomm_channel_event_t*) &event_rls);
13913deb3ec6SMatthias Ringwald                     break;
13923deb3ec6SMatthias Ringwald                 }
13933deb3ec6SMatthias Ringwald 
13943deb3ec6SMatthias Ringwald                 case BT_RFCOMM_RLS_RSP:
13953deb3ec6SMatthias Ringwald                     log_info("Received RLS response");
13963deb3ec6SMatthias Ringwald                     break;
13973deb3ec6SMatthias Ringwald 
13983deb3ec6SMatthias Ringwald                 // Following commands are handled by rfcomm_multiplexer_l2cap_packet_handler
13993deb3ec6SMatthias Ringwald                 // case BT_RFCOMM_TEST_CMD:
14003deb3ec6SMatthias Ringwald                 // case BT_RFCOMM_FCOFF_CMD:
14013deb3ec6SMatthias Ringwald                 // case BT_RFCOMM_FCON_CMD:
14023deb3ec6SMatthias Ringwald                 // everything else is an not supported command
14033deb3ec6SMatthias Ringwald                 default: {
14043deb3ec6SMatthias Ringwald                     log_error("Received unknown UIH command packet - 0x%02x", packet[payload_offset]);
14053deb3ec6SMatthias Ringwald                     multiplexer->nsc_command = packet[payload_offset];
14063deb3ec6SMatthias Ringwald                     break;
14073deb3ec6SMatthias Ringwald                 }
14083deb3ec6SMatthias Ringwald             }
14093deb3ec6SMatthias Ringwald             break;
14103deb3ec6SMatthias Ringwald 
14113deb3ec6SMatthias Ringwald         default:
14123deb3ec6SMatthias Ringwald             log_error("Received unknown RFCOMM message type %x", packet[1]);
14133deb3ec6SMatthias Ringwald             break;
14143deb3ec6SMatthias Ringwald     }
14153deb3ec6SMatthias Ringwald 
14163deb3ec6SMatthias Ringwald     // trigger next action - example W4_PN_RSP: transition to SEND_SABM which only depends on "can send"
14173deb3ec6SMatthias Ringwald     rfcomm_run();
14183deb3ec6SMatthias Ringwald }
14193deb3ec6SMatthias Ringwald 
1420457b5cb1SMatthias Ringwald static void rfcomm_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
14213deb3ec6SMatthias Ringwald 
14223deb3ec6SMatthias Ringwald     // multiplexer handler
14233deb3ec6SMatthias Ringwald     int handled = 0;
14243deb3ec6SMatthias Ringwald     switch (packet_type) {
14253deb3ec6SMatthias Ringwald         case HCI_EVENT_PACKET:
14263deb3ec6SMatthias Ringwald             handled = rfcomm_multiplexer_hci_event_handler(packet, size);
14273deb3ec6SMatthias Ringwald             break;
14283deb3ec6SMatthias Ringwald         case L2CAP_DATA_PACKET:
14293deb3ec6SMatthias Ringwald             handled = rfcomm_multiplexer_l2cap_packet_handler(channel, packet, size);
14303deb3ec6SMatthias Ringwald             break;
14313deb3ec6SMatthias Ringwald         default:
14323deb3ec6SMatthias Ringwald             break;
14333deb3ec6SMatthias Ringwald     }
14343deb3ec6SMatthias Ringwald 
14353deb3ec6SMatthias Ringwald     if (handled) {
14363deb3ec6SMatthias Ringwald         rfcomm_run();
14373deb3ec6SMatthias Ringwald         return;
14383deb3ec6SMatthias Ringwald     }
14393deb3ec6SMatthias Ringwald 
1440fc376368SMatthias Ringwald     // we only handle l2cap packets
1441fc376368SMatthias Ringwald     if (packet_type != L2CAP_DATA_PACKET) return;
1442fc376368SMatthias Ringwald 
1443fc376368SMatthias Ringwald     // ... over open multiplexer channel now
14443deb3ec6SMatthias Ringwald     rfcomm_multiplexer_t * multiplexer = rfcomm_multiplexer_for_l2cap_cid(channel);
1445fc376368SMatthias Ringwald     if (!multiplexer || multiplexer->state != RFCOMM_MULTIPLEXER_OPEN) return;
14463deb3ec6SMatthias Ringwald 
14473deb3ec6SMatthias Ringwald     // channel data ?
14483deb3ec6SMatthias Ringwald     // rfcomm: (0) addr [76543 server channel] [2 direction: initiator uses 1] [1 C/R: CMD by initiator = 1] [0 EA=1]
14493deb3ec6SMatthias Ringwald     const uint8_t frame_dlci = packet[0] >> 2;
14503deb3ec6SMatthias Ringwald 
14513deb3ec6SMatthias Ringwald     if (frame_dlci && (packet[1] == BT_RFCOMM_UIH || packet[1] == BT_RFCOMM_UIH_PF)) {
14523deb3ec6SMatthias Ringwald         rfcomm_channel_packet_handler_uih(multiplexer, packet, size);
14533deb3ec6SMatthias Ringwald         rfcomm_run();
14543deb3ec6SMatthias Ringwald         return;
14553deb3ec6SMatthias Ringwald     }
14563deb3ec6SMatthias Ringwald 
14573deb3ec6SMatthias Ringwald     rfcomm_channel_packet_handler(multiplexer, packet, size);
14583deb3ec6SMatthias Ringwald }
14593deb3ec6SMatthias Ringwald 
14603deb3ec6SMatthias Ringwald static int rfcomm_channel_ready_for_open(rfcomm_channel_t *channel){
14613deb3ec6SMatthias Ringwald     // note: exchanging MSC isn't neccessary to consider channel open
14623deb3ec6SMatthias Ringwald     // note: having outgoing credits is also not necessary to consider channel open
14633deb3ec6SMatthias Ringwald     // log_info("rfcomm_channel_ready_for_open state %u, flags needed %04x, current %04x, rf credits %u, l2cap credits %u ", channel->state, RFCOMM_CHANNEL_STATE_VAR_RCVD_MSC_RSP|RFCOMM_CHANNEL_STATE_VAR_SENT_MSC_RSP|RFCOMM_CHANNEL_STATE_VAR_SENT_CREDITS, channel->state_var, channel->credits_outgoing, channel->multiplexer->l2cap_credits);
14643deb3ec6SMatthias Ringwald     // if ((channel->state_var & RFCOMM_CHANNEL_STATE_VAR_SENT_MSC_RSP) == 0) return 0;
14653deb3ec6SMatthias Ringwald     // if (channel->credits_outgoing == 0) return 0;
14661e35c04dSMatthias Ringwald     log_info("rfcomm_channel_ready_for_open state %u, flags needed %04x, current %04x, rf credits %u",
14671e35c04dSMatthias Ringwald          channel->state, RFCOMM_CHANNEL_STATE_VAR_RCVD_MSC_RSP, channel->state_var, channel->credits_outgoing);
14683deb3ec6SMatthias Ringwald     if ((channel->state_var & RFCOMM_CHANNEL_STATE_VAR_RCVD_MSC_RSP) == 0) return 0;
14693deb3ec6SMatthias Ringwald     if ((channel->state_var & RFCOMM_CHANNEL_STATE_VAR_SENT_CREDITS) == 0) return 0;
14703deb3ec6SMatthias Ringwald 
14713deb3ec6SMatthias Ringwald     return 1;
14723deb3ec6SMatthias Ringwald }
14733deb3ec6SMatthias Ringwald 
14743deb3ec6SMatthias Ringwald static int rfcomm_channel_ready_for_incoming_dlc_setup(rfcomm_channel_t * channel){
14753deb3ec6SMatthias Ringwald     log_info("rfcomm_channel_ready_for_incoming_dlc_setup state var %04x", channel->state_var);
14763deb3ec6SMatthias Ringwald     // Client accept and SABM/UA is required, PN RSP is needed if PN was received
14773deb3ec6SMatthias Ringwald     if ((channel->state_var & RFCOMM_CHANNEL_STATE_VAR_CLIENT_ACCEPTED) == 0) return 0;
14783deb3ec6SMatthias Ringwald     if ((channel->state_var & RFCOMM_CHANNEL_STATE_VAR_RCVD_SABM      ) == 0) return 0;
14793deb3ec6SMatthias Ringwald     if ((channel->state_var & RFCOMM_CHANNEL_STATE_VAR_SEND_UA        ) != 0) return 0;
14803deb3ec6SMatthias Ringwald     if ((channel->state_var & RFCOMM_CHANNEL_STATE_VAR_SEND_PN_RSP    ) != 0) return 0;
14813deb3ec6SMatthias Ringwald     return 1;
14823deb3ec6SMatthias Ringwald }
14833deb3ec6SMatthias Ringwald 
14843deb3ec6SMatthias Ringwald inline static void rfcomm_channel_state_add(rfcomm_channel_t *channel, RFCOMM_CHANNEL_STATE_VAR event){
14853deb3ec6SMatthias Ringwald     channel->state_var = (RFCOMM_CHANNEL_STATE_VAR) (channel->state_var | event);
14863deb3ec6SMatthias Ringwald }
14873deb3ec6SMatthias Ringwald inline static void rfcomm_channel_state_remove(rfcomm_channel_t *channel, RFCOMM_CHANNEL_STATE_VAR event){
14883deb3ec6SMatthias Ringwald     channel->state_var = (RFCOMM_CHANNEL_STATE_VAR) (channel->state_var & ~event);
14893deb3ec6SMatthias Ringwald }
14903deb3ec6SMatthias Ringwald 
14913deb3ec6SMatthias Ringwald static void rfcomm_channel_state_machine(rfcomm_channel_t *channel, rfcomm_channel_event_t *event){
14923deb3ec6SMatthias Ringwald 
14933deb3ec6SMatthias Ringwald     // log_info("rfcomm_channel_state_machine: state %u, state_var %04x, event %u", channel->state, channel->state_var ,event->type);
14943deb3ec6SMatthias Ringwald 
14953deb3ec6SMatthias Ringwald     rfcomm_multiplexer_t *multiplexer = channel->multiplexer;
14963deb3ec6SMatthias Ringwald 
14973deb3ec6SMatthias Ringwald     // TODO: integrate in common switch
14983deb3ec6SMatthias Ringwald     if (event->type == CH_EVT_RCVD_DISC){
14993deb3ec6SMatthias Ringwald         rfcomm_emit_channel_closed(channel);
15003deb3ec6SMatthias Ringwald         channel->state = RFCOMM_CHANNEL_SEND_UA_AFTER_DISC;
15013deb3ec6SMatthias Ringwald         return;
15023deb3ec6SMatthias Ringwald     }
15033deb3ec6SMatthias Ringwald 
15043deb3ec6SMatthias Ringwald     // TODO: integrate in common switch
15053deb3ec6SMatthias Ringwald     if (event->type == CH_EVT_RCVD_DM){
15063deb3ec6SMatthias Ringwald         log_info("Received DM message for #%u", channel->dlci);
15073deb3ec6SMatthias Ringwald         log_info("-> Closing channel locally for #%u", channel->dlci);
15083deb3ec6SMatthias Ringwald         rfcomm_emit_channel_closed(channel);
15093deb3ec6SMatthias Ringwald         rfcomm_channel_finalize(channel);
15103deb3ec6SMatthias Ringwald         return;
15113deb3ec6SMatthias Ringwald     }
15123deb3ec6SMatthias Ringwald 
15133deb3ec6SMatthias Ringwald     // remote port negotiation command - just accept everything for now
15143deb3ec6SMatthias Ringwald     //
15153deb3ec6SMatthias Ringwald     // "The RPN command can be used before a new DLC is opened and should be used whenever the port settings change."
15163deb3ec6SMatthias Ringwald     // "The RPN command is specified as optional in TS 07.10, but it is mandatory to recognize and respond to it in RFCOMM.
15173deb3ec6SMatthias Ringwald     //   (Although the handling of individual settings are implementation-dependent.)"
15183deb3ec6SMatthias Ringwald     //
15193deb3ec6SMatthias Ringwald 
15203deb3ec6SMatthias Ringwald     // TODO: integrate in common switch
15213deb3ec6SMatthias Ringwald     if (event->type == CH_EVT_RCVD_RPN_CMD){
15223deb3ec6SMatthias Ringwald         // control port parameters
15233deb3ec6SMatthias Ringwald         rfcomm_channel_event_rpn_t *event_rpn = (rfcomm_channel_event_rpn_t*) event;
15243deb3ec6SMatthias Ringwald         rfcomm_rpn_data_update(&channel->rpn_data, &event_rpn->data);
15253deb3ec6SMatthias Ringwald         rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_RPN_RSP);
15263deb3ec6SMatthias Ringwald         // notify client about new settings
15273deb3ec6SMatthias Ringwald         rfcomm_emit_port_configuration(channel);
15283deb3ec6SMatthias Ringwald         return;
15293deb3ec6SMatthias Ringwald     }
15303deb3ec6SMatthias Ringwald 
15313deb3ec6SMatthias Ringwald     // TODO: integrate in common switch
15323deb3ec6SMatthias Ringwald     if (event->type == CH_EVT_RCVD_RPN_REQ){
15333deb3ec6SMatthias Ringwald         // no values got accepted (no values have beens sent)
15343deb3ec6SMatthias Ringwald         channel->rpn_data.parameter_mask_0 = 0x00;
15353deb3ec6SMatthias Ringwald         channel->rpn_data.parameter_mask_1 = 0x00;
15363deb3ec6SMatthias Ringwald         rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_RPN_RSP);
15373deb3ec6SMatthias Ringwald         return;
15383deb3ec6SMatthias Ringwald     }
15393deb3ec6SMatthias Ringwald 
15403deb3ec6SMatthias Ringwald     if (event->type == CH_EVT_RCVD_RLS_CMD){
15413deb3ec6SMatthias Ringwald         rfcomm_channel_event_rls_t * event_rls = (rfcomm_channel_event_rls_t*) event;
15423deb3ec6SMatthias Ringwald         channel->rls_line_status = event_rls->line_status & 0x0f;
15433deb3ec6SMatthias Ringwald         log_info("CH_EVT_RCVD_RLS_CMD setting line status to 0x%0x", channel->rls_line_status);
15443deb3ec6SMatthias Ringwald         rfcomm_emit_remote_line_status(channel, event_rls->line_status);
15453deb3ec6SMatthias Ringwald         return;
15463deb3ec6SMatthias Ringwald     }
15473deb3ec6SMatthias Ringwald 
15483deb3ec6SMatthias Ringwald     // TODO: integrate in common swich
15493deb3ec6SMatthias Ringwald     if (event->type == CH_EVT_READY_TO_SEND){
15503deb3ec6SMatthias Ringwald         if (channel->state_var & RFCOMM_CHANNEL_STATE_VAR_SEND_RPN_RSP){
15513deb3ec6SMatthias Ringwald             log_info("Sending Remote Port Negotiation RSP for #%u", channel->dlci);
15523deb3ec6SMatthias Ringwald             rfcomm_channel_state_remove(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_RPN_RSP);
15533deb3ec6SMatthias Ringwald             rfcomm_send_uih_rpn_rsp(multiplexer, channel->dlci, &channel->rpn_data);
15543deb3ec6SMatthias Ringwald             return;
15553deb3ec6SMatthias Ringwald         }
15563deb3ec6SMatthias Ringwald         if (channel->state_var & RFCOMM_CHANNEL_STATE_VAR_SEND_MSC_RSP){
15573deb3ec6SMatthias Ringwald             log_info("Sending MSC RSP for #%u", channel->dlci);
15583deb3ec6SMatthias Ringwald             rfcomm_channel_state_remove(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_MSC_RSP);
15593deb3ec6SMatthias Ringwald             rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_SENT_MSC_RSP);
15603deb3ec6SMatthias Ringwald             rfcomm_send_uih_msc_rsp(multiplexer, channel->dlci, 0x8d);  // ea=1,fc=0,rtc=1,rtr=1,ic=0,dv=1
15613deb3ec6SMatthias Ringwald             return;
15623deb3ec6SMatthias Ringwald         }
15633deb3ec6SMatthias Ringwald         if (channel->rls_line_status != RFCOMM_RLS_STATUS_INVALID){
15643deb3ec6SMatthias Ringwald             log_info("Sending RLS RSP 0x%0x", channel->rls_line_status);
15653deb3ec6SMatthias Ringwald             uint8_t line_status = channel->rls_line_status;
15663deb3ec6SMatthias Ringwald             channel->rls_line_status = RFCOMM_RLS_STATUS_INVALID;
15673deb3ec6SMatthias Ringwald             rfcomm_send_uih_rls_rsp(multiplexer, channel->dlci, line_status);
15683deb3ec6SMatthias Ringwald             return;
15693deb3ec6SMatthias Ringwald         }
15703deb3ec6SMatthias Ringwald     }
15713deb3ec6SMatthias Ringwald 
15723deb3ec6SMatthias Ringwald     // emit MSC status to app
15733deb3ec6SMatthias Ringwald     if (event->type == CH_EVT_RCVD_MSC_CMD){
15743deb3ec6SMatthias Ringwald         // notify client about new settings
15753deb3ec6SMatthias Ringwald         rfcomm_channel_event_msc_t *event_msc = (rfcomm_channel_event_msc_t*) event;
15763deb3ec6SMatthias Ringwald         uint8_t modem_status_event[2+1];
15773deb3ec6SMatthias Ringwald         modem_status_event[0] = RFCOMM_EVENT_REMOTE_MODEM_STATUS;
15783deb3ec6SMatthias Ringwald         modem_status_event[1] = 1;
15793deb3ec6SMatthias Ringwald         modem_status_event[2] = event_msc->modem_status;
1580fc376368SMatthias Ringwald         (channel->packet_handler)(HCI_EVENT_PACKET, channel->rfcomm_cid, (uint8_t*)&modem_status_event, sizeof(modem_status_event));
15813deb3ec6SMatthias Ringwald         // no return, MSC_CMD will be handled by state machine below
15823deb3ec6SMatthias Ringwald     }
15833deb3ec6SMatthias Ringwald 
15843deb3ec6SMatthias Ringwald     rfcomm_channel_event_pn_t * event_pn = (rfcomm_channel_event_pn_t*) event;
15853deb3ec6SMatthias Ringwald 
15863deb3ec6SMatthias Ringwald     switch (channel->state) {
15873deb3ec6SMatthias Ringwald         case RFCOMM_CHANNEL_CLOSED:
15883deb3ec6SMatthias Ringwald             switch (event->type){
15893deb3ec6SMatthias Ringwald                 case CH_EVT_RCVD_SABM:
15903deb3ec6SMatthias Ringwald                     log_info("-> Inform app");
15913deb3ec6SMatthias Ringwald                     rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_RCVD_SABM);
15923deb3ec6SMatthias Ringwald                     channel->state = RFCOMM_CHANNEL_INCOMING_SETUP;
15933deb3ec6SMatthias Ringwald                     rfcomm_emit_connection_request(channel);
15943deb3ec6SMatthias Ringwald                     break;
15953deb3ec6SMatthias Ringwald                 case CH_EVT_RCVD_PN:
15963deb3ec6SMatthias Ringwald                     rfcomm_channel_accept_pn(channel, event_pn);
15973deb3ec6SMatthias Ringwald                     log_info("-> Inform app");
15983deb3ec6SMatthias Ringwald                     rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_RCVD_PN);
15993deb3ec6SMatthias Ringwald                     channel->state = RFCOMM_CHANNEL_INCOMING_SETUP;
16003deb3ec6SMatthias Ringwald                     rfcomm_emit_connection_request(channel);
16013deb3ec6SMatthias Ringwald                     break;
16023deb3ec6SMatthias Ringwald                 default:
16033deb3ec6SMatthias Ringwald                     break;
16043deb3ec6SMatthias Ringwald             }
16053deb3ec6SMatthias Ringwald             break;
16063deb3ec6SMatthias Ringwald 
16073deb3ec6SMatthias Ringwald         case RFCOMM_CHANNEL_INCOMING_SETUP:
16083deb3ec6SMatthias Ringwald             switch (event->type){
16093deb3ec6SMatthias Ringwald                 case CH_EVT_RCVD_SABM:
16103deb3ec6SMatthias Ringwald                     rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_RCVD_SABM);
16113deb3ec6SMatthias Ringwald                     if (channel->state_var & RFCOMM_CHANNEL_STATE_VAR_CLIENT_ACCEPTED) {
16123deb3ec6SMatthias Ringwald                         rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_UA);
16133deb3ec6SMatthias Ringwald                     }
16143deb3ec6SMatthias Ringwald                     break;
16153deb3ec6SMatthias Ringwald                 case CH_EVT_RCVD_PN:
16163deb3ec6SMatthias Ringwald                     rfcomm_channel_accept_pn(channel, event_pn);
16173deb3ec6SMatthias Ringwald                     rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_RCVD_PN);
16183deb3ec6SMatthias Ringwald                     if (channel->state_var & RFCOMM_CHANNEL_STATE_VAR_CLIENT_ACCEPTED) {
16193deb3ec6SMatthias Ringwald                         rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_PN_RSP);
16203deb3ec6SMatthias Ringwald                     }
16213deb3ec6SMatthias Ringwald                     break;
16223deb3ec6SMatthias Ringwald                 case CH_EVT_READY_TO_SEND:
16233deb3ec6SMatthias Ringwald                     // if / else if is used to check for state transition after sending
16243deb3ec6SMatthias Ringwald                     if (channel->state_var & RFCOMM_CHANNEL_STATE_VAR_SEND_PN_RSP){
16253deb3ec6SMatthias Ringwald                         log_info("Sending UIH Parameter Negotiation Respond for #%u", channel->dlci);
16263deb3ec6SMatthias Ringwald                         rfcomm_channel_state_remove(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_PN_RSP);
16273deb3ec6SMatthias Ringwald                         rfcomm_send_uih_pn_response(multiplexer, channel->dlci, channel->pn_priority, channel->max_frame_size);
16283deb3ec6SMatthias Ringwald                     } else if (channel->state_var & RFCOMM_CHANNEL_STATE_VAR_SEND_UA){
16293deb3ec6SMatthias Ringwald                         log_info("Sending UA #%u", channel->dlci);
16303deb3ec6SMatthias Ringwald                         rfcomm_channel_state_remove(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_UA);
16313deb3ec6SMatthias Ringwald                         rfcomm_send_ua(multiplexer, channel->dlci);
16323deb3ec6SMatthias Ringwald                     }
16333deb3ec6SMatthias Ringwald                     if (rfcomm_channel_ready_for_incoming_dlc_setup(channel)){
16343deb3ec6SMatthias Ringwald                         log_info("Incomping setup done, requesting send MSC CMD and send Credits");
16353deb3ec6SMatthias Ringwald                         rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_MSC_CMD);
16363deb3ec6SMatthias Ringwald                         rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_CREDITS);
16373deb3ec6SMatthias Ringwald                         channel->state = RFCOMM_CHANNEL_DLC_SETUP;
16383deb3ec6SMatthias Ringwald                     }
16393deb3ec6SMatthias Ringwald                     break;
16403deb3ec6SMatthias Ringwald                 default:
16413deb3ec6SMatthias Ringwald                     break;
16423deb3ec6SMatthias Ringwald             }
16433deb3ec6SMatthias Ringwald             break;
16443deb3ec6SMatthias Ringwald 
16453deb3ec6SMatthias Ringwald         case RFCOMM_CHANNEL_W4_MULTIPLEXER:
16463deb3ec6SMatthias Ringwald             switch (event->type) {
16473deb3ec6SMatthias Ringwald                 case CH_EVT_MULTIPLEXER_READY:
16483deb3ec6SMatthias Ringwald                     log_info("Muliplexer opened, sending UIH PN next");
16493deb3ec6SMatthias Ringwald                     channel->state = RFCOMM_CHANNEL_SEND_UIH_PN;
16503deb3ec6SMatthias Ringwald                     break;
16513deb3ec6SMatthias Ringwald                 default:
16523deb3ec6SMatthias Ringwald                     break;
16533deb3ec6SMatthias Ringwald             }
16543deb3ec6SMatthias Ringwald             break;
16553deb3ec6SMatthias Ringwald 
16563deb3ec6SMatthias Ringwald         case RFCOMM_CHANNEL_SEND_UIH_PN:
16573deb3ec6SMatthias Ringwald             switch (event->type) {
16583deb3ec6SMatthias Ringwald                 case CH_EVT_READY_TO_SEND:
16593deb3ec6SMatthias Ringwald                     log_info("Sending UIH Parameter Negotiation Command for #%u (channel 0x%p)", channel->dlci, channel );
16603deb3ec6SMatthias Ringwald                     channel->state = RFCOMM_CHANNEL_W4_PN_RSP;
16613deb3ec6SMatthias Ringwald                     rfcomm_send_uih_pn_command(multiplexer, channel->dlci, channel->max_frame_size);
16623deb3ec6SMatthias Ringwald                     break;
16633deb3ec6SMatthias Ringwald                 default:
16643deb3ec6SMatthias Ringwald                     break;
16653deb3ec6SMatthias Ringwald             }
16663deb3ec6SMatthias Ringwald             break;
16673deb3ec6SMatthias Ringwald 
16683deb3ec6SMatthias Ringwald         case RFCOMM_CHANNEL_W4_PN_RSP:
16693deb3ec6SMatthias Ringwald             switch (event->type){
16703deb3ec6SMatthias Ringwald                 case CH_EVT_RCVD_PN_RSP:
16713deb3ec6SMatthias Ringwald                     // update max frame size
16723deb3ec6SMatthias Ringwald                     if (channel->max_frame_size > event_pn->max_frame_size) {
16733deb3ec6SMatthias Ringwald                         channel->max_frame_size = event_pn->max_frame_size;
16743deb3ec6SMatthias Ringwald                     }
16753deb3ec6SMatthias Ringwald                     // new credits
16763deb3ec6SMatthias Ringwald                     channel->credits_outgoing = event_pn->credits_outgoing;
16773deb3ec6SMatthias Ringwald                     channel->state = RFCOMM_CHANNEL_SEND_SABM_W4_UA;
16783deb3ec6SMatthias Ringwald                     break;
16793deb3ec6SMatthias Ringwald                 default:
16803deb3ec6SMatthias Ringwald                     break;
16813deb3ec6SMatthias Ringwald             }
16823deb3ec6SMatthias Ringwald             break;
16833deb3ec6SMatthias Ringwald 
16843deb3ec6SMatthias Ringwald         case RFCOMM_CHANNEL_SEND_SABM_W4_UA:
16853deb3ec6SMatthias Ringwald             switch (event->type) {
16863deb3ec6SMatthias Ringwald                 case CH_EVT_READY_TO_SEND:
16873deb3ec6SMatthias Ringwald                     log_info("Sending SABM #%u", channel->dlci);
16883deb3ec6SMatthias Ringwald                     channel->state = RFCOMM_CHANNEL_W4_UA;
16893deb3ec6SMatthias Ringwald                     rfcomm_send_sabm(multiplexer, channel->dlci);
16903deb3ec6SMatthias Ringwald                     break;
16913deb3ec6SMatthias Ringwald                 default:
16923deb3ec6SMatthias Ringwald                     break;
16933deb3ec6SMatthias Ringwald             }
16943deb3ec6SMatthias Ringwald             break;
16953deb3ec6SMatthias Ringwald 
16963deb3ec6SMatthias Ringwald         case RFCOMM_CHANNEL_W4_UA:
16973deb3ec6SMatthias Ringwald             switch (event->type){
16983deb3ec6SMatthias Ringwald                 case CH_EVT_RCVD_UA:
16993deb3ec6SMatthias Ringwald                     channel->state = RFCOMM_CHANNEL_DLC_SETUP;
17003deb3ec6SMatthias Ringwald                     rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_MSC_CMD);
17013deb3ec6SMatthias Ringwald                     rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_CREDITS);
17023deb3ec6SMatthias Ringwald                     break;
17033deb3ec6SMatthias Ringwald                 default:
17043deb3ec6SMatthias Ringwald                     break;
17053deb3ec6SMatthias Ringwald             }
17063deb3ec6SMatthias Ringwald             break;
17073deb3ec6SMatthias Ringwald 
17083deb3ec6SMatthias Ringwald         case RFCOMM_CHANNEL_DLC_SETUP:
17093deb3ec6SMatthias Ringwald             switch (event->type){
17103deb3ec6SMatthias Ringwald                 case CH_EVT_RCVD_MSC_CMD:
17113deb3ec6SMatthias Ringwald                     rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_RCVD_MSC_CMD);
17123deb3ec6SMatthias Ringwald                     rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_MSC_RSP);
17133deb3ec6SMatthias Ringwald                     break;
17143deb3ec6SMatthias Ringwald                 case CH_EVT_RCVD_MSC_RSP:
17153deb3ec6SMatthias Ringwald                     rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_RCVD_MSC_RSP);
17163deb3ec6SMatthias Ringwald                     break;
17173deb3ec6SMatthias Ringwald 
17183deb3ec6SMatthias Ringwald                 case CH_EVT_READY_TO_SEND:
17193deb3ec6SMatthias Ringwald                     if (channel->state_var & RFCOMM_CHANNEL_STATE_VAR_SEND_MSC_CMD){
17203deb3ec6SMatthias Ringwald                         log_info("Sending MSC CMD for #%u", channel->dlci);
17213deb3ec6SMatthias Ringwald                         rfcomm_channel_state_remove(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_MSC_CMD);
17223deb3ec6SMatthias Ringwald                         rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_SENT_MSC_CMD);
17233deb3ec6SMatthias Ringwald                         rfcomm_send_uih_msc_cmd(multiplexer, channel->dlci , 0x8d);  // ea=1,fc=0,rtc=1,rtr=1,ic=0,dv=1
17243deb3ec6SMatthias Ringwald                         break;
17253deb3ec6SMatthias Ringwald                     }
17263deb3ec6SMatthias Ringwald                     if (channel->state_var & RFCOMM_CHANNEL_STATE_VAR_SEND_CREDITS){
17273deb3ec6SMatthias Ringwald                         log_info("Providing credits for #%u", channel->dlci);
17283deb3ec6SMatthias Ringwald                         rfcomm_channel_state_remove(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_CREDITS);
17293deb3ec6SMatthias Ringwald                         rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_SENT_CREDITS);
17303deb3ec6SMatthias Ringwald 
17313deb3ec6SMatthias Ringwald                         if (channel->new_credits_incoming) {
17323deb3ec6SMatthias Ringwald                             uint8_t new_credits = channel->new_credits_incoming;
17333deb3ec6SMatthias Ringwald                             channel->new_credits_incoming = 0;
17343deb3ec6SMatthias Ringwald                             rfcomm_channel_send_credits(channel, new_credits);
17353deb3ec6SMatthias Ringwald                         }
17363deb3ec6SMatthias Ringwald                         break;
17373deb3ec6SMatthias Ringwald 
17383deb3ec6SMatthias Ringwald                     }
17393deb3ec6SMatthias Ringwald                     break;
17403deb3ec6SMatthias Ringwald                 default:
17413deb3ec6SMatthias Ringwald                     break;
17423deb3ec6SMatthias Ringwald             }
17433deb3ec6SMatthias Ringwald             // finally done?
17443deb3ec6SMatthias Ringwald             if (rfcomm_channel_ready_for_open(channel)){
17453deb3ec6SMatthias Ringwald                 channel->state = RFCOMM_CHANNEL_OPEN;
17463deb3ec6SMatthias Ringwald                 rfcomm_channel_opened(channel);
17473deb3ec6SMatthias Ringwald             }
17483deb3ec6SMatthias Ringwald             break;
17493deb3ec6SMatthias Ringwald 
17503deb3ec6SMatthias Ringwald         case RFCOMM_CHANNEL_OPEN:
17513deb3ec6SMatthias Ringwald             switch (event->type){
17523deb3ec6SMatthias Ringwald                 case CH_EVT_RCVD_MSC_CMD:
17533deb3ec6SMatthias Ringwald                     rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_MSC_RSP);
17543deb3ec6SMatthias Ringwald                     break;
17553deb3ec6SMatthias Ringwald                 case CH_EVT_READY_TO_SEND:
17563deb3ec6SMatthias Ringwald                     if (channel->new_credits_incoming) {
17573deb3ec6SMatthias Ringwald                         uint8_t new_credits = channel->new_credits_incoming;
17583deb3ec6SMatthias Ringwald                         channel->new_credits_incoming = 0;
17593deb3ec6SMatthias Ringwald                         rfcomm_channel_send_credits(channel, new_credits);
17603deb3ec6SMatthias Ringwald                         break;
17613deb3ec6SMatthias Ringwald                     }
17623deb3ec6SMatthias Ringwald                     break;
1763b31d33b2SMatthias Ringwald                 case CH_EVT_RCVD_CREDITS:
1764b31d33b2SMatthias Ringwald                     rfcomm_notify_channel_can_send();
17653deb3ec6SMatthias Ringwald                     break;
17663deb3ec6SMatthias Ringwald                 default:
17673deb3ec6SMatthias Ringwald                     break;
17683deb3ec6SMatthias Ringwald             }
17693deb3ec6SMatthias Ringwald             break;
17703deb3ec6SMatthias Ringwald 
17713deb3ec6SMatthias Ringwald         case RFCOMM_CHANNEL_SEND_DM:
17723deb3ec6SMatthias Ringwald             switch (event->type) {
17733deb3ec6SMatthias Ringwald                 case CH_EVT_READY_TO_SEND:
17743deb3ec6SMatthias Ringwald                     log_info("Sending DM_PF for #%u", channel->dlci);
17753deb3ec6SMatthias Ringwald                     // don't emit channel closed - channel was never open
17763deb3ec6SMatthias Ringwald                     channel->state = RFCOMM_CHANNEL_CLOSED;
17773deb3ec6SMatthias Ringwald                     rfcomm_send_dm_pf(multiplexer, channel->dlci);
17783deb3ec6SMatthias Ringwald                     rfcomm_channel_finalize(channel);
17793deb3ec6SMatthias Ringwald                     break;
17803deb3ec6SMatthias Ringwald                 default:
17813deb3ec6SMatthias Ringwald                     break;
17823deb3ec6SMatthias Ringwald             }
17833deb3ec6SMatthias Ringwald             break;
17843deb3ec6SMatthias Ringwald 
17853deb3ec6SMatthias Ringwald         case RFCOMM_CHANNEL_SEND_DISC:
17863deb3ec6SMatthias Ringwald             switch (event->type) {
17873deb3ec6SMatthias Ringwald                 case CH_EVT_READY_TO_SEND:
17883deb3ec6SMatthias Ringwald                     channel->state = RFCOMM_CHANNEL_W4_UA_AFTER_UA;
17893deb3ec6SMatthias Ringwald                     rfcomm_send_disc(multiplexer, channel->dlci);
17903deb3ec6SMatthias Ringwald                     break;
17913deb3ec6SMatthias Ringwald                 default:
17923deb3ec6SMatthias Ringwald                     break;
17933deb3ec6SMatthias Ringwald             }
17943deb3ec6SMatthias Ringwald             break;
17953deb3ec6SMatthias Ringwald 
17963deb3ec6SMatthias Ringwald         case RFCOMM_CHANNEL_W4_UA_AFTER_UA:
17973deb3ec6SMatthias Ringwald             switch (event->type){
17983deb3ec6SMatthias Ringwald                 case CH_EVT_RCVD_UA:
17993deb3ec6SMatthias Ringwald                     channel->state = RFCOMM_CHANNEL_CLOSED;
18003deb3ec6SMatthias Ringwald                     rfcomm_emit_channel_closed(channel);
18013deb3ec6SMatthias Ringwald                     rfcomm_channel_finalize(channel);
18023deb3ec6SMatthias Ringwald                     break;
18033deb3ec6SMatthias Ringwald                 default:
18043deb3ec6SMatthias Ringwald                     break;
18053deb3ec6SMatthias Ringwald             }
18063deb3ec6SMatthias Ringwald             break;
18073deb3ec6SMatthias Ringwald 
18083deb3ec6SMatthias Ringwald         case RFCOMM_CHANNEL_SEND_UA_AFTER_DISC:
18093deb3ec6SMatthias Ringwald             switch (event->type) {
18103deb3ec6SMatthias Ringwald                 case CH_EVT_READY_TO_SEND:
18113deb3ec6SMatthias Ringwald                     log_info("Sending UA after DISC for #%u", channel->dlci);
18123deb3ec6SMatthias Ringwald                     channel->state = RFCOMM_CHANNEL_CLOSED;
18133deb3ec6SMatthias Ringwald                     rfcomm_send_ua(multiplexer, channel->dlci);
18143deb3ec6SMatthias Ringwald                     rfcomm_channel_finalize(channel);
18153deb3ec6SMatthias Ringwald                     break;
18163deb3ec6SMatthias Ringwald                 default:
18173deb3ec6SMatthias Ringwald                     break;
18183deb3ec6SMatthias Ringwald             }
18193deb3ec6SMatthias Ringwald             break;
18203deb3ec6SMatthias Ringwald 
18213deb3ec6SMatthias Ringwald         default:
18223deb3ec6SMatthias Ringwald             break;
18233deb3ec6SMatthias Ringwald     }
18243deb3ec6SMatthias Ringwald }
18253deb3ec6SMatthias Ringwald 
18263deb3ec6SMatthias Ringwald 
18273deb3ec6SMatthias Ringwald // MARK: RFCOMM RUN
18283deb3ec6SMatthias Ringwald // process outstanding signaling tasks
18293deb3ec6SMatthias Ringwald static void rfcomm_run(void){
18303deb3ec6SMatthias Ringwald 
1831665d90f2SMatthias Ringwald     btstack_linked_item_t *it;
1832665d90f2SMatthias Ringwald     btstack_linked_item_t *next;
18333deb3ec6SMatthias Ringwald 
1834665d90f2SMatthias Ringwald     for (it = (btstack_linked_item_t *) rfcomm_multiplexers; it ; it = next){
18353deb3ec6SMatthias Ringwald 
18363deb3ec6SMatthias Ringwald         next = it->next;    // be prepared for removal of channel in state machine
18373deb3ec6SMatthias Ringwald 
18383deb3ec6SMatthias Ringwald         rfcomm_multiplexer_t * multiplexer = ((rfcomm_multiplexer_t *) it);
18393deb3ec6SMatthias Ringwald 
18403deb3ec6SMatthias Ringwald         if (!l2cap_can_send_packet_now(multiplexer->l2cap_cid)) {
18413deb3ec6SMatthias Ringwald             // log_info("rfcomm_run A cannot send l2cap packet for #%u, credits %u", multiplexer->l2cap_cid, multiplexer->l2cap_credits);
18423deb3ec6SMatthias Ringwald             continue;
18433deb3ec6SMatthias Ringwald         }
18443deb3ec6SMatthias Ringwald         // log_info("rfcomm_run: multi 0x%08x, state %u", (int) multiplexer, multiplexer->state);
18453deb3ec6SMatthias Ringwald 
18463deb3ec6SMatthias Ringwald         rfcomm_multiplexer_state_machine(multiplexer, MULT_EV_READY_TO_SEND);
18473deb3ec6SMatthias Ringwald     }
18483deb3ec6SMatthias Ringwald 
1849665d90f2SMatthias Ringwald     for (it = (btstack_linked_item_t *) rfcomm_channels; it ; it = next){
18503deb3ec6SMatthias Ringwald 
18513deb3ec6SMatthias Ringwald         next = it->next;    // be prepared for removal of channel in state machine
18523deb3ec6SMatthias Ringwald 
18533deb3ec6SMatthias Ringwald         rfcomm_channel_t * channel = ((rfcomm_channel_t *) it);
18543deb3ec6SMatthias Ringwald         rfcomm_multiplexer_t * multiplexer = channel->multiplexer;
18553deb3ec6SMatthias Ringwald 
18563deb3ec6SMatthias Ringwald         if (!l2cap_can_send_packet_now(multiplexer->l2cap_cid)) {
18573deb3ec6SMatthias Ringwald             // log_info("rfcomm_run B cannot send l2cap packet for #%u, credits %u", multiplexer->l2cap_cid, multiplexer->l2cap_credits);
18583deb3ec6SMatthias Ringwald             continue;
18593deb3ec6SMatthias Ringwald         }
18603deb3ec6SMatthias Ringwald 
18613deb3ec6SMatthias Ringwald         rfcomm_channel_event_t event = { CH_EVT_READY_TO_SEND };
18623deb3ec6SMatthias Ringwald         rfcomm_channel_state_machine(channel, &event);
18633deb3ec6SMatthias Ringwald     }
18643deb3ec6SMatthias Ringwald }
18653deb3ec6SMatthias Ringwald 
18663deb3ec6SMatthias Ringwald // MARK: RFCOMM BTstack API
18673deb3ec6SMatthias Ringwald 
18683deb3ec6SMatthias Ringwald void rfcomm_init(void){
18693deb3ec6SMatthias Ringwald     rfcomm_client_cid_generator = 0;
18703deb3ec6SMatthias Ringwald     rfcomm_multiplexers = NULL;
18713deb3ec6SMatthias Ringwald     rfcomm_services     = NULL;
18723deb3ec6SMatthias Ringwald     rfcomm_channels     = NULL;
18733deb3ec6SMatthias Ringwald     rfcomm_security_level = LEVEL_2;
18743deb3ec6SMatthias Ringwald }
18753deb3ec6SMatthias Ringwald 
18763deb3ec6SMatthias Ringwald void rfcomm_set_required_security_level(gap_security_level_t security_level){
18773deb3ec6SMatthias Ringwald     rfcomm_security_level = security_level;
18783deb3ec6SMatthias Ringwald }
18793deb3ec6SMatthias Ringwald 
18803deb3ec6SMatthias Ringwald int rfcomm_can_send_packet_now(uint16_t rfcomm_cid){
18813deb3ec6SMatthias Ringwald     rfcomm_channel_t * channel = rfcomm_channel_for_rfcomm_cid(rfcomm_cid);
18823deb3ec6SMatthias Ringwald     if (!channel){
188328190c0bSMatthias Ringwald         log_error("rfcomm_send cid 0x%02x doesn't exist!", rfcomm_cid);
1884b31d33b2SMatthias Ringwald         return 0;
18853deb3ec6SMatthias Ringwald     }
1886b31d33b2SMatthias Ringwald     int res = rfcomm_channel_can_send(channel);
1887b31d33b2SMatthias Ringwald     if (!res){
1888b31d33b2SMatthias Ringwald         channel->waiting_for_can_send_now = 1;
1889b31d33b2SMatthias Ringwald     }
1890b31d33b2SMatthias Ringwald     return res;
18913deb3ec6SMatthias Ringwald }
18923deb3ec6SMatthias Ringwald 
18933deb3ec6SMatthias Ringwald static int rfcomm_assert_send_valid(rfcomm_channel_t * channel , uint16_t len){
18943deb3ec6SMatthias Ringwald     if (len > channel->max_frame_size){
189528190c0bSMatthias Ringwald         log_error("rfcomm_send cid 0x%02x, rfcomm data lenght exceeds MTU!", channel->rfcomm_cid);
18963deb3ec6SMatthias Ringwald         return RFCOMM_DATA_LEN_EXCEEDS_MTU;
18973deb3ec6SMatthias Ringwald     }
18983deb3ec6SMatthias Ringwald 
18993deb3ec6SMatthias Ringwald     if (!channel->credits_outgoing){
190028190c0bSMatthias Ringwald         log_info("rfcomm_send cid 0x%02x, no rfcomm outgoing credits!", channel->rfcomm_cid);
19013deb3ec6SMatthias Ringwald         return RFCOMM_NO_OUTGOING_CREDITS;
19023deb3ec6SMatthias Ringwald     }
19033deb3ec6SMatthias Ringwald 
19043deb3ec6SMatthias Ringwald     if ((channel->multiplexer->fcon & 1) == 0){
190528190c0bSMatthias Ringwald         log_info("rfcomm_send cid 0x%02x, aggregate flow off!", channel->rfcomm_cid);
19063deb3ec6SMatthias Ringwald         return RFCOMM_AGGREGATE_FLOW_OFF;
19073deb3ec6SMatthias Ringwald     }
19083deb3ec6SMatthias Ringwald     return 0;
19093deb3ec6SMatthias Ringwald }
19103deb3ec6SMatthias Ringwald 
19113deb3ec6SMatthias Ringwald // pre: rfcomm_can_send_packet_now(rfcomm_cid) == true
19123deb3ec6SMatthias Ringwald int rfcomm_reserve_packet_buffer(void){
19133deb3ec6SMatthias Ringwald     return l2cap_reserve_packet_buffer();
19143deb3ec6SMatthias Ringwald }
19153deb3ec6SMatthias Ringwald 
19163deb3ec6SMatthias Ringwald void rfcomm_release_packet_buffer(void){
19173deb3ec6SMatthias Ringwald     l2cap_release_packet_buffer();
19183deb3ec6SMatthias Ringwald }
19193deb3ec6SMatthias Ringwald 
19203deb3ec6SMatthias Ringwald uint8_t * rfcomm_get_outgoing_buffer(void){
19213deb3ec6SMatthias Ringwald     uint8_t * rfcomm_out_buffer = l2cap_get_outgoing_buffer();
19223deb3ec6SMatthias Ringwald     // address + control + length (16) + no credit field
19233deb3ec6SMatthias Ringwald     return &rfcomm_out_buffer[4];
19243deb3ec6SMatthias Ringwald }
19253deb3ec6SMatthias Ringwald 
19263deb3ec6SMatthias Ringwald uint16_t rfcomm_get_max_frame_size(uint16_t rfcomm_cid){
19273deb3ec6SMatthias Ringwald     rfcomm_channel_t * channel = rfcomm_channel_for_rfcomm_cid(rfcomm_cid);
19283deb3ec6SMatthias Ringwald     if (!channel){
19293deb3ec6SMatthias Ringwald         log_error("rfcomm_get_max_frame_size cid 0x%02x doesn't exist!", rfcomm_cid);
19303deb3ec6SMatthias Ringwald         return 0;
19313deb3ec6SMatthias Ringwald     }
19323deb3ec6SMatthias Ringwald     return channel->max_frame_size;
19333deb3ec6SMatthias Ringwald }
19343deb3ec6SMatthias Ringwald int rfcomm_send_prepared(uint16_t rfcomm_cid, uint16_t len){
19353deb3ec6SMatthias Ringwald     rfcomm_channel_t * channel = rfcomm_channel_for_rfcomm_cid(rfcomm_cid);
19363deb3ec6SMatthias Ringwald     if (!channel){
19373deb3ec6SMatthias Ringwald         log_error("rfcomm_send_prepared cid 0x%02x doesn't exist!", rfcomm_cid);
19383deb3ec6SMatthias Ringwald         return 0;
19393deb3ec6SMatthias Ringwald     }
19403deb3ec6SMatthias Ringwald 
19413deb3ec6SMatthias Ringwald     int err = rfcomm_assert_send_valid(channel, len);
19423deb3ec6SMatthias Ringwald     if (err) return err;
194368d15bfcSMatthias Ringwald     if (!l2cap_can_send_prepared_packet_now(channel->multiplexer->l2cap_cid)){
194478707112SMatthias Ringwald         log_error("rfcomm_send_prepared: l2cap cannot send now");
194578707112SMatthias Ringwald         return BTSTACK_ACL_BUFFERS_FULL;
194678707112SMatthias Ringwald     }
19473deb3ec6SMatthias Ringwald 
19483deb3ec6SMatthias Ringwald     // send might cause l2cap to emit new credits, update counters first
19493deb3ec6SMatthias Ringwald     channel->credits_outgoing--;
19503deb3ec6SMatthias Ringwald 
19513deb3ec6SMatthias Ringwald     int result = rfcomm_send_uih_prepared(channel->multiplexer, channel->dlci, len);
19523deb3ec6SMatthias Ringwald 
19533deb3ec6SMatthias Ringwald     if (result != 0) {
19543deb3ec6SMatthias Ringwald         channel->credits_outgoing++;
195578707112SMatthias Ringwald         log_error("rfcomm_send_prepared: error %d", result);
19563deb3ec6SMatthias Ringwald         return result;
19573deb3ec6SMatthias Ringwald     }
19583deb3ec6SMatthias Ringwald 
19593deb3ec6SMatthias Ringwald     return result;
19603deb3ec6SMatthias Ringwald }
19613deb3ec6SMatthias Ringwald 
196228190c0bSMatthias Ringwald int rfcomm_send(uint16_t rfcomm_cid, uint8_t *data, uint16_t len){
19633deb3ec6SMatthias Ringwald     rfcomm_channel_t * channel = rfcomm_channel_for_rfcomm_cid(rfcomm_cid);
19643deb3ec6SMatthias Ringwald     if (!channel){
196528190c0bSMatthias Ringwald         log_error("rfcomm_send cid 0x%02x doesn't exist!", rfcomm_cid);
19663deb3ec6SMatthias Ringwald         return 1;
19673deb3ec6SMatthias Ringwald     }
19683deb3ec6SMatthias Ringwald 
19693deb3ec6SMatthias Ringwald     int err = rfcomm_assert_send_valid(channel, len);
19703deb3ec6SMatthias Ringwald     if (err) return err;
197168d15bfcSMatthias Ringwald     if (!l2cap_can_send_packet_now(channel->multiplexer->l2cap_cid)){
197278707112SMatthias Ringwald         log_error("rfcomm_send_internal: l2cap cannot send now");
197378707112SMatthias Ringwald         return BTSTACK_ACL_BUFFERS_FULL;
197478707112SMatthias Ringwald     }
19753deb3ec6SMatthias Ringwald 
19763deb3ec6SMatthias Ringwald     rfcomm_reserve_packet_buffer();
19773deb3ec6SMatthias Ringwald     uint8_t * rfcomm_payload = rfcomm_get_outgoing_buffer();
19783deb3ec6SMatthias Ringwald     memcpy(rfcomm_payload, data, len);
197978707112SMatthias Ringwald     err = rfcomm_send_prepared(rfcomm_cid, len);
198078707112SMatthias Ringwald     if (err){
198178707112SMatthias Ringwald         rfcomm_release_packet_buffer();
198278707112SMatthias Ringwald     }
198378707112SMatthias Ringwald     return err;
19843deb3ec6SMatthias Ringwald }
19853deb3ec6SMatthias Ringwald 
19863deb3ec6SMatthias Ringwald // Sends Local Lnie Status, see LINE_STATUS_..
19873deb3ec6SMatthias Ringwald int rfcomm_send_local_line_status(uint16_t rfcomm_cid, uint8_t line_status){
19883deb3ec6SMatthias Ringwald     rfcomm_channel_t * channel = rfcomm_channel_for_rfcomm_cid(rfcomm_cid);
19893deb3ec6SMatthias Ringwald     if (!channel){
19903deb3ec6SMatthias Ringwald         log_error("rfcomm_send_local_line_status cid 0x%02x doesn't exist!", rfcomm_cid);
19913deb3ec6SMatthias Ringwald         return 0;
19923deb3ec6SMatthias Ringwald     }
19933deb3ec6SMatthias Ringwald     return rfcomm_send_uih_rls_cmd(channel->multiplexer, channel->dlci, line_status);
19943deb3ec6SMatthias Ringwald }
19953deb3ec6SMatthias Ringwald 
19963deb3ec6SMatthias Ringwald // Sned local modem status. see MODEM_STAUS_..
19973deb3ec6SMatthias Ringwald int rfcomm_send_modem_status(uint16_t rfcomm_cid, uint8_t modem_status){
19983deb3ec6SMatthias Ringwald     rfcomm_channel_t * channel = rfcomm_channel_for_rfcomm_cid(rfcomm_cid);
19993deb3ec6SMatthias Ringwald     if (!channel){
20003deb3ec6SMatthias Ringwald         log_error("rfcomm_send_modem_status cid 0x%02x doesn't exist!", rfcomm_cid);
20013deb3ec6SMatthias Ringwald         return 0;
20023deb3ec6SMatthias Ringwald     }
20033deb3ec6SMatthias Ringwald     return rfcomm_send_uih_msc_cmd(channel->multiplexer, channel->dlci, modem_status);
20043deb3ec6SMatthias Ringwald }
20053deb3ec6SMatthias Ringwald 
20063deb3ec6SMatthias Ringwald // Configure remote port
20073deb3ec6SMatthias Ringwald int rfcomm_send_port_configuration(uint16_t rfcomm_cid, rpn_baud_t baud_rate, rpn_data_bits_t data_bits, rpn_stop_bits_t stop_bits, rpn_parity_t parity, rpn_flow_control_t flow_control){
20083deb3ec6SMatthias Ringwald     rfcomm_channel_t * channel = rfcomm_channel_for_rfcomm_cid(rfcomm_cid);
20093deb3ec6SMatthias Ringwald     if (!channel){
20103deb3ec6SMatthias Ringwald         log_error("rfcomm_send_port_configuration cid 0x%02x doesn't exist!", rfcomm_cid);
20113deb3ec6SMatthias Ringwald         return 0;
20123deb3ec6SMatthias Ringwald     }
20133deb3ec6SMatthias Ringwald     rfcomm_rpn_data_t rpn_data;
20143deb3ec6SMatthias Ringwald     rpn_data.baud_rate = baud_rate;
20153deb3ec6SMatthias Ringwald     rpn_data.flags = data_bits | (stop_bits << 2) | (parity << 3);
20163deb3ec6SMatthias Ringwald     rpn_data.flow_control = flow_control;
20173deb3ec6SMatthias Ringwald     rpn_data.xon = 0;
20183deb3ec6SMatthias Ringwald     rpn_data.xoff = 0;
20193deb3ec6SMatthias Ringwald     rpn_data.parameter_mask_0 = 0x1f;   // all but xon/xoff
20203deb3ec6SMatthias Ringwald     rpn_data.parameter_mask_1 = 0x3f;   // all flow control options
20213deb3ec6SMatthias Ringwald     return rfcomm_send_uih_rpn_cmd(channel->multiplexer, channel->dlci, &rpn_data);
20223deb3ec6SMatthias Ringwald }
20233deb3ec6SMatthias Ringwald 
20243deb3ec6SMatthias Ringwald // Query remote port
20253deb3ec6SMatthias Ringwald int rfcomm_query_port_configuration(uint16_t rfcomm_cid){
20263deb3ec6SMatthias Ringwald     rfcomm_channel_t * channel = rfcomm_channel_for_rfcomm_cid(rfcomm_cid);
20273deb3ec6SMatthias Ringwald     if (!channel){
20283deb3ec6SMatthias Ringwald         log_error("rfcomm_query_port_configuration cid 0x%02x doesn't exist!", rfcomm_cid);
20293deb3ec6SMatthias Ringwald         return 0;
20303deb3ec6SMatthias Ringwald     }
20313deb3ec6SMatthias Ringwald     return rfcomm_send_uih_rpn_req(channel->multiplexer, channel->dlci);
20323deb3ec6SMatthias Ringwald }
20333deb3ec6SMatthias Ringwald 
2034aa4dd815SMatthias Ringwald 
2035ccb8ddfbSMatthias Ringwald static uint8_t rfcomm_channel_create_internal(btstack_packet_handler_t packet_handler, bd_addr_t addr, uint8_t server_channel, uint8_t incoming_flow_control, uint8_t initial_credits, uint16_t * out_rfcomm_cid){
20365d1e858fSMatthias Ringwald     log_info("RFCOMM_CREATE_CHANNEL addr %s channel #%u init credits %u",  bd_addr_to_str(addr), server_channel, initial_credits);
20375d1e858fSMatthias Ringwald 
20385d1e858fSMatthias Ringwald     // create new multiplexer if necessary
20395d1e858fSMatthias Ringwald     uint8_t status = 0;
20405d1e858fSMatthias Ringwald     int new_multiplexer = 0;
20415d1e858fSMatthias Ringwald     rfcomm_channel_t * channel = NULL;
20425d1e858fSMatthias Ringwald     rfcomm_multiplexer_t * multiplexer = rfcomm_multiplexer_for_addr(addr);
20435d1e858fSMatthias Ringwald     if (!multiplexer) {
20445d1e858fSMatthias Ringwald         multiplexer = rfcomm_multiplexer_create_for_addr(addr);
20455d1e858fSMatthias Ringwald         if (!multiplexer){
20465d1e858fSMatthias Ringwald             status = BTSTACK_MEMORY_ALLOC_FAILED;
20475d1e858fSMatthias Ringwald             goto fail;
20485d1e858fSMatthias Ringwald         }
20495d1e858fSMatthias Ringwald         multiplexer->outgoing = 1;
20505d1e858fSMatthias Ringwald         multiplexer->state = RFCOMM_MULTIPLEXER_W4_CONNECT;
20515d1e858fSMatthias Ringwald         new_multiplexer = 1;
20525d1e858fSMatthias Ringwald     }
20535d1e858fSMatthias Ringwald 
20545d1e858fSMatthias Ringwald     // prepare channel
20555d1e858fSMatthias Ringwald     channel = rfcomm_channel_create(multiplexer, NULL, server_channel);
20565d1e858fSMatthias Ringwald     if (!channel){
20575d1e858fSMatthias Ringwald         status = BTSTACK_MEMORY_ALLOC_FAILED;
20585d1e858fSMatthias Ringwald         goto fail;
20595d1e858fSMatthias Ringwald     }
2060ccb8ddfbSMatthias Ringwald 
20615d1e858fSMatthias Ringwald     // rfcomm_cid is already assigned by rfcomm_channel_create
20625d1e858fSMatthias Ringwald     channel->incoming_flow_control = incoming_flow_control;
20635d1e858fSMatthias Ringwald     channel->new_credits_incoming  = initial_credits;
2064ccb8ddfbSMatthias Ringwald     channel->packet_handler = packet_handler;
20655d1e858fSMatthias Ringwald 
20665d1e858fSMatthias Ringwald     // return rfcomm_cid
2067432fe57eSMatthias Ringwald     if (out_rfcomm_cid){
20685d1e858fSMatthias Ringwald         *out_rfcomm_cid = channel->rfcomm_cid;
2069432fe57eSMatthias Ringwald     }
20705d1e858fSMatthias Ringwald 
20715d1e858fSMatthias Ringwald     // start multiplexer setup
20725d1e858fSMatthias Ringwald     if (multiplexer->state != RFCOMM_MULTIPLEXER_OPEN) {
20735d1e858fSMatthias Ringwald         channel->state = RFCOMM_CHANNEL_W4_MULTIPLEXER;
20745d1e858fSMatthias Ringwald         uint16_t l2cap_cid = 0;
20755d1e858fSMatthias Ringwald         status = l2cap_create_channel(rfcomm_packet_handler, addr, PSM_RFCOMM, l2cap_max_mtu(), &l2cap_cid);
20765d1e858fSMatthias Ringwald         if (status) goto fail;
20775d1e858fSMatthias Ringwald         multiplexer->l2cap_cid = l2cap_cid;
20785d1e858fSMatthias Ringwald         return 0;
20795d1e858fSMatthias Ringwald     }
20805d1e858fSMatthias Ringwald 
20815d1e858fSMatthias Ringwald     channel->state = RFCOMM_CHANNEL_SEND_UIH_PN;
20825d1e858fSMatthias Ringwald 
20835d1e858fSMatthias Ringwald     // start connecting, if multiplexer is already up and running
20845d1e858fSMatthias Ringwald     rfcomm_run();
20855d1e858fSMatthias Ringwald     return 0;
20865d1e858fSMatthias Ringwald 
20875d1e858fSMatthias Ringwald fail:
20885d1e858fSMatthias Ringwald     if (new_multiplexer) btstack_memory_rfcomm_multiplexer_free(multiplexer);
20895d1e858fSMatthias Ringwald     if (channel)         btstack_memory_rfcomm_channel_free(channel);
20905d1e858fSMatthias Ringwald     return status;
20915d1e858fSMatthias Ringwald }
20925d1e858fSMatthias Ringwald 
2093ccb8ddfbSMatthias Ringwald uint8_t rfcomm_create_channel_with_initial_credits(btstack_packet_handler_t packet_handler, bd_addr_t addr, uint8_t server_channel, uint8_t initial_credits, uint16_t * out_rfcomm_cid){
2094ccb8ddfbSMatthias Ringwald     return rfcomm_channel_create_internal(packet_handler, addr, server_channel, 1, initial_credits, out_rfcomm_cid);
20955d1e858fSMatthias Ringwald }
20965d1e858fSMatthias Ringwald 
2097ccb8ddfbSMatthias Ringwald uint8_t rfcomm_create_channel(btstack_packet_handler_t packet_handler, bd_addr_t addr, uint8_t server_channel, uint16_t * out_rfcomm_cid){
2098ccb8ddfbSMatthias Ringwald     return rfcomm_channel_create_internal(packet_handler, addr, server_channel, 0, RFCOMM_CREDITS, out_rfcomm_cid);
20995d1e858fSMatthias Ringwald }
21005d1e858fSMatthias Ringwald 
210128190c0bSMatthias Ringwald void rfcomm_disconnect(uint16_t rfcomm_cid){
21023deb3ec6SMatthias Ringwald     log_info("RFCOMM_DISCONNECT cid 0x%02x", rfcomm_cid);
21033deb3ec6SMatthias Ringwald     rfcomm_channel_t * channel = rfcomm_channel_for_rfcomm_cid(rfcomm_cid);
21043deb3ec6SMatthias Ringwald     if (channel) {
21053deb3ec6SMatthias Ringwald         channel->state = RFCOMM_CHANNEL_SEND_DISC;
21063deb3ec6SMatthias Ringwald     }
21073deb3ec6SMatthias Ringwald 
21083deb3ec6SMatthias Ringwald     // process
21093deb3ec6SMatthias Ringwald     rfcomm_run();
21103deb3ec6SMatthias Ringwald }
21113deb3ec6SMatthias Ringwald 
2112ccb8ddfbSMatthias Ringwald static uint8_t rfcomm_register_service_internal(btstack_packet_handler_t packet_handler,
2113ccb8ddfbSMatthias Ringwald     uint8_t channel, uint16_t max_frame_size, uint8_t incoming_flow_control, uint8_t initial_credits){
2114ccb8ddfbSMatthias Ringwald 
2115ccb8ddfbSMatthias Ringwald     log_info("RFCOMM_REGISTER_SERVICE channel #%u mtu %u flow_control %u credits %u",
21163deb3ec6SMatthias Ringwald              channel, max_frame_size, incoming_flow_control, initial_credits);
2117457b5cb1SMatthias Ringwald 
21183deb3ec6SMatthias Ringwald     // check if already registered
21193deb3ec6SMatthias Ringwald     rfcomm_service_t * service = rfcomm_service_for_channel(channel);
21203deb3ec6SMatthias Ringwald     if (service){
2121457b5cb1SMatthias Ringwald         return RFCOMM_CHANNEL_ALREADY_REGISTERED;
21223deb3ec6SMatthias Ringwald     }
21233deb3ec6SMatthias Ringwald 
21243deb3ec6SMatthias Ringwald     // alloc structure
21253deb3ec6SMatthias Ringwald     service = btstack_memory_rfcomm_service_get();
21263deb3ec6SMatthias Ringwald     if (!service) {
2127457b5cb1SMatthias Ringwald         return BTSTACK_MEMORY_ALLOC_FAILED;
21283deb3ec6SMatthias Ringwald     }
21293deb3ec6SMatthias Ringwald 
21303deb3ec6SMatthias Ringwald     // register with l2cap if not registered before, max MTU
2131665d90f2SMatthias Ringwald     if (btstack_linked_list_empty(&rfcomm_services)){
2132be2053a6SMatthias Ringwald         l2cap_register_service(rfcomm_packet_handler, PSM_RFCOMM, 0xffff, rfcomm_security_level);
21333deb3ec6SMatthias Ringwald     }
21343deb3ec6SMatthias Ringwald 
21353deb3ec6SMatthias Ringwald     // fill in
2136ccb8ddfbSMatthias Ringwald     service->packet_handler = packet_handler;
21373deb3ec6SMatthias Ringwald     service->server_channel = channel;
21383deb3ec6SMatthias Ringwald     service->max_frame_size = max_frame_size;
21393deb3ec6SMatthias Ringwald     service->incoming_flow_control = incoming_flow_control;
21403deb3ec6SMatthias Ringwald     service->incoming_initial_credits = initial_credits;
21413deb3ec6SMatthias Ringwald 
21423deb3ec6SMatthias Ringwald     // add to services list
2143665d90f2SMatthias Ringwald     btstack_linked_list_add(&rfcomm_services, (btstack_linked_item_t *) service);
21443deb3ec6SMatthias Ringwald 
2145457b5cb1SMatthias Ringwald     return 0;
21463deb3ec6SMatthias Ringwald }
21473deb3ec6SMatthias Ringwald 
2148ccb8ddfbSMatthias Ringwald uint8_t rfcomm_register_service_with_initial_credits(btstack_packet_handler_t packet_handler,
2149ccb8ddfbSMatthias Ringwald     uint8_t channel, uint16_t max_frame_size, uint8_t initial_credits){
2150ccb8ddfbSMatthias Ringwald 
2151ccb8ddfbSMatthias Ringwald     return rfcomm_register_service_internal(packet_handler, channel, max_frame_size, 1, initial_credits);
21523deb3ec6SMatthias Ringwald }
21533deb3ec6SMatthias Ringwald 
2154ccb8ddfbSMatthias Ringwald uint8_t rfcomm_register_service(btstack_packet_handler_t packet_handler, uint8_t channel,
2155ccb8ddfbSMatthias Ringwald     uint16_t max_frame_size){
2156ccb8ddfbSMatthias Ringwald 
2157ccb8ddfbSMatthias Ringwald     return rfcomm_register_service_internal(packet_handler, channel, max_frame_size, 0,RFCOMM_CREDITS);
21583deb3ec6SMatthias Ringwald }
21593deb3ec6SMatthias Ringwald 
2160457b5cb1SMatthias Ringwald void rfcomm_unregister_service(uint8_t service_channel){
21613deb3ec6SMatthias Ringwald     log_info("RFCOMM_UNREGISTER_SERVICE #%u", service_channel);
21623deb3ec6SMatthias Ringwald     rfcomm_service_t *service = rfcomm_service_for_channel(service_channel);
21633deb3ec6SMatthias Ringwald     if (!service) return;
2164665d90f2SMatthias Ringwald     btstack_linked_list_remove(&rfcomm_services, (btstack_linked_item_t *) service);
21653deb3ec6SMatthias Ringwald     btstack_memory_rfcomm_service_free(service);
21663deb3ec6SMatthias Ringwald 
21673deb3ec6SMatthias Ringwald     // unregister if no services active
2168665d90f2SMatthias Ringwald     if (btstack_linked_list_empty(&rfcomm_services)){
21693deb3ec6SMatthias Ringwald         // bt_send_cmd(&l2cap_unregister_service, PSM_RFCOMM);
217002f83142SMatthias Ringwald         l2cap_unregister_service(PSM_RFCOMM);
21713deb3ec6SMatthias Ringwald     }
21723deb3ec6SMatthias Ringwald }
21733deb3ec6SMatthias Ringwald 
217428190c0bSMatthias Ringwald void rfcomm_accept_connection(uint16_t rfcomm_cid){
21753deb3ec6SMatthias Ringwald     log_info("RFCOMM_ACCEPT_CONNECTION cid 0x%02x", rfcomm_cid);
21763deb3ec6SMatthias Ringwald     rfcomm_channel_t * channel = rfcomm_channel_for_rfcomm_cid(rfcomm_cid);
21773deb3ec6SMatthias Ringwald     if (!channel) return;
21783deb3ec6SMatthias Ringwald     switch (channel->state) {
21793deb3ec6SMatthias Ringwald         case RFCOMM_CHANNEL_INCOMING_SETUP:
21803deb3ec6SMatthias Ringwald             rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_CLIENT_ACCEPTED);
21813deb3ec6SMatthias Ringwald             if (channel->state_var & RFCOMM_CHANNEL_STATE_VAR_RCVD_PN){
21823deb3ec6SMatthias Ringwald                 rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_PN_RSP);
21833deb3ec6SMatthias Ringwald             }
21843deb3ec6SMatthias Ringwald             if (channel->state_var & RFCOMM_CHANNEL_STATE_VAR_RCVD_SABM){
21853deb3ec6SMatthias Ringwald                 rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_UA);
21863deb3ec6SMatthias Ringwald             }
21873deb3ec6SMatthias Ringwald             // at least one of { PN RSP, UA } needs to be sent
21883deb3ec6SMatthias Ringwald             // state transistion incoming setup -> dlc setup happens in rfcomm_run after these have been sent
21893deb3ec6SMatthias Ringwald             break;
21903deb3ec6SMatthias Ringwald         default:
21913deb3ec6SMatthias Ringwald             break;
21923deb3ec6SMatthias Ringwald     }
21933deb3ec6SMatthias Ringwald 
21943deb3ec6SMatthias Ringwald     // process
21953deb3ec6SMatthias Ringwald     rfcomm_run();
21963deb3ec6SMatthias Ringwald }
21973deb3ec6SMatthias Ringwald 
219828190c0bSMatthias Ringwald void rfcomm_decline_connection(uint16_t rfcomm_cid){
21993deb3ec6SMatthias Ringwald     log_info("RFCOMM_DECLINE_CONNECTION cid 0x%02x", rfcomm_cid);
22003deb3ec6SMatthias Ringwald     rfcomm_channel_t * channel = rfcomm_channel_for_rfcomm_cid(rfcomm_cid);
22013deb3ec6SMatthias Ringwald     if (!channel) return;
22023deb3ec6SMatthias Ringwald     switch (channel->state) {
22033deb3ec6SMatthias Ringwald         case RFCOMM_CHANNEL_INCOMING_SETUP:
22043deb3ec6SMatthias Ringwald             channel->state = RFCOMM_CHANNEL_SEND_DM;
22053deb3ec6SMatthias Ringwald             break;
22063deb3ec6SMatthias Ringwald         default:
22073deb3ec6SMatthias Ringwald             break;
22083deb3ec6SMatthias Ringwald     }
22093deb3ec6SMatthias Ringwald 
22103deb3ec6SMatthias Ringwald     // process
22113deb3ec6SMatthias Ringwald     rfcomm_run();
22123deb3ec6SMatthias Ringwald }
22133deb3ec6SMatthias Ringwald 
22143deb3ec6SMatthias Ringwald void rfcomm_grant_credits(uint16_t rfcomm_cid, uint8_t credits){
22153deb3ec6SMatthias Ringwald     log_info("RFCOMM_GRANT_CREDITS cid 0x%02x credits %u", rfcomm_cid, credits);
22163deb3ec6SMatthias Ringwald     rfcomm_channel_t * channel = rfcomm_channel_for_rfcomm_cid(rfcomm_cid);
22173deb3ec6SMatthias Ringwald     if (!channel) return;
22183deb3ec6SMatthias Ringwald     if (!channel->incoming_flow_control) return;
22193deb3ec6SMatthias Ringwald     channel->new_credits_incoming += credits;
22203deb3ec6SMatthias Ringwald 
22213deb3ec6SMatthias Ringwald     // process
22223deb3ec6SMatthias Ringwald     rfcomm_run();
22233deb3ec6SMatthias Ringwald }
22243deb3ec6SMatthias Ringwald 
22253deb3ec6SMatthias Ringwald 
2226b1c4ef5fSMatthias Ringwald /*
2227b1c4ef5fSMatthias Ringwald  * CRC (reversed crc) lookup table as calculated by the table generator in ETSI TS 101 369 V6.3.0.
2228b1c4ef5fSMatthias Ringwald  */
2229b1c4ef5fSMatthias Ringwald static const uint8_t crc8table[256] = {    /* reversed, 8-bit, poly=0x07 */
2230b1c4ef5fSMatthias Ringwald     0x00, 0x91, 0xE3, 0x72, 0x07, 0x96, 0xE4, 0x75, 0x0E, 0x9F, 0xED, 0x7C, 0x09, 0x98, 0xEA, 0x7B,
2231b1c4ef5fSMatthias Ringwald     0x1C, 0x8D, 0xFF, 0x6E, 0x1B, 0x8A, 0xF8, 0x69, 0x12, 0x83, 0xF1, 0x60, 0x15, 0x84, 0xF6, 0x67,
2232b1c4ef5fSMatthias Ringwald     0x38, 0xA9, 0xDB, 0x4A, 0x3F, 0xAE, 0xDC, 0x4D, 0x36, 0xA7, 0xD5, 0x44, 0x31, 0xA0, 0xD2, 0x43,
2233b1c4ef5fSMatthias Ringwald     0x24, 0xB5, 0xC7, 0x56, 0x23, 0xB2, 0xC0, 0x51, 0x2A, 0xBB, 0xC9, 0x58, 0x2D, 0xBC, 0xCE, 0x5F,
2234b1c4ef5fSMatthias Ringwald     0x70, 0xE1, 0x93, 0x02, 0x77, 0xE6, 0x94, 0x05, 0x7E, 0xEF, 0x9D, 0x0C, 0x79, 0xE8, 0x9A, 0x0B,
2235b1c4ef5fSMatthias Ringwald     0x6C, 0xFD, 0x8F, 0x1E, 0x6B, 0xFA, 0x88, 0x19, 0x62, 0xF3, 0x81, 0x10, 0x65, 0xF4, 0x86, 0x17,
2236b1c4ef5fSMatthias Ringwald     0x48, 0xD9, 0xAB, 0x3A, 0x4F, 0xDE, 0xAC, 0x3D, 0x46, 0xD7, 0xA5, 0x34, 0x41, 0xD0, 0xA2, 0x33,
2237b1c4ef5fSMatthias Ringwald     0x54, 0xC5, 0xB7, 0x26, 0x53, 0xC2, 0xB0, 0x21, 0x5A, 0xCB, 0xB9, 0x28, 0x5D, 0xCC, 0xBE, 0x2F,
2238b1c4ef5fSMatthias Ringwald     0xE0, 0x71, 0x03, 0x92, 0xE7, 0x76, 0x04, 0x95, 0xEE, 0x7F, 0x0D, 0x9C, 0xE9, 0x78, 0x0A, 0x9B,
2239b1c4ef5fSMatthias Ringwald     0xFC, 0x6D, 0x1F, 0x8E, 0xFB, 0x6A, 0x18, 0x89, 0xF2, 0x63, 0x11, 0x80, 0xF5, 0x64, 0x16, 0x87,
2240b1c4ef5fSMatthias Ringwald     0xD8, 0x49, 0x3B, 0xAA, 0xDF, 0x4E, 0x3C, 0xAD, 0xD6, 0x47, 0x35, 0xA4, 0xD1, 0x40, 0x32, 0xA3,
2241b1c4ef5fSMatthias Ringwald     0xC4, 0x55, 0x27, 0xB6, 0xC3, 0x52, 0x20, 0xB1, 0xCA, 0x5B, 0x29, 0xB8, 0xCD, 0x5C, 0x2E, 0xBF,
2242b1c4ef5fSMatthias Ringwald     0x90, 0x01, 0x73, 0xE2, 0x97, 0x06, 0x74, 0xE5, 0x9E, 0x0F, 0x7D, 0xEC, 0x99, 0x08, 0x7A, 0xEB,
2243b1c4ef5fSMatthias Ringwald     0x8C, 0x1D, 0x6F, 0xFE, 0x8B, 0x1A, 0x68, 0xF9, 0x82, 0x13, 0x61, 0xF0, 0x85, 0x14, 0x66, 0xF7,
2244b1c4ef5fSMatthias Ringwald     0xA8, 0x39, 0x4B, 0xDA, 0xAF, 0x3E, 0x4C, 0xDD, 0xA6, 0x37, 0x45, 0xD4, 0xA1, 0x30, 0x42, 0xD3,
2245b1c4ef5fSMatthias Ringwald     0xB4, 0x25, 0x57, 0xC6, 0xB3, 0x22, 0x50, 0xC1, 0xBA, 0x2B, 0x59, 0xC8, 0xBD, 0x2C, 0x5E, 0xCF
2246b1c4ef5fSMatthias Ringwald };
2247b1c4ef5fSMatthias Ringwald 
2248b1c4ef5fSMatthias Ringwald #define CRC8_INIT  0xFF          // Initial FCS value
2249b1c4ef5fSMatthias Ringwald #define CRC8_OK    0xCF          // Good final FCS value
2250b1c4ef5fSMatthias Ringwald /*-----------------------------------------------------------------------------------*/
2251b1c4ef5fSMatthias Ringwald static uint8_t crc8(uint8_t *data, uint16_t len)
2252b1c4ef5fSMatthias Ringwald {
2253b1c4ef5fSMatthias Ringwald     uint16_t count;
2254b1c4ef5fSMatthias Ringwald     uint8_t crc = CRC8_INIT;
2255b1c4ef5fSMatthias Ringwald     for (count = 0; count < len; count++)
2256b1c4ef5fSMatthias Ringwald         crc = crc8table[crc ^ data[count]];
2257b1c4ef5fSMatthias Ringwald     return crc;
2258b1c4ef5fSMatthias Ringwald }
2259b1c4ef5fSMatthias Ringwald 
2260b1c4ef5fSMatthias Ringwald /*-----------------------------------------------------------------------------------*/
2261b1c4ef5fSMatthias Ringwald uint8_t crc8_check(uint8_t *data, uint16_t len, uint8_t check_sum)
2262b1c4ef5fSMatthias Ringwald {
2263b1c4ef5fSMatthias Ringwald     uint8_t crc;
2264b1c4ef5fSMatthias Ringwald 
2265b1c4ef5fSMatthias Ringwald     crc = crc8(data, len);
2266b1c4ef5fSMatthias Ringwald 
2267b1c4ef5fSMatthias Ringwald     crc = crc8table[crc ^ check_sum];
2268b1c4ef5fSMatthias Ringwald     if (crc == CRC8_OK)
2269b1c4ef5fSMatthias Ringwald         return 0;               /* Valid */
2270b1c4ef5fSMatthias Ringwald     else
2271b1c4ef5fSMatthias Ringwald         return 1;               /* Failed */
2272b1c4ef5fSMatthias Ringwald 
2273b1c4ef5fSMatthias Ringwald }
2274b1c4ef5fSMatthias Ringwald 
2275b1c4ef5fSMatthias Ringwald /*-----------------------------------------------------------------------------------*/
2276b1c4ef5fSMatthias Ringwald uint8_t crc8_calc(uint8_t *data, uint16_t len)
2277b1c4ef5fSMatthias Ringwald {
2278b1c4ef5fSMatthias Ringwald     /* Ones complement */
2279b1c4ef5fSMatthias Ringwald     return 0xFF - crc8(data, len);
2280b1c4ef5fSMatthias Ringwald }
2281b1c4ef5fSMatthias Ringwald 
2282b1c4ef5fSMatthias Ringwald 
22833deb3ec6SMatthias Ringwald 
22843deb3ec6SMatthias Ringwald 
2285