xref: /btstack/src/classic/rfcomm.c (revision e9a7c22d24fa70ef6e913b7b1e32fda2c32d9ef3)
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 
4716ece135SMatthias Ringwald #include "btstack_debug.h"
480e2df43fSMatthias Ringwald #include "btstack_event.h"
49e628322dSMatthias Ringwald #include "btstack_memory.h"
50e628322dSMatthias Ringwald #include "btstack_util.h"
5159c6af15SMatthias Ringwald #include "classic/core.h"
523edc84c5SMatthias Ringwald #include "classic/rfcomm.h"
53e628322dSMatthias Ringwald #include "hci.h"
54e628322dSMatthias Ringwald #include "hci_cmd.h"
55e628322dSMatthias Ringwald #include "hci_dump.h"
56e628322dSMatthias Ringwald #include "l2cap.h"
573deb3ec6SMatthias Ringwald 
583deb3ec6SMatthias Ringwald // workaround for missing PRIxPTR on mspgcc (16/20-bit MCU)
593deb3ec6SMatthias Ringwald #ifndef PRIxPTR
603deb3ec6SMatthias Ringwald #if defined(__MSP430X__)  &&  defined(__MSP430X_LARGE__)
613deb3ec6SMatthias Ringwald #define PRIxPTR "lx"
623deb3ec6SMatthias Ringwald #else
633deb3ec6SMatthias Ringwald #define PRIxPTR "x"
643deb3ec6SMatthias Ringwald #endif
653deb3ec6SMatthias Ringwald #endif
663deb3ec6SMatthias Ringwald 
673deb3ec6SMatthias Ringwald #define RFCOMM_MULIPLEXER_TIMEOUT_MS 60000
683deb3ec6SMatthias Ringwald 
693deb3ec6SMatthias Ringwald #define RFCOMM_CREDITS 10
703deb3ec6SMatthias Ringwald 
713deb3ec6SMatthias Ringwald // FCS calc
723deb3ec6SMatthias Ringwald #define BT_RFCOMM_CODE_WORD         0xE0 // pol = x8+x2+x1+1
733deb3ec6SMatthias Ringwald #define BT_RFCOMM_CRC_CHECK_LEN     3
743deb3ec6SMatthias Ringwald #define BT_RFCOMM_UIHCRC_CHECK_LEN  2
753deb3ec6SMatthias Ringwald 
76e628322dSMatthias Ringwald 
77e628322dSMatthias Ringwald typedef enum {
78e628322dSMatthias Ringwald     CH_EVT_RCVD_SABM = 1,
79e628322dSMatthias Ringwald     CH_EVT_RCVD_UA,
80e628322dSMatthias Ringwald     CH_EVT_RCVD_PN,
81e628322dSMatthias Ringwald     CH_EVT_RCVD_PN_RSP,
82e628322dSMatthias Ringwald     CH_EVT_RCVD_DISC,
83e628322dSMatthias Ringwald     CH_EVT_RCVD_DM,
84e628322dSMatthias Ringwald     CH_EVT_RCVD_MSC_CMD,
85e628322dSMatthias Ringwald     CH_EVT_RCVD_MSC_RSP,
86e628322dSMatthias Ringwald     CH_EVT_RCVD_NSC_RSP,
87e628322dSMatthias Ringwald     CH_EVT_RCVD_RLS_CMD,
88e628322dSMatthias Ringwald     CH_EVT_RCVD_RLS_RSP,
89e628322dSMatthias Ringwald     CH_EVT_RCVD_RPN_CMD,
90e628322dSMatthias Ringwald     CH_EVT_RCVD_RPN_REQ,
91e628322dSMatthias Ringwald     CH_EVT_RCVD_CREDITS,
92e628322dSMatthias Ringwald     CH_EVT_MULTIPLEXER_READY,
93e628322dSMatthias Ringwald     CH_EVT_READY_TO_SEND,
94e628322dSMatthias Ringwald } RFCOMM_CHANNEL_EVENT;
95e628322dSMatthias Ringwald 
96e628322dSMatthias Ringwald typedef struct rfcomm_channel_event {
97e628322dSMatthias Ringwald     RFCOMM_CHANNEL_EVENT type;
98e628322dSMatthias Ringwald     uint16_t dummy; // force rfcomm_channel_event to be 2-byte aligned -> avoid -Wcast-align warning
99e628322dSMatthias Ringwald } rfcomm_channel_event_t;
100e628322dSMatthias Ringwald 
101e628322dSMatthias Ringwald typedef struct rfcomm_channel_event_pn {
102e628322dSMatthias Ringwald     rfcomm_channel_event_t super;
103e628322dSMatthias Ringwald     uint16_t max_frame_size;
104e628322dSMatthias Ringwald     uint8_t  priority;
105e628322dSMatthias Ringwald     uint8_t  credits_outgoing;
106e628322dSMatthias Ringwald } rfcomm_channel_event_pn_t;
107e628322dSMatthias Ringwald 
108e628322dSMatthias Ringwald typedef struct rfcomm_channel_event_rpn {
109e628322dSMatthias Ringwald     rfcomm_channel_event_t super;
110e628322dSMatthias Ringwald     rfcomm_rpn_data_t data;
111e628322dSMatthias Ringwald } rfcomm_channel_event_rpn_t;
112e628322dSMatthias Ringwald 
113e628322dSMatthias Ringwald typedef struct rfcomm_channel_event_rls {
114e628322dSMatthias Ringwald     rfcomm_channel_event_t super;
115e628322dSMatthias Ringwald     uint8_t line_status;
116e628322dSMatthias Ringwald } rfcomm_channel_event_rls_t;
117e628322dSMatthias Ringwald 
118e628322dSMatthias Ringwald typedef struct rfcomm_channel_event_msc {
119e628322dSMatthias Ringwald     rfcomm_channel_event_t super;
120e628322dSMatthias Ringwald     uint8_t modem_status;
121e628322dSMatthias Ringwald } rfcomm_channel_event_msc_t;
122e628322dSMatthias Ringwald 
1233deb3ec6SMatthias Ringwald 
1243deb3ec6SMatthias Ringwald // global rfcomm data
1253deb3ec6SMatthias Ringwald static uint16_t      rfcomm_client_cid_generator;  // used for client channel IDs
1263deb3ec6SMatthias Ringwald 
1273deb3ec6SMatthias Ringwald // linked lists for all
1288f2a52f4SMatthias Ringwald static btstack_linked_list_t rfcomm_multiplexers = NULL;
1298f2a52f4SMatthias Ringwald static btstack_linked_list_t rfcomm_channels = NULL;
1308f2a52f4SMatthias Ringwald static btstack_linked_list_t rfcomm_services = NULL;
1313deb3ec6SMatthias Ringwald 
1323deb3ec6SMatthias Ringwald static gap_security_level_t rfcomm_security_level;
1333deb3ec6SMatthias Ringwald 
134b31d33b2SMatthias Ringwald static int  rfcomm_channel_can_send(rfcomm_channel_t * channel);
135b31d33b2SMatthias Ringwald static int  rfcomm_channel_ready_for_open(rfcomm_channel_t *channel);
13662b5b741SMatthias Ringwald static int rfcomm_channel_ready_to_send(rfcomm_channel_t * channel);
1373232fa30SMatthias Ringwald static void rfcomm_channel_state_machine_with_channel(rfcomm_channel_t *channel, const rfcomm_channel_event_t *event);
1383232fa30SMatthias Ringwald static void rfcomm_channel_state_machine_with_dlci(rfcomm_multiplexer_t * multiplexer, uint8_t dlci, const rfcomm_channel_event_t *event);
139b31d33b2SMatthias Ringwald static void rfcomm_emit_can_send_now(rfcomm_channel_t *channel);
140b35818ceSMatthias Ringwald static int rfcomm_multiplexer_ready_to_send(rfcomm_multiplexer_t * multiplexer);
1413deb3ec6SMatthias Ringwald static void rfcomm_multiplexer_state_machine(rfcomm_multiplexer_t * multiplexer, RFCOMM_MULTIPLEXER_EVENT event);
1423deb3ec6SMatthias Ringwald 
1433deb3ec6SMatthias Ringwald // MARK: RFCOMM CLIENT EVENTS
1443deb3ec6SMatthias Ringwald 
1453deb3ec6SMatthias Ringwald // data: event (8), len(8), address(48), channel (8), rfcomm_cid (16)
1463deb3ec6SMatthias Ringwald static void rfcomm_emit_connection_request(rfcomm_channel_t *channel) {
1473deb3ec6SMatthias Ringwald     log_info("RFCOMM_EVENT_INCOMING_CONNECTION addr %s channel #%u cid 0x%02x",
1483deb3ec6SMatthias Ringwald              bd_addr_to_str(channel->multiplexer->remote_addr), channel->dlci>>1, channel->rfcomm_cid);
1493deb3ec6SMatthias Ringwald     uint8_t event[11];
1503deb3ec6SMatthias Ringwald     event[0] = RFCOMM_EVENT_INCOMING_CONNECTION;
1513deb3ec6SMatthias Ringwald     event[1] = sizeof(event) - 2;
152724d70a2SMatthias Ringwald     reverse_bd_addr(channel->multiplexer->remote_addr, &event[2]);
1533deb3ec6SMatthias Ringwald     event[8] = channel->dlci >> 1;
154f8fbdce0SMatthias Ringwald     little_endian_store_16(event, 9, channel->rfcomm_cid);
1553deb3ec6SMatthias Ringwald     hci_dump_packet(HCI_EVENT_PACKET, 0, event, sizeof(event));
156b31d33b2SMatthias Ringwald 	(channel->packet_handler)(HCI_EVENT_PACKET, 0, event, sizeof(event));
1573deb3ec6SMatthias Ringwald }
1583deb3ec6SMatthias Ringwald 
1593deb3ec6SMatthias Ringwald // API Change: BTstack-0.3.50x uses
1603deb3ec6SMatthias Ringwald // data: event(8), len(8), status (8), address (48), server channel(8), rfcomm_cid(16), max frame size(16)
1613deb3ec6SMatthias Ringwald // next Cydia release will use SVN version of this
1623deb3ec6SMatthias Ringwald // data: event(8), len(8), status (8), address (48), handle (16), server channel(8), rfcomm_cid(16), max frame size(16)
1633deb3ec6SMatthias Ringwald static void rfcomm_emit_channel_opened(rfcomm_channel_t *channel, uint8_t status) {
164f8f6a918SMatthias Ringwald     log_info("RFCOMM_EVENT_CHANNEL_OPENED status 0x%x addr %s handle 0x%x channel #%u cid 0x%02x mtu %u",
1653deb3ec6SMatthias Ringwald              status, bd_addr_to_str(channel->multiplexer->remote_addr), channel->multiplexer->con_handle,
1663deb3ec6SMatthias Ringwald              channel->dlci>>1, channel->rfcomm_cid, channel->max_frame_size);
1673deb3ec6SMatthias Ringwald     uint8_t event[16];
1683deb3ec6SMatthias Ringwald     uint8_t pos = 0;
169f8f6a918SMatthias Ringwald     event[pos++] = RFCOMM_EVENT_CHANNEL_OPENED;  // 0
1705d1e858fSMatthias Ringwald     event[pos++] = sizeof(event) - 2;                   // 1
1715d1e858fSMatthias Ringwald     event[pos++] = status;                              // 2
172724d70a2SMatthias Ringwald     reverse_bd_addr(channel->multiplexer->remote_addr, &event[pos]); pos += 6; // 3
173f8fbdce0SMatthias Ringwald     little_endian_store_16(event,  pos, channel->multiplexer->con_handle);   pos += 2; // 9
1745d1e858fSMatthias Ringwald 	event[pos++] = channel->dlci >> 1;                                      // 11
175f8fbdce0SMatthias Ringwald 	little_endian_store_16(event, pos, channel->rfcomm_cid); pos += 2;                 // 12 - channel ID
176f8fbdce0SMatthias Ringwald 	little_endian_store_16(event, pos, channel->max_frame_size); pos += 2;   // max frame size
1773deb3ec6SMatthias Ringwald     hci_dump_packet(HCI_EVENT_PACKET, 0, event, sizeof(event));
178b31d33b2SMatthias Ringwald 	(channel->packet_handler)(HCI_EVENT_PACKET, 0, event, pos);
179b31d33b2SMatthias Ringwald 
180b31d33b2SMatthias Ringwald     // if channel opened successfully, also send can send now if possible
181b31d33b2SMatthias Ringwald     if (status) return;
182b31d33b2SMatthias Ringwald     if (rfcomm_channel_can_send(channel)){
183b31d33b2SMatthias Ringwald         rfcomm_emit_can_send_now(channel);
184b31d33b2SMatthias Ringwald     }
1853deb3ec6SMatthias Ringwald }
1863deb3ec6SMatthias Ringwald 
1873deb3ec6SMatthias Ringwald // data: event(8), len(8), rfcomm_cid(16)
1883deb3ec6SMatthias Ringwald static void rfcomm_emit_channel_closed(rfcomm_channel_t * channel) {
1893deb3ec6SMatthias Ringwald     log_info("RFCOMM_EVENT_CHANNEL_CLOSED cid 0x%02x", channel->rfcomm_cid);
1903deb3ec6SMatthias Ringwald     uint8_t event[4];
1913deb3ec6SMatthias Ringwald     event[0] = RFCOMM_EVENT_CHANNEL_CLOSED;
1923deb3ec6SMatthias Ringwald     event[1] = sizeof(event) - 2;
193f8fbdce0SMatthias Ringwald     little_endian_store_16(event, 2, channel->rfcomm_cid);
1943deb3ec6SMatthias Ringwald     hci_dump_packet(HCI_EVENT_PACKET, 0, event, sizeof(event));
195b31d33b2SMatthias Ringwald 	(channel->packet_handler)(HCI_EVENT_PACKET, 0, event, sizeof(event));
1963deb3ec6SMatthias Ringwald }
1973deb3ec6SMatthias Ringwald 
1983deb3ec6SMatthias Ringwald static void rfcomm_emit_remote_line_status(rfcomm_channel_t *channel, uint8_t line_status){
1993deb3ec6SMatthias Ringwald     log_info("RFCOMM_EVENT_REMOTE_LINE_STATUS cid 0x%02x c, line status 0x%x", channel->rfcomm_cid, line_status);
2003deb3ec6SMatthias Ringwald     uint8_t event[5];
2013deb3ec6SMatthias Ringwald     event[0] = RFCOMM_EVENT_REMOTE_LINE_STATUS;
2023deb3ec6SMatthias Ringwald     event[1] = sizeof(event) - 2;
203f8fbdce0SMatthias Ringwald     little_endian_store_16(event, 2, channel->rfcomm_cid);
2043deb3ec6SMatthias Ringwald     event[4] = line_status;
2053deb3ec6SMatthias Ringwald     hci_dump_packet( HCI_EVENT_PACKET, 0, event, sizeof(event));
206b31d33b2SMatthias Ringwald     (channel->packet_handler)(HCI_EVENT_PACKET, 0, event, sizeof(event));
2073deb3ec6SMatthias Ringwald }
2083deb3ec6SMatthias Ringwald 
2093deb3ec6SMatthias Ringwald static void rfcomm_emit_port_configuration(rfcomm_channel_t *channel){
2103deb3ec6SMatthias Ringwald     // notify client about new settings
2113deb3ec6SMatthias Ringwald     uint8_t event[2+sizeof(rfcomm_rpn_data_t)];
2123deb3ec6SMatthias Ringwald     event[0] = RFCOMM_EVENT_PORT_CONFIGURATION;
2133deb3ec6SMatthias Ringwald     event[1] = sizeof(rfcomm_rpn_data_t);
2143deb3ec6SMatthias Ringwald     memcpy(&event[2], (uint8_t*) &channel->rpn_data, sizeof(rfcomm_rpn_data_t));
2153deb3ec6SMatthias Ringwald     hci_dump_packet( HCI_EVENT_PACKET, 0, event, sizeof(event));
216b31d33b2SMatthias Ringwald     (channel->packet_handler)(HCI_EVENT_PACKET, channel->rfcomm_cid, event, sizeof(event));
217b31d33b2SMatthias Ringwald }
218b31d33b2SMatthias Ringwald 
219b31d33b2SMatthias Ringwald static void rfcomm_emit_can_send_now(rfcomm_channel_t *channel) {
220b31d33b2SMatthias Ringwald     log_info("RFCOMM_EVENT_CHANNEL_CAN_SEND_NOW local_cid 0x%x", channel->rfcomm_cid);
221b31d33b2SMatthias Ringwald     uint8_t event[4];
222b31d33b2SMatthias Ringwald     event[0] = RFCOMM_EVENT_CAN_SEND_NOW;
223b31d33b2SMatthias Ringwald     event[1] = sizeof(event) - 2;
224b31d33b2SMatthias Ringwald     little_endian_store_16(event, 2, channel->rfcomm_cid);
225b31d33b2SMatthias Ringwald     hci_dump_packet( HCI_EVENT_PACKET, 0, event, sizeof(event));
226b31d33b2SMatthias Ringwald     (channel->packet_handler)(HCI_EVENT_PACKET, channel->rfcomm_cid, event, sizeof(event));
2273deb3ec6SMatthias Ringwald }
2283deb3ec6SMatthias Ringwald 
2293deb3ec6SMatthias Ringwald // MARK RFCOMM RPN DATA HELPER
2303deb3ec6SMatthias Ringwald static void rfcomm_rpn_data_set_defaults(rfcomm_rpn_data_t * rpn_data){
2313deb3ec6SMatthias Ringwald         rpn_data->baud_rate = RPN_BAUD_9600;  /* 9600 bps */
2323deb3ec6SMatthias Ringwald         rpn_data->flags = 0x03;               /* 8-n-1 */
2333deb3ec6SMatthias Ringwald         rpn_data->flow_control = 0;           /* no flow control */
2343deb3ec6SMatthias Ringwald         rpn_data->xon  = 0xd1;                /* XON */
2353deb3ec6SMatthias Ringwald         rpn_data->xoff = 0xd3;                /* XOFF */
2363deb3ec6SMatthias Ringwald         rpn_data->parameter_mask_0 = 0x7f;    /* parameter mask, all values set */
2373deb3ec6SMatthias Ringwald         rpn_data->parameter_mask_1 = 0x3f;    /* parameter mask, all values set */
2383deb3ec6SMatthias Ringwald }
2393deb3ec6SMatthias Ringwald 
2403deb3ec6SMatthias Ringwald static void rfcomm_rpn_data_update(rfcomm_rpn_data_t * dest, rfcomm_rpn_data_t * src){
2413deb3ec6SMatthias Ringwald     if (src->parameter_mask_0 & RPN_PARAM_MASK_0_BAUD){
2423deb3ec6SMatthias Ringwald         dest->baud_rate = src->baud_rate;
2433deb3ec6SMatthias Ringwald     }
2443deb3ec6SMatthias Ringwald     if (src->parameter_mask_0 & RPN_PARAM_MASK_0_DATA_BITS){
2453deb3ec6SMatthias Ringwald         dest->flags = (dest->flags & 0xfc) | (src->flags & 0x03);
2463deb3ec6SMatthias Ringwald     }
2473deb3ec6SMatthias Ringwald     if (src->parameter_mask_0 & RPN_PARAM_MASK_0_STOP_BITS){
2483deb3ec6SMatthias Ringwald         dest->flags = (dest->flags & 0xfb) | (src->flags & 0x04);
2493deb3ec6SMatthias Ringwald     }
2503deb3ec6SMatthias Ringwald     if (src->parameter_mask_0 & RPN_PARAM_MASK_0_PARITY){
2513deb3ec6SMatthias Ringwald         dest->flags = (dest->flags & 0xf7) | (src->flags & 0x08);
2523deb3ec6SMatthias Ringwald     }
2533deb3ec6SMatthias Ringwald     if (src->parameter_mask_0 & RPN_PARAM_MASK_0_PARITY_TYPE){
2543deb3ec6SMatthias Ringwald         dest->flags = (dest->flags & 0xfc) | (src->flags & 0x30);
2553deb3ec6SMatthias Ringwald     }
2563deb3ec6SMatthias Ringwald     if (src->parameter_mask_0 & RPN_PARAM_MASK_0_XON_CHAR){
2573deb3ec6SMatthias Ringwald         dest->xon = src->xon;
2583deb3ec6SMatthias Ringwald     }
2593deb3ec6SMatthias Ringwald     if (src->parameter_mask_0 & RPN_PARAM_MASK_0_XOFF_CHAR){
2603deb3ec6SMatthias Ringwald         dest->xoff = src->xoff;
2613deb3ec6SMatthias Ringwald     }
2623deb3ec6SMatthias Ringwald     int i;
2633deb3ec6SMatthias Ringwald     for (i=0; i < 6 ; i++){
2643deb3ec6SMatthias Ringwald         uint8_t mask = 1 << i;
2653deb3ec6SMatthias Ringwald         if (src->parameter_mask_1 & mask){
2663deb3ec6SMatthias Ringwald             dest->flags = (dest->flags & ~mask) | (src->flags & mask);
2673deb3ec6SMatthias Ringwald         }
2683deb3ec6SMatthias Ringwald     }
2693deb3ec6SMatthias Ringwald     // always copy parameter mask, too. informative for client, needed for response
2703deb3ec6SMatthias Ringwald     dest->parameter_mask_0 = src->parameter_mask_0;
2713deb3ec6SMatthias Ringwald     dest->parameter_mask_1 = src->parameter_mask_1;
2723deb3ec6SMatthias Ringwald }
2733deb3ec6SMatthias Ringwald // MARK: RFCOMM MULTIPLEXER HELPER
2743deb3ec6SMatthias Ringwald 
2753deb3ec6SMatthias Ringwald static uint16_t rfcomm_max_frame_size_for_l2cap_mtu(uint16_t l2cap_mtu){
2763deb3ec6SMatthias Ringwald     // Assume RFCOMM header without credits and 2 byte (14 bit) length field
2773deb3ec6SMatthias Ringwald     uint16_t max_frame_size = l2cap_mtu - 5;
2783deb3ec6SMatthias Ringwald     log_info("rfcomm_max_frame_size_for_l2cap_mtu:  %u -> %u", l2cap_mtu, max_frame_size);
2793deb3ec6SMatthias Ringwald     return max_frame_size;
2803deb3ec6SMatthias Ringwald }
2813deb3ec6SMatthias Ringwald 
2823deb3ec6SMatthias Ringwald static void rfcomm_multiplexer_initialize(rfcomm_multiplexer_t *multiplexer){
2833deb3ec6SMatthias Ringwald 
2843deb3ec6SMatthias Ringwald     memset(multiplexer, 0, sizeof(rfcomm_multiplexer_t));
2853deb3ec6SMatthias Ringwald 
2863deb3ec6SMatthias Ringwald     multiplexer->state = RFCOMM_MULTIPLEXER_CLOSED;
2873deb3ec6SMatthias Ringwald     multiplexer->fcon = 1;
2883deb3ec6SMatthias Ringwald     multiplexer->send_dm_for_dlci = 0;
2893deb3ec6SMatthias Ringwald     multiplexer->max_frame_size = rfcomm_max_frame_size_for_l2cap_mtu(l2cap_max_mtu());
2903deb3ec6SMatthias Ringwald     multiplexer->test_data_len = 0;
2913deb3ec6SMatthias Ringwald     multiplexer->nsc_command = 0;
2923deb3ec6SMatthias Ringwald }
2933deb3ec6SMatthias Ringwald 
2943deb3ec6SMatthias Ringwald static rfcomm_multiplexer_t * rfcomm_multiplexer_create_for_addr(bd_addr_t addr){
2953deb3ec6SMatthias Ringwald 
2963deb3ec6SMatthias Ringwald     // alloc structure
2973deb3ec6SMatthias Ringwald     rfcomm_multiplexer_t * multiplexer = btstack_memory_rfcomm_multiplexer_get();
2983deb3ec6SMatthias Ringwald     if (!multiplexer) return NULL;
2993deb3ec6SMatthias Ringwald 
3003deb3ec6SMatthias Ringwald     // fill in
3013deb3ec6SMatthias Ringwald     rfcomm_multiplexer_initialize(multiplexer);
30273988a59SMatthias Ringwald     bd_addr_copy(multiplexer->remote_addr, addr);
3033deb3ec6SMatthias Ringwald 
3043deb3ec6SMatthias Ringwald     // add to services list
305665d90f2SMatthias Ringwald     btstack_linked_list_add(&rfcomm_multiplexers, (btstack_linked_item_t *) multiplexer);
3063deb3ec6SMatthias Ringwald 
3073deb3ec6SMatthias Ringwald     return multiplexer;
3083deb3ec6SMatthias Ringwald }
3093deb3ec6SMatthias Ringwald 
3103deb3ec6SMatthias Ringwald static rfcomm_multiplexer_t * rfcomm_multiplexer_for_addr(bd_addr_t addr){
311665d90f2SMatthias Ringwald     btstack_linked_item_t *it;
312665d90f2SMatthias Ringwald     for (it = (btstack_linked_item_t *) rfcomm_multiplexers; it ; it = it->next){
3133deb3ec6SMatthias Ringwald         rfcomm_multiplexer_t * multiplexer = ((rfcomm_multiplexer_t *) it);
314058e3d6bSMatthias Ringwald         if (bd_addr_cmp(addr, multiplexer->remote_addr) == 0) {
3153deb3ec6SMatthias Ringwald             return multiplexer;
3163deb3ec6SMatthias Ringwald         };
3173deb3ec6SMatthias Ringwald     }
3183deb3ec6SMatthias Ringwald     return NULL;
3193deb3ec6SMatthias Ringwald }
3203deb3ec6SMatthias Ringwald 
3213deb3ec6SMatthias Ringwald static rfcomm_multiplexer_t * rfcomm_multiplexer_for_l2cap_cid(uint16_t l2cap_cid) {
322665d90f2SMatthias Ringwald     btstack_linked_item_t *it;
323665d90f2SMatthias Ringwald     for (it = (btstack_linked_item_t *) rfcomm_multiplexers; it ; it = it->next){
3243deb3ec6SMatthias Ringwald         rfcomm_multiplexer_t * multiplexer = ((rfcomm_multiplexer_t *) it);
3253deb3ec6SMatthias Ringwald         if (multiplexer->l2cap_cid == l2cap_cid) {
3263deb3ec6SMatthias Ringwald             return multiplexer;
3273deb3ec6SMatthias Ringwald         };
3283deb3ec6SMatthias Ringwald     }
3293deb3ec6SMatthias Ringwald     return NULL;
3303deb3ec6SMatthias Ringwald }
3313deb3ec6SMatthias Ringwald 
3323deb3ec6SMatthias Ringwald static int rfcomm_multiplexer_has_channels(rfcomm_multiplexer_t * multiplexer){
333665d90f2SMatthias Ringwald     btstack_linked_item_t *it;
334665d90f2SMatthias Ringwald     for (it = (btstack_linked_item_t *) rfcomm_channels; it ; it = it->next){
3353deb3ec6SMatthias Ringwald         rfcomm_channel_t * channel = ((rfcomm_channel_t *) it);
3363deb3ec6SMatthias Ringwald         if (channel->multiplexer == multiplexer) {
3373deb3ec6SMatthias Ringwald             return 1;
3383deb3ec6SMatthias Ringwald         }
3393deb3ec6SMatthias Ringwald     }
3403deb3ec6SMatthias Ringwald     return 0;
3413deb3ec6SMatthias Ringwald }
3423deb3ec6SMatthias Ringwald 
3433deb3ec6SMatthias Ringwald // MARK: RFCOMM CHANNEL HELPER
3443deb3ec6SMatthias Ringwald 
3453deb3ec6SMatthias Ringwald static void rfcomm_dump_channels(void){
346665d90f2SMatthias Ringwald     btstack_linked_item_t * it;
3473deb3ec6SMatthias Ringwald     int channels = 0;
348665d90f2SMatthias Ringwald     for (it = (btstack_linked_item_t *) rfcomm_channels; it ; it = it->next){
3493deb3ec6SMatthias Ringwald         rfcomm_channel_t * channel = (rfcomm_channel_t *) it;
3503deb3ec6SMatthias Ringwald         log_info("Channel #%u: addr %p, state %u", channels, channel, channel->state);
3513deb3ec6SMatthias Ringwald         channels++;
3523deb3ec6SMatthias Ringwald     }
3533deb3ec6SMatthias Ringwald }
3543deb3ec6SMatthias Ringwald 
3553deb3ec6SMatthias Ringwald static void rfcomm_channel_initialize(rfcomm_channel_t *channel, rfcomm_multiplexer_t *multiplexer,
3563deb3ec6SMatthias Ringwald                                rfcomm_service_t *service, uint8_t server_channel){
3573deb3ec6SMatthias Ringwald 
3583deb3ec6SMatthias Ringwald     // don't use 0 as channel id
3593deb3ec6SMatthias Ringwald     if (rfcomm_client_cid_generator == 0) ++rfcomm_client_cid_generator;
3603deb3ec6SMatthias Ringwald 
3613deb3ec6SMatthias Ringwald     // setup channel
3623deb3ec6SMatthias Ringwald     memset(channel, 0, sizeof(rfcomm_channel_t));
3633deb3ec6SMatthias Ringwald 
364ccb8ddfbSMatthias Ringwald     // set defaults for port configuration (even for services)
365ccb8ddfbSMatthias Ringwald     rfcomm_rpn_data_set_defaults(&channel->rpn_data);
366ccb8ddfbSMatthias Ringwald 
3673deb3ec6SMatthias Ringwald     channel->state            = RFCOMM_CHANNEL_CLOSED;
3683deb3ec6SMatthias Ringwald     channel->state_var        = RFCOMM_CHANNEL_STATE_VAR_NONE;
3693deb3ec6SMatthias Ringwald 
3703deb3ec6SMatthias Ringwald     channel->multiplexer      = multiplexer;
3713deb3ec6SMatthias Ringwald     channel->rfcomm_cid       = rfcomm_client_cid_generator++;
3723deb3ec6SMatthias Ringwald     channel->max_frame_size   = multiplexer->max_frame_size;
3733deb3ec6SMatthias Ringwald 
3743deb3ec6SMatthias Ringwald     channel->credits_incoming = 0;
3753deb3ec6SMatthias Ringwald     channel->credits_outgoing = 0;
3763deb3ec6SMatthias Ringwald 
3773deb3ec6SMatthias Ringwald     // incoming flow control not active
3783deb3ec6SMatthias Ringwald     channel->new_credits_incoming  = RFCOMM_CREDITS;
3793deb3ec6SMatthias Ringwald     channel->incoming_flow_control = 0;
3803deb3ec6SMatthias Ringwald 
3813deb3ec6SMatthias Ringwald     channel->rls_line_status       = RFCOMM_RLS_STATUS_INVALID;
3823deb3ec6SMatthias Ringwald 
383ccb8ddfbSMatthias Ringwald     channel->service = service;
3843deb3ec6SMatthias Ringwald 	if (service) {
3853deb3ec6SMatthias Ringwald 		// incoming connection
3863deb3ec6SMatthias Ringwald     	channel->dlci = (server_channel << 1) |  multiplexer->outgoing;
3873deb3ec6SMatthias Ringwald         if (channel->max_frame_size > service->max_frame_size) {
3883deb3ec6SMatthias Ringwald             channel->max_frame_size = service->max_frame_size;
3893deb3ec6SMatthias Ringwald         }
3903deb3ec6SMatthias Ringwald         channel->incoming_flow_control = service->incoming_flow_control;
3913deb3ec6SMatthias Ringwald         channel->new_credits_incoming  = service->incoming_initial_credits;
392ccb8ddfbSMatthias Ringwald         channel->packet_handler        = service->packet_handler;
3933deb3ec6SMatthias Ringwald 	} else {
3943deb3ec6SMatthias Ringwald 		// outgoing connection
3953deb3ec6SMatthias Ringwald 		channel->dlci = (server_channel << 1) | (multiplexer->outgoing ^ 1);
3963deb3ec6SMatthias Ringwald 	}
3973deb3ec6SMatthias Ringwald }
3983deb3ec6SMatthias Ringwald 
3993deb3ec6SMatthias Ringwald // service == NULL -> outgoing channel
4003deb3ec6SMatthias Ringwald static rfcomm_channel_t * rfcomm_channel_create(rfcomm_multiplexer_t * multiplexer,
4013deb3ec6SMatthias Ringwald                                                 rfcomm_service_t * service, uint8_t server_channel){
4023deb3ec6SMatthias Ringwald 
4033deb3ec6SMatthias Ringwald     log_info("rfcomm_channel_create for service %p, channel %u --- list of channels:", service, server_channel);
4043deb3ec6SMatthias Ringwald     rfcomm_dump_channels();
4053deb3ec6SMatthias Ringwald 
4063deb3ec6SMatthias Ringwald     // alloc structure
4073deb3ec6SMatthias Ringwald     rfcomm_channel_t * channel = btstack_memory_rfcomm_channel_get();
4083deb3ec6SMatthias Ringwald     if (!channel) return NULL;
4093deb3ec6SMatthias Ringwald 
4103deb3ec6SMatthias Ringwald     // fill in
4113deb3ec6SMatthias Ringwald     rfcomm_channel_initialize(channel, multiplexer, service, server_channel);
4123deb3ec6SMatthias Ringwald 
4133deb3ec6SMatthias Ringwald     // add to services list
414665d90f2SMatthias Ringwald     btstack_linked_list_add(&rfcomm_channels, (btstack_linked_item_t *) channel);
4153deb3ec6SMatthias Ringwald 
4163deb3ec6SMatthias Ringwald     return channel;
4173deb3ec6SMatthias Ringwald }
4183deb3ec6SMatthias Ringwald 
419b31d33b2SMatthias Ringwald static void rfcomm_notify_channel_can_send(void){
420b31d33b2SMatthias Ringwald     btstack_linked_list_iterator_t it;
421b31d33b2SMatthias Ringwald     btstack_linked_list_iterator_init(&it, &rfcomm_channels);
422b31d33b2SMatthias Ringwald     while (btstack_linked_list_iterator_has_next(&it)){
423b31d33b2SMatthias Ringwald         rfcomm_channel_t * channel = (rfcomm_channel_t *) btstack_linked_list_iterator_next(&it);
424b31d33b2SMatthias Ringwald         if (!channel->waiting_for_can_send_now) continue; // didn't try to send yet
425b31d33b2SMatthias Ringwald         if (!rfcomm_channel_can_send(channel)) continue;  // or cannot yet either
426b31d33b2SMatthias Ringwald 
427b31d33b2SMatthias Ringwald         channel->waiting_for_can_send_now = 0;
428b31d33b2SMatthias Ringwald         rfcomm_emit_can_send_now(channel);
429b31d33b2SMatthias Ringwald     }
430b31d33b2SMatthias Ringwald }
431b31d33b2SMatthias Ringwald 
4323deb3ec6SMatthias Ringwald static rfcomm_channel_t * rfcomm_channel_for_rfcomm_cid(uint16_t rfcomm_cid){
433665d90f2SMatthias Ringwald     btstack_linked_item_t *it;
434665d90f2SMatthias Ringwald     for (it = (btstack_linked_item_t *) rfcomm_channels; it ; it = it->next){
4353deb3ec6SMatthias Ringwald         rfcomm_channel_t * channel = ((rfcomm_channel_t *) it);
4363deb3ec6SMatthias Ringwald         if (channel->rfcomm_cid == rfcomm_cid) {
4373deb3ec6SMatthias Ringwald             return channel;
4383deb3ec6SMatthias Ringwald         };
4393deb3ec6SMatthias Ringwald     }
4403deb3ec6SMatthias Ringwald     return NULL;
4413deb3ec6SMatthias Ringwald }
4423deb3ec6SMatthias Ringwald 
4433deb3ec6SMatthias Ringwald static rfcomm_channel_t * rfcomm_channel_for_multiplexer_and_dlci(rfcomm_multiplexer_t * multiplexer, uint8_t dlci){
444665d90f2SMatthias Ringwald     btstack_linked_item_t *it;
445665d90f2SMatthias Ringwald     for (it = (btstack_linked_item_t *) rfcomm_channels; it ; it = it->next){
4463deb3ec6SMatthias Ringwald         rfcomm_channel_t * channel = ((rfcomm_channel_t *) it);
4473deb3ec6SMatthias Ringwald         if (channel->dlci == dlci && channel->multiplexer == multiplexer) {
4483deb3ec6SMatthias Ringwald             return channel;
4493deb3ec6SMatthias Ringwald         };
4503deb3ec6SMatthias Ringwald     }
4513deb3ec6SMatthias Ringwald     return NULL;
4523deb3ec6SMatthias Ringwald }
4533deb3ec6SMatthias Ringwald 
4543deb3ec6SMatthias Ringwald static rfcomm_service_t * rfcomm_service_for_channel(uint8_t server_channel){
455665d90f2SMatthias Ringwald     btstack_linked_item_t *it;
456665d90f2SMatthias Ringwald     for (it = (btstack_linked_item_t *) rfcomm_services; it ; it = it->next){
4573deb3ec6SMatthias Ringwald         rfcomm_service_t * service = ((rfcomm_service_t *) it);
4583deb3ec6SMatthias Ringwald         if ( service->server_channel == server_channel){
4593deb3ec6SMatthias Ringwald             return service;
4603deb3ec6SMatthias Ringwald         };
4613deb3ec6SMatthias Ringwald     }
4623deb3ec6SMatthias Ringwald     return NULL;
4633deb3ec6SMatthias Ringwald }
4643deb3ec6SMatthias Ringwald 
4653deb3ec6SMatthias Ringwald // MARK: RFCOMM SEND
4663deb3ec6SMatthias Ringwald 
4673deb3ec6SMatthias Ringwald /**
4683deb3ec6SMatthias Ringwald  * @param credits - only used for RFCOMM flow control in UIH wiht P/F = 1
4693deb3ec6SMatthias Ringwald  */
4703deb3ec6SMatthias 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){
4713deb3ec6SMatthias Ringwald 
4723deb3ec6SMatthias Ringwald     if (!l2cap_can_send_packet_now(multiplexer->l2cap_cid)) return BTSTACK_ACL_BUFFERS_FULL;
4733deb3ec6SMatthias Ringwald 
4743deb3ec6SMatthias Ringwald     l2cap_reserve_packet_buffer();
4753deb3ec6SMatthias Ringwald     uint8_t * rfcomm_out_buffer = l2cap_get_outgoing_buffer();
4763deb3ec6SMatthias Ringwald 
4773deb3ec6SMatthias Ringwald 	uint16_t pos = 0;
4783deb3ec6SMatthias Ringwald 	uint8_t crc_fields = 3;
4793deb3ec6SMatthias Ringwald 
4803deb3ec6SMatthias Ringwald 	rfcomm_out_buffer[pos++] = address;
4813deb3ec6SMatthias Ringwald 	rfcomm_out_buffer[pos++] = control;
4823deb3ec6SMatthias Ringwald 
4833deb3ec6SMatthias Ringwald 	// length field can be 1 or 2 octets
4843deb3ec6SMatthias Ringwald 	if (len < 128){
4853deb3ec6SMatthias Ringwald 		rfcomm_out_buffer[pos++] = (len << 1)| 1;     // bits 0-6
4863deb3ec6SMatthias Ringwald 	} else {
4873deb3ec6SMatthias Ringwald 		rfcomm_out_buffer[pos++] = (len & 0x7f) << 1; // bits 0-6
4883deb3ec6SMatthias Ringwald 		rfcomm_out_buffer[pos++] = len >> 7;          // bits 7-14
4893deb3ec6SMatthias Ringwald 		crc_fields++;
4903deb3ec6SMatthias Ringwald 	}
4913deb3ec6SMatthias Ringwald 
4923deb3ec6SMatthias Ringwald 	// add credits for UIH frames when PF bit is set
4933deb3ec6SMatthias Ringwald 	if (control == BT_RFCOMM_UIH_PF){
4943deb3ec6SMatthias Ringwald 		rfcomm_out_buffer[pos++] = credits;
4953deb3ec6SMatthias Ringwald 	}
4963deb3ec6SMatthias Ringwald 
4973deb3ec6SMatthias Ringwald 	// copy actual data
4983deb3ec6SMatthias Ringwald 	if (len) {
4993deb3ec6SMatthias Ringwald 		memcpy(&rfcomm_out_buffer[pos], data, len);
5003deb3ec6SMatthias Ringwald 		pos += len;
5013deb3ec6SMatthias Ringwald 	}
5023deb3ec6SMatthias Ringwald 
5033deb3ec6SMatthias Ringwald 	// UIH frames only calc FCS over address + control (5.1.1)
5043deb3ec6SMatthias Ringwald 	if ((control & 0xef) == BT_RFCOMM_UIH){
5053deb3ec6SMatthias Ringwald 		crc_fields = 2;
5063deb3ec6SMatthias Ringwald 	}
5073deb3ec6SMatthias Ringwald 	rfcomm_out_buffer[pos++] =  crc8_calc(rfcomm_out_buffer, crc_fields); // calc fcs
5083deb3ec6SMatthias Ringwald 
5093deb3ec6SMatthias Ringwald     int err = l2cap_send_prepared(multiplexer->l2cap_cid, pos);
5103deb3ec6SMatthias Ringwald 
5113deb3ec6SMatthias Ringwald     return err;
5123deb3ec6SMatthias Ringwald }
5133deb3ec6SMatthias Ringwald 
5143deb3ec6SMatthias Ringwald // simplified version of rfcomm_send_packet_for_multiplexer for prepared rfcomm packet (UIH, 2 byte len, no credits)
5153deb3ec6SMatthias Ringwald static int rfcomm_send_uih_prepared(rfcomm_multiplexer_t *multiplexer, uint8_t dlci, uint16_t len){
5163deb3ec6SMatthias Ringwald 
5173deb3ec6SMatthias Ringwald     uint8_t address = (1 << 0) | (multiplexer->outgoing << 1) | (dlci << 2);
5183deb3ec6SMatthias Ringwald     uint8_t control = BT_RFCOMM_UIH;
5193deb3ec6SMatthias Ringwald 
5203deb3ec6SMatthias Ringwald     uint8_t * rfcomm_out_buffer = l2cap_get_outgoing_buffer();
5213deb3ec6SMatthias Ringwald 
5223deb3ec6SMatthias Ringwald     uint16_t pos = 0;
5233deb3ec6SMatthias Ringwald     rfcomm_out_buffer[pos++] = address;
5243deb3ec6SMatthias Ringwald     rfcomm_out_buffer[pos++] = control;
5253deb3ec6SMatthias Ringwald     rfcomm_out_buffer[pos++] = (len & 0x7f) << 1; // bits 0-6
5263deb3ec6SMatthias Ringwald     rfcomm_out_buffer[pos++] = len >> 7;          // bits 7-14
5273deb3ec6SMatthias Ringwald 
5283deb3ec6SMatthias Ringwald     // actual data is already in place
5293deb3ec6SMatthias Ringwald     pos += len;
5303deb3ec6SMatthias Ringwald 
5313deb3ec6SMatthias Ringwald     // UIH frames only calc FCS over address + control (5.1.1)
5323deb3ec6SMatthias Ringwald     rfcomm_out_buffer[pos++] =  crc8_calc(rfcomm_out_buffer, 2); // calc fcs
5333deb3ec6SMatthias Ringwald 
5343deb3ec6SMatthias Ringwald     int err = l2cap_send_prepared(multiplexer->l2cap_cid, pos);
5353deb3ec6SMatthias Ringwald 
5363deb3ec6SMatthias Ringwald     return err;
5373deb3ec6SMatthias Ringwald }
5383deb3ec6SMatthias Ringwald 
5393deb3ec6SMatthias Ringwald // C/R Flag in Address
5403deb3ec6SMatthias Ringwald // - terms: initiator = station that creates multiplexer with SABM
5413deb3ec6SMatthias Ringwald // - terms: responder = station that responds to multiplexer setup with UA
5423deb3ec6SMatthias 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"
5433deb3ec6SMatthias Ringwald //    - command initiator = 1 /response responder = 1
5443deb3ec6SMatthias Ringwald //    - command responder = 0 /response initiator = 0
5453deb3ec6SMatthias Ringwald // "For UIH frames, the C/R bit is always set according to section 5.4.3.1 in GSM 07.10.
5463deb3ec6SMatthias Ringwald //  This applies independently of what is contained wthin the UIH frames, either data or control messages."
5473deb3ec6SMatthias Ringwald //    - c/r = 1 for frames by initiating station, 0 = for frames by responding station
5483deb3ec6SMatthias Ringwald 
5493deb3ec6SMatthias Ringwald // C/R Flag in Message
5503deb3ec6SMatthias 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."
5513deb3ec6SMatthias Ringwald //   - If the C/R bit is set to 1 the message is a command
5523deb3ec6SMatthias Ringwald //   - if it is set to 0 the message is a response.
5533deb3ec6SMatthias Ringwald 
5543deb3ec6SMatthias Ringwald // temp/old messge construction
5553deb3ec6SMatthias Ringwald 
5563deb3ec6SMatthias Ringwald // new object oriented version
5573deb3ec6SMatthias Ringwald static int rfcomm_send_sabm(rfcomm_multiplexer_t *multiplexer, uint8_t dlci){
5583deb3ec6SMatthias Ringwald 	uint8_t address = (1 << 0) | (multiplexer->outgoing << 1) | (dlci << 2);   // command
5593deb3ec6SMatthias Ringwald     return rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_SABM, 0, NULL, 0);
5603deb3ec6SMatthias Ringwald }
5613deb3ec6SMatthias Ringwald 
5623deb3ec6SMatthias Ringwald static int rfcomm_send_disc(rfcomm_multiplexer_t *multiplexer, uint8_t dlci){
5633deb3ec6SMatthias Ringwald 	uint8_t address = (1 << 0) | (multiplexer->outgoing << 1) | (dlci << 2);  // command
5643deb3ec6SMatthias Ringwald     return rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_DISC, 0, NULL, 0);
5653deb3ec6SMatthias Ringwald }
5663deb3ec6SMatthias Ringwald 
5673deb3ec6SMatthias Ringwald static int rfcomm_send_ua(rfcomm_multiplexer_t *multiplexer, uint8_t dlci){
5683deb3ec6SMatthias Ringwald 	uint8_t address = (1 << 0) | ((multiplexer->outgoing ^ 1) << 1) | (dlci << 2); // response
5693deb3ec6SMatthias Ringwald     return rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_UA, 0, NULL, 0);
5703deb3ec6SMatthias Ringwald }
5713deb3ec6SMatthias Ringwald 
5723deb3ec6SMatthias Ringwald static int rfcomm_send_dm_pf(rfcomm_multiplexer_t *multiplexer, uint8_t dlci){
5733deb3ec6SMatthias Ringwald 	uint8_t address = (1 << 0) | ((multiplexer->outgoing ^ 1) << 1) | (dlci << 2); // response
5743deb3ec6SMatthias Ringwald     return rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_DM_PF, 0, NULL, 0);
5753deb3ec6SMatthias Ringwald }
5763deb3ec6SMatthias Ringwald 
5773deb3ec6SMatthias Ringwald static int rfcomm_send_uih_fc_rsp(rfcomm_multiplexer_t *multiplexer, uint8_t fcon) {
5783deb3ec6SMatthias Ringwald     uint8_t address = (1 << 0) | (multiplexer->outgoing<< 1);
5793deb3ec6SMatthias Ringwald     uint8_t payload[2];
5803deb3ec6SMatthias Ringwald     uint8_t pos = 0;
5813deb3ec6SMatthias Ringwald     payload[pos++] = fcon ? BT_RFCOMM_FCON_RSP : BT_RFCOMM_FCOFF_RSP;
5823deb3ec6SMatthias Ringwald     payload[pos++] = (0 << 1) | 1;  // len
5833deb3ec6SMatthias Ringwald     return rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_UIH, 0, (uint8_t *) payload, pos);
5843deb3ec6SMatthias Ringwald }
5853deb3ec6SMatthias Ringwald 
5863deb3ec6SMatthias Ringwald // static int rfcomm_send_uih_test_cmd(rfcomm_multiplexer_t *multiplexer, uint8_t * data, uint16_t len) {
5873deb3ec6SMatthias Ringwald //     uint8_t address = (1 << 0) | (multiplexer->outgoing << 1);
5883deb3ec6SMatthias Ringwald //     uint8_t payload[2+len];
5893deb3ec6SMatthias Ringwald //     uint8_t pos = 0;
5903deb3ec6SMatthias Ringwald //     payload[pos++] = BT_RFCOMM_TEST_CMD;
5913deb3ec6SMatthias Ringwald //     payload[pos++] = (len + 1) << 1 | 1;  // len
5923deb3ec6SMatthias Ringwald //     memcpy(&payload[pos], data, len);
5933deb3ec6SMatthias Ringwald //     pos += len;
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_test_rsp(rfcomm_multiplexer_t *multiplexer, uint8_t * data, uint16_t len) {
5983deb3ec6SMatthias Ringwald     uint8_t address = (1 << 0) | (multiplexer->outgoing << 1);
5993deb3ec6SMatthias Ringwald     uint8_t payload[2+RFCOMM_TEST_DATA_MAX_LEN];
6003deb3ec6SMatthias Ringwald     uint8_t pos = 0;
6013deb3ec6SMatthias Ringwald     payload[pos++] = BT_RFCOMM_TEST_RSP;
6023deb3ec6SMatthias Ringwald     if (len > RFCOMM_TEST_DATA_MAX_LEN) {
6033deb3ec6SMatthias Ringwald         len = RFCOMM_TEST_DATA_MAX_LEN;
6043deb3ec6SMatthias Ringwald     }
6053deb3ec6SMatthias Ringwald     payload[pos++] = (len << 1) | 1;  // len
6063deb3ec6SMatthias Ringwald     memcpy(&payload[pos], data, len);
6073deb3ec6SMatthias Ringwald     pos += len;
6083deb3ec6SMatthias Ringwald     return rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_UIH, 0, (uint8_t *) payload, pos);
6093deb3ec6SMatthias Ringwald }
6103deb3ec6SMatthias Ringwald 
6113deb3ec6SMatthias Ringwald static int rfcomm_send_uih_msc_cmd(rfcomm_multiplexer_t *multiplexer, uint8_t dlci, uint8_t signals) {
6123deb3ec6SMatthias Ringwald 	uint8_t address = (1 << 0) | (multiplexer->outgoing << 1);
6133deb3ec6SMatthias Ringwald 	uint8_t payload[4];
6143deb3ec6SMatthias Ringwald 	uint8_t pos = 0;
6153deb3ec6SMatthias Ringwald 	payload[pos++] = BT_RFCOMM_MSC_CMD;
6163deb3ec6SMatthias Ringwald 	payload[pos++] = (2 << 1) | 1;  // len
6173deb3ec6SMatthias Ringwald 	payload[pos++] = (1 << 0) | (1 << 1) | (dlci << 2); // CMD => C/R = 1
6183deb3ec6SMatthias Ringwald 	payload[pos++] = signals;
6193deb3ec6SMatthias Ringwald 	return rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_UIH, 0, (uint8_t *) payload, pos);
6203deb3ec6SMatthias Ringwald }
6213deb3ec6SMatthias Ringwald 
6223deb3ec6SMatthias Ringwald static int rfcomm_send_uih_msc_rsp(rfcomm_multiplexer_t *multiplexer, uint8_t dlci, uint8_t signals) {
6233deb3ec6SMatthias Ringwald 	uint8_t address = (1 << 0) | (multiplexer->outgoing<< 1);
6243deb3ec6SMatthias Ringwald 	uint8_t payload[4];
6253deb3ec6SMatthias Ringwald 	uint8_t pos = 0;
6263deb3ec6SMatthias Ringwald 	payload[pos++] = BT_RFCOMM_MSC_RSP;
6273deb3ec6SMatthias Ringwald 	payload[pos++] = (2 << 1) | 1;  // len
6283deb3ec6SMatthias Ringwald 	payload[pos++] = (1 << 0) | (1 << 1) | (dlci << 2); // CMD => C/R = 1
6293deb3ec6SMatthias Ringwald 	payload[pos++] = signals;
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_nsc_rsp(rfcomm_multiplexer_t *multiplexer, uint8_t command) {
6343deb3ec6SMatthias Ringwald     uint8_t address = (1 << 0) | (multiplexer->outgoing<< 1);
6353deb3ec6SMatthias Ringwald     uint8_t payload[3];
6363deb3ec6SMatthias Ringwald     uint8_t pos = 0;
6373deb3ec6SMatthias Ringwald     payload[pos++] = BT_RFCOMM_NSC_RSP;
6383deb3ec6SMatthias Ringwald     payload[pos++] = (1 << 1) | 1;  // len
6393deb3ec6SMatthias Ringwald     payload[pos++] = command;
6403deb3ec6SMatthias Ringwald     return rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_UIH, 0, (uint8_t *) payload, pos);
6413deb3ec6SMatthias Ringwald }
6423deb3ec6SMatthias Ringwald 
6433deb3ec6SMatthias Ringwald static int rfcomm_send_uih_pn_command(rfcomm_multiplexer_t *multiplexer, uint8_t dlci, uint16_t max_frame_size){
6443deb3ec6SMatthias Ringwald 	uint8_t payload[10];
6453deb3ec6SMatthias Ringwald 	uint8_t address = (1 << 0) | (multiplexer->outgoing << 1);
6463deb3ec6SMatthias Ringwald 	uint8_t pos = 0;
6473deb3ec6SMatthias Ringwald 	payload[pos++] = BT_RFCOMM_PN_CMD;
6483deb3ec6SMatthias Ringwald 	payload[pos++] = (8 << 1) | 1;  // len
6493deb3ec6SMatthias Ringwald 	payload[pos++] = dlci;
6503deb3ec6SMatthias Ringwald 	payload[pos++] = 0xf0; // pre-defined for Bluetooth, see 5.5.3 of TS 07.10 Adaption for RFCOMM
6513deb3ec6SMatthias Ringwald 	payload[pos++] = 0; // priority
6523deb3ec6SMatthias Ringwald 	payload[pos++] = 0; // max 60 seconds ack
6533deb3ec6SMatthias Ringwald 	payload[pos++] = max_frame_size & 0xff; // max framesize low
6543deb3ec6SMatthias Ringwald 	payload[pos++] = max_frame_size >> 8;   // max framesize high
6553deb3ec6SMatthias Ringwald 	payload[pos++] = 0x00; // number of retransmissions
6563deb3ec6SMatthias Ringwald 	payload[pos++] = 0x00; // (unused error recovery window) initial number of credits
6573deb3ec6SMatthias Ringwald 	return rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_UIH, 0, (uint8_t *) payload, pos);
6583deb3ec6SMatthias Ringwald }
6593deb3ec6SMatthias Ringwald 
660d6549a6eSMatthias Ringwald // "The response may not change the DLCI, the priority, the convergence layer, or the timer value." rfcomm_tutorial.pdf
6613deb3ec6SMatthias Ringwald static int rfcomm_send_uih_pn_response(rfcomm_multiplexer_t *multiplexer, uint8_t dlci,
6623deb3ec6SMatthias Ringwald                                        uint8_t priority, uint16_t max_frame_size){
6633deb3ec6SMatthias Ringwald 	uint8_t payload[10];
6643deb3ec6SMatthias Ringwald 	uint8_t address = (1 << 0) | (multiplexer->outgoing << 1);
6653deb3ec6SMatthias Ringwald 	uint8_t pos = 0;
6663deb3ec6SMatthias Ringwald 	payload[pos++] = BT_RFCOMM_PN_RSP;
6673deb3ec6SMatthias Ringwald 	payload[pos++] = (8 << 1) | 1;  // len
6683deb3ec6SMatthias Ringwald 	payload[pos++] = dlci;
6693deb3ec6SMatthias Ringwald 	payload[pos++] = 0xe0; // pre defined for Bluetooth, see 5.5.3 of TS 07.10 Adaption for RFCOMM
6703deb3ec6SMatthias Ringwald 	payload[pos++] = priority; // priority
6713deb3ec6SMatthias Ringwald 	payload[pos++] = 0; // max 60 seconds ack
6723deb3ec6SMatthias Ringwald 	payload[pos++] = max_frame_size & 0xff; // max framesize low
6733deb3ec6SMatthias Ringwald 	payload[pos++] = max_frame_size >> 8;   // max framesize high
6743deb3ec6SMatthias Ringwald 	payload[pos++] = 0x00; // number of retransmissions
6753deb3ec6SMatthias Ringwald 	payload[pos++] = 0x00; // (unused error recovery window) initial number of credits
6763deb3ec6SMatthias Ringwald 	return rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_UIH, 0, (uint8_t *) payload, pos);
6773deb3ec6SMatthias Ringwald }
6783deb3ec6SMatthias Ringwald 
6793deb3ec6SMatthias Ringwald static int rfcomm_send_uih_rls_cmd(rfcomm_multiplexer_t *multiplexer, uint8_t dlci, uint8_t line_status) {
6803deb3ec6SMatthias Ringwald     uint8_t address = (1 << 0) | (multiplexer->outgoing << 1);
6813deb3ec6SMatthias Ringwald     uint8_t payload[4];
6823deb3ec6SMatthias Ringwald     uint8_t pos = 0;
6833deb3ec6SMatthias Ringwald     payload[pos++] = BT_RFCOMM_RLS_CMD;
6843deb3ec6SMatthias Ringwald     payload[pos++] = (2 << 1) | 1;  // len
6853deb3ec6SMatthias Ringwald     payload[pos++] = (1 << 0) | (1 << 1) | (dlci << 2); // CMD => C/R = 1
6863deb3ec6SMatthias Ringwald     payload[pos++] = line_status;
6873deb3ec6SMatthias Ringwald     return rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_UIH, 0, (uint8_t *) payload, pos);
6883deb3ec6SMatthias Ringwald }
6893deb3ec6SMatthias Ringwald 
6903deb3ec6SMatthias Ringwald static int rfcomm_send_uih_rls_rsp(rfcomm_multiplexer_t *multiplexer, uint8_t dlci, uint8_t line_status) {
6913deb3ec6SMatthias Ringwald     uint8_t address = (1 << 0) | (multiplexer->outgoing << 1);
6923deb3ec6SMatthias Ringwald     uint8_t payload[4];
6933deb3ec6SMatthias Ringwald     uint8_t pos = 0;
6943deb3ec6SMatthias Ringwald     payload[pos++] = BT_RFCOMM_RLS_RSP;
6953deb3ec6SMatthias Ringwald     payload[pos++] = (2 << 1) | 1;  // len
6963deb3ec6SMatthias Ringwald     payload[pos++] = (1 << 0) | (1 << 1) | (dlci << 2); // CMD => C/R = 1
6973deb3ec6SMatthias Ringwald     payload[pos++] = line_status;
6983deb3ec6SMatthias Ringwald     return rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_UIH, 0, (uint8_t *) payload, pos);
6993deb3ec6SMatthias Ringwald }
7003deb3ec6SMatthias Ringwald 
7013deb3ec6SMatthias Ringwald static int rfcomm_send_uih_rpn_cmd(rfcomm_multiplexer_t *multiplexer, uint8_t dlci, rfcomm_rpn_data_t *rpn_data) {
7023deb3ec6SMatthias Ringwald     uint8_t payload[10];
7033deb3ec6SMatthias Ringwald     uint8_t address = (1 << 0) | (multiplexer->outgoing << 1);
7043deb3ec6SMatthias Ringwald     uint8_t pos = 0;
7053deb3ec6SMatthias Ringwald     payload[pos++] = BT_RFCOMM_RPN_CMD;
7063deb3ec6SMatthias Ringwald     payload[pos++] = (8 << 1) | 1;  // len
7073deb3ec6SMatthias Ringwald     payload[pos++] = (1 << 0) | (1 << 1) | (dlci << 2); // CMD => C/R = 1
7083deb3ec6SMatthias Ringwald     payload[pos++] = rpn_data->baud_rate;
7093deb3ec6SMatthias Ringwald     payload[pos++] = rpn_data->flags;
7103deb3ec6SMatthias Ringwald     payload[pos++] = rpn_data->flow_control;
7113deb3ec6SMatthias Ringwald     payload[pos++] = rpn_data->xon;
7123deb3ec6SMatthias Ringwald     payload[pos++] = rpn_data->xoff;
7133deb3ec6SMatthias Ringwald     payload[pos++] = rpn_data->parameter_mask_0;
7143deb3ec6SMatthias Ringwald     payload[pos++] = rpn_data->parameter_mask_1;
7153deb3ec6SMatthias Ringwald     return rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_UIH, 0, (uint8_t *) payload, pos);
7163deb3ec6SMatthias Ringwald }
7173deb3ec6SMatthias Ringwald 
7183deb3ec6SMatthias Ringwald static int rfcomm_send_uih_rpn_req(rfcomm_multiplexer_t *multiplexer, uint8_t dlci) {
7193deb3ec6SMatthias Ringwald     uint8_t payload[3];
7203deb3ec6SMatthias Ringwald     uint8_t address = (1 << 0) | (multiplexer->outgoing << 1);
7213deb3ec6SMatthias Ringwald     uint8_t pos = 0;
7223deb3ec6SMatthias Ringwald     payload[pos++] = BT_RFCOMM_RPN_CMD;
7233deb3ec6SMatthias Ringwald     payload[pos++] = (1 << 1) | 1;  // len
7243deb3ec6SMatthias Ringwald     payload[pos++] = (1 << 0) | (1 << 1) | (dlci << 2); // CMD => C/R = 1
7253deb3ec6SMatthias Ringwald     return rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_UIH, 0, (uint8_t *) payload, pos);
7263deb3ec6SMatthias Ringwald }
7273deb3ec6SMatthias Ringwald 
7283deb3ec6SMatthias Ringwald static int rfcomm_send_uih_rpn_rsp(rfcomm_multiplexer_t *multiplexer, uint8_t dlci, rfcomm_rpn_data_t *rpn_data) {
7293deb3ec6SMatthias Ringwald 	uint8_t payload[10];
7303deb3ec6SMatthias Ringwald 	uint8_t address = (1 << 0) | (multiplexer->outgoing << 1);
7313deb3ec6SMatthias Ringwald 	uint8_t pos = 0;
7323deb3ec6SMatthias Ringwald 	payload[pos++] = BT_RFCOMM_RPN_RSP;
7333deb3ec6SMatthias Ringwald 	payload[pos++] = (8 << 1) | 1;  // len
7343deb3ec6SMatthias Ringwald 	payload[pos++] = (1 << 0) | (1 << 1) | (dlci << 2); // CMD => C/R = 1
7353deb3ec6SMatthias Ringwald 	payload[pos++] = rpn_data->baud_rate;
7363deb3ec6SMatthias Ringwald 	payload[pos++] = rpn_data->flags;
7373deb3ec6SMatthias Ringwald 	payload[pos++] = rpn_data->flow_control;
7383deb3ec6SMatthias Ringwald 	payload[pos++] = rpn_data->xon;
7393deb3ec6SMatthias Ringwald 	payload[pos++] = rpn_data->xoff;
7403deb3ec6SMatthias Ringwald 	payload[pos++] = rpn_data->parameter_mask_0;
7413deb3ec6SMatthias Ringwald 	payload[pos++] = rpn_data->parameter_mask_1;
7423deb3ec6SMatthias Ringwald 	return rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_UIH, 0, (uint8_t *) payload, pos);
7433deb3ec6SMatthias Ringwald }
7443deb3ec6SMatthias Ringwald 
7453deb3ec6SMatthias Ringwald static void rfcomm_send_uih_credits(rfcomm_multiplexer_t *multiplexer, uint8_t dlci,  uint8_t credits){
7463deb3ec6SMatthias Ringwald     uint8_t address = (1 << 0) | (multiplexer->outgoing << 1) |  (dlci << 2);
7473deb3ec6SMatthias Ringwald     rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_UIH_PF, credits, NULL, 0);
7483deb3ec6SMatthias Ringwald }
7493deb3ec6SMatthias Ringwald 
7503deb3ec6SMatthias Ringwald // MARK: RFCOMM MULTIPLEXER
7513deb3ec6SMatthias Ringwald static void rfcomm_multiplexer_stop_timer(rfcomm_multiplexer_t * multiplexer){
7523deb3ec6SMatthias Ringwald     if (multiplexer->timer_active) {
753528a4a3bSMatthias Ringwald         btstack_run_loop_remove_timer(&multiplexer->timer);
7543deb3ec6SMatthias Ringwald         multiplexer->timer_active = 0;
7553deb3ec6SMatthias Ringwald     }
7563deb3ec6SMatthias Ringwald }
7573deb3ec6SMatthias Ringwald static void rfcomm_multiplexer_free(rfcomm_multiplexer_t * multiplexer){
758665d90f2SMatthias Ringwald     btstack_linked_list_remove( &rfcomm_multiplexers, (btstack_linked_item_t *) multiplexer);
7593deb3ec6SMatthias Ringwald     btstack_memory_rfcomm_multiplexer_free(multiplexer);
7603deb3ec6SMatthias Ringwald }
7613deb3ec6SMatthias Ringwald 
7623deb3ec6SMatthias Ringwald static void rfcomm_multiplexer_finalize(rfcomm_multiplexer_t * multiplexer){
7633deb3ec6SMatthias Ringwald     // remove (potential) timer
7643deb3ec6SMatthias Ringwald     rfcomm_multiplexer_stop_timer(multiplexer);
7653deb3ec6SMatthias Ringwald 
7663deb3ec6SMatthias Ringwald     // close and remove all channels
767665d90f2SMatthias Ringwald     btstack_linked_item_t *it = (btstack_linked_item_t *) &rfcomm_channels;
7683deb3ec6SMatthias Ringwald     while (it->next){
7693deb3ec6SMatthias Ringwald         rfcomm_channel_t * channel = (rfcomm_channel_t *) it->next;
7703deb3ec6SMatthias Ringwald         if (channel->multiplexer == multiplexer) {
7713deb3ec6SMatthias Ringwald             // emit appropriate events
77267a68729SMatthias Ringwald             switch(channel->state){
77367a68729SMatthias Ringwald                 case RFCOMM_CHANNEL_OPEN:
7743deb3ec6SMatthias Ringwald                     rfcomm_emit_channel_closed(channel);
77567a68729SMatthias Ringwald                     break;
77667a68729SMatthias Ringwald                 case RFCOMM_CHANNEL_SEND_UA_AFTER_DISC:
77767a68729SMatthias Ringwald                     // remote didn't wait until we send the UA disc
77867a68729SMatthias Ringwald                     break;
77967a68729SMatthias Ringwald                 default:
7803deb3ec6SMatthias Ringwald                     rfcomm_emit_channel_opened(channel, RFCOMM_MULTIPLEXER_STOPPED);
78167a68729SMatthias Ringwald                     break;
7823deb3ec6SMatthias Ringwald             }
7833deb3ec6SMatthias Ringwald             // remove from list
7843deb3ec6SMatthias Ringwald             it->next = it->next->next;
7853deb3ec6SMatthias Ringwald             // free channel struct
7863deb3ec6SMatthias Ringwald             btstack_memory_rfcomm_channel_free(channel);
7873deb3ec6SMatthias Ringwald         } else {
7883deb3ec6SMatthias Ringwald             it = it->next;
7893deb3ec6SMatthias Ringwald         }
7903deb3ec6SMatthias Ringwald     }
7913deb3ec6SMatthias Ringwald 
7923deb3ec6SMatthias Ringwald     // remove mutliplexer
7933deb3ec6SMatthias Ringwald     rfcomm_multiplexer_free(multiplexer);
7943deb3ec6SMatthias Ringwald }
7953deb3ec6SMatthias Ringwald 
796ec820d77SMatthias Ringwald static void rfcomm_multiplexer_timer_handler(btstack_timer_source_t *timer){
797c5b64319SMatthias Ringwald     rfcomm_multiplexer_t * multiplexer = (rfcomm_multiplexer_t*) btstack_run_loop_get_timer_context(timer);
7983deb3ec6SMatthias Ringwald     if (rfcomm_multiplexer_has_channels(multiplexer)) return;
7993deb3ec6SMatthias Ringwald 
8003deb3ec6SMatthias Ringwald     log_info("rfcomm_multiplexer_timer_handler timeout: shutting down multiplexer! (no channels)");
8013deb3ec6SMatthias Ringwald     uint16_t l2cap_cid = multiplexer->l2cap_cid;
8023deb3ec6SMatthias Ringwald     rfcomm_multiplexer_finalize(multiplexer);
803ce8f182eSMatthias Ringwald     l2cap_disconnect(l2cap_cid, 0x13);
8043deb3ec6SMatthias Ringwald }
8053deb3ec6SMatthias Ringwald 
8063deb3ec6SMatthias Ringwald static void rfcomm_multiplexer_prepare_idle_timer(rfcomm_multiplexer_t * multiplexer){
8073deb3ec6SMatthias Ringwald     if (multiplexer->timer_active) {
808528a4a3bSMatthias Ringwald         btstack_run_loop_remove_timer(&multiplexer->timer);
8093deb3ec6SMatthias Ringwald         multiplexer->timer_active = 0;
8103deb3ec6SMatthias Ringwald     }
8113deb3ec6SMatthias Ringwald     if (rfcomm_multiplexer_has_channels(multiplexer)) return;
8123deb3ec6SMatthias Ringwald 
8133deb3ec6SMatthias Ringwald     // start idle timer for multiplexer timeout check as there are no rfcomm channels yet
814528a4a3bSMatthias Ringwald     btstack_run_loop_set_timer(&multiplexer->timer, RFCOMM_MULIPLEXER_TIMEOUT_MS);
81591a977e8SMatthias Ringwald     btstack_run_loop_set_timer_handler(&multiplexer->timer, rfcomm_multiplexer_timer_handler);
81691a977e8SMatthias Ringwald     btstack_run_loop_set_timer_context(&multiplexer->timer, multiplexer);
817528a4a3bSMatthias Ringwald     btstack_run_loop_add_timer(&multiplexer->timer);
8183deb3ec6SMatthias Ringwald     multiplexer->timer_active = 1;
8193deb3ec6SMatthias Ringwald }
8203deb3ec6SMatthias Ringwald 
8213deb3ec6SMatthias Ringwald static void rfcomm_multiplexer_opened(rfcomm_multiplexer_t *multiplexer){
8223deb3ec6SMatthias Ringwald     log_info("Multiplexer up and running");
8233deb3ec6SMatthias Ringwald     multiplexer->state = RFCOMM_MULTIPLEXER_OPEN;
8243deb3ec6SMatthias Ringwald 
82562b5b741SMatthias Ringwald     const rfcomm_channel_event_t event = { CH_EVT_MULTIPLEXER_READY };
8263deb3ec6SMatthias Ringwald 
8273deb3ec6SMatthias Ringwald     // transition of channels that wait for multiplexer
828665d90f2SMatthias Ringwald     btstack_linked_item_t *it;
829665d90f2SMatthias Ringwald     for (it = (btstack_linked_item_t *) rfcomm_channels; it ; it = it->next){
8303deb3ec6SMatthias Ringwald         rfcomm_channel_t * channel = ((rfcomm_channel_t *) it);
8313deb3ec6SMatthias Ringwald         if (channel->multiplexer != multiplexer) continue;
8323232fa30SMatthias Ringwald         rfcomm_channel_state_machine_with_channel(channel, &event);
83362b5b741SMatthias Ringwald         if (rfcomm_channel_ready_to_send(channel)){
83462b5b741SMatthias Ringwald             l2cap_request_can_send_now_event(multiplexer->l2cap_cid);
83562b5b741SMatthias Ringwald         }
8363deb3ec6SMatthias Ringwald     }
8373deb3ec6SMatthias Ringwald     rfcomm_multiplexer_prepare_idle_timer(multiplexer);
838b35818ceSMatthias Ringwald 
839b35818ceSMatthias Ringwald     // request can send now for multiplexer if ready
840b35818ceSMatthias Ringwald     if (rfcomm_multiplexer_ready_to_send(multiplexer)){
841b35818ceSMatthias Ringwald         l2cap_request_can_send_now_event(multiplexer->l2cap_cid);
842b35818ceSMatthias Ringwald     }
8433deb3ec6SMatthias Ringwald }
8443deb3ec6SMatthias Ringwald 
845b35818ceSMatthias Ringwald static void rfcomm_handle_can_send_now(uint16_t l2cap_cid){
846b35818ceSMatthias Ringwald 
847*e9a7c22dSMatthias Ringwald     log_debug("rfcomm_handle_can_send_now enter: %u", l2cap_cid);
84862b5b741SMatthias Ringwald 
849*e9a7c22dSMatthias Ringwald     btstack_linked_list_iterator_t it;
850*e9a7c22dSMatthias Ringwald     int token_consumed = 0;
851*e9a7c22dSMatthias Ringwald 
852*e9a7c22dSMatthias Ringwald     // forward token to multiplexer
853b35818ceSMatthias Ringwald     btstack_linked_list_iterator_init(&it, &rfcomm_multiplexers);
854*e9a7c22dSMatthias Ringwald     while (!token_consumed && btstack_linked_list_iterator_has_next(&it)){
855b35818ceSMatthias Ringwald         rfcomm_multiplexer_t * multiplexer = (rfcomm_multiplexer_t *) btstack_linked_list_iterator_next(&it);
856b35818ceSMatthias Ringwald         if (multiplexer->l2cap_cid != l2cap_cid) continue;
857b35818ceSMatthias Ringwald         if (rfcomm_multiplexer_ready_to_send(multiplexer)){
858*e9a7c22dSMatthias Ringwald             log_debug("rfcomm_handle_can_send_now enter: multiplexer token");
859*e9a7c22dSMatthias Ringwald             token_consumed = 1;
860b35818ceSMatthias Ringwald             rfcomm_multiplexer_state_machine(multiplexer, MULT_EV_READY_TO_SEND);
861b35818ceSMatthias Ringwald         }
862b35818ceSMatthias Ringwald     }
863b35818ceSMatthias Ringwald 
864*e9a7c22dSMatthias Ringwald     // forward token to channel state machine
86562b5b741SMatthias Ringwald     btstack_linked_list_iterator_init(&it, &rfcomm_channels);
866*e9a7c22dSMatthias Ringwald     while (!token_consumed && btstack_linked_list_iterator_has_next(&it)){
86762b5b741SMatthias Ringwald         rfcomm_channel_t * channel = (rfcomm_channel_t *) btstack_linked_list_iterator_next(&it);
86862b5b741SMatthias Ringwald         if (channel->multiplexer->l2cap_cid != l2cap_cid) continue;
86962b5b741SMatthias Ringwald         // channel state machine
87062b5b741SMatthias Ringwald         if (rfcomm_channel_ready_to_send(channel)){
871*e9a7c22dSMatthias Ringwald             log_debug("rfcomm_handle_can_send_now enter: channel token");
872*e9a7c22dSMatthias Ringwald             token_consumed = 1;
87362b5b741SMatthias Ringwald             const rfcomm_channel_event_t event = { CH_EVT_READY_TO_SEND };
8743232fa30SMatthias Ringwald             rfcomm_channel_state_machine_with_channel(channel, &event);
87562b5b741SMatthias Ringwald         }
8765ef5325cSMatthias Ringwald     }
8775ef5325cSMatthias Ringwald 
878*e9a7c22dSMatthias Ringwald     // forward token to client
8795ef5325cSMatthias Ringwald     btstack_linked_list_iterator_init(&it, &rfcomm_channels);
880*e9a7c22dSMatthias Ringwald     while (!token_consumed && btstack_linked_list_iterator_has_next(&it)){
8815ef5325cSMatthias Ringwald         rfcomm_channel_t * channel = (rfcomm_channel_t *) btstack_linked_list_iterator_next(&it);
8825ef5325cSMatthias Ringwald         if (channel->multiplexer->l2cap_cid != l2cap_cid) continue;
88362b5b741SMatthias Ringwald         // client waiting for can send now
88462b5b741SMatthias Ringwald         if (!channel->waiting_for_can_send_now)    continue;
88562b5b741SMatthias Ringwald         if (!channel->credits_outgoing)            continue;
88662b5b741SMatthias Ringwald         if ((channel->multiplexer->fcon & 1) == 0) continue;
88762b5b741SMatthias Ringwald 
888*e9a7c22dSMatthias Ringwald         log_debug("rfcomm_handle_can_send_now enter: client token");
889*e9a7c22dSMatthias Ringwald         token_consumed = 1;
89062b5b741SMatthias Ringwald         channel->waiting_for_can_send_now = 0;
89162b5b741SMatthias Ringwald         rfcomm_emit_can_send_now(channel);
89262b5b741SMatthias Ringwald     }
893*e9a7c22dSMatthias Ringwald 
894*e9a7c22dSMatthias Ringwald     // if token was consumed, request another one
895*e9a7c22dSMatthias Ringwald     if (token_consumed) {
896*e9a7c22dSMatthias Ringwald         l2cap_request_can_send_now_event(l2cap_cid);
89762b5b741SMatthias Ringwald     }
898*e9a7c22dSMatthias Ringwald 
899*e9a7c22dSMatthias Ringwald     log_debug("rfcomm_handle_can_send_now exit");
900b35818ceSMatthias Ringwald }
9013deb3ec6SMatthias Ringwald 
902f7d61b10SMatthias Ringwald static void rfcomm_multiplexer_set_state_and_request_can_send_now_event(rfcomm_multiplexer_t * multiplexer, RFCOMM_MULTIPLEXER_STATE state){
903f7d61b10SMatthias Ringwald     multiplexer->state = state;
904f7d61b10SMatthias Ringwald     l2cap_request_can_send_now_event(multiplexer->l2cap_cid);
905f7d61b10SMatthias Ringwald }
906f7d61b10SMatthias Ringwald 
9073deb3ec6SMatthias Ringwald /**
9083deb3ec6SMatthias Ringwald  * @return handled packet
9093deb3ec6SMatthias Ringwald  */
9100d78ab98SMatthias Ringwald static int rfcomm_hci_event_handler(uint8_t *packet, uint16_t size){
9113deb3ec6SMatthias Ringwald     bd_addr_t event_addr;
9123deb3ec6SMatthias Ringwald     uint16_t  psm;
9133deb3ec6SMatthias Ringwald     uint16_t l2cap_cid;
9143deb3ec6SMatthias Ringwald     hci_con_handle_t con_handle;
9153deb3ec6SMatthias Ringwald     rfcomm_multiplexer_t *multiplexer = NULL;
9163deb3ec6SMatthias Ringwald     uint8_t status;
9173deb3ec6SMatthias Ringwald 
9180e2df43fSMatthias Ringwald     switch (hci_event_packet_get_type(packet)) {
9193deb3ec6SMatthias Ringwald 
9203deb3ec6SMatthias Ringwald         // accept incoming PSM_RFCOMM connection if no multiplexer exists yet
9213deb3ec6SMatthias Ringwald         case L2CAP_EVENT_INCOMING_CONNECTION:
9223deb3ec6SMatthias Ringwald             // data: event(8), len(8), address(48), handle (16),  psm (16), source cid(16) dest cid(16)
923724d70a2SMatthias Ringwald             reverse_bd_addr(&packet[2], event_addr);
924f8fbdce0SMatthias Ringwald             con_handle = little_endian_read_16(packet,  8);
925f8fbdce0SMatthias Ringwald             psm        = little_endian_read_16(packet, 10);
926f8fbdce0SMatthias Ringwald             l2cap_cid  = little_endian_read_16(packet, 12);
9273deb3ec6SMatthias Ringwald 
9283deb3ec6SMatthias Ringwald             if (psm != PSM_RFCOMM) break;
9293deb3ec6SMatthias Ringwald 
9303deb3ec6SMatthias Ringwald             multiplexer = rfcomm_multiplexer_for_addr(event_addr);
9313deb3ec6SMatthias Ringwald 
9323deb3ec6SMatthias Ringwald             if (multiplexer) {
9333deb3ec6SMatthias Ringwald                 log_info("INCOMING_CONNECTION (l2cap_cid 0x%02x) for PSM_RFCOMM => decline - multiplexer already exists", l2cap_cid);
9347ef6a7bbSMatthias Ringwald                 l2cap_decline_connection(l2cap_cid);
9353deb3ec6SMatthias Ringwald                 return 1;
9363deb3ec6SMatthias Ringwald             }
9373deb3ec6SMatthias Ringwald 
9383deb3ec6SMatthias Ringwald             // create and inititialize new multiplexer instance (incoming)
9393deb3ec6SMatthias Ringwald             multiplexer = rfcomm_multiplexer_create_for_addr(event_addr);
9403deb3ec6SMatthias Ringwald             if (!multiplexer){
9413deb3ec6SMatthias Ringwald                 log_info("INCOMING_CONNECTION (l2cap_cid 0x%02x) for PSM_RFCOMM => decline - no memory left", l2cap_cid);
9427ef6a7bbSMatthias Ringwald                 l2cap_decline_connection(l2cap_cid);
9433deb3ec6SMatthias Ringwald                 return 1;
9443deb3ec6SMatthias Ringwald             }
9453deb3ec6SMatthias Ringwald 
9463deb3ec6SMatthias Ringwald             multiplexer->con_handle = con_handle;
9473deb3ec6SMatthias Ringwald             multiplexer->l2cap_cid = l2cap_cid;
9480d78ab98SMatthias Ringwald             //
9493deb3ec6SMatthias Ringwald             multiplexer->state = RFCOMM_MULTIPLEXER_W4_SABM_0;
9503deb3ec6SMatthias Ringwald             log_info("L2CAP_EVENT_INCOMING_CONNECTION (l2cap_cid 0x%02x) for PSM_RFCOMM => accept", l2cap_cid);
951ce8f182eSMatthias Ringwald             l2cap_accept_connection(l2cap_cid);
9523deb3ec6SMatthias Ringwald             return 1;
9533deb3ec6SMatthias Ringwald 
9543deb3ec6SMatthias Ringwald         // l2cap connection opened -> store l2cap_cid, remote_addr
9553deb3ec6SMatthias Ringwald         case L2CAP_EVENT_CHANNEL_OPENED:
9563deb3ec6SMatthias Ringwald 
957f8fbdce0SMatthias Ringwald             if (little_endian_read_16(packet, 11) != PSM_RFCOMM) break;
9583deb3ec6SMatthias Ringwald 
9593deb3ec6SMatthias Ringwald             status = packet[2];
9603deb3ec6SMatthias Ringwald             log_info("L2CAP_EVENT_CHANNEL_OPENED for PSM_RFCOMM, status %u", status);
9613deb3ec6SMatthias Ringwald 
9623deb3ec6SMatthias Ringwald             // get multiplexer for remote addr
963f8fbdce0SMatthias Ringwald             con_handle = little_endian_read_16(packet, 9);
964f8fbdce0SMatthias Ringwald             l2cap_cid = little_endian_read_16(packet, 13);
965724d70a2SMatthias Ringwald             reverse_bd_addr(&packet[3], event_addr);
9663deb3ec6SMatthias Ringwald             multiplexer = rfcomm_multiplexer_for_addr(event_addr);
9673deb3ec6SMatthias Ringwald             if (!multiplexer) {
9683deb3ec6SMatthias Ringwald                 log_error("L2CAP_EVENT_CHANNEL_OPENED but no multiplexer prepared");
9693deb3ec6SMatthias Ringwald                 return 1;
9703deb3ec6SMatthias Ringwald             }
9713deb3ec6SMatthias Ringwald 
9723deb3ec6SMatthias Ringwald             // on l2cap open error discard everything
9733deb3ec6SMatthias Ringwald             if (status){
9743deb3ec6SMatthias Ringwald 
9753deb3ec6SMatthias Ringwald                 // remove (potential) timer
9763deb3ec6SMatthias Ringwald                 rfcomm_multiplexer_stop_timer(multiplexer);
9773deb3ec6SMatthias Ringwald 
9783deb3ec6SMatthias Ringwald                 // emit rfcomm_channel_opened with status and free channel
979665d90f2SMatthias Ringwald                 btstack_linked_item_t * it = (btstack_linked_item_t *) &rfcomm_channels;
9803deb3ec6SMatthias Ringwald                 while (it->next) {
9813deb3ec6SMatthias Ringwald                     rfcomm_channel_t * channel = (rfcomm_channel_t *) it->next;
9823deb3ec6SMatthias Ringwald                     if (channel->multiplexer == multiplexer){
9833deb3ec6SMatthias Ringwald                         rfcomm_emit_channel_opened(channel, status);
9843deb3ec6SMatthias Ringwald                         it->next = it->next->next;
9853deb3ec6SMatthias Ringwald                         btstack_memory_rfcomm_channel_free(channel);
9863deb3ec6SMatthias Ringwald                     } else {
9873deb3ec6SMatthias Ringwald                         it = it->next;
9883deb3ec6SMatthias Ringwald                     }
9893deb3ec6SMatthias Ringwald                 }
9903deb3ec6SMatthias Ringwald 
9913deb3ec6SMatthias Ringwald                 // free multiplexer
9923deb3ec6SMatthias Ringwald                 rfcomm_multiplexer_free(multiplexer);
9933deb3ec6SMatthias Ringwald                 return 1;
9943deb3ec6SMatthias Ringwald             }
9953deb3ec6SMatthias Ringwald 
9960d78ab98SMatthias Ringwald             // following could be: rfcom_multiplexer_state_machein(..., EVENT_L2CAP_OPENED)
9970d78ab98SMatthias Ringwald 
9983deb3ec6SMatthias Ringwald             if (multiplexer->state == RFCOMM_MULTIPLEXER_W4_CONNECT) {
9993deb3ec6SMatthias Ringwald                 log_info("L2CAP_EVENT_CHANNEL_OPENED: outgoing connection");
10003deb3ec6SMatthias Ringwald                 // wrong remote addr
1001058e3d6bSMatthias Ringwald                 if (bd_addr_cmp(event_addr, multiplexer->remote_addr)) break;
10023deb3ec6SMatthias Ringwald                 multiplexer->l2cap_cid = l2cap_cid;
10033deb3ec6SMatthias Ringwald                 multiplexer->con_handle = con_handle;
10043deb3ec6SMatthias Ringwald                 // send SABM #0
1005f7d61b10SMatthias Ringwald                 rfcomm_multiplexer_set_state_and_request_can_send_now_event(multiplexer, RFCOMM_MULTIPLEXER_SEND_SABM_0);
1006b35818ceSMatthias Ringwald 
10073deb3ec6SMatthias Ringwald             } else { // multiplexer->state == RFCOMM_MULTIPLEXER_W4_SABM_0
10083deb3ec6SMatthias Ringwald 
10093deb3ec6SMatthias Ringwald                 // set max frame size based on l2cap MTU
1010f8fbdce0SMatthias Ringwald                 multiplexer->max_frame_size = rfcomm_max_frame_size_for_l2cap_mtu(little_endian_read_16(packet, 17));
10113deb3ec6SMatthias Ringwald             }
10123deb3ec6SMatthias Ringwald             return 1;
10133deb3ec6SMatthias Ringwald 
10143deb3ec6SMatthias Ringwald             // l2cap disconnect -> state = RFCOMM_MULTIPLEXER_CLOSED;
10153deb3ec6SMatthias Ringwald 
1016b31d33b2SMatthias Ringwald         // Notify channel packet handler if they can send now
1017b31d33b2SMatthias Ringwald         case L2CAP_EVENT_CAN_SEND_NOW:
1018b35818ceSMatthias Ringwald             l2cap_cid = l2cap_event_can_send_now_get_local_cid(packet);
1019b35818ceSMatthias Ringwald             rfcomm_handle_can_send_now(l2cap_cid);
10200d78ab98SMatthias Ringwald             return 1;
10213deb3ec6SMatthias Ringwald 
10223deb3ec6SMatthias Ringwald         case L2CAP_EVENT_CHANNEL_CLOSED:
10233deb3ec6SMatthias Ringwald             // data: event (8), len(8), channel (16)
1024f8fbdce0SMatthias Ringwald             l2cap_cid = little_endian_read_16(packet, 2);
10253deb3ec6SMatthias Ringwald             multiplexer = rfcomm_multiplexer_for_l2cap_cid(l2cap_cid);
10263deb3ec6SMatthias Ringwald             log_info("L2CAP_EVENT_CHANNEL_CLOSED cid 0x%0x, mult %p", l2cap_cid, multiplexer);
10273deb3ec6SMatthias Ringwald             if (!multiplexer) break;
10283deb3ec6SMatthias Ringwald             log_info("L2CAP_EVENT_CHANNEL_CLOSED state %u", multiplexer->state);
10297d20d6a4SMatthias Ringwald             // no need to call l2cap_disconnect here, as it's already closed
10303deb3ec6SMatthias Ringwald             rfcomm_multiplexer_finalize(multiplexer);
1031d5499c6fSMatthias Ringwald             return 1;
1032d5499c6fSMatthias Ringwald 
10333deb3ec6SMatthias Ringwald         default:
10343deb3ec6SMatthias Ringwald             break;
10353deb3ec6SMatthias Ringwald     }
10363deb3ec6SMatthias Ringwald     return 0;
10373deb3ec6SMatthias Ringwald }
10383deb3ec6SMatthias Ringwald 
10393deb3ec6SMatthias Ringwald static int rfcomm_multiplexer_l2cap_packet_handler(uint16_t channel, uint8_t *packet, uint16_t size){
10403deb3ec6SMatthias Ringwald 
10413deb3ec6SMatthias Ringwald     // get or create a multiplexer for a certain device
10423deb3ec6SMatthias Ringwald     rfcomm_multiplexer_t *multiplexer = rfcomm_multiplexer_for_l2cap_cid(channel);
10433deb3ec6SMatthias Ringwald     if (!multiplexer) return 0;
10443deb3ec6SMatthias Ringwald 
10453deb3ec6SMatthias Ringwald     uint16_t l2cap_cid = multiplexer->l2cap_cid;
10463deb3ec6SMatthias Ringwald 
10473deb3ec6SMatthias Ringwald 	// but only care for multiplexer control channel
10483deb3ec6SMatthias Ringwald     uint8_t frame_dlci = packet[0] >> 2;
10493deb3ec6SMatthias Ringwald     if (frame_dlci) return 0;
10503deb3ec6SMatthias Ringwald     const uint8_t length_offset = (packet[2] & 1) ^ 1;  // to be used for pos >= 3
10513deb3ec6SMatthias Ringwald     const uint8_t credit_offset = ((packet[1] & BT_RFCOMM_UIH_PF) == BT_RFCOMM_UIH_PF) ? 1 : 0;   // credits for uih_pf frames
10523deb3ec6SMatthias Ringwald     const uint8_t payload_offset = 3 + length_offset + credit_offset;
10533deb3ec6SMatthias Ringwald     switch (packet[1]){
10543deb3ec6SMatthias Ringwald 
10553deb3ec6SMatthias Ringwald         case BT_RFCOMM_SABM:
10563deb3ec6SMatthias Ringwald             if (multiplexer->state == RFCOMM_MULTIPLEXER_W4_SABM_0){
10573deb3ec6SMatthias Ringwald                 log_info("Received SABM #0");
10583deb3ec6SMatthias Ringwald                 multiplexer->outgoing = 0;
1059f7d61b10SMatthias Ringwald                 rfcomm_multiplexer_set_state_and_request_can_send_now_event(multiplexer, RFCOMM_MULTIPLEXER_SEND_UA_0);
10603deb3ec6SMatthias Ringwald                 return 1;
10613deb3ec6SMatthias Ringwald             }
10623deb3ec6SMatthias Ringwald             break;
10633deb3ec6SMatthias Ringwald 
10643deb3ec6SMatthias Ringwald         case BT_RFCOMM_UA:
10653deb3ec6SMatthias Ringwald             if (multiplexer->state == RFCOMM_MULTIPLEXER_W4_UA_0) {
10663deb3ec6SMatthias Ringwald                 // UA #0 -> send UA #0, state = RFCOMM_MULTIPLEXER_OPEN
10673deb3ec6SMatthias Ringwald                 log_info("Received UA #0 ");
10683deb3ec6SMatthias Ringwald                 rfcomm_multiplexer_opened(multiplexer);
10693deb3ec6SMatthias Ringwald                 return 1;
10703deb3ec6SMatthias Ringwald             }
10713deb3ec6SMatthias Ringwald             break;
10723deb3ec6SMatthias Ringwald 
10733deb3ec6SMatthias Ringwald         case BT_RFCOMM_DISC:
10743deb3ec6SMatthias Ringwald             // DISC #0 -> send UA #0, close multiplexer
10753deb3ec6SMatthias Ringwald             log_info("Received DISC #0, (ougoing = %u)", multiplexer->outgoing);
1076f7d61b10SMatthias Ringwald             rfcomm_multiplexer_set_state_and_request_can_send_now_event(multiplexer, RFCOMM_MULTIPLEXER_SEND_UA_0_AND_DISC);
10773deb3ec6SMatthias Ringwald             return 1;
10783deb3ec6SMatthias Ringwald 
10793deb3ec6SMatthias Ringwald         case BT_RFCOMM_DM:
10803deb3ec6SMatthias Ringwald             // DM #0 - we shouldn't get this, just give up
10813deb3ec6SMatthias Ringwald             log_info("Received DM #0");
10823deb3ec6SMatthias Ringwald             log_info("-> Closing down multiplexer");
10833deb3ec6SMatthias Ringwald             rfcomm_multiplexer_finalize(multiplexer);
1084ce8f182eSMatthias Ringwald             l2cap_disconnect(l2cap_cid, 0x13);
10853deb3ec6SMatthias Ringwald             return 1;
10863deb3ec6SMatthias Ringwald 
10873deb3ec6SMatthias Ringwald         case BT_RFCOMM_UIH:
10883deb3ec6SMatthias Ringwald             if (packet[payload_offset] == BT_RFCOMM_CLD_CMD){
10893deb3ec6SMatthias Ringwald                 // Multiplexer close down (CLD) -> close mutliplexer
10903deb3ec6SMatthias Ringwald                 log_info("Received Multiplexer close down command");
10913deb3ec6SMatthias Ringwald                 log_info("-> Closing down multiplexer");
10923deb3ec6SMatthias Ringwald                 rfcomm_multiplexer_finalize(multiplexer);
1093ce8f182eSMatthias Ringwald                 l2cap_disconnect(l2cap_cid, 0x13);
10943deb3ec6SMatthias Ringwald                 return 1;
10953deb3ec6SMatthias Ringwald             }
10963deb3ec6SMatthias Ringwald             switch (packet[payload_offset]){
10973deb3ec6SMatthias Ringwald                 case BT_RFCOMM_CLD_CMD:
10983deb3ec6SMatthias Ringwald                      // Multiplexer close down (CLD) -> close mutliplexer
10993deb3ec6SMatthias Ringwald                     log_info("Received Multiplexer close down command");
11003deb3ec6SMatthias Ringwald                     log_info("-> Closing down multiplexer");
11013deb3ec6SMatthias Ringwald                     rfcomm_multiplexer_finalize(multiplexer);
1102ce8f182eSMatthias Ringwald                     l2cap_disconnect(l2cap_cid, 0x13);
11033deb3ec6SMatthias Ringwald                     return 1;
11043deb3ec6SMatthias Ringwald 
11053deb3ec6SMatthias Ringwald                 case BT_RFCOMM_FCON_CMD:
11063deb3ec6SMatthias Ringwald                     multiplexer->fcon = 0x81;
1107b35818ceSMatthias Ringwald                     l2cap_request_can_send_now_event(multiplexer->l2cap_cid);
1108b35818ceSMatthias Ringwald                     return 1;
11093deb3ec6SMatthias Ringwald 
11103deb3ec6SMatthias Ringwald                 case BT_RFCOMM_FCOFF_CMD:
11113deb3ec6SMatthias Ringwald                     multiplexer->fcon = 0x80;
1112b35818ceSMatthias Ringwald                     l2cap_request_can_send_now_event(multiplexer->l2cap_cid);
1113b35818ceSMatthias Ringwald                     return 1;
11143deb3ec6SMatthias Ringwald 
11153deb3ec6SMatthias Ringwald                 case BT_RFCOMM_TEST_CMD: {
11163deb3ec6SMatthias Ringwald                     log_info("Received test command");
11173deb3ec6SMatthias Ringwald                     int len = packet[payload_offset+1] >> 1; // length < 125
11183deb3ec6SMatthias Ringwald                     if (len > RFCOMM_TEST_DATA_MAX_LEN){
11193deb3ec6SMatthias Ringwald                         len = RFCOMM_TEST_DATA_MAX_LEN;
11203deb3ec6SMatthias Ringwald                     }
11213deb3ec6SMatthias Ringwald                     multiplexer->test_data_len = len;
11223deb3ec6SMatthias Ringwald                     memcpy(multiplexer->test_data, &packet[payload_offset + 2], len);
1123b35818ceSMatthias Ringwald                     l2cap_request_can_send_now_event(multiplexer->l2cap_cid);
11243deb3ec6SMatthias Ringwald                     return 1;
11253deb3ec6SMatthias Ringwald                 }
11263deb3ec6SMatthias Ringwald                 default:
11273deb3ec6SMatthias Ringwald                     break;
11283deb3ec6SMatthias Ringwald             }
11293deb3ec6SMatthias Ringwald             break;
11303deb3ec6SMatthias Ringwald 
11313deb3ec6SMatthias Ringwald         default:
11323deb3ec6SMatthias Ringwald             break;
11333deb3ec6SMatthias Ringwald 
11343deb3ec6SMatthias Ringwald     }
11353deb3ec6SMatthias Ringwald     return 0;
11363deb3ec6SMatthias Ringwald }
11373deb3ec6SMatthias Ringwald 
1138b35818ceSMatthias Ringwald static int rfcomm_multiplexer_ready_to_send(rfcomm_multiplexer_t * multiplexer){
1139b35818ceSMatthias Ringwald     if (multiplexer->send_dm_for_dlci) return 1;
1140b35818ceSMatthias Ringwald     if (multiplexer->nsc_command) return 1;
1141b35818ceSMatthias Ringwald     if (multiplexer->fcon & 0x80) return 1;
1142b35818ceSMatthias Ringwald     switch (multiplexer->state){
1143b35818ceSMatthias Ringwald         case RFCOMM_MULTIPLEXER_SEND_SABM_0:
1144b35818ceSMatthias Ringwald         case RFCOMM_MULTIPLEXER_SEND_UA_0:
1145b35818ceSMatthias Ringwald         case RFCOMM_MULTIPLEXER_SEND_UA_0_AND_DISC:
1146b35818ceSMatthias Ringwald             return 1;
1147b35818ceSMatthias Ringwald         case RFCOMM_MULTIPLEXER_OPEN:
1148b35818ceSMatthias Ringwald             if (multiplexer->test_data_len) {
1149b35818ceSMatthias Ringwald                 return 1;
1150b35818ceSMatthias Ringwald             }
1151b35818ceSMatthias Ringwald             break;
1152b35818ceSMatthias Ringwald         default:
1153b35818ceSMatthias Ringwald             break;
1154b35818ceSMatthias Ringwald     }
1155b35818ceSMatthias Ringwald     return 0;
1156b35818ceSMatthias Ringwald }
1157b35818ceSMatthias Ringwald 
11583deb3ec6SMatthias Ringwald static void rfcomm_multiplexer_state_machine(rfcomm_multiplexer_t * multiplexer, RFCOMM_MULTIPLEXER_EVENT event){
11593deb3ec6SMatthias Ringwald 
1160f7d61b10SMatthias Ringwald     if (event != MULT_EV_READY_TO_SEND) return;
1161f7d61b10SMatthias Ringwald 
11623deb3ec6SMatthias Ringwald     uint16_t l2cap_cid = multiplexer->l2cap_cid;
11633deb3ec6SMatthias Ringwald 
11643deb3ec6SMatthias Ringwald     // process stored DM responses
11653deb3ec6SMatthias Ringwald     if (multiplexer->send_dm_for_dlci){
11663deb3ec6SMatthias Ringwald         uint8_t dlci = multiplexer->send_dm_for_dlci;
11673deb3ec6SMatthias Ringwald         multiplexer->send_dm_for_dlci = 0;
11683deb3ec6SMatthias Ringwald         rfcomm_send_dm_pf(multiplexer, dlci);
11693deb3ec6SMatthias Ringwald         return;
11703deb3ec6SMatthias Ringwald     }
11713deb3ec6SMatthias Ringwald 
11723deb3ec6SMatthias Ringwald     if (multiplexer->nsc_command){
11733deb3ec6SMatthias Ringwald         uint8_t command = multiplexer->nsc_command;
11743deb3ec6SMatthias Ringwald         multiplexer->nsc_command = 0;
11753deb3ec6SMatthias Ringwald         rfcomm_send_uih_nsc_rsp(multiplexer, command);
11763deb3ec6SMatthias Ringwald         return;
11773deb3ec6SMatthias Ringwald     }
11783deb3ec6SMatthias Ringwald 
11793deb3ec6SMatthias Ringwald     if (multiplexer->fcon & 0x80){
11803deb3ec6SMatthias Ringwald         multiplexer->fcon &= 0x01;
11813deb3ec6SMatthias Ringwald         rfcomm_send_uih_fc_rsp(multiplexer, multiplexer->fcon);
1182f7d61b10SMatthias Ringwald 
11833deb3ec6SMatthias Ringwald         if (multiplexer->fcon == 0) return;
11843deb3ec6SMatthias Ringwald         // trigger client to send again after sending FCon Response
1185b31d33b2SMatthias Ringwald         rfcomm_notify_channel_can_send();
11863deb3ec6SMatthias Ringwald         return;
11873deb3ec6SMatthias Ringwald     }
11883deb3ec6SMatthias Ringwald 
11893deb3ec6SMatthias Ringwald     switch (multiplexer->state) {
11903deb3ec6SMatthias Ringwald         case RFCOMM_MULTIPLEXER_SEND_SABM_0:
11913deb3ec6SMatthias Ringwald             log_info("Sending SABM #0 - (multi 0x%p)", multiplexer);
11923deb3ec6SMatthias Ringwald             multiplexer->state = RFCOMM_MULTIPLEXER_W4_UA_0;
11933deb3ec6SMatthias Ringwald             rfcomm_send_sabm(multiplexer, 0);
11943deb3ec6SMatthias Ringwald             break;
11953deb3ec6SMatthias Ringwald         case RFCOMM_MULTIPLEXER_SEND_UA_0:
11963deb3ec6SMatthias Ringwald             log_info("Sending UA #0");
11973deb3ec6SMatthias Ringwald             multiplexer->state = RFCOMM_MULTIPLEXER_OPEN;
11983deb3ec6SMatthias Ringwald             rfcomm_send_ua(multiplexer, 0);
1199f7d61b10SMatthias Ringwald 
12003deb3ec6SMatthias Ringwald             rfcomm_multiplexer_opened(multiplexer);
12013deb3ec6SMatthias Ringwald             break;
12023deb3ec6SMatthias Ringwald         case RFCOMM_MULTIPLEXER_SEND_UA_0_AND_DISC:
12033deb3ec6SMatthias Ringwald             // try to detect authentication errors: drop link key if multiplexer closed before first channel got opened
12043deb3ec6SMatthias Ringwald             if (!multiplexer->at_least_one_connection){
12053deb3ec6SMatthias Ringwald                 log_info("TODO: no connections established - delete link key prophylactically");
12063deb3ec6SMatthias Ringwald                 // hci_send_cmd(&hci_delete_stored_link_key, multiplexer->remote_addr);
12073deb3ec6SMatthias Ringwald             }
12083deb3ec6SMatthias Ringwald             log_info("Sending UA #0");
12093deb3ec6SMatthias Ringwald             log_info("Closing down multiplexer");
12103deb3ec6SMatthias Ringwald             multiplexer->state = RFCOMM_MULTIPLEXER_CLOSED;
12113deb3ec6SMatthias Ringwald             rfcomm_send_ua(multiplexer, 0);
1212f7d61b10SMatthias Ringwald 
12133deb3ec6SMatthias Ringwald             rfcomm_multiplexer_finalize(multiplexer);
1214ce8f182eSMatthias Ringwald             l2cap_disconnect(l2cap_cid, 0x13);
12153deb3ec6SMatthias Ringwald             break;
12163deb3ec6SMatthias Ringwald         case RFCOMM_MULTIPLEXER_OPEN:
12173deb3ec6SMatthias Ringwald             // respond to test command
12183deb3ec6SMatthias Ringwald             if (multiplexer->test_data_len){
12193deb3ec6SMatthias Ringwald                 int len = multiplexer->test_data_len;
12203deb3ec6SMatthias Ringwald                 log_info("Sending TEST Response with %u bytes", len);
12213deb3ec6SMatthias Ringwald                 multiplexer->test_data_len = 0;
12223deb3ec6SMatthias Ringwald                 rfcomm_send_uih_test_rsp(multiplexer, multiplexer->test_data, len);
12233deb3ec6SMatthias Ringwald                 return;
12243deb3ec6SMatthias Ringwald             }
12253deb3ec6SMatthias Ringwald             break;
12263deb3ec6SMatthias Ringwald         default:
12273deb3ec6SMatthias Ringwald             break;
12283deb3ec6SMatthias Ringwald     }
12293deb3ec6SMatthias Ringwald }
12303deb3ec6SMatthias Ringwald 
12313deb3ec6SMatthias Ringwald // MARK: RFCOMM CHANNEL
12323deb3ec6SMatthias Ringwald 
12333deb3ec6SMatthias Ringwald static void rfcomm_channel_send_credits(rfcomm_channel_t *channel, uint8_t credits){
12343deb3ec6SMatthias Ringwald     channel->credits_incoming += credits;
1235ec3f4248SMatthias Ringwald     rfcomm_send_uih_credits(channel->multiplexer, channel->dlci, credits);
12363deb3ec6SMatthias Ringwald }
12373deb3ec6SMatthias Ringwald 
1238b31d33b2SMatthias Ringwald static int rfcomm_channel_can_send(rfcomm_channel_t * channel){
1239b31d33b2SMatthias Ringwald     if (!channel->credits_outgoing) return 0;
1240b31d33b2SMatthias Ringwald     if ((channel->multiplexer->fcon & 1) == 0) return 0;
1241b31d33b2SMatthias Ringwald     return l2cap_can_send_packet_now(channel->multiplexer->l2cap_cid);
1242b31d33b2SMatthias Ringwald }
1243b31d33b2SMatthias Ringwald 
12443deb3ec6SMatthias Ringwald static void rfcomm_channel_opened(rfcomm_channel_t *rfChannel){
12453deb3ec6SMatthias Ringwald 
12463deb3ec6SMatthias Ringwald     log_info("rfcomm_channel_opened!");
12473deb3ec6SMatthias Ringwald 
12483deb3ec6SMatthias Ringwald     rfChannel->state = RFCOMM_CHANNEL_OPEN;
12493deb3ec6SMatthias Ringwald     rfcomm_emit_channel_opened(rfChannel, 0);
12503deb3ec6SMatthias Ringwald     rfcomm_emit_port_configuration(rfChannel);
12513deb3ec6SMatthias Ringwald 
12523deb3ec6SMatthias Ringwald     // remove (potential) timer
12533deb3ec6SMatthias Ringwald     rfcomm_multiplexer_t *multiplexer = rfChannel->multiplexer;
12543deb3ec6SMatthias Ringwald     if (multiplexer->timer_active) {
1255528a4a3bSMatthias Ringwald         btstack_run_loop_remove_timer(&multiplexer->timer);
12563deb3ec6SMatthias Ringwald         multiplexer->timer_active = 0;
12573deb3ec6SMatthias Ringwald     }
12583deb3ec6SMatthias Ringwald     // hack for problem detecting authentication failure
12593deb3ec6SMatthias Ringwald     multiplexer->at_least_one_connection = 1;
12603deb3ec6SMatthias Ringwald 
126162b5b741SMatthias Ringwald     // request can send now if channel ready
126262b5b741SMatthias Ringwald     if (rfcomm_channel_ready_to_send(rfChannel)){
126362b5b741SMatthias Ringwald         l2cap_request_can_send_now_event(multiplexer->l2cap_cid);
126462b5b741SMatthias Ringwald     }
12653deb3ec6SMatthias Ringwald }
12663deb3ec6SMatthias Ringwald 
12673deb3ec6SMatthias Ringwald static void rfcomm_channel_packet_handler_uih(rfcomm_multiplexer_t *multiplexer, uint8_t * packet, uint16_t size){
12683deb3ec6SMatthias Ringwald     const uint8_t frame_dlci = packet[0] >> 2;
12693deb3ec6SMatthias Ringwald     const uint8_t length_offset = (packet[2] & 1) ^ 1;  // to be used for pos >= 3
12703deb3ec6SMatthias Ringwald     const uint8_t credit_offset = ((packet[1] & BT_RFCOMM_UIH_PF) == BT_RFCOMM_UIH_PF) ? 1 : 0;   // credits for uih_pf frames
12713deb3ec6SMatthias Ringwald     const uint8_t payload_offset = 3 + length_offset + credit_offset;
12723deb3ec6SMatthias Ringwald 
12733deb3ec6SMatthias Ringwald     rfcomm_channel_t * channel = rfcomm_channel_for_multiplexer_and_dlci(multiplexer, frame_dlci);
12743deb3ec6SMatthias Ringwald     if (!channel) return;
12753deb3ec6SMatthias Ringwald 
12763deb3ec6SMatthias Ringwald     // handle new outgoing credits
12773deb3ec6SMatthias Ringwald     if (packet[1] == BT_RFCOMM_UIH_PF) {
12783deb3ec6SMatthias Ringwald 
12793deb3ec6SMatthias Ringwald         // add them
12803deb3ec6SMatthias Ringwald         uint16_t new_credits = packet[3+length_offset];
12813deb3ec6SMatthias Ringwald         channel->credits_outgoing += new_credits;
12823deb3ec6SMatthias Ringwald         log_info( "RFCOMM data UIH_PF, new credits: %u, now %u", new_credits, channel->credits_outgoing);
12833deb3ec6SMatthias Ringwald 
12843deb3ec6SMatthias Ringwald         // notify channel statemachine
12853deb3ec6SMatthias Ringwald         rfcomm_channel_event_t channel_event = { CH_EVT_RCVD_CREDITS };
12863232fa30SMatthias Ringwald         rfcomm_channel_state_machine_with_channel(channel, &channel_event);
12873232fa30SMatthias Ringwald         if (rfcomm_channel_ready_to_send(channel)){
128862b5b741SMatthias Ringwald             l2cap_request_can_send_now_event(multiplexer->l2cap_cid);
128962b5b741SMatthias Ringwald         }
12903deb3ec6SMatthias Ringwald     }
12913deb3ec6SMatthias Ringwald 
12923deb3ec6SMatthias Ringwald     // contains payload?
12933deb3ec6SMatthias Ringwald     if (size - 1 > payload_offset){
12943deb3ec6SMatthias Ringwald 
12953deb3ec6SMatthias Ringwald         // log_info( "RFCOMM data UIH_PF, size %u, channel %p", size-payload_offset-1, rfChannel->connection);
12963deb3ec6SMatthias Ringwald 
12973deb3ec6SMatthias Ringwald         // decrease incoming credit counter
12983deb3ec6SMatthias Ringwald         if (channel->credits_incoming > 0){
12993deb3ec6SMatthias Ringwald             channel->credits_incoming--;
13003deb3ec6SMatthias Ringwald         }
13013deb3ec6SMatthias Ringwald 
13023deb3ec6SMatthias Ringwald         // deliver payload
1303fc376368SMatthias Ringwald         (channel->packet_handler)(RFCOMM_DATA_PACKET, channel->rfcomm_cid,
13043deb3ec6SMatthias Ringwald                               &packet[payload_offset], size-payload_offset-1);
13053deb3ec6SMatthias Ringwald     }
13063deb3ec6SMatthias Ringwald 
13073deb3ec6SMatthias Ringwald     // automatically provide new credits to remote device, if no incoming flow control
13083deb3ec6SMatthias Ringwald     if (!channel->incoming_flow_control && channel->credits_incoming < 5){
13093deb3ec6SMatthias Ringwald         channel->new_credits_incoming = RFCOMM_CREDITS;
131062b5b741SMatthias Ringwald         l2cap_request_can_send_now_event(multiplexer->l2cap_cid);
13113deb3ec6SMatthias Ringwald     }
13123deb3ec6SMatthias Ringwald }
13133deb3ec6SMatthias Ringwald 
13143deb3ec6SMatthias Ringwald static void rfcomm_channel_accept_pn(rfcomm_channel_t *channel, rfcomm_channel_event_pn_t *event){
13153deb3ec6SMatthias Ringwald     // priority of client request
13163deb3ec6SMatthias Ringwald     channel->pn_priority = event->priority;
13173deb3ec6SMatthias Ringwald 
13183deb3ec6SMatthias Ringwald     // new credits
13193deb3ec6SMatthias Ringwald     channel->credits_outgoing = event->credits_outgoing;
13203deb3ec6SMatthias Ringwald 
13213deb3ec6SMatthias Ringwald     // negotiate max frame size
13223deb3ec6SMatthias Ringwald     if (channel->max_frame_size > channel->multiplexer->max_frame_size) {
13233deb3ec6SMatthias Ringwald         channel->max_frame_size = channel->multiplexer->max_frame_size;
13243deb3ec6SMatthias Ringwald     }
13253deb3ec6SMatthias Ringwald     if (channel->max_frame_size > event->max_frame_size) {
13263deb3ec6SMatthias Ringwald         channel->max_frame_size = event->max_frame_size;
13273deb3ec6SMatthias Ringwald     }
13283deb3ec6SMatthias Ringwald 
13293deb3ec6SMatthias Ringwald }
13303deb3ec6SMatthias Ringwald 
13313deb3ec6SMatthias Ringwald static void rfcomm_channel_finalize(rfcomm_channel_t *channel){
13323deb3ec6SMatthias Ringwald 
13333deb3ec6SMatthias Ringwald     rfcomm_multiplexer_t *multiplexer = channel->multiplexer;
13343deb3ec6SMatthias Ringwald 
13353deb3ec6SMatthias Ringwald     // remove from list
1336665d90f2SMatthias Ringwald     btstack_linked_list_remove( &rfcomm_channels, (btstack_linked_item_t *) channel);
13373deb3ec6SMatthias Ringwald 
13383deb3ec6SMatthias Ringwald     // free channel
13393deb3ec6SMatthias Ringwald     btstack_memory_rfcomm_channel_free(channel);
13403deb3ec6SMatthias Ringwald 
13413deb3ec6SMatthias Ringwald     // update multiplexer timeout after channel was removed from list
13423deb3ec6SMatthias Ringwald     rfcomm_multiplexer_prepare_idle_timer(multiplexer);
13433deb3ec6SMatthias Ringwald }
13443deb3ec6SMatthias Ringwald 
13453232fa30SMatthias Ringwald static void rfcomm_channel_state_machine_with_dlci(rfcomm_multiplexer_t * multiplexer, uint8_t dlci, const rfcomm_channel_event_t *event){
13463deb3ec6SMatthias Ringwald 
13473deb3ec6SMatthias Ringwald     // TODO: if client max frame size is smaller than RFCOMM_DEFAULT_SIZE, send PN
13483deb3ec6SMatthias Ringwald 
13493deb3ec6SMatthias Ringwald 
13503deb3ec6SMatthias Ringwald     // lookup existing channel
13513deb3ec6SMatthias Ringwald     rfcomm_channel_t * channel = rfcomm_channel_for_multiplexer_and_dlci(multiplexer, dlci);
13523deb3ec6SMatthias Ringwald 
13533232fa30SMatthias Ringwald     // log_info("rfcomm_channel_state_machine_with_dlci lookup dlci #%u = 0x%08x - event %u", dlci, (int) channel, event->type);
13543deb3ec6SMatthias Ringwald 
13553deb3ec6SMatthias Ringwald     if (channel) {
13563232fa30SMatthias Ringwald         rfcomm_channel_state_machine_with_channel(channel, event);
13573232fa30SMatthias Ringwald         if (rfcomm_channel_ready_to_send(channel)){
13583232fa30SMatthias Ringwald             l2cap_request_can_send_now_event(multiplexer->l2cap_cid);
13593232fa30SMatthias Ringwald         }
13603deb3ec6SMatthias Ringwald         return;
13613deb3ec6SMatthias Ringwald     }
13623deb3ec6SMatthias Ringwald 
13633deb3ec6SMatthias Ringwald     // service registered?
13643deb3ec6SMatthias Ringwald     rfcomm_service_t * service = rfcomm_service_for_channel(dlci >> 1);
13653232fa30SMatthias Ringwald     // log_info("rfcomm_channel_state_machine_with_dlci service dlci #%u = 0x%08x", dlci, (int) service);
13663deb3ec6SMatthias Ringwald     if (!service) {
13673deb3ec6SMatthias Ringwald         // discard request by sending disconnected mode
13683deb3ec6SMatthias Ringwald         multiplexer->send_dm_for_dlci = dlci;
136962b5b741SMatthias Ringwald         l2cap_request_can_send_now_event(multiplexer->l2cap_cid);
13703deb3ec6SMatthias Ringwald         return;
13713deb3ec6SMatthias Ringwald     }
13723deb3ec6SMatthias Ringwald 
13733deb3ec6SMatthias Ringwald     // create channel for some events
13743deb3ec6SMatthias Ringwald     switch (event->type) {
13753deb3ec6SMatthias Ringwald         case CH_EVT_RCVD_SABM:
13763deb3ec6SMatthias Ringwald         case CH_EVT_RCVD_PN:
13773deb3ec6SMatthias Ringwald         case CH_EVT_RCVD_RPN_REQ:
13783deb3ec6SMatthias Ringwald         case CH_EVT_RCVD_RPN_CMD:
13793deb3ec6SMatthias Ringwald             // setup incoming channel
13803deb3ec6SMatthias Ringwald             channel = rfcomm_channel_create(multiplexer, service, dlci >> 1);
13813deb3ec6SMatthias Ringwald             if (!channel){
13823deb3ec6SMatthias Ringwald                 // discard request by sending disconnected mode
13833deb3ec6SMatthias Ringwald                 multiplexer->send_dm_for_dlci = dlci;
138462b5b741SMatthias Ringwald                 l2cap_request_can_send_now_event(multiplexer->l2cap_cid);
13853deb3ec6SMatthias Ringwald             }
13863deb3ec6SMatthias Ringwald             break;
13873deb3ec6SMatthias Ringwald         default:
13883deb3ec6SMatthias Ringwald             break;
13893deb3ec6SMatthias Ringwald     }
13903deb3ec6SMatthias Ringwald 
13913deb3ec6SMatthias Ringwald     if (!channel) {
13923deb3ec6SMatthias Ringwald         // discard request by sending disconnected mode
13933deb3ec6SMatthias Ringwald         multiplexer->send_dm_for_dlci = dlci;
139462b5b741SMatthias Ringwald         l2cap_request_can_send_now_event(multiplexer->l2cap_cid);
13953deb3ec6SMatthias Ringwald         return;
13963deb3ec6SMatthias Ringwald     }
139762b5b741SMatthias Ringwald 
13983232fa30SMatthias Ringwald     rfcomm_channel_state_machine_with_channel(channel, event);
13993232fa30SMatthias Ringwald     if (rfcomm_channel_ready_to_send(channel)){
14003232fa30SMatthias Ringwald         l2cap_request_can_send_now_event(multiplexer->l2cap_cid);
14013232fa30SMatthias Ringwald     }
14023deb3ec6SMatthias Ringwald }
14033deb3ec6SMatthias Ringwald 
14043deb3ec6SMatthias Ringwald static void rfcomm_channel_packet_handler(rfcomm_multiplexer_t * multiplexer,  uint8_t *packet, uint16_t size){
14053deb3ec6SMatthias Ringwald 
14063deb3ec6SMatthias Ringwald     // rfcomm: (0) addr [76543 server channel] [2 direction: initiator uses 1] [1 C/R: CMD by initiator = 1] [0 EA=1]
14073deb3ec6SMatthias Ringwald     const uint8_t frame_dlci = packet[0] >> 2;
14083deb3ec6SMatthias Ringwald     uint8_t message_dlci; // used by commands in UIH(_PF) packets
14093deb3ec6SMatthias Ringwald 	uint8_t message_len;  //   "
14103deb3ec6SMatthias Ringwald 
14113deb3ec6SMatthias Ringwald     // rfcomm: (1) command/control
14123deb3ec6SMatthias Ringwald     // -- credits_offset = 1 if command == BT_RFCOMM_UIH_PF
14133deb3ec6SMatthias Ringwald     const uint8_t credit_offset = ((packet[1] & BT_RFCOMM_UIH_PF) == BT_RFCOMM_UIH_PF) ? 1 : 0;   // credits for uih_pf frames
14143deb3ec6SMatthias Ringwald     // rfcomm: (2) length. if bit 0 is cleared, 2 byte length is used. (little endian)
14153deb3ec6SMatthias Ringwald     const uint8_t length_offset = (packet[2] & 1) ^ 1;  // to be used for pos >= 3
14163deb3ec6SMatthias Ringwald     // rfcomm: (3+length_offset) credits if credits_offset == 1
14173deb3ec6SMatthias Ringwald     // rfcomm: (3+length_offest+credits_offset)
14183deb3ec6SMatthias Ringwald     const uint8_t payload_offset = 3 + length_offset + credit_offset;
14193deb3ec6SMatthias Ringwald 
14203deb3ec6SMatthias Ringwald     rfcomm_channel_event_t event;
14213deb3ec6SMatthias Ringwald     rfcomm_channel_event_pn_t event_pn;
14223deb3ec6SMatthias Ringwald     rfcomm_channel_event_rpn_t event_rpn;
14233deb3ec6SMatthias Ringwald     rfcomm_channel_event_msc_t event_msc;
14243deb3ec6SMatthias Ringwald 
14253deb3ec6SMatthias Ringwald     // switch by rfcomm message type
14263deb3ec6SMatthias Ringwald     switch(packet[1]) {
14273deb3ec6SMatthias Ringwald 
14283deb3ec6SMatthias Ringwald         case BT_RFCOMM_SABM:
14293deb3ec6SMatthias Ringwald             event.type = CH_EVT_RCVD_SABM;
14303deb3ec6SMatthias Ringwald             log_info("Received SABM #%u", frame_dlci);
14313232fa30SMatthias Ringwald             rfcomm_channel_state_machine_with_dlci(multiplexer, frame_dlci, &event);
14323deb3ec6SMatthias Ringwald             break;
14333deb3ec6SMatthias Ringwald 
14343deb3ec6SMatthias Ringwald         case BT_RFCOMM_UA:
14353deb3ec6SMatthias Ringwald             event.type = CH_EVT_RCVD_UA;
14363deb3ec6SMatthias Ringwald             log_info("Received UA #%u",frame_dlci);
14373232fa30SMatthias Ringwald             rfcomm_channel_state_machine_with_dlci(multiplexer, frame_dlci, &event);
14383deb3ec6SMatthias Ringwald             break;
14393deb3ec6SMatthias Ringwald 
14403deb3ec6SMatthias Ringwald         case BT_RFCOMM_DISC:
14413deb3ec6SMatthias Ringwald             event.type = CH_EVT_RCVD_DISC;
14423232fa30SMatthias Ringwald             rfcomm_channel_state_machine_with_dlci(multiplexer, frame_dlci, &event);
14433deb3ec6SMatthias Ringwald             break;
14443deb3ec6SMatthias Ringwald 
14453deb3ec6SMatthias Ringwald         case BT_RFCOMM_DM:
14463deb3ec6SMatthias Ringwald         case BT_RFCOMM_DM_PF:
14473deb3ec6SMatthias Ringwald             event.type = CH_EVT_RCVD_DM;
14483232fa30SMatthias Ringwald             rfcomm_channel_state_machine_with_dlci(multiplexer, frame_dlci, &event);
14493deb3ec6SMatthias Ringwald             break;
14503deb3ec6SMatthias Ringwald 
14513deb3ec6SMatthias Ringwald         case BT_RFCOMM_UIH_PF:
14523deb3ec6SMatthias Ringwald         case BT_RFCOMM_UIH:
14533deb3ec6SMatthias Ringwald 
14543deb3ec6SMatthias Ringwald             message_len  = packet[payload_offset+1] >> 1;
14553deb3ec6SMatthias Ringwald 
14563deb3ec6SMatthias Ringwald             switch (packet[payload_offset]) {
14573deb3ec6SMatthias Ringwald                 case BT_RFCOMM_PN_CMD:
14583deb3ec6SMatthias Ringwald                     message_dlci = packet[payload_offset+2];
14593deb3ec6SMatthias Ringwald                     event_pn.super.type = CH_EVT_RCVD_PN;
14603deb3ec6SMatthias Ringwald                     event_pn.priority = packet[payload_offset+4];
1461f8fbdce0SMatthias Ringwald                     event_pn.max_frame_size = little_endian_read_16(packet, payload_offset+6);
14623deb3ec6SMatthias Ringwald                     event_pn.credits_outgoing = packet[payload_offset+9];
14633deb3ec6SMatthias Ringwald                     log_info("Received UIH Parameter Negotiation Command for #%u, credits %u",
14643deb3ec6SMatthias Ringwald                         message_dlci, event_pn.credits_outgoing);
14653232fa30SMatthias Ringwald                     rfcomm_channel_state_machine_with_dlci(multiplexer, message_dlci, (rfcomm_channel_event_t*) &event_pn);
14663deb3ec6SMatthias Ringwald                     break;
14673deb3ec6SMatthias Ringwald 
14683deb3ec6SMatthias Ringwald                 case BT_RFCOMM_PN_RSP:
14693deb3ec6SMatthias Ringwald                     message_dlci = packet[payload_offset+2];
14703deb3ec6SMatthias Ringwald                     event_pn.super.type = CH_EVT_RCVD_PN_RSP;
14713deb3ec6SMatthias Ringwald                     event_pn.priority = packet[payload_offset+4];
1472f8fbdce0SMatthias Ringwald                     event_pn.max_frame_size = little_endian_read_16(packet, payload_offset+6);
14733deb3ec6SMatthias Ringwald                     event_pn.credits_outgoing = packet[payload_offset+9];
14743deb3ec6SMatthias Ringwald                     log_info("Received UIH Parameter Negotiation Response max frame %u, credits %u",
14753deb3ec6SMatthias Ringwald                             event_pn.max_frame_size, event_pn.credits_outgoing);
14763232fa30SMatthias Ringwald                     rfcomm_channel_state_machine_with_dlci(multiplexer, message_dlci, (rfcomm_channel_event_t*) &event_pn);
14773deb3ec6SMatthias Ringwald                     break;
14783deb3ec6SMatthias Ringwald 
14793deb3ec6SMatthias Ringwald                 case BT_RFCOMM_MSC_CMD:
14803deb3ec6SMatthias Ringwald                     message_dlci = packet[payload_offset+2] >> 2;
14813deb3ec6SMatthias Ringwald                     event_msc.super.type = CH_EVT_RCVD_MSC_CMD;
14823deb3ec6SMatthias Ringwald                     event_msc.modem_status = packet[payload_offset+3];
14833deb3ec6SMatthias Ringwald                     log_info("Received MSC CMD for #%u, ", message_dlci);
14843232fa30SMatthias Ringwald                     rfcomm_channel_state_machine_with_dlci(multiplexer, message_dlci, (rfcomm_channel_event_t*) &event_msc);
14853deb3ec6SMatthias Ringwald                     break;
14863deb3ec6SMatthias Ringwald 
14873deb3ec6SMatthias Ringwald                 case BT_RFCOMM_MSC_RSP:
14883deb3ec6SMatthias Ringwald                     message_dlci = packet[payload_offset+2] >> 2;
14893deb3ec6SMatthias Ringwald                     event.type = CH_EVT_RCVD_MSC_RSP;
14903deb3ec6SMatthias Ringwald                     log_info("Received MSC RSP for #%u", message_dlci);
14913232fa30SMatthias Ringwald                     rfcomm_channel_state_machine_with_dlci(multiplexer, message_dlci, &event);
14923deb3ec6SMatthias Ringwald                     break;
14933deb3ec6SMatthias Ringwald 
14943deb3ec6SMatthias Ringwald                 case BT_RFCOMM_RPN_CMD:
14953deb3ec6SMatthias Ringwald                     message_dlci = packet[payload_offset+2] >> 2;
14963deb3ec6SMatthias Ringwald                     switch (message_len){
14973deb3ec6SMatthias Ringwald                         case 1:
14983deb3ec6SMatthias Ringwald                             log_info("Received Remote Port Negotiation Request for #%u", message_dlci);
14993deb3ec6SMatthias Ringwald                             event.type = CH_EVT_RCVD_RPN_REQ;
15003232fa30SMatthias Ringwald                             rfcomm_channel_state_machine_with_dlci(multiplexer, message_dlci, &event);
15013deb3ec6SMatthias Ringwald                             break;
15023deb3ec6SMatthias Ringwald                         case 8:
15033deb3ec6SMatthias Ringwald                             log_info("Received Remote Port Negotiation Update for #%u", message_dlci);
15043deb3ec6SMatthias Ringwald                             event_rpn.super.type = CH_EVT_RCVD_RPN_CMD;
15053deb3ec6SMatthias Ringwald                             event_rpn.data = *(rfcomm_rpn_data_t*) &packet[payload_offset+3];
15063232fa30SMatthias Ringwald                             rfcomm_channel_state_machine_with_dlci(multiplexer, message_dlci, (rfcomm_channel_event_t*) &event_rpn);
15073deb3ec6SMatthias Ringwald                             break;
15083deb3ec6SMatthias Ringwald                         default:
15093deb3ec6SMatthias Ringwald                             break;
15103deb3ec6SMatthias Ringwald                     }
15113deb3ec6SMatthias Ringwald                     break;
15123deb3ec6SMatthias Ringwald 
15133deb3ec6SMatthias Ringwald                 case BT_RFCOMM_RPN_RSP:
15143deb3ec6SMatthias Ringwald                     log_info("Received RPN response");
15153deb3ec6SMatthias Ringwald                     break;
15163deb3ec6SMatthias Ringwald 
15173deb3ec6SMatthias Ringwald                 case BT_RFCOMM_RLS_CMD: {
15183deb3ec6SMatthias Ringwald                     log_info("Received RLS command");
15193deb3ec6SMatthias Ringwald                     message_dlci = packet[payload_offset+2] >> 2;
15203deb3ec6SMatthias Ringwald                     rfcomm_channel_event_rls_t event_rls;
15213deb3ec6SMatthias Ringwald                     event_rls.super.type = CH_EVT_RCVD_RLS_CMD;
15223deb3ec6SMatthias Ringwald                     event_rls.line_status = packet[payload_offset+3];
15233232fa30SMatthias Ringwald                     rfcomm_channel_state_machine_with_dlci(multiplexer, message_dlci, (rfcomm_channel_event_t*) &event_rls);
15243deb3ec6SMatthias Ringwald                     break;
15253deb3ec6SMatthias Ringwald                 }
15263deb3ec6SMatthias Ringwald 
15273deb3ec6SMatthias Ringwald                 case BT_RFCOMM_RLS_RSP:
15283deb3ec6SMatthias Ringwald                     log_info("Received RLS response");
15293deb3ec6SMatthias Ringwald                     break;
15303deb3ec6SMatthias Ringwald 
15313deb3ec6SMatthias Ringwald                 // Following commands are handled by rfcomm_multiplexer_l2cap_packet_handler
15323deb3ec6SMatthias Ringwald                 // case BT_RFCOMM_TEST_CMD:
15333deb3ec6SMatthias Ringwald                 // case BT_RFCOMM_FCOFF_CMD:
15343deb3ec6SMatthias Ringwald                 // case BT_RFCOMM_FCON_CMD:
15353deb3ec6SMatthias Ringwald                 // everything else is an not supported command
15363deb3ec6SMatthias Ringwald                 default: {
15373deb3ec6SMatthias Ringwald                     log_error("Received unknown UIH command packet - 0x%02x", packet[payload_offset]);
15383deb3ec6SMatthias Ringwald                     multiplexer->nsc_command = packet[payload_offset];
15393deb3ec6SMatthias Ringwald                     break;
15403deb3ec6SMatthias Ringwald                 }
15413deb3ec6SMatthias Ringwald             }
15423deb3ec6SMatthias Ringwald             break;
15433deb3ec6SMatthias Ringwald 
15443deb3ec6SMatthias Ringwald         default:
15453deb3ec6SMatthias Ringwald             log_error("Received unknown RFCOMM message type %x", packet[1]);
15463deb3ec6SMatthias Ringwald             break;
15473deb3ec6SMatthias Ringwald     }
15483deb3ec6SMatthias Ringwald 
15493deb3ec6SMatthias Ringwald     // trigger next action - example W4_PN_RSP: transition to SEND_SABM which only depends on "can send"
155062b5b741SMatthias Ringwald     if (rfcomm_multiplexer_ready_to_send(multiplexer)){
155162b5b741SMatthias Ringwald         l2cap_request_can_send_now_event(multiplexer->l2cap_cid);
155262b5b741SMatthias Ringwald     }
15533deb3ec6SMatthias Ringwald }
15543deb3ec6SMatthias Ringwald 
1555457b5cb1SMatthias Ringwald static void rfcomm_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
15563deb3ec6SMatthias Ringwald 
15570d78ab98SMatthias Ringwald     if (packet_type == HCI_EVENT_PACKET){
15580d78ab98SMatthias Ringwald         rfcomm_hci_event_handler(packet, size);
15590d78ab98SMatthias Ringwald         return;
15603deb3ec6SMatthias Ringwald     }
15613deb3ec6SMatthias Ringwald 
15620d78ab98SMatthias Ringwald     // we only handle l2cap packets for:
15630d78ab98SMatthias Ringwald     if (packet_type != L2CAP_DATA_PACKET) return;
15640d78ab98SMatthias Ringwald 
15650d78ab98SMatthias Ringwald     //  - multiplexer itself
15660d78ab98SMatthias Ringwald     int handled = rfcomm_multiplexer_l2cap_packet_handler(channel, packet, size);
15670d78ab98SMatthias Ringwald 
1568b35818ceSMatthias Ringwald     if (handled) return;
15693deb3ec6SMatthias Ringwald 
15700d78ab98SMatthias Ringwald     // - channel over open mutliplexer
15713deb3ec6SMatthias Ringwald     rfcomm_multiplexer_t * multiplexer = rfcomm_multiplexer_for_l2cap_cid(channel);
1572fc376368SMatthias Ringwald     if (!multiplexer || multiplexer->state != RFCOMM_MULTIPLEXER_OPEN) return;
15733deb3ec6SMatthias Ringwald 
15743deb3ec6SMatthias Ringwald     // channel data ?
15753deb3ec6SMatthias Ringwald     // rfcomm: (0) addr [76543 server channel] [2 direction: initiator uses 1] [1 C/R: CMD by initiator = 1] [0 EA=1]
15763deb3ec6SMatthias Ringwald     const uint8_t frame_dlci = packet[0] >> 2;
15773deb3ec6SMatthias Ringwald 
15783deb3ec6SMatthias Ringwald     if (frame_dlci && (packet[1] == BT_RFCOMM_UIH || packet[1] == BT_RFCOMM_UIH_PF)) {
15793deb3ec6SMatthias Ringwald         rfcomm_channel_packet_handler_uih(multiplexer, packet, size);
15803deb3ec6SMatthias Ringwald         return;
15813deb3ec6SMatthias Ringwald     }
15823deb3ec6SMatthias Ringwald 
15833deb3ec6SMatthias Ringwald     rfcomm_channel_packet_handler(multiplexer, packet, size);
15843deb3ec6SMatthias Ringwald }
15853deb3ec6SMatthias Ringwald 
15863deb3ec6SMatthias Ringwald static int rfcomm_channel_ready_for_open(rfcomm_channel_t *channel){
15873deb3ec6SMatthias Ringwald     // note: exchanging MSC isn't neccessary to consider channel open
15883deb3ec6SMatthias Ringwald     // note: having outgoing credits is also not necessary to consider channel open
15893deb3ec6SMatthias 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);
15903deb3ec6SMatthias Ringwald     // if ((channel->state_var & RFCOMM_CHANNEL_STATE_VAR_SENT_MSC_RSP) == 0) return 0;
15913deb3ec6SMatthias Ringwald     // if (channel->credits_outgoing == 0) return 0;
15921e35c04dSMatthias Ringwald     log_info("rfcomm_channel_ready_for_open state %u, flags needed %04x, current %04x, rf credits %u",
15931e35c04dSMatthias Ringwald          channel->state, RFCOMM_CHANNEL_STATE_VAR_RCVD_MSC_RSP, channel->state_var, channel->credits_outgoing);
15943deb3ec6SMatthias Ringwald     if ((channel->state_var & RFCOMM_CHANNEL_STATE_VAR_RCVD_MSC_RSP) == 0) return 0;
15953deb3ec6SMatthias Ringwald     if ((channel->state_var & RFCOMM_CHANNEL_STATE_VAR_SENT_CREDITS) == 0) return 0;
15963deb3ec6SMatthias Ringwald 
15973deb3ec6SMatthias Ringwald     return 1;
15983deb3ec6SMatthias Ringwald }
15993deb3ec6SMatthias Ringwald 
16003deb3ec6SMatthias Ringwald static int rfcomm_channel_ready_for_incoming_dlc_setup(rfcomm_channel_t * channel){
16013deb3ec6SMatthias Ringwald     log_info("rfcomm_channel_ready_for_incoming_dlc_setup state var %04x", channel->state_var);
16023deb3ec6SMatthias Ringwald     // Client accept and SABM/UA is required, PN RSP is needed if PN was received
16033deb3ec6SMatthias Ringwald     if ((channel->state_var & RFCOMM_CHANNEL_STATE_VAR_CLIENT_ACCEPTED) == 0) return 0;
16043deb3ec6SMatthias Ringwald     if ((channel->state_var & RFCOMM_CHANNEL_STATE_VAR_RCVD_SABM      ) == 0) return 0;
16053deb3ec6SMatthias Ringwald     if ((channel->state_var & RFCOMM_CHANNEL_STATE_VAR_SEND_UA        ) != 0) return 0;
16063deb3ec6SMatthias Ringwald     if ((channel->state_var & RFCOMM_CHANNEL_STATE_VAR_SEND_PN_RSP    ) != 0) return 0;
16073deb3ec6SMatthias Ringwald     return 1;
16083deb3ec6SMatthias Ringwald }
16093deb3ec6SMatthias Ringwald 
16103deb3ec6SMatthias Ringwald inline static void rfcomm_channel_state_add(rfcomm_channel_t *channel, RFCOMM_CHANNEL_STATE_VAR event){
16113deb3ec6SMatthias Ringwald     channel->state_var = (RFCOMM_CHANNEL_STATE_VAR) (channel->state_var | event);
16123deb3ec6SMatthias Ringwald }
16133deb3ec6SMatthias Ringwald inline static void rfcomm_channel_state_remove(rfcomm_channel_t *channel, RFCOMM_CHANNEL_STATE_VAR event){
16143deb3ec6SMatthias Ringwald     channel->state_var = (RFCOMM_CHANNEL_STATE_VAR) (channel->state_var & ~event);
16153deb3ec6SMatthias Ringwald }
16163deb3ec6SMatthias Ringwald 
161762b5b741SMatthias Ringwald static int rfcomm_channel_ready_to_send(rfcomm_channel_t * channel){
161862b5b741SMatthias Ringwald     switch (channel->state){
161962b5b741SMatthias Ringwald         case RFCOMM_CHANNEL_SEND_UIH_PN:
162062b5b741SMatthias Ringwald             log_debug("ch-ready: state %u", channel->state);
162162b5b741SMatthias Ringwald             return 1;
162262b5b741SMatthias Ringwald         case RFCOMM_CHANNEL_SEND_SABM_W4_UA:
162362b5b741SMatthias Ringwald             log_debug("ch-ready: state %u", channel->state);
162462b5b741SMatthias Ringwald             return 1;
162562b5b741SMatthias Ringwald         case RFCOMM_CHANNEL_SEND_UA_AFTER_DISC:
162662b5b741SMatthias Ringwald             log_debug("ch-ready: state %u", channel->state);
162762b5b741SMatthias Ringwald             return 1;
162862b5b741SMatthias Ringwald         case RFCOMM_CHANNEL_SEND_DISC:
162962b5b741SMatthias Ringwald             log_debug("ch-ready: state %u", channel->state);
163062b5b741SMatthias Ringwald             return 1;
163162b5b741SMatthias Ringwald         case RFCOMM_CHANNEL_SEND_DM:
163262b5b741SMatthias Ringwald             log_debug("ch-ready: state %u", channel->state);
163362b5b741SMatthias Ringwald             return 1;
163462b5b741SMatthias Ringwald         case RFCOMM_CHANNEL_OPEN:
163562b5b741SMatthias Ringwald             if (channel->new_credits_incoming) {
163662b5b741SMatthias Ringwald                 log_debug("ch-ready: channel open & new_credits_incoming") ;
163762b5b741SMatthias Ringwald                 return 1;
163862b5b741SMatthias Ringwald             }
163962b5b741SMatthias Ringwald             break;
16408ed5c2eaSMatthias Ringwald         case RFCOMM_CHANNEL_DLC_SETUP:
16418ed5c2eaSMatthias Ringwald             if (channel->state_var & (
16428ed5c2eaSMatthias Ringwald                 RFCOMM_CHANNEL_STATE_VAR_SEND_MSC_CMD  |
16438ed5c2eaSMatthias Ringwald                 RFCOMM_CHANNEL_STATE_VAR_SEND_CREDITS
16448ed5c2eaSMatthias Ringwald              )) {
16458ed5c2eaSMatthias Ringwald                 log_debug("ch-ready: channel dlc setup & send msc cmd or send credits") ;
16468ed5c2eaSMatthias Ringwald                 return 1;
16478ed5c2eaSMatthias Ringwald             }
16488ed5c2eaSMatthias Ringwald             break;
16498ed5c2eaSMatthias Ringwald 
165062b5b741SMatthias Ringwald         default:
165162b5b741SMatthias Ringwald             break;
165262b5b741SMatthias Ringwald     }
165362b5b741SMatthias Ringwald 
165462b5b741SMatthias Ringwald     if (channel->state_var & (
165562b5b741SMatthias Ringwald         RFCOMM_CHANNEL_STATE_VAR_SEND_PN_RSP   |
165662b5b741SMatthias Ringwald         RFCOMM_CHANNEL_STATE_VAR_SEND_RPN_INFO |
165762b5b741SMatthias Ringwald         RFCOMM_CHANNEL_STATE_VAR_SEND_RPN_RSP  |
165862b5b741SMatthias Ringwald         RFCOMM_CHANNEL_STATE_VAR_SEND_UA       |
16598ed5c2eaSMatthias Ringwald         RFCOMM_CHANNEL_STATE_VAR_SEND_MSC_RSP
166062b5b741SMatthias Ringwald                              )){
166162b5b741SMatthias Ringwald         log_debug("ch-ready: state %x, state var %x", channel->state, channel->state_var);
166262b5b741SMatthias Ringwald         return 1;
166362b5b741SMatthias Ringwald     }
166462b5b741SMatthias Ringwald 
166562b5b741SMatthias Ringwald     if (channel->rls_line_status != RFCOMM_RLS_STATUS_INVALID) {
166662b5b741SMatthias Ringwald         log_debug("ch-ready: rls_line_status");
166762b5b741SMatthias Ringwald         return 1;
166862b5b741SMatthias Ringwald     }
166962b5b741SMatthias Ringwald 
167062b5b741SMatthias Ringwald     return 0;
167162b5b741SMatthias Ringwald }
167262b5b741SMatthias Ringwald 
167362b5b741SMatthias Ringwald 
16743232fa30SMatthias Ringwald static void rfcomm_channel_state_machine_with_channel(rfcomm_channel_t *channel, const rfcomm_channel_event_t *event){
16753deb3ec6SMatthias Ringwald 
16763232fa30SMatthias Ringwald     // log_info("rfcomm_channel_state_machine_with_channel: state %u, state_var %04x, event %u", channel->state, channel->state_var ,event->type);
16773deb3ec6SMatthias Ringwald 
16783deb3ec6SMatthias Ringwald     rfcomm_multiplexer_t *multiplexer = channel->multiplexer;
16793deb3ec6SMatthias Ringwald 
16803deb3ec6SMatthias Ringwald     // TODO: integrate in common switch
16813deb3ec6SMatthias Ringwald     if (event->type == CH_EVT_RCVD_DISC){
16823deb3ec6SMatthias Ringwald         rfcomm_emit_channel_closed(channel);
16833deb3ec6SMatthias Ringwald         channel->state = RFCOMM_CHANNEL_SEND_UA_AFTER_DISC;
16843deb3ec6SMatthias Ringwald         return;
16853deb3ec6SMatthias Ringwald     }
16863deb3ec6SMatthias Ringwald 
16873deb3ec6SMatthias Ringwald     // TODO: integrate in common switch
16883deb3ec6SMatthias Ringwald     if (event->type == CH_EVT_RCVD_DM){
16893deb3ec6SMatthias Ringwald         log_info("Received DM message for #%u", channel->dlci);
16903deb3ec6SMatthias Ringwald         log_info("-> Closing channel locally for #%u", channel->dlci);
16913deb3ec6SMatthias Ringwald         rfcomm_emit_channel_closed(channel);
16923deb3ec6SMatthias Ringwald         rfcomm_channel_finalize(channel);
16933deb3ec6SMatthias Ringwald         return;
16943deb3ec6SMatthias Ringwald     }
16953deb3ec6SMatthias Ringwald 
16963deb3ec6SMatthias Ringwald     // remote port negotiation command - just accept everything for now
16973deb3ec6SMatthias Ringwald     //
16983deb3ec6SMatthias Ringwald     // "The RPN command can be used before a new DLC is opened and should be used whenever the port settings change."
16993deb3ec6SMatthias Ringwald     // "The RPN command is specified as optional in TS 07.10, but it is mandatory to recognize and respond to it in RFCOMM.
17003deb3ec6SMatthias Ringwald     //   (Although the handling of individual settings are implementation-dependent.)"
17013deb3ec6SMatthias Ringwald     //
17023deb3ec6SMatthias Ringwald 
17033deb3ec6SMatthias Ringwald     // TODO: integrate in common switch
17043deb3ec6SMatthias Ringwald     if (event->type == CH_EVT_RCVD_RPN_CMD){
17053deb3ec6SMatthias Ringwald         // control port parameters
17063deb3ec6SMatthias Ringwald         rfcomm_channel_event_rpn_t *event_rpn = (rfcomm_channel_event_rpn_t*) event;
17073deb3ec6SMatthias Ringwald         rfcomm_rpn_data_update(&channel->rpn_data, &event_rpn->data);
17083deb3ec6SMatthias Ringwald         rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_RPN_RSP);
17093deb3ec6SMatthias Ringwald         // notify client about new settings
17103deb3ec6SMatthias Ringwald         rfcomm_emit_port_configuration(channel);
17113deb3ec6SMatthias Ringwald         return;
17123deb3ec6SMatthias Ringwald     }
17133deb3ec6SMatthias Ringwald 
17143deb3ec6SMatthias Ringwald     // TODO: integrate in common switch
17153deb3ec6SMatthias Ringwald     if (event->type == CH_EVT_RCVD_RPN_REQ){
17163deb3ec6SMatthias Ringwald         // no values got accepted (no values have beens sent)
17173deb3ec6SMatthias Ringwald         channel->rpn_data.parameter_mask_0 = 0x00;
17183deb3ec6SMatthias Ringwald         channel->rpn_data.parameter_mask_1 = 0x00;
17193deb3ec6SMatthias Ringwald         rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_RPN_RSP);
17203deb3ec6SMatthias Ringwald         return;
17213deb3ec6SMatthias Ringwald     }
17223deb3ec6SMatthias Ringwald 
17233deb3ec6SMatthias Ringwald     if (event->type == CH_EVT_RCVD_RLS_CMD){
17243deb3ec6SMatthias Ringwald         rfcomm_channel_event_rls_t * event_rls = (rfcomm_channel_event_rls_t*) event;
17253deb3ec6SMatthias Ringwald         channel->rls_line_status = event_rls->line_status & 0x0f;
17263deb3ec6SMatthias Ringwald         log_info("CH_EVT_RCVD_RLS_CMD setting line status to 0x%0x", channel->rls_line_status);
17273deb3ec6SMatthias Ringwald         rfcomm_emit_remote_line_status(channel, event_rls->line_status);
17283deb3ec6SMatthias Ringwald         return;
17293deb3ec6SMatthias Ringwald     }
17303deb3ec6SMatthias Ringwald 
173162b5b741SMatthias Ringwald     // TODO: integrate in common switch
17323deb3ec6SMatthias Ringwald     if (event->type == CH_EVT_READY_TO_SEND){
17333deb3ec6SMatthias Ringwald         if (channel->state_var & RFCOMM_CHANNEL_STATE_VAR_SEND_RPN_RSP){
17343deb3ec6SMatthias Ringwald             log_info("Sending Remote Port Negotiation RSP for #%u", channel->dlci);
17353deb3ec6SMatthias Ringwald             rfcomm_channel_state_remove(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_RPN_RSP);
17363deb3ec6SMatthias Ringwald             rfcomm_send_uih_rpn_rsp(multiplexer, channel->dlci, &channel->rpn_data);
17373deb3ec6SMatthias Ringwald             return;
17383deb3ec6SMatthias Ringwald         }
17393deb3ec6SMatthias Ringwald         if (channel->state_var & RFCOMM_CHANNEL_STATE_VAR_SEND_MSC_RSP){
17403deb3ec6SMatthias Ringwald             log_info("Sending MSC RSP for #%u", channel->dlci);
17413deb3ec6SMatthias Ringwald             rfcomm_channel_state_remove(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_MSC_RSP);
17423deb3ec6SMatthias Ringwald             rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_SENT_MSC_RSP);
17433deb3ec6SMatthias Ringwald             rfcomm_send_uih_msc_rsp(multiplexer, channel->dlci, 0x8d);  // ea=1,fc=0,rtc=1,rtr=1,ic=0,dv=1
17443deb3ec6SMatthias Ringwald             return;
17453deb3ec6SMatthias Ringwald         }
17463deb3ec6SMatthias Ringwald         if (channel->rls_line_status != RFCOMM_RLS_STATUS_INVALID){
17473deb3ec6SMatthias Ringwald             log_info("Sending RLS RSP 0x%0x", channel->rls_line_status);
17483deb3ec6SMatthias Ringwald             uint8_t line_status = channel->rls_line_status;
17493deb3ec6SMatthias Ringwald             channel->rls_line_status = RFCOMM_RLS_STATUS_INVALID;
17503deb3ec6SMatthias Ringwald             rfcomm_send_uih_rls_rsp(multiplexer, channel->dlci, line_status);
17513deb3ec6SMatthias Ringwald             return;
17523deb3ec6SMatthias Ringwald         }
17533deb3ec6SMatthias Ringwald     }
17543deb3ec6SMatthias Ringwald 
17553deb3ec6SMatthias Ringwald     // emit MSC status to app
17563deb3ec6SMatthias Ringwald     if (event->type == CH_EVT_RCVD_MSC_CMD){
17573deb3ec6SMatthias Ringwald         // notify client about new settings
17583deb3ec6SMatthias Ringwald         rfcomm_channel_event_msc_t *event_msc = (rfcomm_channel_event_msc_t*) event;
17593deb3ec6SMatthias Ringwald         uint8_t modem_status_event[2+1];
17603deb3ec6SMatthias Ringwald         modem_status_event[0] = RFCOMM_EVENT_REMOTE_MODEM_STATUS;
17613deb3ec6SMatthias Ringwald         modem_status_event[1] = 1;
17623deb3ec6SMatthias Ringwald         modem_status_event[2] = event_msc->modem_status;
1763fc376368SMatthias Ringwald         (channel->packet_handler)(HCI_EVENT_PACKET, channel->rfcomm_cid, (uint8_t*)&modem_status_event, sizeof(modem_status_event));
17643deb3ec6SMatthias Ringwald         // no return, MSC_CMD will be handled by state machine below
17653deb3ec6SMatthias Ringwald     }
17663deb3ec6SMatthias Ringwald 
17673deb3ec6SMatthias Ringwald     rfcomm_channel_event_pn_t * event_pn = (rfcomm_channel_event_pn_t*) event;
17683deb3ec6SMatthias Ringwald 
17693deb3ec6SMatthias Ringwald     switch (channel->state) {
17703deb3ec6SMatthias Ringwald         case RFCOMM_CHANNEL_CLOSED:
17713deb3ec6SMatthias Ringwald             switch (event->type){
17723deb3ec6SMatthias Ringwald                 case CH_EVT_RCVD_SABM:
17733deb3ec6SMatthias Ringwald                     log_info("-> Inform app");
17743deb3ec6SMatthias Ringwald                     rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_RCVD_SABM);
17753deb3ec6SMatthias Ringwald                     channel->state = RFCOMM_CHANNEL_INCOMING_SETUP;
17763deb3ec6SMatthias Ringwald                     rfcomm_emit_connection_request(channel);
17773deb3ec6SMatthias Ringwald                     break;
17783deb3ec6SMatthias Ringwald                 case CH_EVT_RCVD_PN:
17793deb3ec6SMatthias Ringwald                     rfcomm_channel_accept_pn(channel, event_pn);
17803deb3ec6SMatthias Ringwald                     log_info("-> Inform app");
17813deb3ec6SMatthias Ringwald                     rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_RCVD_PN);
17823deb3ec6SMatthias Ringwald                     channel->state = RFCOMM_CHANNEL_INCOMING_SETUP;
17833deb3ec6SMatthias Ringwald                     rfcomm_emit_connection_request(channel);
17843deb3ec6SMatthias Ringwald                     break;
17853deb3ec6SMatthias Ringwald                 default:
17863deb3ec6SMatthias Ringwald                     break;
17873deb3ec6SMatthias Ringwald             }
17883deb3ec6SMatthias Ringwald             break;
17893deb3ec6SMatthias Ringwald 
17903deb3ec6SMatthias Ringwald         case RFCOMM_CHANNEL_INCOMING_SETUP:
17913deb3ec6SMatthias Ringwald             switch (event->type){
17923deb3ec6SMatthias Ringwald                 case CH_EVT_RCVD_SABM:
17933deb3ec6SMatthias Ringwald                     rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_RCVD_SABM);
17943deb3ec6SMatthias Ringwald                     if (channel->state_var & RFCOMM_CHANNEL_STATE_VAR_CLIENT_ACCEPTED) {
17953deb3ec6SMatthias Ringwald                         rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_UA);
17963deb3ec6SMatthias Ringwald                     }
17973deb3ec6SMatthias Ringwald                     break;
17983deb3ec6SMatthias Ringwald                 case CH_EVT_RCVD_PN:
17993deb3ec6SMatthias Ringwald                     rfcomm_channel_accept_pn(channel, event_pn);
18003deb3ec6SMatthias Ringwald                     rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_RCVD_PN);
18013deb3ec6SMatthias Ringwald                     if (channel->state_var & RFCOMM_CHANNEL_STATE_VAR_CLIENT_ACCEPTED) {
18023deb3ec6SMatthias Ringwald                         rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_PN_RSP);
18033deb3ec6SMatthias Ringwald                     }
18043deb3ec6SMatthias Ringwald                     break;
18053deb3ec6SMatthias Ringwald                 case CH_EVT_READY_TO_SEND:
18063deb3ec6SMatthias Ringwald                     // if / else if is used to check for state transition after sending
18073deb3ec6SMatthias Ringwald                     if (channel->state_var & RFCOMM_CHANNEL_STATE_VAR_SEND_PN_RSP){
18083deb3ec6SMatthias Ringwald                         log_info("Sending UIH Parameter Negotiation Respond for #%u", channel->dlci);
18093deb3ec6SMatthias Ringwald                         rfcomm_channel_state_remove(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_PN_RSP);
18103deb3ec6SMatthias Ringwald                         rfcomm_send_uih_pn_response(multiplexer, channel->dlci, channel->pn_priority, channel->max_frame_size);
18113deb3ec6SMatthias Ringwald                     } else if (channel->state_var & RFCOMM_CHANNEL_STATE_VAR_SEND_UA){
18123deb3ec6SMatthias Ringwald                         log_info("Sending UA #%u", channel->dlci);
18133deb3ec6SMatthias Ringwald                         rfcomm_channel_state_remove(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_UA);
18143deb3ec6SMatthias Ringwald                         rfcomm_send_ua(multiplexer, channel->dlci);
18153deb3ec6SMatthias Ringwald                     }
18163deb3ec6SMatthias Ringwald                     if (rfcomm_channel_ready_for_incoming_dlc_setup(channel)){
18173deb3ec6SMatthias Ringwald                         log_info("Incomping setup done, requesting send MSC CMD and send Credits");
18183deb3ec6SMatthias Ringwald                         rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_MSC_CMD);
18193deb3ec6SMatthias Ringwald                         rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_CREDITS);
1820daf17d1fSMatthias Ringwald                         channel->state = RFCOMM_CHANNEL_DLC_SETUP;
18213deb3ec6SMatthias Ringwald                      }
18223deb3ec6SMatthias Ringwald                     break;
18233deb3ec6SMatthias Ringwald                 default:
18243deb3ec6SMatthias Ringwald                     break;
18253deb3ec6SMatthias Ringwald             }
18263deb3ec6SMatthias Ringwald             break;
18273deb3ec6SMatthias Ringwald 
18283deb3ec6SMatthias Ringwald         case RFCOMM_CHANNEL_W4_MULTIPLEXER:
18293deb3ec6SMatthias Ringwald             switch (event->type) {
18303deb3ec6SMatthias Ringwald                 case CH_EVT_MULTIPLEXER_READY:
18313deb3ec6SMatthias Ringwald                     log_info("Muliplexer opened, sending UIH PN next");
18323deb3ec6SMatthias Ringwald                     channel->state = RFCOMM_CHANNEL_SEND_UIH_PN;
18333deb3ec6SMatthias Ringwald                     break;
18343deb3ec6SMatthias Ringwald                 default:
18353deb3ec6SMatthias Ringwald                     break;
18363deb3ec6SMatthias Ringwald             }
18373deb3ec6SMatthias Ringwald             break;
18383deb3ec6SMatthias Ringwald 
18393deb3ec6SMatthias Ringwald         case RFCOMM_CHANNEL_SEND_UIH_PN:
18403deb3ec6SMatthias Ringwald             switch (event->type) {
18413deb3ec6SMatthias Ringwald                 case CH_EVT_READY_TO_SEND:
18423deb3ec6SMatthias Ringwald                     log_info("Sending UIH Parameter Negotiation Command for #%u (channel 0x%p)", channel->dlci, channel );
18433deb3ec6SMatthias Ringwald                     channel->state = RFCOMM_CHANNEL_W4_PN_RSP;
18443deb3ec6SMatthias Ringwald                     rfcomm_send_uih_pn_command(multiplexer, channel->dlci, channel->max_frame_size);
18453deb3ec6SMatthias Ringwald                     break;
18463deb3ec6SMatthias Ringwald                 default:
18473deb3ec6SMatthias Ringwald                     break;
18483deb3ec6SMatthias Ringwald             }
18493deb3ec6SMatthias Ringwald             break;
18503deb3ec6SMatthias Ringwald 
18513deb3ec6SMatthias Ringwald         case RFCOMM_CHANNEL_W4_PN_RSP:
18523deb3ec6SMatthias Ringwald             switch (event->type){
18533deb3ec6SMatthias Ringwald                 case CH_EVT_RCVD_PN_RSP:
18543deb3ec6SMatthias Ringwald                     // update max frame size
18553deb3ec6SMatthias Ringwald                     if (channel->max_frame_size > event_pn->max_frame_size) {
18563deb3ec6SMatthias Ringwald                         channel->max_frame_size = event_pn->max_frame_size;
18573deb3ec6SMatthias Ringwald                     }
18583deb3ec6SMatthias Ringwald                     // new credits
18593deb3ec6SMatthias Ringwald                     channel->credits_outgoing = event_pn->credits_outgoing;
18603deb3ec6SMatthias Ringwald                     channel->state = RFCOMM_CHANNEL_SEND_SABM_W4_UA;
18613deb3ec6SMatthias Ringwald                     break;
18623deb3ec6SMatthias Ringwald                 default:
18633deb3ec6SMatthias Ringwald                     break;
18643deb3ec6SMatthias Ringwald             }
18653deb3ec6SMatthias Ringwald             break;
18663deb3ec6SMatthias Ringwald 
18673deb3ec6SMatthias Ringwald         case RFCOMM_CHANNEL_SEND_SABM_W4_UA:
18683deb3ec6SMatthias Ringwald             switch (event->type) {
18693deb3ec6SMatthias Ringwald                 case CH_EVT_READY_TO_SEND:
18703deb3ec6SMatthias Ringwald                     log_info("Sending SABM #%u", channel->dlci);
18713deb3ec6SMatthias Ringwald                     channel->state = RFCOMM_CHANNEL_W4_UA;
18723deb3ec6SMatthias Ringwald                     rfcomm_send_sabm(multiplexer, channel->dlci);
18733deb3ec6SMatthias Ringwald                     break;
18743deb3ec6SMatthias Ringwald                 default:
18753deb3ec6SMatthias Ringwald                     break;
18763deb3ec6SMatthias Ringwald             }
18773deb3ec6SMatthias Ringwald             break;
18783deb3ec6SMatthias Ringwald 
18793deb3ec6SMatthias Ringwald         case RFCOMM_CHANNEL_W4_UA:
18803deb3ec6SMatthias Ringwald             switch (event->type){
18813deb3ec6SMatthias Ringwald                 case CH_EVT_RCVD_UA:
18823deb3ec6SMatthias Ringwald                     channel->state = RFCOMM_CHANNEL_DLC_SETUP;
18833deb3ec6SMatthias Ringwald                     rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_MSC_CMD);
18843deb3ec6SMatthias Ringwald                     rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_CREDITS);
18853deb3ec6SMatthias Ringwald                     break;
18863deb3ec6SMatthias Ringwald                 default:
18873deb3ec6SMatthias Ringwald                     break;
18883deb3ec6SMatthias Ringwald             }
18893deb3ec6SMatthias Ringwald             break;
18903deb3ec6SMatthias Ringwald 
18913deb3ec6SMatthias Ringwald         case RFCOMM_CHANNEL_DLC_SETUP:
18923deb3ec6SMatthias Ringwald             switch (event->type){
18933deb3ec6SMatthias Ringwald                 case CH_EVT_RCVD_MSC_CMD:
18943deb3ec6SMatthias Ringwald                     rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_RCVD_MSC_CMD);
18953deb3ec6SMatthias Ringwald                     rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_MSC_RSP);
18963deb3ec6SMatthias Ringwald                     break;
18973deb3ec6SMatthias Ringwald                 case CH_EVT_RCVD_MSC_RSP:
18983deb3ec6SMatthias Ringwald                     rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_RCVD_MSC_RSP);
18993deb3ec6SMatthias Ringwald                     break;
19003deb3ec6SMatthias Ringwald 
19013deb3ec6SMatthias Ringwald                 case CH_EVT_READY_TO_SEND:
19023deb3ec6SMatthias Ringwald                     if (channel->state_var & RFCOMM_CHANNEL_STATE_VAR_SEND_MSC_CMD){
19033deb3ec6SMatthias Ringwald                         log_info("Sending MSC CMD for #%u", channel->dlci);
19043deb3ec6SMatthias Ringwald                         rfcomm_channel_state_remove(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_MSC_CMD);
19053deb3ec6SMatthias Ringwald                         rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_SENT_MSC_CMD);
19063deb3ec6SMatthias Ringwald                         rfcomm_send_uih_msc_cmd(multiplexer, channel->dlci , 0x8d);  // ea=1,fc=0,rtc=1,rtr=1,ic=0,dv=1
19073deb3ec6SMatthias Ringwald                         break;
19083deb3ec6SMatthias Ringwald                     }
19093deb3ec6SMatthias Ringwald                     if (channel->state_var & RFCOMM_CHANNEL_STATE_VAR_SEND_CREDITS){
19103deb3ec6SMatthias Ringwald                         log_info("Providing credits for #%u", channel->dlci);
19113deb3ec6SMatthias Ringwald                         rfcomm_channel_state_remove(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_CREDITS);
19123deb3ec6SMatthias Ringwald                         rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_SENT_CREDITS);
19133deb3ec6SMatthias Ringwald 
19143deb3ec6SMatthias Ringwald                         if (channel->new_credits_incoming) {
19153deb3ec6SMatthias Ringwald                             uint8_t new_credits = channel->new_credits_incoming;
19163deb3ec6SMatthias Ringwald                             channel->new_credits_incoming = 0;
19173deb3ec6SMatthias Ringwald                             rfcomm_channel_send_credits(channel, new_credits);
19183deb3ec6SMatthias Ringwald                         }
19193deb3ec6SMatthias Ringwald                         break;
19203deb3ec6SMatthias Ringwald 
19213deb3ec6SMatthias Ringwald                     }
19223deb3ec6SMatthias Ringwald                     break;
19233deb3ec6SMatthias Ringwald                 default:
19243deb3ec6SMatthias Ringwald                     break;
19253deb3ec6SMatthias Ringwald             }
19263deb3ec6SMatthias Ringwald             // finally done?
19273deb3ec6SMatthias Ringwald             if (rfcomm_channel_ready_for_open(channel)){
19283deb3ec6SMatthias Ringwald                 channel->state = RFCOMM_CHANNEL_OPEN;
19293deb3ec6SMatthias Ringwald                 rfcomm_channel_opened(channel);
19303deb3ec6SMatthias Ringwald             }
19313deb3ec6SMatthias Ringwald             break;
19323deb3ec6SMatthias Ringwald 
19333deb3ec6SMatthias Ringwald         case RFCOMM_CHANNEL_OPEN:
19343deb3ec6SMatthias Ringwald             switch (event->type){
19353deb3ec6SMatthias Ringwald                 case CH_EVT_RCVD_MSC_CMD:
19363deb3ec6SMatthias Ringwald                     rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_MSC_RSP);
19373deb3ec6SMatthias Ringwald                     break;
19383deb3ec6SMatthias Ringwald                 case CH_EVT_READY_TO_SEND:
19393deb3ec6SMatthias Ringwald                     if (channel->new_credits_incoming) {
19403deb3ec6SMatthias Ringwald                         uint8_t new_credits = channel->new_credits_incoming;
19413deb3ec6SMatthias Ringwald                         channel->new_credits_incoming = 0;
19423deb3ec6SMatthias Ringwald                         rfcomm_channel_send_credits(channel, new_credits);
19433deb3ec6SMatthias Ringwald                         break;
19443deb3ec6SMatthias Ringwald                     }
19453deb3ec6SMatthias Ringwald                     break;
1946b31d33b2SMatthias Ringwald                 case CH_EVT_RCVD_CREDITS:
1947b31d33b2SMatthias Ringwald                     rfcomm_notify_channel_can_send();
19483deb3ec6SMatthias Ringwald                     break;
19493deb3ec6SMatthias Ringwald                 default:
19503deb3ec6SMatthias Ringwald                     break;
19513deb3ec6SMatthias Ringwald             }
19523deb3ec6SMatthias Ringwald             break;
19533deb3ec6SMatthias Ringwald 
19543deb3ec6SMatthias Ringwald         case RFCOMM_CHANNEL_SEND_DM:
19553deb3ec6SMatthias Ringwald             switch (event->type) {
19563deb3ec6SMatthias Ringwald                 case CH_EVT_READY_TO_SEND:
19573deb3ec6SMatthias Ringwald                     log_info("Sending DM_PF for #%u", channel->dlci);
19583deb3ec6SMatthias Ringwald                     // don't emit channel closed - channel was never open
19593deb3ec6SMatthias Ringwald                     channel->state = RFCOMM_CHANNEL_CLOSED;
19603deb3ec6SMatthias Ringwald                     rfcomm_send_dm_pf(multiplexer, channel->dlci);
19613deb3ec6SMatthias Ringwald                     rfcomm_channel_finalize(channel);
19623deb3ec6SMatthias Ringwald                     break;
19633deb3ec6SMatthias Ringwald                 default:
19643deb3ec6SMatthias Ringwald                     break;
19653deb3ec6SMatthias Ringwald             }
19663deb3ec6SMatthias Ringwald             break;
19673deb3ec6SMatthias Ringwald 
19683deb3ec6SMatthias Ringwald         case RFCOMM_CHANNEL_SEND_DISC:
19693deb3ec6SMatthias Ringwald             switch (event->type) {
19703deb3ec6SMatthias Ringwald                 case CH_EVT_READY_TO_SEND:
19713deb3ec6SMatthias Ringwald                     channel->state = RFCOMM_CHANNEL_W4_UA_AFTER_UA;
19723deb3ec6SMatthias Ringwald                     rfcomm_send_disc(multiplexer, channel->dlci);
19733deb3ec6SMatthias Ringwald                     break;
19743deb3ec6SMatthias Ringwald                 default:
19753deb3ec6SMatthias Ringwald                     break;
19763deb3ec6SMatthias Ringwald             }
19773deb3ec6SMatthias Ringwald             break;
19783deb3ec6SMatthias Ringwald 
19793deb3ec6SMatthias Ringwald         case RFCOMM_CHANNEL_W4_UA_AFTER_UA:
19803deb3ec6SMatthias Ringwald             switch (event->type){
19813deb3ec6SMatthias Ringwald                 case CH_EVT_RCVD_UA:
19823deb3ec6SMatthias Ringwald                     channel->state = RFCOMM_CHANNEL_CLOSED;
19833deb3ec6SMatthias Ringwald                     rfcomm_emit_channel_closed(channel);
19843deb3ec6SMatthias Ringwald                     rfcomm_channel_finalize(channel);
19853deb3ec6SMatthias Ringwald                     break;
19863deb3ec6SMatthias Ringwald                 default:
19873deb3ec6SMatthias Ringwald                     break;
19883deb3ec6SMatthias Ringwald             }
19893deb3ec6SMatthias Ringwald             break;
19903deb3ec6SMatthias Ringwald 
19913deb3ec6SMatthias Ringwald         case RFCOMM_CHANNEL_SEND_UA_AFTER_DISC:
19923deb3ec6SMatthias Ringwald             switch (event->type) {
19933deb3ec6SMatthias Ringwald                 case CH_EVT_READY_TO_SEND:
19943deb3ec6SMatthias Ringwald                     log_info("Sending UA after DISC for #%u", channel->dlci);
19953deb3ec6SMatthias Ringwald                     channel->state = RFCOMM_CHANNEL_CLOSED;
19963deb3ec6SMatthias Ringwald                     rfcomm_send_ua(multiplexer, channel->dlci);
19973deb3ec6SMatthias Ringwald                     rfcomm_channel_finalize(channel);
19983deb3ec6SMatthias Ringwald                     break;
19993deb3ec6SMatthias Ringwald                 default:
20003deb3ec6SMatthias Ringwald                     break;
20013deb3ec6SMatthias Ringwald             }
20023deb3ec6SMatthias Ringwald             break;
20033deb3ec6SMatthias Ringwald 
20043deb3ec6SMatthias Ringwald         default:
20053deb3ec6SMatthias Ringwald             break;
20063deb3ec6SMatthias Ringwald     }
20073deb3ec6SMatthias Ringwald }
20083deb3ec6SMatthias Ringwald 
20093deb3ec6SMatthias Ringwald // MARK: RFCOMM BTstack API
20103deb3ec6SMatthias Ringwald 
20113deb3ec6SMatthias Ringwald void rfcomm_init(void){
20123deb3ec6SMatthias Ringwald     rfcomm_client_cid_generator = 0;
20133deb3ec6SMatthias Ringwald     rfcomm_multiplexers = NULL;
20143deb3ec6SMatthias Ringwald     rfcomm_services     = NULL;
20153deb3ec6SMatthias Ringwald     rfcomm_channels     = NULL;
20163deb3ec6SMatthias Ringwald     rfcomm_security_level = LEVEL_2;
20173deb3ec6SMatthias Ringwald }
20183deb3ec6SMatthias Ringwald 
20193deb3ec6SMatthias Ringwald void rfcomm_set_required_security_level(gap_security_level_t security_level){
20203deb3ec6SMatthias Ringwald     rfcomm_security_level = security_level;
20213deb3ec6SMatthias Ringwald }
20223deb3ec6SMatthias Ringwald 
20233deb3ec6SMatthias Ringwald int rfcomm_can_send_packet_now(uint16_t rfcomm_cid){
20243deb3ec6SMatthias Ringwald     rfcomm_channel_t * channel = rfcomm_channel_for_rfcomm_cid(rfcomm_cid);
20253deb3ec6SMatthias Ringwald     if (!channel){
202628190c0bSMatthias Ringwald         log_error("rfcomm_send cid 0x%02x doesn't exist!", rfcomm_cid);
2027b31d33b2SMatthias Ringwald         return 0;
20283deb3ec6SMatthias Ringwald     }
20290b9d7e78SMatthias Ringwald     return rfcomm_channel_can_send(channel);
20303deb3ec6SMatthias Ringwald }
20313deb3ec6SMatthias Ringwald 
2032225a2744SMatthias Ringwald void rfcomm_request_can_send_now_event(uint16_t rfcomm_cid){
2033225a2744SMatthias Ringwald     rfcomm_channel_t * channel = rfcomm_channel_for_rfcomm_cid(rfcomm_cid);
2034225a2744SMatthias Ringwald     if (!channel){
2035225a2744SMatthias Ringwald         log_error("rfcomm_send cid 0x%02x doesn't exist!", rfcomm_cid);
2036225a2744SMatthias Ringwald         return;
2037225a2744SMatthias Ringwald     }
2038225a2744SMatthias Ringwald     channel->waiting_for_can_send_now = 1;
20394fea3822SMatthias Ringwald     l2cap_request_can_send_now_event(channel->multiplexer->l2cap_cid);
2040225a2744SMatthias Ringwald }
2041225a2744SMatthias Ringwald 
20423deb3ec6SMatthias Ringwald static int rfcomm_assert_send_valid(rfcomm_channel_t * channel , uint16_t len){
20433deb3ec6SMatthias Ringwald     if (len > channel->max_frame_size){
204428190c0bSMatthias Ringwald         log_error("rfcomm_send cid 0x%02x, rfcomm data lenght exceeds MTU!", channel->rfcomm_cid);
20453deb3ec6SMatthias Ringwald         return RFCOMM_DATA_LEN_EXCEEDS_MTU;
20463deb3ec6SMatthias Ringwald     }
20473deb3ec6SMatthias Ringwald 
20483deb3ec6SMatthias Ringwald     if (!channel->credits_outgoing){
204928190c0bSMatthias Ringwald         log_info("rfcomm_send cid 0x%02x, no rfcomm outgoing credits!", channel->rfcomm_cid);
20503deb3ec6SMatthias Ringwald         return RFCOMM_NO_OUTGOING_CREDITS;
20513deb3ec6SMatthias Ringwald     }
20523deb3ec6SMatthias Ringwald 
20533deb3ec6SMatthias Ringwald     if ((channel->multiplexer->fcon & 1) == 0){
205428190c0bSMatthias Ringwald         log_info("rfcomm_send cid 0x%02x, aggregate flow off!", channel->rfcomm_cid);
20553deb3ec6SMatthias Ringwald         return RFCOMM_AGGREGATE_FLOW_OFF;
20563deb3ec6SMatthias Ringwald     }
20573deb3ec6SMatthias Ringwald     return 0;
20583deb3ec6SMatthias Ringwald }
20593deb3ec6SMatthias Ringwald 
20603deb3ec6SMatthias Ringwald // pre: rfcomm_can_send_packet_now(rfcomm_cid) == true
20613deb3ec6SMatthias Ringwald int rfcomm_reserve_packet_buffer(void){
20623deb3ec6SMatthias Ringwald     return l2cap_reserve_packet_buffer();
20633deb3ec6SMatthias Ringwald }
20643deb3ec6SMatthias Ringwald 
20653deb3ec6SMatthias Ringwald void rfcomm_release_packet_buffer(void){
20663deb3ec6SMatthias Ringwald     l2cap_release_packet_buffer();
20673deb3ec6SMatthias Ringwald }
20683deb3ec6SMatthias Ringwald 
20693deb3ec6SMatthias Ringwald uint8_t * rfcomm_get_outgoing_buffer(void){
20703deb3ec6SMatthias Ringwald     uint8_t * rfcomm_out_buffer = l2cap_get_outgoing_buffer();
20713deb3ec6SMatthias Ringwald     // address + control + length (16) + no credit field
20723deb3ec6SMatthias Ringwald     return &rfcomm_out_buffer[4];
20733deb3ec6SMatthias Ringwald }
20743deb3ec6SMatthias Ringwald 
20753deb3ec6SMatthias Ringwald uint16_t rfcomm_get_max_frame_size(uint16_t rfcomm_cid){
20763deb3ec6SMatthias Ringwald     rfcomm_channel_t * channel = rfcomm_channel_for_rfcomm_cid(rfcomm_cid);
20773deb3ec6SMatthias Ringwald     if (!channel){
20783deb3ec6SMatthias Ringwald         log_error("rfcomm_get_max_frame_size cid 0x%02x doesn't exist!", rfcomm_cid);
20793deb3ec6SMatthias Ringwald         return 0;
20803deb3ec6SMatthias Ringwald     }
20813deb3ec6SMatthias Ringwald     return channel->max_frame_size;
20823deb3ec6SMatthias Ringwald }
20833deb3ec6SMatthias Ringwald int rfcomm_send_prepared(uint16_t rfcomm_cid, uint16_t len){
20843deb3ec6SMatthias Ringwald     rfcomm_channel_t * channel = rfcomm_channel_for_rfcomm_cid(rfcomm_cid);
20853deb3ec6SMatthias Ringwald     if (!channel){
20863deb3ec6SMatthias Ringwald         log_error("rfcomm_send_prepared cid 0x%02x doesn't exist!", rfcomm_cid);
20873deb3ec6SMatthias Ringwald         return 0;
20883deb3ec6SMatthias Ringwald     }
20893deb3ec6SMatthias Ringwald 
20903deb3ec6SMatthias Ringwald     int err = rfcomm_assert_send_valid(channel, len);
20913deb3ec6SMatthias Ringwald     if (err) return err;
209268d15bfcSMatthias Ringwald     if (!l2cap_can_send_prepared_packet_now(channel->multiplexer->l2cap_cid)){
209378707112SMatthias Ringwald         log_error("rfcomm_send_prepared: l2cap cannot send now");
209478707112SMatthias Ringwald         return BTSTACK_ACL_BUFFERS_FULL;
209578707112SMatthias Ringwald     }
20963deb3ec6SMatthias Ringwald 
20973deb3ec6SMatthias Ringwald     // send might cause l2cap to emit new credits, update counters first
20983deb3ec6SMatthias Ringwald     channel->credits_outgoing--;
20993deb3ec6SMatthias Ringwald 
21003deb3ec6SMatthias Ringwald     int result = rfcomm_send_uih_prepared(channel->multiplexer, channel->dlci, len);
21013deb3ec6SMatthias Ringwald 
21023deb3ec6SMatthias Ringwald     if (result != 0) {
21033deb3ec6SMatthias Ringwald         channel->credits_outgoing++;
210478707112SMatthias Ringwald         log_error("rfcomm_send_prepared: error %d", result);
21053deb3ec6SMatthias Ringwald         return result;
21063deb3ec6SMatthias Ringwald     }
21073deb3ec6SMatthias Ringwald 
21083deb3ec6SMatthias Ringwald     return result;
21093deb3ec6SMatthias Ringwald }
21103deb3ec6SMatthias Ringwald 
211128190c0bSMatthias Ringwald int rfcomm_send(uint16_t rfcomm_cid, uint8_t *data, uint16_t len){
21123deb3ec6SMatthias Ringwald     rfcomm_channel_t * channel = rfcomm_channel_for_rfcomm_cid(rfcomm_cid);
21133deb3ec6SMatthias Ringwald     if (!channel){
211428190c0bSMatthias Ringwald         log_error("rfcomm_send cid 0x%02x doesn't exist!", rfcomm_cid);
21153deb3ec6SMatthias Ringwald         return 1;
21163deb3ec6SMatthias Ringwald     }
21173deb3ec6SMatthias Ringwald 
21183deb3ec6SMatthias Ringwald     int err = rfcomm_assert_send_valid(channel, len);
21193deb3ec6SMatthias Ringwald     if (err) return err;
212068d15bfcSMatthias Ringwald     if (!l2cap_can_send_packet_now(channel->multiplexer->l2cap_cid)){
212178707112SMatthias Ringwald         log_error("rfcomm_send_internal: l2cap cannot send now");
212278707112SMatthias Ringwald         return BTSTACK_ACL_BUFFERS_FULL;
212378707112SMatthias Ringwald     }
21243deb3ec6SMatthias Ringwald 
21253deb3ec6SMatthias Ringwald     rfcomm_reserve_packet_buffer();
21263deb3ec6SMatthias Ringwald     uint8_t * rfcomm_payload = rfcomm_get_outgoing_buffer();
21273deb3ec6SMatthias Ringwald     memcpy(rfcomm_payload, data, len);
212878707112SMatthias Ringwald     err = rfcomm_send_prepared(rfcomm_cid, len);
212978707112SMatthias Ringwald     if (err){
213078707112SMatthias Ringwald         rfcomm_release_packet_buffer();
213178707112SMatthias Ringwald     }
213278707112SMatthias Ringwald     return err;
21333deb3ec6SMatthias Ringwald }
21343deb3ec6SMatthias Ringwald 
21353deb3ec6SMatthias Ringwald // Sends Local Lnie Status, see LINE_STATUS_..
21363deb3ec6SMatthias Ringwald int rfcomm_send_local_line_status(uint16_t rfcomm_cid, uint8_t line_status){
21373deb3ec6SMatthias Ringwald     rfcomm_channel_t * channel = rfcomm_channel_for_rfcomm_cid(rfcomm_cid);
21383deb3ec6SMatthias Ringwald     if (!channel){
21393deb3ec6SMatthias Ringwald         log_error("rfcomm_send_local_line_status cid 0x%02x doesn't exist!", rfcomm_cid);
21403deb3ec6SMatthias Ringwald         return 0;
21413deb3ec6SMatthias Ringwald     }
21423deb3ec6SMatthias Ringwald     return rfcomm_send_uih_rls_cmd(channel->multiplexer, channel->dlci, line_status);
21433deb3ec6SMatthias Ringwald }
21443deb3ec6SMatthias Ringwald 
21453deb3ec6SMatthias Ringwald // Sned local modem status. see MODEM_STAUS_..
21463deb3ec6SMatthias Ringwald int rfcomm_send_modem_status(uint16_t rfcomm_cid, uint8_t modem_status){
21473deb3ec6SMatthias Ringwald     rfcomm_channel_t * channel = rfcomm_channel_for_rfcomm_cid(rfcomm_cid);
21483deb3ec6SMatthias Ringwald     if (!channel){
21493deb3ec6SMatthias Ringwald         log_error("rfcomm_send_modem_status cid 0x%02x doesn't exist!", rfcomm_cid);
21503deb3ec6SMatthias Ringwald         return 0;
21513deb3ec6SMatthias Ringwald     }
21523deb3ec6SMatthias Ringwald     return rfcomm_send_uih_msc_cmd(channel->multiplexer, channel->dlci, modem_status);
21533deb3ec6SMatthias Ringwald }
21543deb3ec6SMatthias Ringwald 
21553deb3ec6SMatthias Ringwald // Configure remote port
21563deb3ec6SMatthias 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){
21573deb3ec6SMatthias Ringwald     rfcomm_channel_t * channel = rfcomm_channel_for_rfcomm_cid(rfcomm_cid);
21583deb3ec6SMatthias Ringwald     if (!channel){
21593deb3ec6SMatthias Ringwald         log_error("rfcomm_send_port_configuration cid 0x%02x doesn't exist!", rfcomm_cid);
21603deb3ec6SMatthias Ringwald         return 0;
21613deb3ec6SMatthias Ringwald     }
21623deb3ec6SMatthias Ringwald     rfcomm_rpn_data_t rpn_data;
21633deb3ec6SMatthias Ringwald     rpn_data.baud_rate = baud_rate;
21643deb3ec6SMatthias Ringwald     rpn_data.flags = data_bits | (stop_bits << 2) | (parity << 3);
21653deb3ec6SMatthias Ringwald     rpn_data.flow_control = flow_control;
21663deb3ec6SMatthias Ringwald     rpn_data.xon = 0;
21673deb3ec6SMatthias Ringwald     rpn_data.xoff = 0;
21683deb3ec6SMatthias Ringwald     rpn_data.parameter_mask_0 = 0x1f;   // all but xon/xoff
21693deb3ec6SMatthias Ringwald     rpn_data.parameter_mask_1 = 0x3f;   // all flow control options
21703deb3ec6SMatthias Ringwald     return rfcomm_send_uih_rpn_cmd(channel->multiplexer, channel->dlci, &rpn_data);
21713deb3ec6SMatthias Ringwald }
21723deb3ec6SMatthias Ringwald 
21733deb3ec6SMatthias Ringwald // Query remote port
21743deb3ec6SMatthias Ringwald int rfcomm_query_port_configuration(uint16_t rfcomm_cid){
21753deb3ec6SMatthias Ringwald     rfcomm_channel_t * channel = rfcomm_channel_for_rfcomm_cid(rfcomm_cid);
21763deb3ec6SMatthias Ringwald     if (!channel){
21773deb3ec6SMatthias Ringwald         log_error("rfcomm_query_port_configuration cid 0x%02x doesn't exist!", rfcomm_cid);
21783deb3ec6SMatthias Ringwald         return 0;
21793deb3ec6SMatthias Ringwald     }
21803deb3ec6SMatthias Ringwald     return rfcomm_send_uih_rpn_req(channel->multiplexer, channel->dlci);
21813deb3ec6SMatthias Ringwald }
21823deb3ec6SMatthias Ringwald 
2183aa4dd815SMatthias Ringwald 
2184ccb8ddfbSMatthias 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){
21855d1e858fSMatthias Ringwald     log_info("RFCOMM_CREATE_CHANNEL addr %s channel #%u init credits %u",  bd_addr_to_str(addr), server_channel, initial_credits);
21865d1e858fSMatthias Ringwald 
21875d1e858fSMatthias Ringwald     // create new multiplexer if necessary
21885d1e858fSMatthias Ringwald     uint8_t status = 0;
2189fc966bd3SMatthias Ringwald     uint8_t dlci = 0;
21905d1e858fSMatthias Ringwald     int new_multiplexer = 0;
21915d1e858fSMatthias Ringwald     rfcomm_channel_t * channel = NULL;
21925d1e858fSMatthias Ringwald     rfcomm_multiplexer_t * multiplexer = rfcomm_multiplexer_for_addr(addr);
21935d1e858fSMatthias Ringwald     if (!multiplexer) {
21945d1e858fSMatthias Ringwald         multiplexer = rfcomm_multiplexer_create_for_addr(addr);
21955d1e858fSMatthias Ringwald         if (!multiplexer){
21965d1e858fSMatthias Ringwald             status = BTSTACK_MEMORY_ALLOC_FAILED;
21975d1e858fSMatthias Ringwald             goto fail;
21985d1e858fSMatthias Ringwald         }
21995d1e858fSMatthias Ringwald         multiplexer->outgoing = 1;
22005d1e858fSMatthias Ringwald         multiplexer->state = RFCOMM_MULTIPLEXER_W4_CONNECT;
22015d1e858fSMatthias Ringwald         new_multiplexer = 1;
22025d1e858fSMatthias Ringwald     }
22035d1e858fSMatthias Ringwald 
22042a1147c9SMatthias Ringwald     // check if channel for this remote service already exists
2205fc966bd3SMatthias Ringwald     dlci = (server_channel << 1) | (multiplexer->outgoing ^ 1);
22062a1147c9SMatthias Ringwald     channel = rfcomm_channel_for_multiplexer_and_dlci(multiplexer, dlci);
22072a1147c9SMatthias Ringwald     if (channel){
22082a1147c9SMatthias Ringwald         status = RFCOMM_CHANNEL_ALREADY_REGISTERED;
22092a1147c9SMatthias Ringwald         goto fail;
22102a1147c9SMatthias Ringwald     }
22112a1147c9SMatthias Ringwald 
22125d1e858fSMatthias Ringwald     // prepare channel
22135d1e858fSMatthias Ringwald     channel = rfcomm_channel_create(multiplexer, NULL, server_channel);
22145d1e858fSMatthias Ringwald     if (!channel){
22155d1e858fSMatthias Ringwald         status = BTSTACK_MEMORY_ALLOC_FAILED;
22165d1e858fSMatthias Ringwald         goto fail;
22175d1e858fSMatthias Ringwald     }
2218ccb8ddfbSMatthias Ringwald 
22195d1e858fSMatthias Ringwald     // rfcomm_cid is already assigned by rfcomm_channel_create
22205d1e858fSMatthias Ringwald     channel->incoming_flow_control = incoming_flow_control;
22215d1e858fSMatthias Ringwald     channel->new_credits_incoming  = initial_credits;
2222ccb8ddfbSMatthias Ringwald     channel->packet_handler = packet_handler;
22235d1e858fSMatthias Ringwald 
22245d1e858fSMatthias Ringwald     // return rfcomm_cid
2225432fe57eSMatthias Ringwald     if (out_rfcomm_cid){
22265d1e858fSMatthias Ringwald         *out_rfcomm_cid = channel->rfcomm_cid;
2227432fe57eSMatthias Ringwald     }
22285d1e858fSMatthias Ringwald 
22295d1e858fSMatthias Ringwald     // start multiplexer setup
22305d1e858fSMatthias Ringwald     if (multiplexer->state != RFCOMM_MULTIPLEXER_OPEN) {
22315d1e858fSMatthias Ringwald         channel->state = RFCOMM_CHANNEL_W4_MULTIPLEXER;
22325d1e858fSMatthias Ringwald         uint16_t l2cap_cid = 0;
22335d1e858fSMatthias Ringwald         status = l2cap_create_channel(rfcomm_packet_handler, addr, PSM_RFCOMM, l2cap_max_mtu(), &l2cap_cid);
22345d1e858fSMatthias Ringwald         if (status) goto fail;
22355d1e858fSMatthias Ringwald         multiplexer->l2cap_cid = l2cap_cid;
22365d1e858fSMatthias Ringwald         return 0;
22375d1e858fSMatthias Ringwald     }
22385d1e858fSMatthias Ringwald 
22395d1e858fSMatthias Ringwald     channel->state = RFCOMM_CHANNEL_SEND_UIH_PN;
22405d1e858fSMatthias Ringwald 
22415d1e858fSMatthias Ringwald     // start connecting, if multiplexer is already up and running
224262b5b741SMatthias Ringwald     l2cap_request_can_send_now_event(multiplexer->l2cap_cid);
22435d1e858fSMatthias Ringwald     return 0;
22445d1e858fSMatthias Ringwald 
22455d1e858fSMatthias Ringwald fail:
22465d1e858fSMatthias Ringwald     if (new_multiplexer) btstack_memory_rfcomm_multiplexer_free(multiplexer);
22475d1e858fSMatthias Ringwald     if (channel)         btstack_memory_rfcomm_channel_free(channel);
22485d1e858fSMatthias Ringwald     return status;
22495d1e858fSMatthias Ringwald }
22505d1e858fSMatthias Ringwald 
2251ccb8ddfbSMatthias 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){
2252ccb8ddfbSMatthias Ringwald     return rfcomm_channel_create_internal(packet_handler, addr, server_channel, 1, initial_credits, out_rfcomm_cid);
22535d1e858fSMatthias Ringwald }
22545d1e858fSMatthias Ringwald 
2255ccb8ddfbSMatthias 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){
2256ccb8ddfbSMatthias Ringwald     return rfcomm_channel_create_internal(packet_handler, addr, server_channel, 0, RFCOMM_CREDITS, out_rfcomm_cid);
22575d1e858fSMatthias Ringwald }
22585d1e858fSMatthias Ringwald 
225928190c0bSMatthias Ringwald void rfcomm_disconnect(uint16_t rfcomm_cid){
22603deb3ec6SMatthias Ringwald     log_info("RFCOMM_DISCONNECT cid 0x%02x", rfcomm_cid);
22613deb3ec6SMatthias Ringwald     rfcomm_channel_t * channel = rfcomm_channel_for_rfcomm_cid(rfcomm_cid);
226270c27508SMatthias Ringwald     if (!channel) return;
22633deb3ec6SMatthias Ringwald 
226470c27508SMatthias Ringwald     channel->state = RFCOMM_CHANNEL_SEND_DISC;
226562b5b741SMatthias Ringwald     l2cap_request_can_send_now_event(channel->multiplexer->l2cap_cid);
22663deb3ec6SMatthias Ringwald }
22673deb3ec6SMatthias Ringwald 
2268ccb8ddfbSMatthias Ringwald static uint8_t rfcomm_register_service_internal(btstack_packet_handler_t packet_handler,
2269ccb8ddfbSMatthias Ringwald     uint8_t channel, uint16_t max_frame_size, uint8_t incoming_flow_control, uint8_t initial_credits){
2270ccb8ddfbSMatthias Ringwald 
2271ccb8ddfbSMatthias Ringwald     log_info("RFCOMM_REGISTER_SERVICE channel #%u mtu %u flow_control %u credits %u",
22723deb3ec6SMatthias Ringwald              channel, max_frame_size, incoming_flow_control, initial_credits);
2273457b5cb1SMatthias Ringwald 
22743deb3ec6SMatthias Ringwald     // check if already registered
22753deb3ec6SMatthias Ringwald     rfcomm_service_t * service = rfcomm_service_for_channel(channel);
22763deb3ec6SMatthias Ringwald     if (service){
2277457b5cb1SMatthias Ringwald         return RFCOMM_CHANNEL_ALREADY_REGISTERED;
22783deb3ec6SMatthias Ringwald     }
22793deb3ec6SMatthias Ringwald 
22803deb3ec6SMatthias Ringwald     // alloc structure
22813deb3ec6SMatthias Ringwald     service = btstack_memory_rfcomm_service_get();
22823deb3ec6SMatthias Ringwald     if (!service) {
2283457b5cb1SMatthias Ringwald         return BTSTACK_MEMORY_ALLOC_FAILED;
22843deb3ec6SMatthias Ringwald     }
22853deb3ec6SMatthias Ringwald 
22863deb3ec6SMatthias Ringwald     // register with l2cap if not registered before, max MTU
2287665d90f2SMatthias Ringwald     if (btstack_linked_list_empty(&rfcomm_services)){
2288be2053a6SMatthias Ringwald         l2cap_register_service(rfcomm_packet_handler, PSM_RFCOMM, 0xffff, rfcomm_security_level);
22893deb3ec6SMatthias Ringwald     }
22903deb3ec6SMatthias Ringwald 
22913deb3ec6SMatthias Ringwald     // fill in
2292ccb8ddfbSMatthias Ringwald     service->packet_handler = packet_handler;
22933deb3ec6SMatthias Ringwald     service->server_channel = channel;
22943deb3ec6SMatthias Ringwald     service->max_frame_size = max_frame_size;
22953deb3ec6SMatthias Ringwald     service->incoming_flow_control = incoming_flow_control;
22963deb3ec6SMatthias Ringwald     service->incoming_initial_credits = initial_credits;
22973deb3ec6SMatthias Ringwald 
22983deb3ec6SMatthias Ringwald     // add to services list
2299665d90f2SMatthias Ringwald     btstack_linked_list_add(&rfcomm_services, (btstack_linked_item_t *) service);
23003deb3ec6SMatthias Ringwald 
2301457b5cb1SMatthias Ringwald     return 0;
23023deb3ec6SMatthias Ringwald }
23033deb3ec6SMatthias Ringwald 
2304ccb8ddfbSMatthias Ringwald uint8_t rfcomm_register_service_with_initial_credits(btstack_packet_handler_t packet_handler,
2305ccb8ddfbSMatthias Ringwald     uint8_t channel, uint16_t max_frame_size, uint8_t initial_credits){
2306ccb8ddfbSMatthias Ringwald 
2307ccb8ddfbSMatthias Ringwald     return rfcomm_register_service_internal(packet_handler, channel, max_frame_size, 1, initial_credits);
23083deb3ec6SMatthias Ringwald }
23093deb3ec6SMatthias Ringwald 
2310ccb8ddfbSMatthias Ringwald uint8_t rfcomm_register_service(btstack_packet_handler_t packet_handler, uint8_t channel,
2311ccb8ddfbSMatthias Ringwald     uint16_t max_frame_size){
2312ccb8ddfbSMatthias Ringwald 
2313ccb8ddfbSMatthias Ringwald     return rfcomm_register_service_internal(packet_handler, channel, max_frame_size, 0,RFCOMM_CREDITS);
23143deb3ec6SMatthias Ringwald }
23153deb3ec6SMatthias Ringwald 
2316457b5cb1SMatthias Ringwald void rfcomm_unregister_service(uint8_t service_channel){
23173deb3ec6SMatthias Ringwald     log_info("RFCOMM_UNREGISTER_SERVICE #%u", service_channel);
23183deb3ec6SMatthias Ringwald     rfcomm_service_t *service = rfcomm_service_for_channel(service_channel);
23193deb3ec6SMatthias Ringwald     if (!service) return;
2320665d90f2SMatthias Ringwald     btstack_linked_list_remove(&rfcomm_services, (btstack_linked_item_t *) service);
23213deb3ec6SMatthias Ringwald     btstack_memory_rfcomm_service_free(service);
23223deb3ec6SMatthias Ringwald 
23233deb3ec6SMatthias Ringwald     // unregister if no services active
2324665d90f2SMatthias Ringwald     if (btstack_linked_list_empty(&rfcomm_services)){
23253deb3ec6SMatthias Ringwald         // bt_send_cmd(&l2cap_unregister_service, PSM_RFCOMM);
232602f83142SMatthias Ringwald         l2cap_unregister_service(PSM_RFCOMM);
23273deb3ec6SMatthias Ringwald     }
23283deb3ec6SMatthias Ringwald }
23293deb3ec6SMatthias Ringwald 
233028190c0bSMatthias Ringwald void rfcomm_accept_connection(uint16_t rfcomm_cid){
23313deb3ec6SMatthias Ringwald     log_info("RFCOMM_ACCEPT_CONNECTION cid 0x%02x", rfcomm_cid);
23323deb3ec6SMatthias Ringwald     rfcomm_channel_t * channel = rfcomm_channel_for_rfcomm_cid(rfcomm_cid);
23333deb3ec6SMatthias Ringwald     if (!channel) return;
23343deb3ec6SMatthias Ringwald     switch (channel->state) {
23353deb3ec6SMatthias Ringwald         case RFCOMM_CHANNEL_INCOMING_SETUP:
23363deb3ec6SMatthias Ringwald             rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_CLIENT_ACCEPTED);
23373deb3ec6SMatthias Ringwald             if (channel->state_var & RFCOMM_CHANNEL_STATE_VAR_RCVD_PN){
23383deb3ec6SMatthias Ringwald                 rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_PN_RSP);
233962b5b741SMatthias Ringwald                 l2cap_request_can_send_now_event(channel->multiplexer->l2cap_cid);
23403deb3ec6SMatthias Ringwald             }
23413deb3ec6SMatthias Ringwald             if (channel->state_var & RFCOMM_CHANNEL_STATE_VAR_RCVD_SABM){
23423deb3ec6SMatthias Ringwald                 rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_UA);
234362b5b741SMatthias Ringwald                 l2cap_request_can_send_now_event(channel->multiplexer->l2cap_cid);
23443deb3ec6SMatthias Ringwald             }
23453deb3ec6SMatthias Ringwald             // at least one of { PN RSP, UA } needs to be sent
23463deb3ec6SMatthias Ringwald             // state transistion incoming setup -> dlc setup happens in rfcomm_run after these have been sent
23473deb3ec6SMatthias Ringwald             break;
23483deb3ec6SMatthias Ringwald         default:
23493deb3ec6SMatthias Ringwald             break;
23503deb3ec6SMatthias Ringwald     }
23513deb3ec6SMatthias Ringwald 
23523deb3ec6SMatthias Ringwald }
23533deb3ec6SMatthias Ringwald 
235428190c0bSMatthias Ringwald void rfcomm_decline_connection(uint16_t rfcomm_cid){
23553deb3ec6SMatthias Ringwald     log_info("RFCOMM_DECLINE_CONNECTION cid 0x%02x", rfcomm_cid);
23563deb3ec6SMatthias Ringwald     rfcomm_channel_t * channel = rfcomm_channel_for_rfcomm_cid(rfcomm_cid);
23573deb3ec6SMatthias Ringwald     if (!channel) return;
23583deb3ec6SMatthias Ringwald     switch (channel->state) {
23593deb3ec6SMatthias Ringwald         case RFCOMM_CHANNEL_INCOMING_SETUP:
23603deb3ec6SMatthias Ringwald             channel->state = RFCOMM_CHANNEL_SEND_DM;
236162b5b741SMatthias Ringwald             l2cap_request_can_send_now_event(channel->multiplexer->l2cap_cid);
23623deb3ec6SMatthias Ringwald             break;
23633deb3ec6SMatthias Ringwald         default:
23643deb3ec6SMatthias Ringwald             break;
23653deb3ec6SMatthias Ringwald     }
23663deb3ec6SMatthias Ringwald }
23673deb3ec6SMatthias Ringwald 
23683deb3ec6SMatthias Ringwald void rfcomm_grant_credits(uint16_t rfcomm_cid, uint8_t credits){
23693deb3ec6SMatthias Ringwald     log_info("RFCOMM_GRANT_CREDITS cid 0x%02x credits %u", rfcomm_cid, credits);
23703deb3ec6SMatthias Ringwald     rfcomm_channel_t * channel = rfcomm_channel_for_rfcomm_cid(rfcomm_cid);
23713deb3ec6SMatthias Ringwald     if (!channel) return;
23723deb3ec6SMatthias Ringwald     if (!channel->incoming_flow_control) return;
23733deb3ec6SMatthias Ringwald     channel->new_credits_incoming += credits;
23743deb3ec6SMatthias Ringwald 
23753deb3ec6SMatthias Ringwald     // process
237662b5b741SMatthias Ringwald     l2cap_request_can_send_now_event(channel->multiplexer->l2cap_cid);
23773deb3ec6SMatthias Ringwald }
23783deb3ec6SMatthias Ringwald 
23793deb3ec6SMatthias Ringwald 
2380b1c4ef5fSMatthias Ringwald /*
2381b1c4ef5fSMatthias Ringwald  * CRC (reversed crc) lookup table as calculated by the table generator in ETSI TS 101 369 V6.3.0.
2382b1c4ef5fSMatthias Ringwald  */
2383b1c4ef5fSMatthias Ringwald static const uint8_t crc8table[256] = {    /* reversed, 8-bit, poly=0x07 */
2384b1c4ef5fSMatthias Ringwald     0x00, 0x91, 0xE3, 0x72, 0x07, 0x96, 0xE4, 0x75, 0x0E, 0x9F, 0xED, 0x7C, 0x09, 0x98, 0xEA, 0x7B,
2385b1c4ef5fSMatthias Ringwald     0x1C, 0x8D, 0xFF, 0x6E, 0x1B, 0x8A, 0xF8, 0x69, 0x12, 0x83, 0xF1, 0x60, 0x15, 0x84, 0xF6, 0x67,
2386b1c4ef5fSMatthias Ringwald     0x38, 0xA9, 0xDB, 0x4A, 0x3F, 0xAE, 0xDC, 0x4D, 0x36, 0xA7, 0xD5, 0x44, 0x31, 0xA0, 0xD2, 0x43,
2387b1c4ef5fSMatthias Ringwald     0x24, 0xB5, 0xC7, 0x56, 0x23, 0xB2, 0xC0, 0x51, 0x2A, 0xBB, 0xC9, 0x58, 0x2D, 0xBC, 0xCE, 0x5F,
2388b1c4ef5fSMatthias Ringwald     0x70, 0xE1, 0x93, 0x02, 0x77, 0xE6, 0x94, 0x05, 0x7E, 0xEF, 0x9D, 0x0C, 0x79, 0xE8, 0x9A, 0x0B,
2389b1c4ef5fSMatthias Ringwald     0x6C, 0xFD, 0x8F, 0x1E, 0x6B, 0xFA, 0x88, 0x19, 0x62, 0xF3, 0x81, 0x10, 0x65, 0xF4, 0x86, 0x17,
2390b1c4ef5fSMatthias Ringwald     0x48, 0xD9, 0xAB, 0x3A, 0x4F, 0xDE, 0xAC, 0x3D, 0x46, 0xD7, 0xA5, 0x34, 0x41, 0xD0, 0xA2, 0x33,
2391b1c4ef5fSMatthias Ringwald     0x54, 0xC5, 0xB7, 0x26, 0x53, 0xC2, 0xB0, 0x21, 0x5A, 0xCB, 0xB9, 0x28, 0x5D, 0xCC, 0xBE, 0x2F,
2392b1c4ef5fSMatthias Ringwald     0xE0, 0x71, 0x03, 0x92, 0xE7, 0x76, 0x04, 0x95, 0xEE, 0x7F, 0x0D, 0x9C, 0xE9, 0x78, 0x0A, 0x9B,
2393b1c4ef5fSMatthias Ringwald     0xFC, 0x6D, 0x1F, 0x8E, 0xFB, 0x6A, 0x18, 0x89, 0xF2, 0x63, 0x11, 0x80, 0xF5, 0x64, 0x16, 0x87,
2394b1c4ef5fSMatthias Ringwald     0xD8, 0x49, 0x3B, 0xAA, 0xDF, 0x4E, 0x3C, 0xAD, 0xD6, 0x47, 0x35, 0xA4, 0xD1, 0x40, 0x32, 0xA3,
2395b1c4ef5fSMatthias Ringwald     0xC4, 0x55, 0x27, 0xB6, 0xC3, 0x52, 0x20, 0xB1, 0xCA, 0x5B, 0x29, 0xB8, 0xCD, 0x5C, 0x2E, 0xBF,
2396b1c4ef5fSMatthias Ringwald     0x90, 0x01, 0x73, 0xE2, 0x97, 0x06, 0x74, 0xE5, 0x9E, 0x0F, 0x7D, 0xEC, 0x99, 0x08, 0x7A, 0xEB,
2397b1c4ef5fSMatthias Ringwald     0x8C, 0x1D, 0x6F, 0xFE, 0x8B, 0x1A, 0x68, 0xF9, 0x82, 0x13, 0x61, 0xF0, 0x85, 0x14, 0x66, 0xF7,
2398b1c4ef5fSMatthias Ringwald     0xA8, 0x39, 0x4B, 0xDA, 0xAF, 0x3E, 0x4C, 0xDD, 0xA6, 0x37, 0x45, 0xD4, 0xA1, 0x30, 0x42, 0xD3,
2399b1c4ef5fSMatthias Ringwald     0xB4, 0x25, 0x57, 0xC6, 0xB3, 0x22, 0x50, 0xC1, 0xBA, 0x2B, 0x59, 0xC8, 0xBD, 0x2C, 0x5E, 0xCF
2400b1c4ef5fSMatthias Ringwald };
2401b1c4ef5fSMatthias Ringwald 
2402b1c4ef5fSMatthias Ringwald #define CRC8_INIT  0xFF          // Initial FCS value
2403b1c4ef5fSMatthias Ringwald #define CRC8_OK    0xCF          // Good final FCS value
2404b1c4ef5fSMatthias Ringwald /*-----------------------------------------------------------------------------------*/
2405b1c4ef5fSMatthias Ringwald static uint8_t crc8(uint8_t *data, uint16_t len)
2406b1c4ef5fSMatthias Ringwald {
2407b1c4ef5fSMatthias Ringwald     uint16_t count;
2408b1c4ef5fSMatthias Ringwald     uint8_t crc = CRC8_INIT;
2409b1c4ef5fSMatthias Ringwald     for (count = 0; count < len; count++)
2410b1c4ef5fSMatthias Ringwald         crc = crc8table[crc ^ data[count]];
2411b1c4ef5fSMatthias Ringwald     return crc;
2412b1c4ef5fSMatthias Ringwald }
2413b1c4ef5fSMatthias Ringwald 
2414b1c4ef5fSMatthias Ringwald /*-----------------------------------------------------------------------------------*/
2415b1c4ef5fSMatthias Ringwald uint8_t crc8_check(uint8_t *data, uint16_t len, uint8_t check_sum)
2416b1c4ef5fSMatthias Ringwald {
2417b1c4ef5fSMatthias Ringwald     uint8_t crc;
2418b1c4ef5fSMatthias Ringwald 
2419b1c4ef5fSMatthias Ringwald     crc = crc8(data, len);
2420b1c4ef5fSMatthias Ringwald 
2421b1c4ef5fSMatthias Ringwald     crc = crc8table[crc ^ check_sum];
2422b1c4ef5fSMatthias Ringwald     if (crc == CRC8_OK)
2423b1c4ef5fSMatthias Ringwald         return 0;               /* Valid */
2424b1c4ef5fSMatthias Ringwald     else
2425b1c4ef5fSMatthias Ringwald         return 1;               /* Failed */
2426b1c4ef5fSMatthias Ringwald 
2427b1c4ef5fSMatthias Ringwald }
2428b1c4ef5fSMatthias Ringwald 
2429b1c4ef5fSMatthias Ringwald /*-----------------------------------------------------------------------------------*/
2430b1c4ef5fSMatthias Ringwald uint8_t crc8_calc(uint8_t *data, uint16_t len)
2431b1c4ef5fSMatthias Ringwald {
2432b1c4ef5fSMatthias Ringwald     /* Ones complement */
2433b1c4ef5fSMatthias Ringwald     return 0xFF - crc8(data, len);
2434b1c4ef5fSMatthias Ringwald }
2435b1c4ef5fSMatthias Ringwald 
2436b1c4ef5fSMatthias Ringwald 
24373deb3ec6SMatthias Ringwald 
24383deb3ec6SMatthias Ringwald 
2439