xref: /btstack/src/classic/rfcomm.c (revision 225a2744a1f2ec36481cee820e162a3561a47bc1)
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);
1363deb3ec6SMatthias Ringwald static void rfcomm_channel_state_machine(rfcomm_channel_t *channel, rfcomm_channel_event_t *event);
1373deb3ec6SMatthias Ringwald static void rfcomm_channel_state_machine_2(rfcomm_multiplexer_t * multiplexer, uint8_t dlci, rfcomm_channel_event_t *event);
138b31d33b2SMatthias Ringwald static void rfcomm_emit_can_send_now(rfcomm_channel_t *channel);
1393deb3ec6SMatthias Ringwald static void rfcomm_multiplexer_state_machine(rfcomm_multiplexer_t * multiplexer, RFCOMM_MULTIPLEXER_EVENT event);
140b31d33b2SMatthias Ringwald static void rfcomm_run(void);
1413deb3ec6SMatthias Ringwald 
1423deb3ec6SMatthias Ringwald // MARK: RFCOMM CLIENT EVENTS
1433deb3ec6SMatthias Ringwald 
1443deb3ec6SMatthias Ringwald // data: event (8), len(8), address(48), channel (8), rfcomm_cid (16)
1453deb3ec6SMatthias Ringwald static void rfcomm_emit_connection_request(rfcomm_channel_t *channel) {
1463deb3ec6SMatthias Ringwald     log_info("RFCOMM_EVENT_INCOMING_CONNECTION addr %s channel #%u cid 0x%02x",
1473deb3ec6SMatthias Ringwald              bd_addr_to_str(channel->multiplexer->remote_addr), channel->dlci>>1, channel->rfcomm_cid);
1483deb3ec6SMatthias Ringwald     uint8_t event[11];
1493deb3ec6SMatthias Ringwald     event[0] = RFCOMM_EVENT_INCOMING_CONNECTION;
1503deb3ec6SMatthias Ringwald     event[1] = sizeof(event) - 2;
151724d70a2SMatthias Ringwald     reverse_bd_addr(channel->multiplexer->remote_addr, &event[2]);
1523deb3ec6SMatthias Ringwald     event[8] = channel->dlci >> 1;
153f8fbdce0SMatthias Ringwald     little_endian_store_16(event, 9, channel->rfcomm_cid);
1543deb3ec6SMatthias Ringwald     hci_dump_packet(HCI_EVENT_PACKET, 0, event, sizeof(event));
155b31d33b2SMatthias Ringwald 	(channel->packet_handler)(HCI_EVENT_PACKET, 0, event, sizeof(event));
1563deb3ec6SMatthias Ringwald }
1573deb3ec6SMatthias Ringwald 
1583deb3ec6SMatthias Ringwald // API Change: BTstack-0.3.50x uses
1593deb3ec6SMatthias Ringwald // data: event(8), len(8), status (8), address (48), server channel(8), rfcomm_cid(16), max frame size(16)
1603deb3ec6SMatthias Ringwald // next Cydia release will use SVN version of this
1613deb3ec6SMatthias Ringwald // data: event(8), len(8), status (8), address (48), handle (16), server channel(8), rfcomm_cid(16), max frame size(16)
1623deb3ec6SMatthias Ringwald static void rfcomm_emit_channel_opened(rfcomm_channel_t *channel, uint8_t status) {
1633deb3ec6SMatthias Ringwald     log_info("RFCOMM_EVENT_OPEN_CHANNEL_COMPLETE status 0x%x addr %s handle 0x%x channel #%u cid 0x%02x mtu %u",
1643deb3ec6SMatthias Ringwald              status, bd_addr_to_str(channel->multiplexer->remote_addr), channel->multiplexer->con_handle,
1653deb3ec6SMatthias Ringwald              channel->dlci>>1, channel->rfcomm_cid, channel->max_frame_size);
1663deb3ec6SMatthias Ringwald     uint8_t event[16];
1673deb3ec6SMatthias Ringwald     uint8_t pos = 0;
1685d1e858fSMatthias Ringwald     event[pos++] = RFCOMM_EVENT_OPEN_CHANNEL_COMPLETE;  // 0
1695d1e858fSMatthias Ringwald     event[pos++] = sizeof(event) - 2;                   // 1
1705d1e858fSMatthias Ringwald     event[pos++] = status;                              // 2
171724d70a2SMatthias Ringwald     reverse_bd_addr(channel->multiplexer->remote_addr, &event[pos]); pos += 6; // 3
172f8fbdce0SMatthias Ringwald     little_endian_store_16(event,  pos, channel->multiplexer->con_handle);   pos += 2; // 9
1735d1e858fSMatthias Ringwald 	event[pos++] = channel->dlci >> 1;                                      // 11
174f8fbdce0SMatthias Ringwald 	little_endian_store_16(event, pos, channel->rfcomm_cid); pos += 2;                 // 12 - channel ID
175f8fbdce0SMatthias Ringwald 	little_endian_store_16(event, pos, channel->max_frame_size); pos += 2;   // max frame size
1763deb3ec6SMatthias Ringwald     hci_dump_packet(HCI_EVENT_PACKET, 0, event, sizeof(event));
177b31d33b2SMatthias Ringwald 	(channel->packet_handler)(HCI_EVENT_PACKET, 0, event, pos);
178b31d33b2SMatthias Ringwald 
179b31d33b2SMatthias Ringwald     // if channel opened successfully, also send can send now if possible
180b31d33b2SMatthias Ringwald     if (status) return;
181b31d33b2SMatthias Ringwald     if (rfcomm_channel_can_send(channel)){
182b31d33b2SMatthias Ringwald         rfcomm_emit_can_send_now(channel);
183b31d33b2SMatthias Ringwald     } else {
184b31d33b2SMatthias Ringwald         channel->waiting_for_can_send_now = 1;
185b31d33b2SMatthias Ringwald     }
1863deb3ec6SMatthias Ringwald }
1873deb3ec6SMatthias Ringwald 
1883deb3ec6SMatthias Ringwald // data: event(8), len(8), rfcomm_cid(16)
1893deb3ec6SMatthias Ringwald static void rfcomm_emit_channel_closed(rfcomm_channel_t * channel) {
1903deb3ec6SMatthias Ringwald     log_info("RFCOMM_EVENT_CHANNEL_CLOSED cid 0x%02x", channel->rfcomm_cid);
1913deb3ec6SMatthias Ringwald     uint8_t event[4];
1923deb3ec6SMatthias Ringwald     event[0] = RFCOMM_EVENT_CHANNEL_CLOSED;
1933deb3ec6SMatthias Ringwald     event[1] = sizeof(event) - 2;
194f8fbdce0SMatthias Ringwald     little_endian_store_16(event, 2, channel->rfcomm_cid);
1953deb3ec6SMatthias Ringwald     hci_dump_packet(HCI_EVENT_PACKET, 0, event, sizeof(event));
196b31d33b2SMatthias Ringwald 	(channel->packet_handler)(HCI_EVENT_PACKET, 0, event, sizeof(event));
1973deb3ec6SMatthias Ringwald }
1983deb3ec6SMatthias Ringwald 
1993deb3ec6SMatthias Ringwald static void rfcomm_emit_remote_line_status(rfcomm_channel_t *channel, uint8_t line_status){
2003deb3ec6SMatthias Ringwald     log_info("RFCOMM_EVENT_REMOTE_LINE_STATUS cid 0x%02x c, line status 0x%x", channel->rfcomm_cid, line_status);
2013deb3ec6SMatthias Ringwald     uint8_t event[5];
2023deb3ec6SMatthias Ringwald     event[0] = RFCOMM_EVENT_REMOTE_LINE_STATUS;
2033deb3ec6SMatthias Ringwald     event[1] = sizeof(event) - 2;
204f8fbdce0SMatthias Ringwald     little_endian_store_16(event, 2, channel->rfcomm_cid);
2053deb3ec6SMatthias Ringwald     event[4] = line_status;
2063deb3ec6SMatthias Ringwald     hci_dump_packet( HCI_EVENT_PACKET, 0, event, sizeof(event));
207b31d33b2SMatthias Ringwald     (channel->packet_handler)(HCI_EVENT_PACKET, 0, event, sizeof(event));
2083deb3ec6SMatthias Ringwald }
2093deb3ec6SMatthias Ringwald 
2103deb3ec6SMatthias Ringwald static void rfcomm_emit_port_configuration(rfcomm_channel_t *channel){
2113deb3ec6SMatthias Ringwald     // notify client about new settings
2123deb3ec6SMatthias Ringwald     uint8_t event[2+sizeof(rfcomm_rpn_data_t)];
2133deb3ec6SMatthias Ringwald     event[0] = RFCOMM_EVENT_PORT_CONFIGURATION;
2143deb3ec6SMatthias Ringwald     event[1] = sizeof(rfcomm_rpn_data_t);
2153deb3ec6SMatthias Ringwald     memcpy(&event[2], (uint8_t*) &channel->rpn_data, sizeof(rfcomm_rpn_data_t));
2163deb3ec6SMatthias Ringwald     hci_dump_packet( HCI_EVENT_PACKET, 0, event, sizeof(event));
217b31d33b2SMatthias Ringwald     (channel->packet_handler)(HCI_EVENT_PACKET, channel->rfcomm_cid, event, sizeof(event));
218b31d33b2SMatthias Ringwald }
219b31d33b2SMatthias Ringwald 
220b31d33b2SMatthias Ringwald static void rfcomm_emit_can_send_now(rfcomm_channel_t *channel) {
221b31d33b2SMatthias Ringwald     log_info("RFCOMM_EVENT_CHANNEL_CAN_SEND_NOW local_cid 0x%x", channel->rfcomm_cid);
222b31d33b2SMatthias Ringwald     uint8_t event[4];
223b31d33b2SMatthias Ringwald     event[0] = RFCOMM_EVENT_CAN_SEND_NOW;
224b31d33b2SMatthias Ringwald     event[1] = sizeof(event) - 2;
225b31d33b2SMatthias Ringwald     little_endian_store_16(event, 2, channel->rfcomm_cid);
226b31d33b2SMatthias Ringwald     hci_dump_packet( HCI_EVENT_PACKET, 0, event, sizeof(event));
227b31d33b2SMatthias Ringwald     (channel->packet_handler)(HCI_EVENT_PACKET, channel->rfcomm_cid, event, sizeof(event));
2283deb3ec6SMatthias Ringwald }
2293deb3ec6SMatthias Ringwald 
2303deb3ec6SMatthias Ringwald // MARK RFCOMM RPN DATA HELPER
2313deb3ec6SMatthias Ringwald static void rfcomm_rpn_data_set_defaults(rfcomm_rpn_data_t * rpn_data){
2323deb3ec6SMatthias Ringwald         rpn_data->baud_rate = RPN_BAUD_9600;  /* 9600 bps */
2333deb3ec6SMatthias Ringwald         rpn_data->flags = 0x03;               /* 8-n-1 */
2343deb3ec6SMatthias Ringwald         rpn_data->flow_control = 0;           /* no flow control */
2353deb3ec6SMatthias Ringwald         rpn_data->xon  = 0xd1;                /* XON */
2363deb3ec6SMatthias Ringwald         rpn_data->xoff = 0xd3;                /* XOFF */
2373deb3ec6SMatthias Ringwald         rpn_data->parameter_mask_0 = 0x7f;    /* parameter mask, all values set */
2383deb3ec6SMatthias Ringwald         rpn_data->parameter_mask_1 = 0x3f;    /* parameter mask, all values set */
2393deb3ec6SMatthias Ringwald }
2403deb3ec6SMatthias Ringwald 
2413deb3ec6SMatthias Ringwald static void rfcomm_rpn_data_update(rfcomm_rpn_data_t * dest, rfcomm_rpn_data_t * src){
2423deb3ec6SMatthias Ringwald     if (src->parameter_mask_0 & RPN_PARAM_MASK_0_BAUD){
2433deb3ec6SMatthias Ringwald         dest->baud_rate = src->baud_rate;
2443deb3ec6SMatthias Ringwald     }
2453deb3ec6SMatthias Ringwald     if (src->parameter_mask_0 & RPN_PARAM_MASK_0_DATA_BITS){
2463deb3ec6SMatthias Ringwald         dest->flags = (dest->flags & 0xfc) | (src->flags & 0x03);
2473deb3ec6SMatthias Ringwald     }
2483deb3ec6SMatthias Ringwald     if (src->parameter_mask_0 & RPN_PARAM_MASK_0_STOP_BITS){
2493deb3ec6SMatthias Ringwald         dest->flags = (dest->flags & 0xfb) | (src->flags & 0x04);
2503deb3ec6SMatthias Ringwald     }
2513deb3ec6SMatthias Ringwald     if (src->parameter_mask_0 & RPN_PARAM_MASK_0_PARITY){
2523deb3ec6SMatthias Ringwald         dest->flags = (dest->flags & 0xf7) | (src->flags & 0x08);
2533deb3ec6SMatthias Ringwald     }
2543deb3ec6SMatthias Ringwald     if (src->parameter_mask_0 & RPN_PARAM_MASK_0_PARITY_TYPE){
2553deb3ec6SMatthias Ringwald         dest->flags = (dest->flags & 0xfc) | (src->flags & 0x30);
2563deb3ec6SMatthias Ringwald     }
2573deb3ec6SMatthias Ringwald     if (src->parameter_mask_0 & RPN_PARAM_MASK_0_XON_CHAR){
2583deb3ec6SMatthias Ringwald         dest->xon = src->xon;
2593deb3ec6SMatthias Ringwald     }
2603deb3ec6SMatthias Ringwald     if (src->parameter_mask_0 & RPN_PARAM_MASK_0_XOFF_CHAR){
2613deb3ec6SMatthias Ringwald         dest->xoff = src->xoff;
2623deb3ec6SMatthias Ringwald     }
2633deb3ec6SMatthias Ringwald     int i;
2643deb3ec6SMatthias Ringwald     for (i=0; i < 6 ; i++){
2653deb3ec6SMatthias Ringwald         uint8_t mask = 1 << i;
2663deb3ec6SMatthias Ringwald         if (src->parameter_mask_1 & mask){
2673deb3ec6SMatthias Ringwald             dest->flags = (dest->flags & ~mask) | (src->flags & mask);
2683deb3ec6SMatthias Ringwald         }
2693deb3ec6SMatthias Ringwald     }
2703deb3ec6SMatthias Ringwald     // always copy parameter mask, too. informative for client, needed for response
2713deb3ec6SMatthias Ringwald     dest->parameter_mask_0 = src->parameter_mask_0;
2723deb3ec6SMatthias Ringwald     dest->parameter_mask_1 = src->parameter_mask_1;
2733deb3ec6SMatthias Ringwald }
2743deb3ec6SMatthias Ringwald // MARK: RFCOMM MULTIPLEXER HELPER
2753deb3ec6SMatthias Ringwald 
2763deb3ec6SMatthias Ringwald static uint16_t rfcomm_max_frame_size_for_l2cap_mtu(uint16_t l2cap_mtu){
2773deb3ec6SMatthias Ringwald     // Assume RFCOMM header without credits and 2 byte (14 bit) length field
2783deb3ec6SMatthias Ringwald     uint16_t max_frame_size = l2cap_mtu - 5;
2793deb3ec6SMatthias Ringwald     log_info("rfcomm_max_frame_size_for_l2cap_mtu:  %u -> %u", l2cap_mtu, max_frame_size);
2803deb3ec6SMatthias Ringwald     return max_frame_size;
2813deb3ec6SMatthias Ringwald }
2823deb3ec6SMatthias Ringwald 
2833deb3ec6SMatthias Ringwald static void rfcomm_multiplexer_initialize(rfcomm_multiplexer_t *multiplexer){
2843deb3ec6SMatthias Ringwald 
2853deb3ec6SMatthias Ringwald     memset(multiplexer, 0, sizeof(rfcomm_multiplexer_t));
2863deb3ec6SMatthias Ringwald 
2873deb3ec6SMatthias Ringwald     multiplexer->state = RFCOMM_MULTIPLEXER_CLOSED;
2883deb3ec6SMatthias Ringwald     multiplexer->fcon = 1;
2893deb3ec6SMatthias Ringwald     multiplexer->send_dm_for_dlci = 0;
2903deb3ec6SMatthias Ringwald     multiplexer->max_frame_size = rfcomm_max_frame_size_for_l2cap_mtu(l2cap_max_mtu());
2913deb3ec6SMatthias Ringwald     multiplexer->test_data_len = 0;
2923deb3ec6SMatthias Ringwald     multiplexer->nsc_command = 0;
2933deb3ec6SMatthias Ringwald }
2943deb3ec6SMatthias Ringwald 
2953deb3ec6SMatthias Ringwald static rfcomm_multiplexer_t * rfcomm_multiplexer_create_for_addr(bd_addr_t addr){
2963deb3ec6SMatthias Ringwald 
2973deb3ec6SMatthias Ringwald     // alloc structure
2983deb3ec6SMatthias Ringwald     rfcomm_multiplexer_t * multiplexer = btstack_memory_rfcomm_multiplexer_get();
2993deb3ec6SMatthias Ringwald     if (!multiplexer) return NULL;
3003deb3ec6SMatthias Ringwald 
3013deb3ec6SMatthias Ringwald     // fill in
3023deb3ec6SMatthias Ringwald     rfcomm_multiplexer_initialize(multiplexer);
30373988a59SMatthias Ringwald     bd_addr_copy(multiplexer->remote_addr, addr);
3043deb3ec6SMatthias Ringwald 
3053deb3ec6SMatthias Ringwald     // add to services list
306665d90f2SMatthias Ringwald     btstack_linked_list_add(&rfcomm_multiplexers, (btstack_linked_item_t *) multiplexer);
3073deb3ec6SMatthias Ringwald 
3083deb3ec6SMatthias Ringwald     return multiplexer;
3093deb3ec6SMatthias Ringwald }
3103deb3ec6SMatthias Ringwald 
3113deb3ec6SMatthias Ringwald static rfcomm_multiplexer_t * rfcomm_multiplexer_for_addr(bd_addr_t addr){
312665d90f2SMatthias Ringwald     btstack_linked_item_t *it;
313665d90f2SMatthias Ringwald     for (it = (btstack_linked_item_t *) rfcomm_multiplexers; it ; it = it->next){
3143deb3ec6SMatthias Ringwald         rfcomm_multiplexer_t * multiplexer = ((rfcomm_multiplexer_t *) it);
315058e3d6bSMatthias Ringwald         if (bd_addr_cmp(addr, multiplexer->remote_addr) == 0) {
3163deb3ec6SMatthias Ringwald             return multiplexer;
3173deb3ec6SMatthias Ringwald         };
3183deb3ec6SMatthias Ringwald     }
3193deb3ec6SMatthias Ringwald     return NULL;
3203deb3ec6SMatthias Ringwald }
3213deb3ec6SMatthias Ringwald 
3223deb3ec6SMatthias Ringwald static rfcomm_multiplexer_t * rfcomm_multiplexer_for_l2cap_cid(uint16_t l2cap_cid) {
323665d90f2SMatthias Ringwald     btstack_linked_item_t *it;
324665d90f2SMatthias Ringwald     for (it = (btstack_linked_item_t *) rfcomm_multiplexers; it ; it = it->next){
3253deb3ec6SMatthias Ringwald         rfcomm_multiplexer_t * multiplexer = ((rfcomm_multiplexer_t *) it);
3263deb3ec6SMatthias Ringwald         if (multiplexer->l2cap_cid == l2cap_cid) {
3273deb3ec6SMatthias Ringwald             return multiplexer;
3283deb3ec6SMatthias Ringwald         };
3293deb3ec6SMatthias Ringwald     }
3303deb3ec6SMatthias Ringwald     return NULL;
3313deb3ec6SMatthias Ringwald }
3323deb3ec6SMatthias Ringwald 
3333deb3ec6SMatthias Ringwald static int rfcomm_multiplexer_has_channels(rfcomm_multiplexer_t * multiplexer){
334665d90f2SMatthias Ringwald     btstack_linked_item_t *it;
335665d90f2SMatthias Ringwald     for (it = (btstack_linked_item_t *) rfcomm_channels; it ; it = it->next){
3363deb3ec6SMatthias Ringwald         rfcomm_channel_t * channel = ((rfcomm_channel_t *) it);
3373deb3ec6SMatthias Ringwald         if (channel->multiplexer == multiplexer) {
3383deb3ec6SMatthias Ringwald             return 1;
3393deb3ec6SMatthias Ringwald         }
3403deb3ec6SMatthias Ringwald     }
3413deb3ec6SMatthias Ringwald     return 0;
3423deb3ec6SMatthias Ringwald }
3433deb3ec6SMatthias Ringwald 
3443deb3ec6SMatthias Ringwald // MARK: RFCOMM CHANNEL HELPER
3453deb3ec6SMatthias Ringwald 
3463deb3ec6SMatthias Ringwald static void rfcomm_dump_channels(void){
347665d90f2SMatthias Ringwald     btstack_linked_item_t * it;
3483deb3ec6SMatthias Ringwald     int channels = 0;
349665d90f2SMatthias Ringwald     for (it = (btstack_linked_item_t *) rfcomm_channels; it ; it = it->next){
3503deb3ec6SMatthias Ringwald         rfcomm_channel_t * channel = (rfcomm_channel_t *) it;
3513deb3ec6SMatthias Ringwald         log_info("Channel #%u: addr %p, state %u", channels, channel, channel->state);
3523deb3ec6SMatthias Ringwald         channels++;
3533deb3ec6SMatthias Ringwald     }
3543deb3ec6SMatthias Ringwald }
3553deb3ec6SMatthias Ringwald 
3563deb3ec6SMatthias Ringwald static void rfcomm_channel_initialize(rfcomm_channel_t *channel, rfcomm_multiplexer_t *multiplexer,
3573deb3ec6SMatthias Ringwald                                rfcomm_service_t *service, uint8_t server_channel){
3583deb3ec6SMatthias Ringwald 
3593deb3ec6SMatthias Ringwald     // don't use 0 as channel id
3603deb3ec6SMatthias Ringwald     if (rfcomm_client_cid_generator == 0) ++rfcomm_client_cid_generator;
3613deb3ec6SMatthias Ringwald 
3623deb3ec6SMatthias Ringwald     // setup channel
3633deb3ec6SMatthias Ringwald     memset(channel, 0, sizeof(rfcomm_channel_t));
3643deb3ec6SMatthias Ringwald 
365ccb8ddfbSMatthias Ringwald     // set defaults for port configuration (even for services)
366ccb8ddfbSMatthias Ringwald     rfcomm_rpn_data_set_defaults(&channel->rpn_data);
367ccb8ddfbSMatthias Ringwald 
3683deb3ec6SMatthias Ringwald     channel->state            = RFCOMM_CHANNEL_CLOSED;
3693deb3ec6SMatthias Ringwald     channel->state_var        = RFCOMM_CHANNEL_STATE_VAR_NONE;
3703deb3ec6SMatthias Ringwald 
3713deb3ec6SMatthias Ringwald     channel->multiplexer      = multiplexer;
3723deb3ec6SMatthias Ringwald     channel->rfcomm_cid       = rfcomm_client_cid_generator++;
3733deb3ec6SMatthias Ringwald     channel->max_frame_size   = multiplexer->max_frame_size;
3743deb3ec6SMatthias Ringwald 
3753deb3ec6SMatthias Ringwald     channel->credits_incoming = 0;
3763deb3ec6SMatthias Ringwald     channel->credits_outgoing = 0;
3773deb3ec6SMatthias Ringwald 
3783deb3ec6SMatthias Ringwald     // incoming flow control not active
3793deb3ec6SMatthias Ringwald     channel->new_credits_incoming  = RFCOMM_CREDITS;
3803deb3ec6SMatthias Ringwald     channel->incoming_flow_control = 0;
3813deb3ec6SMatthias Ringwald 
3823deb3ec6SMatthias Ringwald     channel->rls_line_status       = RFCOMM_RLS_STATUS_INVALID;
3833deb3ec6SMatthias Ringwald 
384ccb8ddfbSMatthias Ringwald     channel->service = service;
3853deb3ec6SMatthias Ringwald 	if (service) {
3863deb3ec6SMatthias Ringwald 		// incoming connection
3873deb3ec6SMatthias Ringwald     	channel->dlci = (server_channel << 1) |  multiplexer->outgoing;
3883deb3ec6SMatthias Ringwald         if (channel->max_frame_size > service->max_frame_size) {
3893deb3ec6SMatthias Ringwald             channel->max_frame_size = service->max_frame_size;
3903deb3ec6SMatthias Ringwald         }
3913deb3ec6SMatthias Ringwald         channel->incoming_flow_control = service->incoming_flow_control;
3923deb3ec6SMatthias Ringwald         channel->new_credits_incoming  = service->incoming_initial_credits;
393ccb8ddfbSMatthias Ringwald         channel->packet_handler        = service->packet_handler;
3943deb3ec6SMatthias Ringwald 	} else {
3953deb3ec6SMatthias Ringwald 		// outgoing connection
3963deb3ec6SMatthias Ringwald 		channel->dlci = (server_channel << 1) | (multiplexer->outgoing ^ 1);
3973deb3ec6SMatthias Ringwald 	}
3983deb3ec6SMatthias Ringwald }
3993deb3ec6SMatthias Ringwald 
4003deb3ec6SMatthias Ringwald // service == NULL -> outgoing channel
4013deb3ec6SMatthias Ringwald static rfcomm_channel_t * rfcomm_channel_create(rfcomm_multiplexer_t * multiplexer,
4023deb3ec6SMatthias Ringwald                                                 rfcomm_service_t * service, uint8_t server_channel){
4033deb3ec6SMatthias Ringwald 
4043deb3ec6SMatthias Ringwald     log_info("rfcomm_channel_create for service %p, channel %u --- list of channels:", service, server_channel);
4053deb3ec6SMatthias Ringwald     rfcomm_dump_channels();
4063deb3ec6SMatthias Ringwald 
4073deb3ec6SMatthias Ringwald     // alloc structure
4083deb3ec6SMatthias Ringwald     rfcomm_channel_t * channel = btstack_memory_rfcomm_channel_get();
4093deb3ec6SMatthias Ringwald     if (!channel) return NULL;
4103deb3ec6SMatthias Ringwald 
4113deb3ec6SMatthias Ringwald     // fill in
4123deb3ec6SMatthias Ringwald     rfcomm_channel_initialize(channel, multiplexer, service, server_channel);
4133deb3ec6SMatthias Ringwald 
4143deb3ec6SMatthias Ringwald     // add to services list
415665d90f2SMatthias Ringwald     btstack_linked_list_add(&rfcomm_channels, (btstack_linked_item_t *) channel);
4163deb3ec6SMatthias Ringwald 
4173deb3ec6SMatthias Ringwald     return channel;
4183deb3ec6SMatthias Ringwald }
4193deb3ec6SMatthias Ringwald 
420b31d33b2SMatthias Ringwald static void rfcomm_notify_channel_can_send(void){
421b31d33b2SMatthias Ringwald     btstack_linked_list_iterator_t it;
422b31d33b2SMatthias Ringwald     btstack_linked_list_iterator_init(&it, &rfcomm_channels);
423b31d33b2SMatthias Ringwald     while (btstack_linked_list_iterator_has_next(&it)){
424b31d33b2SMatthias Ringwald         rfcomm_channel_t * channel = (rfcomm_channel_t *) btstack_linked_list_iterator_next(&it);
425b31d33b2SMatthias Ringwald         if (!channel->waiting_for_can_send_now) continue; // didn't try to send yet
426b31d33b2SMatthias Ringwald         if (!rfcomm_channel_can_send(channel)) continue;  // or cannot yet either
427b31d33b2SMatthias Ringwald 
428b31d33b2SMatthias Ringwald         channel->waiting_for_can_send_now = 0;
429b31d33b2SMatthias Ringwald         rfcomm_emit_can_send_now(channel);
430b31d33b2SMatthias Ringwald     }
431b31d33b2SMatthias Ringwald }
432b31d33b2SMatthias Ringwald 
4333deb3ec6SMatthias Ringwald static rfcomm_channel_t * rfcomm_channel_for_rfcomm_cid(uint16_t rfcomm_cid){
434665d90f2SMatthias Ringwald     btstack_linked_item_t *it;
435665d90f2SMatthias Ringwald     for (it = (btstack_linked_item_t *) rfcomm_channels; it ; it = it->next){
4363deb3ec6SMatthias Ringwald         rfcomm_channel_t * channel = ((rfcomm_channel_t *) it);
4373deb3ec6SMatthias Ringwald         if (channel->rfcomm_cid == rfcomm_cid) {
4383deb3ec6SMatthias Ringwald             return channel;
4393deb3ec6SMatthias Ringwald         };
4403deb3ec6SMatthias Ringwald     }
4413deb3ec6SMatthias Ringwald     return NULL;
4423deb3ec6SMatthias Ringwald }
4433deb3ec6SMatthias Ringwald 
4443deb3ec6SMatthias Ringwald static rfcomm_channel_t * rfcomm_channel_for_multiplexer_and_dlci(rfcomm_multiplexer_t * multiplexer, uint8_t dlci){
445665d90f2SMatthias Ringwald     btstack_linked_item_t *it;
446665d90f2SMatthias Ringwald     for (it = (btstack_linked_item_t *) rfcomm_channels; it ; it = it->next){
4473deb3ec6SMatthias Ringwald         rfcomm_channel_t * channel = ((rfcomm_channel_t *) it);
4483deb3ec6SMatthias Ringwald         if (channel->dlci == dlci && channel->multiplexer == multiplexer) {
4493deb3ec6SMatthias Ringwald             return channel;
4503deb3ec6SMatthias Ringwald         };
4513deb3ec6SMatthias Ringwald     }
4523deb3ec6SMatthias Ringwald     return NULL;
4533deb3ec6SMatthias Ringwald }
4543deb3ec6SMatthias Ringwald 
4553deb3ec6SMatthias Ringwald static rfcomm_service_t * rfcomm_service_for_channel(uint8_t server_channel){
456665d90f2SMatthias Ringwald     btstack_linked_item_t *it;
457665d90f2SMatthias Ringwald     for (it = (btstack_linked_item_t *) rfcomm_services; it ; it = it->next){
4583deb3ec6SMatthias Ringwald         rfcomm_service_t * service = ((rfcomm_service_t *) it);
4593deb3ec6SMatthias Ringwald         if ( service->server_channel == server_channel){
4603deb3ec6SMatthias Ringwald             return service;
4613deb3ec6SMatthias Ringwald         };
4623deb3ec6SMatthias Ringwald     }
4633deb3ec6SMatthias Ringwald     return NULL;
4643deb3ec6SMatthias Ringwald }
4653deb3ec6SMatthias Ringwald 
4663deb3ec6SMatthias Ringwald // MARK: RFCOMM SEND
4673deb3ec6SMatthias Ringwald 
4683deb3ec6SMatthias Ringwald /**
4693deb3ec6SMatthias Ringwald  * @param credits - only used for RFCOMM flow control in UIH wiht P/F = 1
4703deb3ec6SMatthias Ringwald  */
4713deb3ec6SMatthias 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){
4723deb3ec6SMatthias Ringwald 
4733deb3ec6SMatthias Ringwald     if (!l2cap_can_send_packet_now(multiplexer->l2cap_cid)) return BTSTACK_ACL_BUFFERS_FULL;
4743deb3ec6SMatthias Ringwald 
4753deb3ec6SMatthias Ringwald     l2cap_reserve_packet_buffer();
4763deb3ec6SMatthias Ringwald     uint8_t * rfcomm_out_buffer = l2cap_get_outgoing_buffer();
4773deb3ec6SMatthias Ringwald 
4783deb3ec6SMatthias Ringwald 	uint16_t pos = 0;
4793deb3ec6SMatthias Ringwald 	uint8_t crc_fields = 3;
4803deb3ec6SMatthias Ringwald 
4813deb3ec6SMatthias Ringwald 	rfcomm_out_buffer[pos++] = address;
4823deb3ec6SMatthias Ringwald 	rfcomm_out_buffer[pos++] = control;
4833deb3ec6SMatthias Ringwald 
4843deb3ec6SMatthias Ringwald 	// length field can be 1 or 2 octets
4853deb3ec6SMatthias Ringwald 	if (len < 128){
4863deb3ec6SMatthias Ringwald 		rfcomm_out_buffer[pos++] = (len << 1)| 1;     // bits 0-6
4873deb3ec6SMatthias Ringwald 	} else {
4883deb3ec6SMatthias Ringwald 		rfcomm_out_buffer[pos++] = (len & 0x7f) << 1; // bits 0-6
4893deb3ec6SMatthias Ringwald 		rfcomm_out_buffer[pos++] = len >> 7;          // bits 7-14
4903deb3ec6SMatthias Ringwald 		crc_fields++;
4913deb3ec6SMatthias Ringwald 	}
4923deb3ec6SMatthias Ringwald 
4933deb3ec6SMatthias Ringwald 	// add credits for UIH frames when PF bit is set
4943deb3ec6SMatthias Ringwald 	if (control == BT_RFCOMM_UIH_PF){
4953deb3ec6SMatthias Ringwald 		rfcomm_out_buffer[pos++] = credits;
4963deb3ec6SMatthias Ringwald 	}
4973deb3ec6SMatthias Ringwald 
4983deb3ec6SMatthias Ringwald 	// copy actual data
4993deb3ec6SMatthias Ringwald 	if (len) {
5003deb3ec6SMatthias Ringwald 		memcpy(&rfcomm_out_buffer[pos], data, len);
5013deb3ec6SMatthias Ringwald 		pos += len;
5023deb3ec6SMatthias Ringwald 	}
5033deb3ec6SMatthias Ringwald 
5043deb3ec6SMatthias Ringwald 	// UIH frames only calc FCS over address + control (5.1.1)
5053deb3ec6SMatthias Ringwald 	if ((control & 0xef) == BT_RFCOMM_UIH){
5063deb3ec6SMatthias Ringwald 		crc_fields = 2;
5073deb3ec6SMatthias Ringwald 	}
5083deb3ec6SMatthias Ringwald 	rfcomm_out_buffer[pos++] =  crc8_calc(rfcomm_out_buffer, crc_fields); // calc fcs
5093deb3ec6SMatthias Ringwald 
5103deb3ec6SMatthias Ringwald     int err = l2cap_send_prepared(multiplexer->l2cap_cid, pos);
5113deb3ec6SMatthias Ringwald 
5123deb3ec6SMatthias Ringwald     return err;
5133deb3ec6SMatthias Ringwald }
5143deb3ec6SMatthias Ringwald 
5153deb3ec6SMatthias Ringwald // simplified version of rfcomm_send_packet_for_multiplexer for prepared rfcomm packet (UIH, 2 byte len, no credits)
5163deb3ec6SMatthias Ringwald static int rfcomm_send_uih_prepared(rfcomm_multiplexer_t *multiplexer, uint8_t dlci, uint16_t len){
5173deb3ec6SMatthias Ringwald 
5183deb3ec6SMatthias Ringwald     uint8_t address = (1 << 0) | (multiplexer->outgoing << 1) | (dlci << 2);
5193deb3ec6SMatthias Ringwald     uint8_t control = BT_RFCOMM_UIH;
5203deb3ec6SMatthias Ringwald 
5213deb3ec6SMatthias Ringwald     uint8_t * rfcomm_out_buffer = l2cap_get_outgoing_buffer();
5223deb3ec6SMatthias Ringwald 
5233deb3ec6SMatthias Ringwald     uint16_t pos = 0;
5243deb3ec6SMatthias Ringwald     rfcomm_out_buffer[pos++] = address;
5253deb3ec6SMatthias Ringwald     rfcomm_out_buffer[pos++] = control;
5263deb3ec6SMatthias Ringwald     rfcomm_out_buffer[pos++] = (len & 0x7f) << 1; // bits 0-6
5273deb3ec6SMatthias Ringwald     rfcomm_out_buffer[pos++] = len >> 7;          // bits 7-14
5283deb3ec6SMatthias Ringwald 
5293deb3ec6SMatthias Ringwald     // actual data is already in place
5303deb3ec6SMatthias Ringwald     pos += len;
5313deb3ec6SMatthias Ringwald 
5323deb3ec6SMatthias Ringwald     // UIH frames only calc FCS over address + control (5.1.1)
5333deb3ec6SMatthias Ringwald     rfcomm_out_buffer[pos++] =  crc8_calc(rfcomm_out_buffer, 2); // calc fcs
5343deb3ec6SMatthias Ringwald 
5353deb3ec6SMatthias Ringwald     int err = l2cap_send_prepared(multiplexer->l2cap_cid, pos);
5363deb3ec6SMatthias Ringwald 
5373deb3ec6SMatthias Ringwald     return err;
5383deb3ec6SMatthias Ringwald }
5393deb3ec6SMatthias Ringwald 
5403deb3ec6SMatthias Ringwald // C/R Flag in Address
5413deb3ec6SMatthias Ringwald // - terms: initiator = station that creates multiplexer with SABM
5423deb3ec6SMatthias Ringwald // - terms: responder = station that responds to multiplexer setup with UA
5433deb3ec6SMatthias 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"
5443deb3ec6SMatthias Ringwald //    - command initiator = 1 /response responder = 1
5453deb3ec6SMatthias Ringwald //    - command responder = 0 /response initiator = 0
5463deb3ec6SMatthias Ringwald // "For UIH frames, the C/R bit is always set according to section 5.4.3.1 in GSM 07.10.
5473deb3ec6SMatthias Ringwald //  This applies independently of what is contained wthin the UIH frames, either data or control messages."
5483deb3ec6SMatthias Ringwald //    - c/r = 1 for frames by initiating station, 0 = for frames by responding station
5493deb3ec6SMatthias Ringwald 
5503deb3ec6SMatthias Ringwald // C/R Flag in Message
5513deb3ec6SMatthias 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."
5523deb3ec6SMatthias Ringwald //   - If the C/R bit is set to 1 the message is a command
5533deb3ec6SMatthias Ringwald //   - if it is set to 0 the message is a response.
5543deb3ec6SMatthias Ringwald 
5553deb3ec6SMatthias Ringwald // temp/old messge construction
5563deb3ec6SMatthias Ringwald 
5573deb3ec6SMatthias Ringwald // new object oriented version
5583deb3ec6SMatthias Ringwald static int rfcomm_send_sabm(rfcomm_multiplexer_t *multiplexer, uint8_t dlci){
5593deb3ec6SMatthias Ringwald 	uint8_t address = (1 << 0) | (multiplexer->outgoing << 1) | (dlci << 2);   // command
5603deb3ec6SMatthias Ringwald     return rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_SABM, 0, NULL, 0);
5613deb3ec6SMatthias Ringwald }
5623deb3ec6SMatthias Ringwald 
5633deb3ec6SMatthias Ringwald static int rfcomm_send_disc(rfcomm_multiplexer_t *multiplexer, uint8_t dlci){
5643deb3ec6SMatthias Ringwald 	uint8_t address = (1 << 0) | (multiplexer->outgoing << 1) | (dlci << 2);  // command
5653deb3ec6SMatthias Ringwald     return rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_DISC, 0, NULL, 0);
5663deb3ec6SMatthias Ringwald }
5673deb3ec6SMatthias Ringwald 
5683deb3ec6SMatthias Ringwald static int rfcomm_send_ua(rfcomm_multiplexer_t *multiplexer, uint8_t dlci){
5693deb3ec6SMatthias Ringwald 	uint8_t address = (1 << 0) | ((multiplexer->outgoing ^ 1) << 1) | (dlci << 2); // response
5703deb3ec6SMatthias Ringwald     return rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_UA, 0, NULL, 0);
5713deb3ec6SMatthias Ringwald }
5723deb3ec6SMatthias Ringwald 
5733deb3ec6SMatthias Ringwald static int rfcomm_send_dm_pf(rfcomm_multiplexer_t *multiplexer, uint8_t dlci){
5743deb3ec6SMatthias Ringwald 	uint8_t address = (1 << 0) | ((multiplexer->outgoing ^ 1) << 1) | (dlci << 2); // response
5753deb3ec6SMatthias Ringwald     return rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_DM_PF, 0, NULL, 0);
5763deb3ec6SMatthias Ringwald }
5773deb3ec6SMatthias Ringwald 
5783deb3ec6SMatthias Ringwald static int rfcomm_send_uih_fc_rsp(rfcomm_multiplexer_t *multiplexer, uint8_t fcon) {
5793deb3ec6SMatthias Ringwald     uint8_t address = (1 << 0) | (multiplexer->outgoing<< 1);
5803deb3ec6SMatthias Ringwald     uint8_t payload[2];
5813deb3ec6SMatthias Ringwald     uint8_t pos = 0;
5823deb3ec6SMatthias Ringwald     payload[pos++] = fcon ? BT_RFCOMM_FCON_RSP : BT_RFCOMM_FCOFF_RSP;
5833deb3ec6SMatthias Ringwald     payload[pos++] = (0 << 1) | 1;  // len
5843deb3ec6SMatthias Ringwald     return rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_UIH, 0, (uint8_t *) payload, pos);
5853deb3ec6SMatthias Ringwald }
5863deb3ec6SMatthias Ringwald 
5873deb3ec6SMatthias Ringwald // static int rfcomm_send_uih_test_cmd(rfcomm_multiplexer_t *multiplexer, uint8_t * data, uint16_t len) {
5883deb3ec6SMatthias Ringwald //     uint8_t address = (1 << 0) | (multiplexer->outgoing << 1);
5893deb3ec6SMatthias Ringwald //     uint8_t payload[2+len];
5903deb3ec6SMatthias Ringwald //     uint8_t pos = 0;
5913deb3ec6SMatthias Ringwald //     payload[pos++] = BT_RFCOMM_TEST_CMD;
5923deb3ec6SMatthias Ringwald //     payload[pos++] = (len + 1) << 1 | 1;  // len
5933deb3ec6SMatthias Ringwald //     memcpy(&payload[pos], data, len);
5943deb3ec6SMatthias Ringwald //     pos += len;
5953deb3ec6SMatthias Ringwald //     return rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_UIH, 0, (uint8_t *) payload, pos);
5963deb3ec6SMatthias Ringwald // }
5973deb3ec6SMatthias Ringwald 
5983deb3ec6SMatthias Ringwald static int rfcomm_send_uih_test_rsp(rfcomm_multiplexer_t *multiplexer, uint8_t * data, uint16_t len) {
5993deb3ec6SMatthias Ringwald     uint8_t address = (1 << 0) | (multiplexer->outgoing << 1);
6003deb3ec6SMatthias Ringwald     uint8_t payload[2+RFCOMM_TEST_DATA_MAX_LEN];
6013deb3ec6SMatthias Ringwald     uint8_t pos = 0;
6023deb3ec6SMatthias Ringwald     payload[pos++] = BT_RFCOMM_TEST_RSP;
6033deb3ec6SMatthias Ringwald     if (len > RFCOMM_TEST_DATA_MAX_LEN) {
6043deb3ec6SMatthias Ringwald         len = RFCOMM_TEST_DATA_MAX_LEN;
6053deb3ec6SMatthias Ringwald     }
6063deb3ec6SMatthias Ringwald     payload[pos++] = (len << 1) | 1;  // len
6073deb3ec6SMatthias Ringwald     memcpy(&payload[pos], data, len);
6083deb3ec6SMatthias Ringwald     pos += len;
6093deb3ec6SMatthias Ringwald     return rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_UIH, 0, (uint8_t *) payload, pos);
6103deb3ec6SMatthias Ringwald }
6113deb3ec6SMatthias Ringwald 
6123deb3ec6SMatthias Ringwald static int rfcomm_send_uih_msc_cmd(rfcomm_multiplexer_t *multiplexer, uint8_t dlci, uint8_t signals) {
6133deb3ec6SMatthias Ringwald 	uint8_t address = (1 << 0) | (multiplexer->outgoing << 1);
6143deb3ec6SMatthias Ringwald 	uint8_t payload[4];
6153deb3ec6SMatthias Ringwald 	uint8_t pos = 0;
6163deb3ec6SMatthias Ringwald 	payload[pos++] = BT_RFCOMM_MSC_CMD;
6173deb3ec6SMatthias Ringwald 	payload[pos++] = (2 << 1) | 1;  // len
6183deb3ec6SMatthias Ringwald 	payload[pos++] = (1 << 0) | (1 << 1) | (dlci << 2); // CMD => C/R = 1
6193deb3ec6SMatthias Ringwald 	payload[pos++] = signals;
6203deb3ec6SMatthias Ringwald 	return rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_UIH, 0, (uint8_t *) payload, pos);
6213deb3ec6SMatthias Ringwald }
6223deb3ec6SMatthias Ringwald 
6233deb3ec6SMatthias Ringwald static int rfcomm_send_uih_msc_rsp(rfcomm_multiplexer_t *multiplexer, uint8_t dlci, uint8_t signals) {
6243deb3ec6SMatthias Ringwald 	uint8_t address = (1 << 0) | (multiplexer->outgoing<< 1);
6253deb3ec6SMatthias Ringwald 	uint8_t payload[4];
6263deb3ec6SMatthias Ringwald 	uint8_t pos = 0;
6273deb3ec6SMatthias Ringwald 	payload[pos++] = BT_RFCOMM_MSC_RSP;
6283deb3ec6SMatthias Ringwald 	payload[pos++] = (2 << 1) | 1;  // len
6293deb3ec6SMatthias Ringwald 	payload[pos++] = (1 << 0) | (1 << 1) | (dlci << 2); // CMD => C/R = 1
6303deb3ec6SMatthias Ringwald 	payload[pos++] = signals;
6313deb3ec6SMatthias Ringwald 	return rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_UIH, 0, (uint8_t *) payload, pos);
6323deb3ec6SMatthias Ringwald }
6333deb3ec6SMatthias Ringwald 
6343deb3ec6SMatthias Ringwald static int rfcomm_send_uih_nsc_rsp(rfcomm_multiplexer_t *multiplexer, uint8_t command) {
6353deb3ec6SMatthias Ringwald     uint8_t address = (1 << 0) | (multiplexer->outgoing<< 1);
6363deb3ec6SMatthias Ringwald     uint8_t payload[3];
6373deb3ec6SMatthias Ringwald     uint8_t pos = 0;
6383deb3ec6SMatthias Ringwald     payload[pos++] = BT_RFCOMM_NSC_RSP;
6393deb3ec6SMatthias Ringwald     payload[pos++] = (1 << 1) | 1;  // len
6403deb3ec6SMatthias Ringwald     payload[pos++] = command;
6413deb3ec6SMatthias Ringwald     return rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_UIH, 0, (uint8_t *) payload, pos);
6423deb3ec6SMatthias Ringwald }
6433deb3ec6SMatthias Ringwald 
6443deb3ec6SMatthias Ringwald static int rfcomm_send_uih_pn_command(rfcomm_multiplexer_t *multiplexer, uint8_t dlci, uint16_t max_frame_size){
6453deb3ec6SMatthias Ringwald 	uint8_t payload[10];
6463deb3ec6SMatthias Ringwald 	uint8_t address = (1 << 0) | (multiplexer->outgoing << 1);
6473deb3ec6SMatthias Ringwald 	uint8_t pos = 0;
6483deb3ec6SMatthias Ringwald 	payload[pos++] = BT_RFCOMM_PN_CMD;
6493deb3ec6SMatthias Ringwald 	payload[pos++] = (8 << 1) | 1;  // len
6503deb3ec6SMatthias Ringwald 	payload[pos++] = dlci;
6513deb3ec6SMatthias Ringwald 	payload[pos++] = 0xf0; // pre-defined for Bluetooth, see 5.5.3 of TS 07.10 Adaption for RFCOMM
6523deb3ec6SMatthias Ringwald 	payload[pos++] = 0; // priority
6533deb3ec6SMatthias Ringwald 	payload[pos++] = 0; // max 60 seconds ack
6543deb3ec6SMatthias Ringwald 	payload[pos++] = max_frame_size & 0xff; // max framesize low
6553deb3ec6SMatthias Ringwald 	payload[pos++] = max_frame_size >> 8;   // max framesize high
6563deb3ec6SMatthias Ringwald 	payload[pos++] = 0x00; // number of retransmissions
6573deb3ec6SMatthias Ringwald 	payload[pos++] = 0x00; // (unused error recovery window) initial number of credits
6583deb3ec6SMatthias Ringwald 	return rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_UIH, 0, (uint8_t *) payload, pos);
6593deb3ec6SMatthias Ringwald }
6603deb3ec6SMatthias Ringwald 
661d6549a6eSMatthias Ringwald // "The response may not change the DLCI, the priority, the convergence layer, or the timer value." rfcomm_tutorial.pdf
6623deb3ec6SMatthias Ringwald static int rfcomm_send_uih_pn_response(rfcomm_multiplexer_t *multiplexer, uint8_t dlci,
6633deb3ec6SMatthias Ringwald                                        uint8_t priority, uint16_t max_frame_size){
6643deb3ec6SMatthias Ringwald 	uint8_t payload[10];
6653deb3ec6SMatthias Ringwald 	uint8_t address = (1 << 0) | (multiplexer->outgoing << 1);
6663deb3ec6SMatthias Ringwald 	uint8_t pos = 0;
6673deb3ec6SMatthias Ringwald 	payload[pos++] = BT_RFCOMM_PN_RSP;
6683deb3ec6SMatthias Ringwald 	payload[pos++] = (8 << 1) | 1;  // len
6693deb3ec6SMatthias Ringwald 	payload[pos++] = dlci;
6703deb3ec6SMatthias Ringwald 	payload[pos++] = 0xe0; // pre defined for Bluetooth, see 5.5.3 of TS 07.10 Adaption for RFCOMM
6713deb3ec6SMatthias Ringwald 	payload[pos++] = priority; // priority
6723deb3ec6SMatthias Ringwald 	payload[pos++] = 0; // max 60 seconds ack
6733deb3ec6SMatthias Ringwald 	payload[pos++] = max_frame_size & 0xff; // max framesize low
6743deb3ec6SMatthias Ringwald 	payload[pos++] = max_frame_size >> 8;   // max framesize high
6753deb3ec6SMatthias Ringwald 	payload[pos++] = 0x00; // number of retransmissions
6763deb3ec6SMatthias Ringwald 	payload[pos++] = 0x00; // (unused error recovery window) initial number of credits
6773deb3ec6SMatthias Ringwald 	return rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_UIH, 0, (uint8_t *) payload, pos);
6783deb3ec6SMatthias Ringwald }
6793deb3ec6SMatthias Ringwald 
6803deb3ec6SMatthias Ringwald static int rfcomm_send_uih_rls_cmd(rfcomm_multiplexer_t *multiplexer, uint8_t dlci, uint8_t line_status) {
6813deb3ec6SMatthias Ringwald     uint8_t address = (1 << 0) | (multiplexer->outgoing << 1);
6823deb3ec6SMatthias Ringwald     uint8_t payload[4];
6833deb3ec6SMatthias Ringwald     uint8_t pos = 0;
6843deb3ec6SMatthias Ringwald     payload[pos++] = BT_RFCOMM_RLS_CMD;
6853deb3ec6SMatthias Ringwald     payload[pos++] = (2 << 1) | 1;  // len
6863deb3ec6SMatthias Ringwald     payload[pos++] = (1 << 0) | (1 << 1) | (dlci << 2); // CMD => C/R = 1
6873deb3ec6SMatthias Ringwald     payload[pos++] = line_status;
6883deb3ec6SMatthias Ringwald     return rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_UIH, 0, (uint8_t *) payload, pos);
6893deb3ec6SMatthias Ringwald }
6903deb3ec6SMatthias Ringwald 
6913deb3ec6SMatthias Ringwald static int rfcomm_send_uih_rls_rsp(rfcomm_multiplexer_t *multiplexer, uint8_t dlci, uint8_t line_status) {
6923deb3ec6SMatthias Ringwald     uint8_t address = (1 << 0) | (multiplexer->outgoing << 1);
6933deb3ec6SMatthias Ringwald     uint8_t payload[4];
6943deb3ec6SMatthias Ringwald     uint8_t pos = 0;
6953deb3ec6SMatthias Ringwald     payload[pos++] = BT_RFCOMM_RLS_RSP;
6963deb3ec6SMatthias Ringwald     payload[pos++] = (2 << 1) | 1;  // len
6973deb3ec6SMatthias Ringwald     payload[pos++] = (1 << 0) | (1 << 1) | (dlci << 2); // CMD => C/R = 1
6983deb3ec6SMatthias Ringwald     payload[pos++] = line_status;
6993deb3ec6SMatthias Ringwald     return rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_UIH, 0, (uint8_t *) payload, pos);
7003deb3ec6SMatthias Ringwald }
7013deb3ec6SMatthias Ringwald 
7023deb3ec6SMatthias Ringwald static int rfcomm_send_uih_rpn_cmd(rfcomm_multiplexer_t *multiplexer, uint8_t dlci, rfcomm_rpn_data_t *rpn_data) {
7033deb3ec6SMatthias Ringwald     uint8_t payload[10];
7043deb3ec6SMatthias Ringwald     uint8_t address = (1 << 0) | (multiplexer->outgoing << 1);
7053deb3ec6SMatthias Ringwald     uint8_t pos = 0;
7063deb3ec6SMatthias Ringwald     payload[pos++] = BT_RFCOMM_RPN_CMD;
7073deb3ec6SMatthias Ringwald     payload[pos++] = (8 << 1) | 1;  // len
7083deb3ec6SMatthias Ringwald     payload[pos++] = (1 << 0) | (1 << 1) | (dlci << 2); // CMD => C/R = 1
7093deb3ec6SMatthias Ringwald     payload[pos++] = rpn_data->baud_rate;
7103deb3ec6SMatthias Ringwald     payload[pos++] = rpn_data->flags;
7113deb3ec6SMatthias Ringwald     payload[pos++] = rpn_data->flow_control;
7123deb3ec6SMatthias Ringwald     payload[pos++] = rpn_data->xon;
7133deb3ec6SMatthias Ringwald     payload[pos++] = rpn_data->xoff;
7143deb3ec6SMatthias Ringwald     payload[pos++] = rpn_data->parameter_mask_0;
7153deb3ec6SMatthias Ringwald     payload[pos++] = rpn_data->parameter_mask_1;
7163deb3ec6SMatthias Ringwald     return rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_UIH, 0, (uint8_t *) payload, pos);
7173deb3ec6SMatthias Ringwald }
7183deb3ec6SMatthias Ringwald 
7193deb3ec6SMatthias Ringwald static int rfcomm_send_uih_rpn_req(rfcomm_multiplexer_t *multiplexer, uint8_t dlci) {
7203deb3ec6SMatthias Ringwald     uint8_t payload[3];
7213deb3ec6SMatthias Ringwald     uint8_t address = (1 << 0) | (multiplexer->outgoing << 1);
7223deb3ec6SMatthias Ringwald     uint8_t pos = 0;
7233deb3ec6SMatthias Ringwald     payload[pos++] = BT_RFCOMM_RPN_CMD;
7243deb3ec6SMatthias Ringwald     payload[pos++] = (1 << 1) | 1;  // len
7253deb3ec6SMatthias Ringwald     payload[pos++] = (1 << 0) | (1 << 1) | (dlci << 2); // CMD => C/R = 1
7263deb3ec6SMatthias Ringwald     return rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_UIH, 0, (uint8_t *) payload, pos);
7273deb3ec6SMatthias Ringwald }
7283deb3ec6SMatthias Ringwald 
7293deb3ec6SMatthias Ringwald static int rfcomm_send_uih_rpn_rsp(rfcomm_multiplexer_t *multiplexer, uint8_t dlci, rfcomm_rpn_data_t *rpn_data) {
7303deb3ec6SMatthias Ringwald 	uint8_t payload[10];
7313deb3ec6SMatthias Ringwald 	uint8_t address = (1 << 0) | (multiplexer->outgoing << 1);
7323deb3ec6SMatthias Ringwald 	uint8_t pos = 0;
7333deb3ec6SMatthias Ringwald 	payload[pos++] = BT_RFCOMM_RPN_RSP;
7343deb3ec6SMatthias Ringwald 	payload[pos++] = (8 << 1) | 1;  // len
7353deb3ec6SMatthias Ringwald 	payload[pos++] = (1 << 0) | (1 << 1) | (dlci << 2); // CMD => C/R = 1
7363deb3ec6SMatthias Ringwald 	payload[pos++] = rpn_data->baud_rate;
7373deb3ec6SMatthias Ringwald 	payload[pos++] = rpn_data->flags;
7383deb3ec6SMatthias Ringwald 	payload[pos++] = rpn_data->flow_control;
7393deb3ec6SMatthias Ringwald 	payload[pos++] = rpn_data->xon;
7403deb3ec6SMatthias Ringwald 	payload[pos++] = rpn_data->xoff;
7413deb3ec6SMatthias Ringwald 	payload[pos++] = rpn_data->parameter_mask_0;
7423deb3ec6SMatthias Ringwald 	payload[pos++] = rpn_data->parameter_mask_1;
7433deb3ec6SMatthias Ringwald 	return rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_UIH, 0, (uint8_t *) payload, pos);
7443deb3ec6SMatthias Ringwald }
7453deb3ec6SMatthias Ringwald 
7463deb3ec6SMatthias Ringwald static void rfcomm_send_uih_credits(rfcomm_multiplexer_t *multiplexer, uint8_t dlci,  uint8_t credits){
7473deb3ec6SMatthias Ringwald     uint8_t address = (1 << 0) | (multiplexer->outgoing << 1) |  (dlci << 2);
7483deb3ec6SMatthias Ringwald     rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_UIH_PF, credits, NULL, 0);
7493deb3ec6SMatthias Ringwald }
7503deb3ec6SMatthias Ringwald 
7513deb3ec6SMatthias Ringwald // MARK: RFCOMM MULTIPLEXER
7523deb3ec6SMatthias Ringwald static void rfcomm_multiplexer_stop_timer(rfcomm_multiplexer_t * multiplexer){
7533deb3ec6SMatthias Ringwald     if (multiplexer->timer_active) {
754528a4a3bSMatthias Ringwald         btstack_run_loop_remove_timer(&multiplexer->timer);
7553deb3ec6SMatthias Ringwald         multiplexer->timer_active = 0;
7563deb3ec6SMatthias Ringwald     }
7573deb3ec6SMatthias Ringwald }
7583deb3ec6SMatthias Ringwald static void rfcomm_multiplexer_free(rfcomm_multiplexer_t * multiplexer){
759665d90f2SMatthias Ringwald     btstack_linked_list_remove( &rfcomm_multiplexers, (btstack_linked_item_t *) multiplexer);
7603deb3ec6SMatthias Ringwald     btstack_memory_rfcomm_multiplexer_free(multiplexer);
7613deb3ec6SMatthias Ringwald }
7623deb3ec6SMatthias Ringwald 
7633deb3ec6SMatthias Ringwald static void rfcomm_multiplexer_finalize(rfcomm_multiplexer_t * multiplexer){
7643deb3ec6SMatthias Ringwald     // remove (potential) timer
7653deb3ec6SMatthias Ringwald     rfcomm_multiplexer_stop_timer(multiplexer);
7663deb3ec6SMatthias Ringwald 
7673deb3ec6SMatthias Ringwald     // close and remove all channels
768665d90f2SMatthias Ringwald     btstack_linked_item_t *it = (btstack_linked_item_t *) &rfcomm_channels;
7693deb3ec6SMatthias Ringwald     while (it->next){
7703deb3ec6SMatthias Ringwald         rfcomm_channel_t * channel = (rfcomm_channel_t *) it->next;
7713deb3ec6SMatthias Ringwald         if (channel->multiplexer == multiplexer) {
7723deb3ec6SMatthias Ringwald             // emit appropriate events
7733deb3ec6SMatthias Ringwald             if (channel->state == RFCOMM_CHANNEL_OPEN) {
7743deb3ec6SMatthias Ringwald                 rfcomm_emit_channel_closed(channel);
7753deb3ec6SMatthias Ringwald             } else {
7763deb3ec6SMatthias Ringwald                 rfcomm_emit_channel_opened(channel, RFCOMM_MULTIPLEXER_STOPPED);
7773deb3ec6SMatthias Ringwald             }
7783deb3ec6SMatthias Ringwald             // remove from list
7793deb3ec6SMatthias Ringwald             it->next = it->next->next;
7803deb3ec6SMatthias Ringwald             // free channel struct
7813deb3ec6SMatthias Ringwald             btstack_memory_rfcomm_channel_free(channel);
7823deb3ec6SMatthias Ringwald         } else {
7833deb3ec6SMatthias Ringwald             it = it->next;
7843deb3ec6SMatthias Ringwald         }
7853deb3ec6SMatthias Ringwald     }
7863deb3ec6SMatthias Ringwald 
7873deb3ec6SMatthias Ringwald     // remove mutliplexer
7883deb3ec6SMatthias Ringwald     rfcomm_multiplexer_free(multiplexer);
7893deb3ec6SMatthias Ringwald }
7903deb3ec6SMatthias Ringwald 
791ec820d77SMatthias Ringwald static void rfcomm_multiplexer_timer_handler(btstack_timer_source_t *timer){
792c5b64319SMatthias Ringwald     rfcomm_multiplexer_t * multiplexer = (rfcomm_multiplexer_t*) btstack_run_loop_get_timer_context(timer);
7933deb3ec6SMatthias Ringwald     if (rfcomm_multiplexer_has_channels(multiplexer)) return;
7943deb3ec6SMatthias Ringwald 
7953deb3ec6SMatthias Ringwald     log_info("rfcomm_multiplexer_timer_handler timeout: shutting down multiplexer! (no channels)");
7963deb3ec6SMatthias Ringwald     uint16_t l2cap_cid = multiplexer->l2cap_cid;
7973deb3ec6SMatthias Ringwald     rfcomm_multiplexer_finalize(multiplexer);
798ce8f182eSMatthias Ringwald     l2cap_disconnect(l2cap_cid, 0x13);
7993deb3ec6SMatthias Ringwald }
8003deb3ec6SMatthias Ringwald 
8013deb3ec6SMatthias Ringwald static void rfcomm_multiplexer_prepare_idle_timer(rfcomm_multiplexer_t * multiplexer){
8023deb3ec6SMatthias Ringwald     if (multiplexer->timer_active) {
803528a4a3bSMatthias Ringwald         btstack_run_loop_remove_timer(&multiplexer->timer);
8043deb3ec6SMatthias Ringwald         multiplexer->timer_active = 0;
8053deb3ec6SMatthias Ringwald     }
8063deb3ec6SMatthias Ringwald     if (rfcomm_multiplexer_has_channels(multiplexer)) return;
8073deb3ec6SMatthias Ringwald 
8083deb3ec6SMatthias Ringwald     // start idle timer for multiplexer timeout check as there are no rfcomm channels yet
809528a4a3bSMatthias Ringwald     btstack_run_loop_set_timer(&multiplexer->timer, RFCOMM_MULIPLEXER_TIMEOUT_MS);
81091a977e8SMatthias Ringwald     btstack_run_loop_set_timer_handler(&multiplexer->timer, rfcomm_multiplexer_timer_handler);
81191a977e8SMatthias Ringwald     btstack_run_loop_set_timer_context(&multiplexer->timer, multiplexer);
812528a4a3bSMatthias Ringwald     btstack_run_loop_add_timer(&multiplexer->timer);
8133deb3ec6SMatthias Ringwald     multiplexer->timer_active = 1;
8143deb3ec6SMatthias Ringwald }
8153deb3ec6SMatthias Ringwald 
8163deb3ec6SMatthias Ringwald static void rfcomm_multiplexer_opened(rfcomm_multiplexer_t *multiplexer){
8173deb3ec6SMatthias Ringwald     log_info("Multiplexer up and running");
8183deb3ec6SMatthias Ringwald     multiplexer->state = RFCOMM_MULTIPLEXER_OPEN;
8193deb3ec6SMatthias Ringwald 
8203deb3ec6SMatthias Ringwald     rfcomm_channel_event_t event = { CH_EVT_MULTIPLEXER_READY };
8213deb3ec6SMatthias Ringwald 
8223deb3ec6SMatthias Ringwald     // transition of channels that wait for multiplexer
823665d90f2SMatthias Ringwald     btstack_linked_item_t *it;
824665d90f2SMatthias Ringwald     for (it = (btstack_linked_item_t *) rfcomm_channels; it ; it = it->next){
8253deb3ec6SMatthias Ringwald         rfcomm_channel_t * channel = ((rfcomm_channel_t *) it);
8263deb3ec6SMatthias Ringwald         if (channel->multiplexer != multiplexer) continue;
8273deb3ec6SMatthias Ringwald         rfcomm_channel_state_machine(channel, &event);
8283deb3ec6SMatthias Ringwald     }
8293deb3ec6SMatthias Ringwald 
8303deb3ec6SMatthias Ringwald     rfcomm_run();
8313deb3ec6SMatthias Ringwald     rfcomm_multiplexer_prepare_idle_timer(multiplexer);
8323deb3ec6SMatthias Ringwald }
8333deb3ec6SMatthias Ringwald 
8343deb3ec6SMatthias Ringwald 
8353deb3ec6SMatthias Ringwald /**
8363deb3ec6SMatthias Ringwald  * @return handled packet
8373deb3ec6SMatthias Ringwald  */
8383deb3ec6SMatthias Ringwald static int rfcomm_multiplexer_hci_event_handler(uint8_t *packet, uint16_t size){
8393deb3ec6SMatthias Ringwald     bd_addr_t event_addr;
8403deb3ec6SMatthias Ringwald     uint16_t  psm;
8413deb3ec6SMatthias Ringwald     uint16_t l2cap_cid;
8423deb3ec6SMatthias Ringwald     hci_con_handle_t con_handle;
8433deb3ec6SMatthias Ringwald     rfcomm_multiplexer_t *multiplexer = NULL;
8443deb3ec6SMatthias Ringwald     uint8_t status;
8453deb3ec6SMatthias Ringwald 
8460e2df43fSMatthias Ringwald     switch (hci_event_packet_get_type(packet)) {
8473deb3ec6SMatthias Ringwald 
8483deb3ec6SMatthias Ringwald         // accept incoming PSM_RFCOMM connection if no multiplexer exists yet
8493deb3ec6SMatthias Ringwald         case L2CAP_EVENT_INCOMING_CONNECTION:
8503deb3ec6SMatthias Ringwald             // data: event(8), len(8), address(48), handle (16),  psm (16), source cid(16) dest cid(16)
851724d70a2SMatthias Ringwald             reverse_bd_addr(&packet[2], event_addr);
852f8fbdce0SMatthias Ringwald             con_handle = little_endian_read_16(packet,  8);
853f8fbdce0SMatthias Ringwald             psm        = little_endian_read_16(packet, 10);
854f8fbdce0SMatthias Ringwald             l2cap_cid  = little_endian_read_16(packet, 12);
8553deb3ec6SMatthias Ringwald 
8563deb3ec6SMatthias Ringwald             if (psm != PSM_RFCOMM) break;
8573deb3ec6SMatthias Ringwald 
8583deb3ec6SMatthias Ringwald             multiplexer = rfcomm_multiplexer_for_addr(event_addr);
8593deb3ec6SMatthias Ringwald 
8603deb3ec6SMatthias Ringwald             if (multiplexer) {
8613deb3ec6SMatthias Ringwald                 log_info("INCOMING_CONNECTION (l2cap_cid 0x%02x) for PSM_RFCOMM => decline - multiplexer already exists", l2cap_cid);
862ce8f182eSMatthias Ringwald                 l2cap_decline_connection(l2cap_cid,  0x04);    // no resources available
8633deb3ec6SMatthias Ringwald                 return 1;
8643deb3ec6SMatthias Ringwald             }
8653deb3ec6SMatthias Ringwald 
8663deb3ec6SMatthias Ringwald             // create and inititialize new multiplexer instance (incoming)
8673deb3ec6SMatthias Ringwald             multiplexer = rfcomm_multiplexer_create_for_addr(event_addr);
8683deb3ec6SMatthias Ringwald             if (!multiplexer){
8693deb3ec6SMatthias Ringwald                 log_info("INCOMING_CONNECTION (l2cap_cid 0x%02x) for PSM_RFCOMM => decline - no memory left", l2cap_cid);
870ce8f182eSMatthias Ringwald                 l2cap_decline_connection(l2cap_cid,  0x04);    // no resources available
8713deb3ec6SMatthias Ringwald                 return 1;
8723deb3ec6SMatthias Ringwald             }
8733deb3ec6SMatthias Ringwald 
8743deb3ec6SMatthias Ringwald             multiplexer->con_handle = con_handle;
8753deb3ec6SMatthias Ringwald             multiplexer->l2cap_cid = l2cap_cid;
8763deb3ec6SMatthias Ringwald             multiplexer->state = RFCOMM_MULTIPLEXER_W4_SABM_0;
8773deb3ec6SMatthias Ringwald 
8783deb3ec6SMatthias Ringwald             log_info("L2CAP_EVENT_INCOMING_CONNECTION (l2cap_cid 0x%02x) for PSM_RFCOMM => accept", l2cap_cid);
879ce8f182eSMatthias Ringwald             l2cap_accept_connection(l2cap_cid);
8803deb3ec6SMatthias Ringwald             return 1;
8813deb3ec6SMatthias Ringwald 
8823deb3ec6SMatthias Ringwald         // l2cap connection opened -> store l2cap_cid, remote_addr
8833deb3ec6SMatthias Ringwald         case L2CAP_EVENT_CHANNEL_OPENED:
8843deb3ec6SMatthias Ringwald 
885f8fbdce0SMatthias Ringwald             if (little_endian_read_16(packet, 11) != PSM_RFCOMM) break;
8863deb3ec6SMatthias Ringwald 
8873deb3ec6SMatthias Ringwald             status = packet[2];
8883deb3ec6SMatthias Ringwald             log_info("L2CAP_EVENT_CHANNEL_OPENED for PSM_RFCOMM, status %u", status);
8893deb3ec6SMatthias Ringwald 
8903deb3ec6SMatthias Ringwald             // get multiplexer for remote addr
891f8fbdce0SMatthias Ringwald             con_handle = little_endian_read_16(packet, 9);
892f8fbdce0SMatthias Ringwald             l2cap_cid = little_endian_read_16(packet, 13);
893724d70a2SMatthias Ringwald             reverse_bd_addr(&packet[3], event_addr);
8943deb3ec6SMatthias Ringwald             multiplexer = rfcomm_multiplexer_for_addr(event_addr);
8953deb3ec6SMatthias Ringwald             if (!multiplexer) {
8963deb3ec6SMatthias Ringwald                 log_error("L2CAP_EVENT_CHANNEL_OPENED but no multiplexer prepared");
8973deb3ec6SMatthias Ringwald                 return 1;
8983deb3ec6SMatthias Ringwald             }
8993deb3ec6SMatthias Ringwald 
9003deb3ec6SMatthias Ringwald             // on l2cap open error discard everything
9013deb3ec6SMatthias Ringwald             if (status){
9023deb3ec6SMatthias Ringwald 
9033deb3ec6SMatthias Ringwald                 // remove (potential) timer
9043deb3ec6SMatthias Ringwald                 rfcomm_multiplexer_stop_timer(multiplexer);
9053deb3ec6SMatthias Ringwald 
9063deb3ec6SMatthias Ringwald                 // emit rfcomm_channel_opened with status and free channel
907665d90f2SMatthias Ringwald                 btstack_linked_item_t * it = (btstack_linked_item_t *) &rfcomm_channels;
9083deb3ec6SMatthias Ringwald                 while (it->next) {
9093deb3ec6SMatthias Ringwald                     rfcomm_channel_t * channel = (rfcomm_channel_t *) it->next;
9103deb3ec6SMatthias Ringwald                     if (channel->multiplexer == multiplexer){
9113deb3ec6SMatthias Ringwald                         rfcomm_emit_channel_opened(channel, status);
9123deb3ec6SMatthias Ringwald                         it->next = it->next->next;
9133deb3ec6SMatthias Ringwald                         btstack_memory_rfcomm_channel_free(channel);
9143deb3ec6SMatthias Ringwald                     } else {
9153deb3ec6SMatthias Ringwald                         it = it->next;
9163deb3ec6SMatthias Ringwald                     }
9173deb3ec6SMatthias Ringwald                 }
9183deb3ec6SMatthias Ringwald 
9193deb3ec6SMatthias Ringwald                 // free multiplexer
9203deb3ec6SMatthias Ringwald                 rfcomm_multiplexer_free(multiplexer);
9213deb3ec6SMatthias Ringwald                 return 1;
9223deb3ec6SMatthias Ringwald             }
9233deb3ec6SMatthias Ringwald 
9243deb3ec6SMatthias Ringwald             if (multiplexer->state == RFCOMM_MULTIPLEXER_W4_CONNECT) {
9253deb3ec6SMatthias Ringwald                 log_info("L2CAP_EVENT_CHANNEL_OPENED: outgoing connection");
9263deb3ec6SMatthias Ringwald                 // wrong remote addr
927058e3d6bSMatthias Ringwald                 if (bd_addr_cmp(event_addr, multiplexer->remote_addr)) break;
9283deb3ec6SMatthias Ringwald                 multiplexer->l2cap_cid = l2cap_cid;
9293deb3ec6SMatthias Ringwald                 multiplexer->con_handle = con_handle;
9303deb3ec6SMatthias Ringwald                 // send SABM #0
9313deb3ec6SMatthias Ringwald                 multiplexer->state = RFCOMM_MULTIPLEXER_SEND_SABM_0;
9323deb3ec6SMatthias Ringwald             } else { // multiplexer->state == RFCOMM_MULTIPLEXER_W4_SABM_0
9333deb3ec6SMatthias Ringwald 
9343deb3ec6SMatthias Ringwald                 // set max frame size based on l2cap MTU
935f8fbdce0SMatthias Ringwald                 multiplexer->max_frame_size = rfcomm_max_frame_size_for_l2cap_mtu(little_endian_read_16(packet, 17));
9363deb3ec6SMatthias Ringwald             }
9373deb3ec6SMatthias Ringwald             return 1;
9383deb3ec6SMatthias Ringwald 
9393deb3ec6SMatthias Ringwald             // l2cap disconnect -> state = RFCOMM_MULTIPLEXER_CLOSED;
9403deb3ec6SMatthias Ringwald 
941b31d33b2SMatthias Ringwald         // Notify channel packet handler if they can send now
942b31d33b2SMatthias Ringwald         case L2CAP_EVENT_CAN_SEND_NOW:
943b31d33b2SMatthias Ringwald             rfcomm_run();   // rfcomm signaling packets first
944b31d33b2SMatthias Ringwald             rfcomm_notify_channel_can_send();
9453deb3ec6SMatthias Ringwald             break;
9463deb3ec6SMatthias Ringwald 
9473deb3ec6SMatthias Ringwald         case L2CAP_EVENT_CHANNEL_CLOSED:
9483deb3ec6SMatthias Ringwald             // data: event (8), len(8), channel (16)
949f8fbdce0SMatthias Ringwald             l2cap_cid = little_endian_read_16(packet, 2);
9503deb3ec6SMatthias Ringwald             multiplexer = rfcomm_multiplexer_for_l2cap_cid(l2cap_cid);
9513deb3ec6SMatthias Ringwald             log_info("L2CAP_EVENT_CHANNEL_CLOSED cid 0x%0x, mult %p", l2cap_cid, multiplexer);
9523deb3ec6SMatthias Ringwald             if (!multiplexer) break;
9533deb3ec6SMatthias Ringwald             log_info("L2CAP_EVENT_CHANNEL_CLOSED state %u", multiplexer->state);
9543deb3ec6SMatthias Ringwald             switch (multiplexer->state) {
9553deb3ec6SMatthias Ringwald                 case RFCOMM_MULTIPLEXER_W4_CONNECT:
9563deb3ec6SMatthias Ringwald                 case RFCOMM_MULTIPLEXER_SEND_SABM_0:
9573deb3ec6SMatthias Ringwald                 case RFCOMM_MULTIPLEXER_W4_SABM_0:
9583deb3ec6SMatthias Ringwald                 case RFCOMM_MULTIPLEXER_SEND_UA_0:
9593deb3ec6SMatthias Ringwald                 case RFCOMM_MULTIPLEXER_W4_UA_0:
9603deb3ec6SMatthias Ringwald                 case RFCOMM_MULTIPLEXER_OPEN:
9613deb3ec6SMatthias Ringwald                     // don't call l2cap_disconnect as it's alreay closed
9623deb3ec6SMatthias Ringwald                     rfcomm_multiplexer_finalize(multiplexer);
9633deb3ec6SMatthias Ringwald                     return 1;
9643deb3ec6SMatthias Ringwald                 default:
9653deb3ec6SMatthias Ringwald                     break;
9663deb3ec6SMatthias Ringwald             }
9673deb3ec6SMatthias Ringwald             break;
9683deb3ec6SMatthias Ringwald         default:
9693deb3ec6SMatthias Ringwald             break;
9703deb3ec6SMatthias Ringwald     }
9713deb3ec6SMatthias Ringwald     return 0;
9723deb3ec6SMatthias Ringwald }
9733deb3ec6SMatthias Ringwald 
9743deb3ec6SMatthias Ringwald static int rfcomm_multiplexer_l2cap_packet_handler(uint16_t channel, uint8_t *packet, uint16_t size){
9753deb3ec6SMatthias Ringwald 
9763deb3ec6SMatthias Ringwald     // get or create a multiplexer for a certain device
9773deb3ec6SMatthias Ringwald     rfcomm_multiplexer_t *multiplexer = rfcomm_multiplexer_for_l2cap_cid(channel);
9783deb3ec6SMatthias Ringwald     if (!multiplexer) return 0;
9793deb3ec6SMatthias Ringwald 
9803deb3ec6SMatthias Ringwald     uint16_t l2cap_cid = multiplexer->l2cap_cid;
9813deb3ec6SMatthias Ringwald 
9823deb3ec6SMatthias Ringwald 	// but only care for multiplexer control channel
9833deb3ec6SMatthias Ringwald     uint8_t frame_dlci = packet[0] >> 2;
9843deb3ec6SMatthias Ringwald     if (frame_dlci) return 0;
9853deb3ec6SMatthias Ringwald     const uint8_t length_offset = (packet[2] & 1) ^ 1;  // to be used for pos >= 3
9863deb3ec6SMatthias Ringwald     const uint8_t credit_offset = ((packet[1] & BT_RFCOMM_UIH_PF) == BT_RFCOMM_UIH_PF) ? 1 : 0;   // credits for uih_pf frames
9873deb3ec6SMatthias Ringwald     const uint8_t payload_offset = 3 + length_offset + credit_offset;
9883deb3ec6SMatthias Ringwald     switch (packet[1]){
9893deb3ec6SMatthias Ringwald 
9903deb3ec6SMatthias Ringwald         case BT_RFCOMM_SABM:
9913deb3ec6SMatthias Ringwald             if (multiplexer->state == RFCOMM_MULTIPLEXER_W4_SABM_0){
9923deb3ec6SMatthias Ringwald                 log_info("Received SABM #0");
9933deb3ec6SMatthias Ringwald                 multiplexer->outgoing = 0;
9943deb3ec6SMatthias Ringwald                 multiplexer->state = RFCOMM_MULTIPLEXER_SEND_UA_0;
9953deb3ec6SMatthias Ringwald                 return 1;
9963deb3ec6SMatthias Ringwald             }
9973deb3ec6SMatthias Ringwald             break;
9983deb3ec6SMatthias Ringwald 
9993deb3ec6SMatthias Ringwald         case BT_RFCOMM_UA:
10003deb3ec6SMatthias Ringwald             if (multiplexer->state == RFCOMM_MULTIPLEXER_W4_UA_0) {
10013deb3ec6SMatthias Ringwald                 // UA #0 -> send UA #0, state = RFCOMM_MULTIPLEXER_OPEN
10023deb3ec6SMatthias Ringwald                 log_info("Received UA #0 ");
10033deb3ec6SMatthias Ringwald                 rfcomm_multiplexer_opened(multiplexer);
10043deb3ec6SMatthias Ringwald                 return 1;
10053deb3ec6SMatthias Ringwald             }
10063deb3ec6SMatthias Ringwald             break;
10073deb3ec6SMatthias Ringwald 
10083deb3ec6SMatthias Ringwald         case BT_RFCOMM_DISC:
10093deb3ec6SMatthias Ringwald             // DISC #0 -> send UA #0, close multiplexer
10103deb3ec6SMatthias Ringwald             log_info("Received DISC #0, (ougoing = %u)", multiplexer->outgoing);
10113deb3ec6SMatthias Ringwald             multiplexer->state = RFCOMM_MULTIPLEXER_SEND_UA_0_AND_DISC;
10123deb3ec6SMatthias Ringwald             return 1;
10133deb3ec6SMatthias Ringwald 
10143deb3ec6SMatthias Ringwald         case BT_RFCOMM_DM:
10153deb3ec6SMatthias Ringwald             // DM #0 - we shouldn't get this, just give up
10163deb3ec6SMatthias Ringwald             log_info("Received DM #0");
10173deb3ec6SMatthias Ringwald             log_info("-> Closing down multiplexer");
10183deb3ec6SMatthias Ringwald             rfcomm_multiplexer_finalize(multiplexer);
1019ce8f182eSMatthias Ringwald             l2cap_disconnect(l2cap_cid, 0x13);
10203deb3ec6SMatthias Ringwald             return 1;
10213deb3ec6SMatthias Ringwald 
10223deb3ec6SMatthias Ringwald         case BT_RFCOMM_UIH:
10233deb3ec6SMatthias Ringwald             if (packet[payload_offset] == BT_RFCOMM_CLD_CMD){
10243deb3ec6SMatthias Ringwald                 // Multiplexer close down (CLD) -> close mutliplexer
10253deb3ec6SMatthias Ringwald                 log_info("Received Multiplexer close down command");
10263deb3ec6SMatthias Ringwald                 log_info("-> Closing down multiplexer");
10273deb3ec6SMatthias Ringwald                 rfcomm_multiplexer_finalize(multiplexer);
1028ce8f182eSMatthias Ringwald                 l2cap_disconnect(l2cap_cid, 0x13);
10293deb3ec6SMatthias Ringwald                 return 1;
10303deb3ec6SMatthias Ringwald             }
10313deb3ec6SMatthias Ringwald             switch (packet[payload_offset]){
10323deb3ec6SMatthias Ringwald                 case BT_RFCOMM_CLD_CMD:
10333deb3ec6SMatthias Ringwald                      // Multiplexer close down (CLD) -> close mutliplexer
10343deb3ec6SMatthias Ringwald                     log_info("Received Multiplexer close down command");
10353deb3ec6SMatthias Ringwald                     log_info("-> Closing down multiplexer");
10363deb3ec6SMatthias Ringwald                     rfcomm_multiplexer_finalize(multiplexer);
1037ce8f182eSMatthias Ringwald                     l2cap_disconnect(l2cap_cid, 0x13);
10383deb3ec6SMatthias Ringwald                     return 1;
10393deb3ec6SMatthias Ringwald 
10403deb3ec6SMatthias Ringwald                 case BT_RFCOMM_FCON_CMD:
10413deb3ec6SMatthias Ringwald                     multiplexer->fcon = 0x81;
10423deb3ec6SMatthias Ringwald                     break;
10433deb3ec6SMatthias Ringwald 
10443deb3ec6SMatthias Ringwald                 case BT_RFCOMM_FCOFF_CMD:
10453deb3ec6SMatthias Ringwald                     multiplexer->fcon = 0x80;
10463deb3ec6SMatthias Ringwald                     break;
10473deb3ec6SMatthias Ringwald 
10483deb3ec6SMatthias Ringwald                 case BT_RFCOMM_TEST_CMD: {
10493deb3ec6SMatthias Ringwald                     log_info("Received test command");
10503deb3ec6SMatthias Ringwald                     int len = packet[payload_offset+1] >> 1; // length < 125
10513deb3ec6SMatthias Ringwald                     if (len > RFCOMM_TEST_DATA_MAX_LEN){
10523deb3ec6SMatthias Ringwald                         len = RFCOMM_TEST_DATA_MAX_LEN;
10533deb3ec6SMatthias Ringwald                     }
10543deb3ec6SMatthias Ringwald                     multiplexer->test_data_len = len;
10553deb3ec6SMatthias Ringwald                     memcpy(multiplexer->test_data, &packet[payload_offset + 2], len);
10563deb3ec6SMatthias Ringwald                     return 1;
10573deb3ec6SMatthias Ringwald                 }
10583deb3ec6SMatthias Ringwald                 default:
10593deb3ec6SMatthias Ringwald                     break;
10603deb3ec6SMatthias Ringwald             }
10613deb3ec6SMatthias Ringwald             break;
10623deb3ec6SMatthias Ringwald 
10633deb3ec6SMatthias Ringwald         default:
10643deb3ec6SMatthias Ringwald             break;
10653deb3ec6SMatthias Ringwald 
10663deb3ec6SMatthias Ringwald     }
10673deb3ec6SMatthias Ringwald     return 0;
10683deb3ec6SMatthias Ringwald }
10693deb3ec6SMatthias Ringwald 
10703deb3ec6SMatthias Ringwald static void rfcomm_multiplexer_state_machine(rfcomm_multiplexer_t * multiplexer, RFCOMM_MULTIPLEXER_EVENT event){
10713deb3ec6SMatthias Ringwald 
10723deb3ec6SMatthias Ringwald     uint16_t l2cap_cid = multiplexer->l2cap_cid;
10733deb3ec6SMatthias Ringwald 
10743deb3ec6SMatthias Ringwald     // process stored DM responses
10753deb3ec6SMatthias Ringwald     if (multiplexer->send_dm_for_dlci){
10763deb3ec6SMatthias Ringwald         uint8_t dlci = multiplexer->send_dm_for_dlci;
10773deb3ec6SMatthias Ringwald         multiplexer->send_dm_for_dlci = 0;
10783deb3ec6SMatthias Ringwald         rfcomm_send_dm_pf(multiplexer, dlci);
10793deb3ec6SMatthias Ringwald         return;
10803deb3ec6SMatthias Ringwald     }
10813deb3ec6SMatthias Ringwald 
10823deb3ec6SMatthias Ringwald     if (multiplexer->nsc_command){
10833deb3ec6SMatthias Ringwald         uint8_t command = multiplexer->nsc_command;
10843deb3ec6SMatthias Ringwald         multiplexer->nsc_command = 0;
10853deb3ec6SMatthias Ringwald         rfcomm_send_uih_nsc_rsp(multiplexer, command);
10863deb3ec6SMatthias Ringwald         return;
10873deb3ec6SMatthias Ringwald     }
10883deb3ec6SMatthias Ringwald 
10893deb3ec6SMatthias Ringwald     if (multiplexer->fcon & 0x80){
10903deb3ec6SMatthias Ringwald         multiplexer->fcon &= 0x01;
10913deb3ec6SMatthias Ringwald         rfcomm_send_uih_fc_rsp(multiplexer, multiplexer->fcon);
10923deb3ec6SMatthias Ringwald         if (multiplexer->fcon == 0) return;
10933deb3ec6SMatthias Ringwald         // trigger client to send again after sending FCon Response
1094b31d33b2SMatthias Ringwald         rfcomm_notify_channel_can_send();
10953deb3ec6SMatthias Ringwald         return;
10963deb3ec6SMatthias Ringwald     }
10973deb3ec6SMatthias Ringwald 
10983deb3ec6SMatthias Ringwald     switch (multiplexer->state) {
10993deb3ec6SMatthias Ringwald         case RFCOMM_MULTIPLEXER_SEND_SABM_0:
11003deb3ec6SMatthias Ringwald             switch (event) {
11013deb3ec6SMatthias Ringwald                 case MULT_EV_READY_TO_SEND:
11023deb3ec6SMatthias Ringwald                     log_info("Sending SABM #0 - (multi 0x%p)", multiplexer);
11033deb3ec6SMatthias Ringwald                     multiplexer->state = RFCOMM_MULTIPLEXER_W4_UA_0;
11043deb3ec6SMatthias Ringwald                     rfcomm_send_sabm(multiplexer, 0);
11053deb3ec6SMatthias Ringwald                     break;
11063deb3ec6SMatthias Ringwald                 default:
11073deb3ec6SMatthias Ringwald                     break;
11083deb3ec6SMatthias Ringwald             }
11093deb3ec6SMatthias Ringwald             break;
11103deb3ec6SMatthias Ringwald         case RFCOMM_MULTIPLEXER_SEND_UA_0:
11113deb3ec6SMatthias Ringwald             switch (event) {
11123deb3ec6SMatthias Ringwald                 case MULT_EV_READY_TO_SEND:
11133deb3ec6SMatthias Ringwald                     log_info("Sending UA #0");
11143deb3ec6SMatthias Ringwald                     multiplexer->state = RFCOMM_MULTIPLEXER_OPEN;
11153deb3ec6SMatthias Ringwald                     rfcomm_send_ua(multiplexer, 0);
11163deb3ec6SMatthias Ringwald                     rfcomm_multiplexer_opened(multiplexer);
11173deb3ec6SMatthias Ringwald                     break;
11183deb3ec6SMatthias Ringwald                 default:
11193deb3ec6SMatthias Ringwald                     break;
11203deb3ec6SMatthias Ringwald             }
11213deb3ec6SMatthias Ringwald             break;
11223deb3ec6SMatthias Ringwald         case RFCOMM_MULTIPLEXER_SEND_UA_0_AND_DISC:
11233deb3ec6SMatthias Ringwald             switch (event) {
11243deb3ec6SMatthias Ringwald                 case MULT_EV_READY_TO_SEND:
11253deb3ec6SMatthias Ringwald                     // try to detect authentication errors: drop link key if multiplexer closed before first channel got opened
11263deb3ec6SMatthias Ringwald                     if (!multiplexer->at_least_one_connection){
11273deb3ec6SMatthias Ringwald                         log_info("TODO: no connections established - delete link key prophylactically");
11283deb3ec6SMatthias Ringwald                         // hci_send_cmd(&hci_delete_stored_link_key, multiplexer->remote_addr);
11293deb3ec6SMatthias Ringwald                     }
11303deb3ec6SMatthias Ringwald                     log_info("Sending UA #0");
11313deb3ec6SMatthias Ringwald                     log_info("Closing down multiplexer");
11323deb3ec6SMatthias Ringwald                     multiplexer->state = RFCOMM_MULTIPLEXER_CLOSED;
11333deb3ec6SMatthias Ringwald                     rfcomm_send_ua(multiplexer, 0);
11343deb3ec6SMatthias Ringwald                     rfcomm_multiplexer_finalize(multiplexer);
1135ce8f182eSMatthias Ringwald                     l2cap_disconnect(l2cap_cid, 0x13);
11363deb3ec6SMatthias Ringwald                 default:
11373deb3ec6SMatthias Ringwald                     break;
11383deb3ec6SMatthias Ringwald             }
11393deb3ec6SMatthias Ringwald             break;
11403deb3ec6SMatthias Ringwald         case RFCOMM_MULTIPLEXER_OPEN:
11413deb3ec6SMatthias Ringwald             switch (event) {
11423deb3ec6SMatthias Ringwald                 case MULT_EV_READY_TO_SEND:
11433deb3ec6SMatthias Ringwald                     // respond to test command
11443deb3ec6SMatthias Ringwald                     if (multiplexer->test_data_len){
11453deb3ec6SMatthias Ringwald                         int len = multiplexer->test_data_len;
11463deb3ec6SMatthias Ringwald                         log_info("Sending TEST Response with %u bytes", len);
11473deb3ec6SMatthias Ringwald                         multiplexer->test_data_len = 0;
11483deb3ec6SMatthias Ringwald                         rfcomm_send_uih_test_rsp(multiplexer, multiplexer->test_data, len);
11493deb3ec6SMatthias Ringwald                         return;
11503deb3ec6SMatthias Ringwald                     }
11513deb3ec6SMatthias Ringwald                     break;
11523deb3ec6SMatthias Ringwald                 default:
11533deb3ec6SMatthias Ringwald                     break;
11543deb3ec6SMatthias Ringwald             }
11553deb3ec6SMatthias Ringwald             break;
11563deb3ec6SMatthias Ringwald         default:
11573deb3ec6SMatthias Ringwald             break;
11583deb3ec6SMatthias Ringwald     }
11593deb3ec6SMatthias Ringwald }
11603deb3ec6SMatthias Ringwald 
11613deb3ec6SMatthias Ringwald // MARK: RFCOMM CHANNEL
11623deb3ec6SMatthias Ringwald 
11633deb3ec6SMatthias Ringwald static void rfcomm_channel_send_credits(rfcomm_channel_t *channel, uint8_t credits){
11643deb3ec6SMatthias Ringwald     rfcomm_send_uih_credits(channel->multiplexer, channel->dlci, credits);
11653deb3ec6SMatthias Ringwald     channel->credits_incoming += credits;
11663deb3ec6SMatthias Ringwald }
11673deb3ec6SMatthias Ringwald 
1168b31d33b2SMatthias Ringwald static int rfcomm_channel_can_send(rfcomm_channel_t * channel){
1169b31d33b2SMatthias Ringwald     if (!channel->credits_outgoing) return 0;
1170b31d33b2SMatthias Ringwald     if ((channel->multiplexer->fcon & 1) == 0) return 0;
1171b31d33b2SMatthias Ringwald     return l2cap_can_send_packet_now(channel->multiplexer->l2cap_cid);
1172b31d33b2SMatthias Ringwald }
1173b31d33b2SMatthias Ringwald 
11743deb3ec6SMatthias Ringwald static void rfcomm_channel_opened(rfcomm_channel_t *rfChannel){
11753deb3ec6SMatthias Ringwald 
11763deb3ec6SMatthias Ringwald     log_info("rfcomm_channel_opened!");
11773deb3ec6SMatthias Ringwald 
11783deb3ec6SMatthias Ringwald     rfChannel->state = RFCOMM_CHANNEL_OPEN;
11793deb3ec6SMatthias Ringwald     rfcomm_emit_channel_opened(rfChannel, 0);
11803deb3ec6SMatthias Ringwald     rfcomm_emit_port_configuration(rfChannel);
11813deb3ec6SMatthias Ringwald 
11823deb3ec6SMatthias Ringwald     // remove (potential) timer
11833deb3ec6SMatthias Ringwald     rfcomm_multiplexer_t *multiplexer = rfChannel->multiplexer;
11843deb3ec6SMatthias Ringwald     if (multiplexer->timer_active) {
1185528a4a3bSMatthias Ringwald         btstack_run_loop_remove_timer(&multiplexer->timer);
11863deb3ec6SMatthias Ringwald         multiplexer->timer_active = 0;
11873deb3ec6SMatthias Ringwald     }
11883deb3ec6SMatthias Ringwald     // hack for problem detecting authentication failure
11893deb3ec6SMatthias Ringwald     multiplexer->at_least_one_connection = 1;
11903deb3ec6SMatthias Ringwald 
11913deb3ec6SMatthias Ringwald     // start next connection request if pending
11923deb3ec6SMatthias Ringwald     rfcomm_run();
11933deb3ec6SMatthias Ringwald }
11943deb3ec6SMatthias Ringwald 
11953deb3ec6SMatthias Ringwald static void rfcomm_channel_packet_handler_uih(rfcomm_multiplexer_t *multiplexer, uint8_t * packet, uint16_t size){
11963deb3ec6SMatthias Ringwald     const uint8_t frame_dlci = packet[0] >> 2;
11973deb3ec6SMatthias Ringwald     const uint8_t length_offset = (packet[2] & 1) ^ 1;  // to be used for pos >= 3
11983deb3ec6SMatthias Ringwald     const uint8_t credit_offset = ((packet[1] & BT_RFCOMM_UIH_PF) == BT_RFCOMM_UIH_PF) ? 1 : 0;   // credits for uih_pf frames
11993deb3ec6SMatthias Ringwald     const uint8_t payload_offset = 3 + length_offset + credit_offset;
12003deb3ec6SMatthias Ringwald 
12013deb3ec6SMatthias Ringwald     rfcomm_channel_t * channel = rfcomm_channel_for_multiplexer_and_dlci(multiplexer, frame_dlci);
12023deb3ec6SMatthias Ringwald     if (!channel) return;
12033deb3ec6SMatthias Ringwald 
12043deb3ec6SMatthias Ringwald     // handle new outgoing credits
12053deb3ec6SMatthias Ringwald     if (packet[1] == BT_RFCOMM_UIH_PF) {
12063deb3ec6SMatthias Ringwald 
12073deb3ec6SMatthias Ringwald         // add them
12083deb3ec6SMatthias Ringwald         uint16_t new_credits = packet[3+length_offset];
12093deb3ec6SMatthias Ringwald         channel->credits_outgoing += new_credits;
12103deb3ec6SMatthias Ringwald         log_info( "RFCOMM data UIH_PF, new credits: %u, now %u", new_credits, channel->credits_outgoing);
12113deb3ec6SMatthias Ringwald 
12123deb3ec6SMatthias Ringwald         // notify channel statemachine
12133deb3ec6SMatthias Ringwald         rfcomm_channel_event_t channel_event = { CH_EVT_RCVD_CREDITS };
12143deb3ec6SMatthias Ringwald         rfcomm_channel_state_machine(channel, &channel_event);
12153deb3ec6SMatthias Ringwald     }
12163deb3ec6SMatthias Ringwald 
12173deb3ec6SMatthias Ringwald     // contains payload?
12183deb3ec6SMatthias Ringwald     if (size - 1 > payload_offset){
12193deb3ec6SMatthias Ringwald 
12203deb3ec6SMatthias Ringwald         // log_info( "RFCOMM data UIH_PF, size %u, channel %p", size-payload_offset-1, rfChannel->connection);
12213deb3ec6SMatthias Ringwald 
12223deb3ec6SMatthias Ringwald         // decrease incoming credit counter
12233deb3ec6SMatthias Ringwald         if (channel->credits_incoming > 0){
12243deb3ec6SMatthias Ringwald             channel->credits_incoming--;
12253deb3ec6SMatthias Ringwald         }
12263deb3ec6SMatthias Ringwald 
12273deb3ec6SMatthias Ringwald         // deliver payload
1228fc376368SMatthias Ringwald         (channel->packet_handler)(RFCOMM_DATA_PACKET, channel->rfcomm_cid,
12293deb3ec6SMatthias Ringwald                               &packet[payload_offset], size-payload_offset-1);
12303deb3ec6SMatthias Ringwald     }
12313deb3ec6SMatthias Ringwald 
12323deb3ec6SMatthias Ringwald     // automatically provide new credits to remote device, if no incoming flow control
12333deb3ec6SMatthias Ringwald     if (!channel->incoming_flow_control && channel->credits_incoming < 5){
12343deb3ec6SMatthias Ringwald         channel->new_credits_incoming =RFCOMM_CREDITS;
12353deb3ec6SMatthias Ringwald     }
12363deb3ec6SMatthias Ringwald }
12373deb3ec6SMatthias Ringwald 
12383deb3ec6SMatthias Ringwald static void rfcomm_channel_accept_pn(rfcomm_channel_t *channel, rfcomm_channel_event_pn_t *event){
12393deb3ec6SMatthias Ringwald     // priority of client request
12403deb3ec6SMatthias Ringwald     channel->pn_priority = event->priority;
12413deb3ec6SMatthias Ringwald 
12423deb3ec6SMatthias Ringwald     // new credits
12433deb3ec6SMatthias Ringwald     channel->credits_outgoing = event->credits_outgoing;
12443deb3ec6SMatthias Ringwald 
12453deb3ec6SMatthias Ringwald     // negotiate max frame size
12463deb3ec6SMatthias Ringwald     if (channel->max_frame_size > channel->multiplexer->max_frame_size) {
12473deb3ec6SMatthias Ringwald         channel->max_frame_size = channel->multiplexer->max_frame_size;
12483deb3ec6SMatthias Ringwald     }
12493deb3ec6SMatthias Ringwald     if (channel->max_frame_size > event->max_frame_size) {
12503deb3ec6SMatthias Ringwald         channel->max_frame_size = event->max_frame_size;
12513deb3ec6SMatthias Ringwald     }
12523deb3ec6SMatthias Ringwald 
12533deb3ec6SMatthias Ringwald }
12543deb3ec6SMatthias Ringwald 
12553deb3ec6SMatthias Ringwald static void rfcomm_channel_finalize(rfcomm_channel_t *channel){
12563deb3ec6SMatthias Ringwald 
12573deb3ec6SMatthias Ringwald     rfcomm_multiplexer_t *multiplexer = channel->multiplexer;
12583deb3ec6SMatthias Ringwald 
12593deb3ec6SMatthias Ringwald     // remove from list
1260665d90f2SMatthias Ringwald     btstack_linked_list_remove( &rfcomm_channels, (btstack_linked_item_t *) channel);
12613deb3ec6SMatthias Ringwald 
12623deb3ec6SMatthias Ringwald     // free channel
12633deb3ec6SMatthias Ringwald     btstack_memory_rfcomm_channel_free(channel);
12643deb3ec6SMatthias Ringwald 
12653deb3ec6SMatthias Ringwald     // update multiplexer timeout after channel was removed from list
12663deb3ec6SMatthias Ringwald     rfcomm_multiplexer_prepare_idle_timer(multiplexer);
12673deb3ec6SMatthias Ringwald }
12683deb3ec6SMatthias Ringwald 
12693deb3ec6SMatthias Ringwald static void rfcomm_channel_state_machine_2(rfcomm_multiplexer_t * multiplexer, uint8_t dlci, rfcomm_channel_event_t *event){
12703deb3ec6SMatthias Ringwald 
12713deb3ec6SMatthias Ringwald     // TODO: if client max frame size is smaller than RFCOMM_DEFAULT_SIZE, send PN
12723deb3ec6SMatthias Ringwald 
12733deb3ec6SMatthias Ringwald 
12743deb3ec6SMatthias Ringwald     // lookup existing channel
12753deb3ec6SMatthias Ringwald     rfcomm_channel_t * channel = rfcomm_channel_for_multiplexer_and_dlci(multiplexer, dlci);
12763deb3ec6SMatthias Ringwald 
12773deb3ec6SMatthias Ringwald     // log_info("rfcomm_channel_state_machine_2 lookup dlci #%u = 0x%08x - event %u", dlci, (int) channel, event->type);
12783deb3ec6SMatthias Ringwald 
12793deb3ec6SMatthias Ringwald     if (channel) {
12803deb3ec6SMatthias Ringwald         rfcomm_channel_state_machine(channel, event);
12813deb3ec6SMatthias Ringwald         return;
12823deb3ec6SMatthias Ringwald     }
12833deb3ec6SMatthias Ringwald 
12843deb3ec6SMatthias Ringwald     // service registered?
12853deb3ec6SMatthias Ringwald     rfcomm_service_t * service = rfcomm_service_for_channel(dlci >> 1);
12863deb3ec6SMatthias Ringwald     // log_info("rfcomm_channel_state_machine_2 service dlci #%u = 0x%08x", dlci, (int) service);
12873deb3ec6SMatthias Ringwald     if (!service) {
12883deb3ec6SMatthias Ringwald         // discard request by sending disconnected mode
12893deb3ec6SMatthias Ringwald         multiplexer->send_dm_for_dlci = dlci;
12903deb3ec6SMatthias Ringwald         return;
12913deb3ec6SMatthias Ringwald     }
12923deb3ec6SMatthias Ringwald 
12933deb3ec6SMatthias Ringwald     // create channel for some events
12943deb3ec6SMatthias Ringwald     switch (event->type) {
12953deb3ec6SMatthias Ringwald         case CH_EVT_RCVD_SABM:
12963deb3ec6SMatthias Ringwald         case CH_EVT_RCVD_PN:
12973deb3ec6SMatthias Ringwald         case CH_EVT_RCVD_RPN_REQ:
12983deb3ec6SMatthias Ringwald         case CH_EVT_RCVD_RPN_CMD:
12993deb3ec6SMatthias Ringwald             // setup incoming channel
13003deb3ec6SMatthias Ringwald             channel = rfcomm_channel_create(multiplexer, service, dlci >> 1);
13013deb3ec6SMatthias Ringwald             if (!channel){
13023deb3ec6SMatthias Ringwald                 // discard request by sending disconnected mode
13033deb3ec6SMatthias Ringwald                 multiplexer->send_dm_for_dlci = dlci;
13043deb3ec6SMatthias Ringwald             }
13053deb3ec6SMatthias Ringwald             break;
13063deb3ec6SMatthias Ringwald         default:
13073deb3ec6SMatthias Ringwald             break;
13083deb3ec6SMatthias Ringwald     }
13093deb3ec6SMatthias Ringwald 
13103deb3ec6SMatthias Ringwald     if (!channel) {
13113deb3ec6SMatthias Ringwald         // discard request by sending disconnected mode
13123deb3ec6SMatthias Ringwald         multiplexer->send_dm_for_dlci = dlci;
13133deb3ec6SMatthias Ringwald         return;
13143deb3ec6SMatthias Ringwald     }
13153deb3ec6SMatthias Ringwald     rfcomm_channel_state_machine(channel, event);
13163deb3ec6SMatthias Ringwald }
13173deb3ec6SMatthias Ringwald 
13183deb3ec6SMatthias Ringwald static void rfcomm_channel_packet_handler(rfcomm_multiplexer_t * multiplexer,  uint8_t *packet, uint16_t size){
13193deb3ec6SMatthias Ringwald 
13203deb3ec6SMatthias Ringwald     // rfcomm: (0) addr [76543 server channel] [2 direction: initiator uses 1] [1 C/R: CMD by initiator = 1] [0 EA=1]
13213deb3ec6SMatthias Ringwald     const uint8_t frame_dlci = packet[0] >> 2;
13223deb3ec6SMatthias Ringwald     uint8_t message_dlci; // used by commands in UIH(_PF) packets
13233deb3ec6SMatthias Ringwald 	uint8_t message_len;  //   "
13243deb3ec6SMatthias Ringwald 
13253deb3ec6SMatthias Ringwald     // rfcomm: (1) command/control
13263deb3ec6SMatthias Ringwald     // -- credits_offset = 1 if command == BT_RFCOMM_UIH_PF
13273deb3ec6SMatthias Ringwald     const uint8_t credit_offset = ((packet[1] & BT_RFCOMM_UIH_PF) == BT_RFCOMM_UIH_PF) ? 1 : 0;   // credits for uih_pf frames
13283deb3ec6SMatthias Ringwald     // rfcomm: (2) length. if bit 0 is cleared, 2 byte length is used. (little endian)
13293deb3ec6SMatthias Ringwald     const uint8_t length_offset = (packet[2] & 1) ^ 1;  // to be used for pos >= 3
13303deb3ec6SMatthias Ringwald     // rfcomm: (3+length_offset) credits if credits_offset == 1
13313deb3ec6SMatthias Ringwald     // rfcomm: (3+length_offest+credits_offset)
13323deb3ec6SMatthias Ringwald     const uint8_t payload_offset = 3 + length_offset + credit_offset;
13333deb3ec6SMatthias Ringwald 
13343deb3ec6SMatthias Ringwald     rfcomm_channel_event_t event;
13353deb3ec6SMatthias Ringwald     rfcomm_channel_event_pn_t event_pn;
13363deb3ec6SMatthias Ringwald     rfcomm_channel_event_rpn_t event_rpn;
13373deb3ec6SMatthias Ringwald     rfcomm_channel_event_msc_t event_msc;
13383deb3ec6SMatthias Ringwald 
13393deb3ec6SMatthias Ringwald     // switch by rfcomm message type
13403deb3ec6SMatthias Ringwald     switch(packet[1]) {
13413deb3ec6SMatthias Ringwald 
13423deb3ec6SMatthias Ringwald         case BT_RFCOMM_SABM:
13433deb3ec6SMatthias Ringwald             event.type = CH_EVT_RCVD_SABM;
13443deb3ec6SMatthias Ringwald             log_info("Received SABM #%u", frame_dlci);
13453deb3ec6SMatthias Ringwald             rfcomm_channel_state_machine_2(multiplexer, frame_dlci, &event);
13463deb3ec6SMatthias Ringwald             break;
13473deb3ec6SMatthias Ringwald 
13483deb3ec6SMatthias Ringwald         case BT_RFCOMM_UA:
13493deb3ec6SMatthias Ringwald             event.type = CH_EVT_RCVD_UA;
13503deb3ec6SMatthias Ringwald             log_info("Received UA #%u",frame_dlci);
13513deb3ec6SMatthias Ringwald             rfcomm_channel_state_machine_2(multiplexer, frame_dlci, &event);
13523deb3ec6SMatthias Ringwald             break;
13533deb3ec6SMatthias Ringwald 
13543deb3ec6SMatthias Ringwald         case BT_RFCOMM_DISC:
13553deb3ec6SMatthias Ringwald             event.type = CH_EVT_RCVD_DISC;
13563deb3ec6SMatthias Ringwald             rfcomm_channel_state_machine_2(multiplexer, frame_dlci, &event);
13573deb3ec6SMatthias Ringwald             break;
13583deb3ec6SMatthias Ringwald 
13593deb3ec6SMatthias Ringwald         case BT_RFCOMM_DM:
13603deb3ec6SMatthias Ringwald         case BT_RFCOMM_DM_PF:
13613deb3ec6SMatthias Ringwald             event.type = CH_EVT_RCVD_DM;
13623deb3ec6SMatthias Ringwald             rfcomm_channel_state_machine_2(multiplexer, frame_dlci, &event);
13633deb3ec6SMatthias Ringwald             break;
13643deb3ec6SMatthias Ringwald 
13653deb3ec6SMatthias Ringwald         case BT_RFCOMM_UIH_PF:
13663deb3ec6SMatthias Ringwald         case BT_RFCOMM_UIH:
13673deb3ec6SMatthias Ringwald 
13683deb3ec6SMatthias Ringwald             message_len  = packet[payload_offset+1] >> 1;
13693deb3ec6SMatthias Ringwald 
13703deb3ec6SMatthias Ringwald             switch (packet[payload_offset]) {
13713deb3ec6SMatthias Ringwald                 case BT_RFCOMM_PN_CMD:
13723deb3ec6SMatthias Ringwald                     message_dlci = packet[payload_offset+2];
13733deb3ec6SMatthias Ringwald                     event_pn.super.type = CH_EVT_RCVD_PN;
13743deb3ec6SMatthias Ringwald                     event_pn.priority = packet[payload_offset+4];
1375f8fbdce0SMatthias Ringwald                     event_pn.max_frame_size = little_endian_read_16(packet, payload_offset+6);
13763deb3ec6SMatthias Ringwald                     event_pn.credits_outgoing = packet[payload_offset+9];
13773deb3ec6SMatthias Ringwald                     log_info("Received UIH Parameter Negotiation Command for #%u, credits %u",
13783deb3ec6SMatthias Ringwald                         message_dlci, event_pn.credits_outgoing);
13793deb3ec6SMatthias Ringwald                     rfcomm_channel_state_machine_2(multiplexer, message_dlci, (rfcomm_channel_event_t*) &event_pn);
13803deb3ec6SMatthias Ringwald                     break;
13813deb3ec6SMatthias Ringwald 
13823deb3ec6SMatthias Ringwald                 case BT_RFCOMM_PN_RSP:
13833deb3ec6SMatthias Ringwald                     message_dlci = packet[payload_offset+2];
13843deb3ec6SMatthias Ringwald                     event_pn.super.type = CH_EVT_RCVD_PN_RSP;
13853deb3ec6SMatthias Ringwald                     event_pn.priority = packet[payload_offset+4];
1386f8fbdce0SMatthias Ringwald                     event_pn.max_frame_size = little_endian_read_16(packet, payload_offset+6);
13873deb3ec6SMatthias Ringwald                     event_pn.credits_outgoing = packet[payload_offset+9];
13883deb3ec6SMatthias Ringwald                     log_info("Received UIH Parameter Negotiation Response max frame %u, credits %u",
13893deb3ec6SMatthias Ringwald                             event_pn.max_frame_size, event_pn.credits_outgoing);
13903deb3ec6SMatthias Ringwald                     rfcomm_channel_state_machine_2(multiplexer, message_dlci, (rfcomm_channel_event_t*) &event_pn);
13913deb3ec6SMatthias Ringwald                     break;
13923deb3ec6SMatthias Ringwald 
13933deb3ec6SMatthias Ringwald                 case BT_RFCOMM_MSC_CMD:
13943deb3ec6SMatthias Ringwald                     message_dlci = packet[payload_offset+2] >> 2;
13953deb3ec6SMatthias Ringwald                     event_msc.super.type = CH_EVT_RCVD_MSC_CMD;
13963deb3ec6SMatthias Ringwald                     event_msc.modem_status = packet[payload_offset+3];
13973deb3ec6SMatthias Ringwald                     log_info("Received MSC CMD for #%u, ", message_dlci);
13983deb3ec6SMatthias Ringwald                     rfcomm_channel_state_machine_2(multiplexer, message_dlci, (rfcomm_channel_event_t*) &event_msc);
13993deb3ec6SMatthias Ringwald                     break;
14003deb3ec6SMatthias Ringwald 
14013deb3ec6SMatthias Ringwald                 case BT_RFCOMM_MSC_RSP:
14023deb3ec6SMatthias Ringwald                     message_dlci = packet[payload_offset+2] >> 2;
14033deb3ec6SMatthias Ringwald                     event.type = CH_EVT_RCVD_MSC_RSP;
14043deb3ec6SMatthias Ringwald                     log_info("Received MSC RSP for #%u", message_dlci);
14053deb3ec6SMatthias Ringwald                     rfcomm_channel_state_machine_2(multiplexer, message_dlci, &event);
14063deb3ec6SMatthias Ringwald                     break;
14073deb3ec6SMatthias Ringwald 
14083deb3ec6SMatthias Ringwald                 case BT_RFCOMM_RPN_CMD:
14093deb3ec6SMatthias Ringwald                     message_dlci = packet[payload_offset+2] >> 2;
14103deb3ec6SMatthias Ringwald                     switch (message_len){
14113deb3ec6SMatthias Ringwald                         case 1:
14123deb3ec6SMatthias Ringwald                             log_info("Received Remote Port Negotiation Request for #%u", message_dlci);
14133deb3ec6SMatthias Ringwald                             event.type = CH_EVT_RCVD_RPN_REQ;
14143deb3ec6SMatthias Ringwald                             rfcomm_channel_state_machine_2(multiplexer, message_dlci, &event);
14153deb3ec6SMatthias Ringwald                             break;
14163deb3ec6SMatthias Ringwald                         case 8:
14173deb3ec6SMatthias Ringwald                             log_info("Received Remote Port Negotiation Update for #%u", message_dlci);
14183deb3ec6SMatthias Ringwald                             event_rpn.super.type = CH_EVT_RCVD_RPN_CMD;
14193deb3ec6SMatthias Ringwald                             event_rpn.data = *(rfcomm_rpn_data_t*) &packet[payload_offset+3];
14203deb3ec6SMatthias Ringwald                             rfcomm_channel_state_machine_2(multiplexer, message_dlci, (rfcomm_channel_event_t*) &event_rpn);
14213deb3ec6SMatthias Ringwald                             break;
14223deb3ec6SMatthias Ringwald                         default:
14233deb3ec6SMatthias Ringwald                             break;
14243deb3ec6SMatthias Ringwald                     }
14253deb3ec6SMatthias Ringwald                     break;
14263deb3ec6SMatthias Ringwald 
14273deb3ec6SMatthias Ringwald                 case BT_RFCOMM_RPN_RSP:
14283deb3ec6SMatthias Ringwald                     log_info("Received RPN response");
14293deb3ec6SMatthias Ringwald                     break;
14303deb3ec6SMatthias Ringwald 
14313deb3ec6SMatthias Ringwald                 case BT_RFCOMM_RLS_CMD: {
14323deb3ec6SMatthias Ringwald                     log_info("Received RLS command");
14333deb3ec6SMatthias Ringwald                     message_dlci = packet[payload_offset+2] >> 2;
14343deb3ec6SMatthias Ringwald                     rfcomm_channel_event_rls_t event_rls;
14353deb3ec6SMatthias Ringwald                     event_rls.super.type = CH_EVT_RCVD_RLS_CMD;
14363deb3ec6SMatthias Ringwald                     event_rls.line_status = packet[payload_offset+3];
14373deb3ec6SMatthias Ringwald                     rfcomm_channel_state_machine_2(multiplexer, message_dlci, (rfcomm_channel_event_t*) &event_rls);
14383deb3ec6SMatthias Ringwald                     break;
14393deb3ec6SMatthias Ringwald                 }
14403deb3ec6SMatthias Ringwald 
14413deb3ec6SMatthias Ringwald                 case BT_RFCOMM_RLS_RSP:
14423deb3ec6SMatthias Ringwald                     log_info("Received RLS response");
14433deb3ec6SMatthias Ringwald                     break;
14443deb3ec6SMatthias Ringwald 
14453deb3ec6SMatthias Ringwald                 // Following commands are handled by rfcomm_multiplexer_l2cap_packet_handler
14463deb3ec6SMatthias Ringwald                 // case BT_RFCOMM_TEST_CMD:
14473deb3ec6SMatthias Ringwald                 // case BT_RFCOMM_FCOFF_CMD:
14483deb3ec6SMatthias Ringwald                 // case BT_RFCOMM_FCON_CMD:
14493deb3ec6SMatthias Ringwald                 // everything else is an not supported command
14503deb3ec6SMatthias Ringwald                 default: {
14513deb3ec6SMatthias Ringwald                     log_error("Received unknown UIH command packet - 0x%02x", packet[payload_offset]);
14523deb3ec6SMatthias Ringwald                     multiplexer->nsc_command = packet[payload_offset];
14533deb3ec6SMatthias Ringwald                     break;
14543deb3ec6SMatthias Ringwald                 }
14553deb3ec6SMatthias Ringwald             }
14563deb3ec6SMatthias Ringwald             break;
14573deb3ec6SMatthias Ringwald 
14583deb3ec6SMatthias Ringwald         default:
14593deb3ec6SMatthias Ringwald             log_error("Received unknown RFCOMM message type %x", packet[1]);
14603deb3ec6SMatthias Ringwald             break;
14613deb3ec6SMatthias Ringwald     }
14623deb3ec6SMatthias Ringwald 
14633deb3ec6SMatthias Ringwald     // trigger next action - example W4_PN_RSP: transition to SEND_SABM which only depends on "can send"
14643deb3ec6SMatthias Ringwald     rfcomm_run();
14653deb3ec6SMatthias Ringwald }
14663deb3ec6SMatthias Ringwald 
1467457b5cb1SMatthias Ringwald static void rfcomm_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
14683deb3ec6SMatthias Ringwald 
14693deb3ec6SMatthias Ringwald     // multiplexer handler
14703deb3ec6SMatthias Ringwald     int handled = 0;
14713deb3ec6SMatthias Ringwald     switch (packet_type) {
14723deb3ec6SMatthias Ringwald         case HCI_EVENT_PACKET:
14733deb3ec6SMatthias Ringwald             handled = rfcomm_multiplexer_hci_event_handler(packet, size);
14743deb3ec6SMatthias Ringwald             break;
14753deb3ec6SMatthias Ringwald         case L2CAP_DATA_PACKET:
14763deb3ec6SMatthias Ringwald             handled = rfcomm_multiplexer_l2cap_packet_handler(channel, packet, size);
14773deb3ec6SMatthias Ringwald             break;
14783deb3ec6SMatthias Ringwald         default:
14793deb3ec6SMatthias Ringwald             break;
14803deb3ec6SMatthias Ringwald     }
14813deb3ec6SMatthias Ringwald 
14823deb3ec6SMatthias Ringwald     if (handled) {
14833deb3ec6SMatthias Ringwald         rfcomm_run();
14843deb3ec6SMatthias Ringwald         return;
14853deb3ec6SMatthias Ringwald     }
14863deb3ec6SMatthias Ringwald 
1487fc376368SMatthias Ringwald     // we only handle l2cap packets
1488fc376368SMatthias Ringwald     if (packet_type != L2CAP_DATA_PACKET) return;
1489fc376368SMatthias Ringwald 
1490fc376368SMatthias Ringwald     // ... over open multiplexer channel now
14913deb3ec6SMatthias Ringwald     rfcomm_multiplexer_t * multiplexer = rfcomm_multiplexer_for_l2cap_cid(channel);
1492fc376368SMatthias Ringwald     if (!multiplexer || multiplexer->state != RFCOMM_MULTIPLEXER_OPEN) return;
14933deb3ec6SMatthias Ringwald 
14943deb3ec6SMatthias Ringwald     // channel data ?
14953deb3ec6SMatthias Ringwald     // rfcomm: (0) addr [76543 server channel] [2 direction: initiator uses 1] [1 C/R: CMD by initiator = 1] [0 EA=1]
14963deb3ec6SMatthias Ringwald     const uint8_t frame_dlci = packet[0] >> 2;
14973deb3ec6SMatthias Ringwald 
14983deb3ec6SMatthias Ringwald     if (frame_dlci && (packet[1] == BT_RFCOMM_UIH || packet[1] == BT_RFCOMM_UIH_PF)) {
14993deb3ec6SMatthias Ringwald         rfcomm_channel_packet_handler_uih(multiplexer, packet, size);
15003deb3ec6SMatthias Ringwald         rfcomm_run();
15013deb3ec6SMatthias Ringwald         return;
15023deb3ec6SMatthias Ringwald     }
15033deb3ec6SMatthias Ringwald 
15043deb3ec6SMatthias Ringwald     rfcomm_channel_packet_handler(multiplexer, packet, size);
15053deb3ec6SMatthias Ringwald }
15063deb3ec6SMatthias Ringwald 
15073deb3ec6SMatthias Ringwald static int rfcomm_channel_ready_for_open(rfcomm_channel_t *channel){
15083deb3ec6SMatthias Ringwald     // note: exchanging MSC isn't neccessary to consider channel open
15093deb3ec6SMatthias Ringwald     // note: having outgoing credits is also not necessary to consider channel open
15103deb3ec6SMatthias 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);
15113deb3ec6SMatthias Ringwald     // if ((channel->state_var & RFCOMM_CHANNEL_STATE_VAR_SENT_MSC_RSP) == 0) return 0;
15123deb3ec6SMatthias Ringwald     // if (channel->credits_outgoing == 0) return 0;
15131e35c04dSMatthias Ringwald     log_info("rfcomm_channel_ready_for_open state %u, flags needed %04x, current %04x, rf credits %u",
15141e35c04dSMatthias Ringwald          channel->state, RFCOMM_CHANNEL_STATE_VAR_RCVD_MSC_RSP, channel->state_var, channel->credits_outgoing);
15153deb3ec6SMatthias Ringwald     if ((channel->state_var & RFCOMM_CHANNEL_STATE_VAR_RCVD_MSC_RSP) == 0) return 0;
15163deb3ec6SMatthias Ringwald     if ((channel->state_var & RFCOMM_CHANNEL_STATE_VAR_SENT_CREDITS) == 0) return 0;
15173deb3ec6SMatthias Ringwald 
15183deb3ec6SMatthias Ringwald     return 1;
15193deb3ec6SMatthias Ringwald }
15203deb3ec6SMatthias Ringwald 
15213deb3ec6SMatthias Ringwald static int rfcomm_channel_ready_for_incoming_dlc_setup(rfcomm_channel_t * channel){
15223deb3ec6SMatthias Ringwald     log_info("rfcomm_channel_ready_for_incoming_dlc_setup state var %04x", channel->state_var);
15233deb3ec6SMatthias Ringwald     // Client accept and SABM/UA is required, PN RSP is needed if PN was received
15243deb3ec6SMatthias Ringwald     if ((channel->state_var & RFCOMM_CHANNEL_STATE_VAR_CLIENT_ACCEPTED) == 0) return 0;
15253deb3ec6SMatthias Ringwald     if ((channel->state_var & RFCOMM_CHANNEL_STATE_VAR_RCVD_SABM      ) == 0) return 0;
15263deb3ec6SMatthias Ringwald     if ((channel->state_var & RFCOMM_CHANNEL_STATE_VAR_SEND_UA        ) != 0) return 0;
15273deb3ec6SMatthias Ringwald     if ((channel->state_var & RFCOMM_CHANNEL_STATE_VAR_SEND_PN_RSP    ) != 0) return 0;
15283deb3ec6SMatthias Ringwald     return 1;
15293deb3ec6SMatthias Ringwald }
15303deb3ec6SMatthias Ringwald 
15313deb3ec6SMatthias Ringwald inline static void rfcomm_channel_state_add(rfcomm_channel_t *channel, RFCOMM_CHANNEL_STATE_VAR event){
15323deb3ec6SMatthias Ringwald     channel->state_var = (RFCOMM_CHANNEL_STATE_VAR) (channel->state_var | event);
15333deb3ec6SMatthias Ringwald }
15343deb3ec6SMatthias Ringwald inline static void rfcomm_channel_state_remove(rfcomm_channel_t *channel, RFCOMM_CHANNEL_STATE_VAR event){
15353deb3ec6SMatthias Ringwald     channel->state_var = (RFCOMM_CHANNEL_STATE_VAR) (channel->state_var & ~event);
15363deb3ec6SMatthias Ringwald }
15373deb3ec6SMatthias Ringwald 
15383deb3ec6SMatthias Ringwald static void rfcomm_channel_state_machine(rfcomm_channel_t *channel, rfcomm_channel_event_t *event){
15393deb3ec6SMatthias Ringwald 
15403deb3ec6SMatthias Ringwald     // log_info("rfcomm_channel_state_machine: state %u, state_var %04x, event %u", channel->state, channel->state_var ,event->type);
15413deb3ec6SMatthias Ringwald 
15423deb3ec6SMatthias Ringwald     rfcomm_multiplexer_t *multiplexer = channel->multiplexer;
15433deb3ec6SMatthias Ringwald 
15443deb3ec6SMatthias Ringwald     // TODO: integrate in common switch
15453deb3ec6SMatthias Ringwald     if (event->type == CH_EVT_RCVD_DISC){
15463deb3ec6SMatthias Ringwald         rfcomm_emit_channel_closed(channel);
15473deb3ec6SMatthias Ringwald         channel->state = RFCOMM_CHANNEL_SEND_UA_AFTER_DISC;
15483deb3ec6SMatthias Ringwald         return;
15493deb3ec6SMatthias Ringwald     }
15503deb3ec6SMatthias Ringwald 
15513deb3ec6SMatthias Ringwald     // TODO: integrate in common switch
15523deb3ec6SMatthias Ringwald     if (event->type == CH_EVT_RCVD_DM){
15533deb3ec6SMatthias Ringwald         log_info("Received DM message for #%u", channel->dlci);
15543deb3ec6SMatthias Ringwald         log_info("-> Closing channel locally for #%u", channel->dlci);
15553deb3ec6SMatthias Ringwald         rfcomm_emit_channel_closed(channel);
15563deb3ec6SMatthias Ringwald         rfcomm_channel_finalize(channel);
15573deb3ec6SMatthias Ringwald         return;
15583deb3ec6SMatthias Ringwald     }
15593deb3ec6SMatthias Ringwald 
15603deb3ec6SMatthias Ringwald     // remote port negotiation command - just accept everything for now
15613deb3ec6SMatthias Ringwald     //
15623deb3ec6SMatthias Ringwald     // "The RPN command can be used before a new DLC is opened and should be used whenever the port settings change."
15633deb3ec6SMatthias Ringwald     // "The RPN command is specified as optional in TS 07.10, but it is mandatory to recognize and respond to it in RFCOMM.
15643deb3ec6SMatthias Ringwald     //   (Although the handling of individual settings are implementation-dependent.)"
15653deb3ec6SMatthias Ringwald     //
15663deb3ec6SMatthias Ringwald 
15673deb3ec6SMatthias Ringwald     // TODO: integrate in common switch
15683deb3ec6SMatthias Ringwald     if (event->type == CH_EVT_RCVD_RPN_CMD){
15693deb3ec6SMatthias Ringwald         // control port parameters
15703deb3ec6SMatthias Ringwald         rfcomm_channel_event_rpn_t *event_rpn = (rfcomm_channel_event_rpn_t*) event;
15713deb3ec6SMatthias Ringwald         rfcomm_rpn_data_update(&channel->rpn_data, &event_rpn->data);
15723deb3ec6SMatthias Ringwald         rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_RPN_RSP);
15733deb3ec6SMatthias Ringwald         // notify client about new settings
15743deb3ec6SMatthias Ringwald         rfcomm_emit_port_configuration(channel);
15753deb3ec6SMatthias Ringwald         return;
15763deb3ec6SMatthias Ringwald     }
15773deb3ec6SMatthias Ringwald 
15783deb3ec6SMatthias Ringwald     // TODO: integrate in common switch
15793deb3ec6SMatthias Ringwald     if (event->type == CH_EVT_RCVD_RPN_REQ){
15803deb3ec6SMatthias Ringwald         // no values got accepted (no values have beens sent)
15813deb3ec6SMatthias Ringwald         channel->rpn_data.parameter_mask_0 = 0x00;
15823deb3ec6SMatthias Ringwald         channel->rpn_data.parameter_mask_1 = 0x00;
15833deb3ec6SMatthias Ringwald         rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_RPN_RSP);
15843deb3ec6SMatthias Ringwald         return;
15853deb3ec6SMatthias Ringwald     }
15863deb3ec6SMatthias Ringwald 
15873deb3ec6SMatthias Ringwald     if (event->type == CH_EVT_RCVD_RLS_CMD){
15883deb3ec6SMatthias Ringwald         rfcomm_channel_event_rls_t * event_rls = (rfcomm_channel_event_rls_t*) event;
15893deb3ec6SMatthias Ringwald         channel->rls_line_status = event_rls->line_status & 0x0f;
15903deb3ec6SMatthias Ringwald         log_info("CH_EVT_RCVD_RLS_CMD setting line status to 0x%0x", channel->rls_line_status);
15913deb3ec6SMatthias Ringwald         rfcomm_emit_remote_line_status(channel, event_rls->line_status);
15923deb3ec6SMatthias Ringwald         return;
15933deb3ec6SMatthias Ringwald     }
15943deb3ec6SMatthias Ringwald 
15953deb3ec6SMatthias Ringwald     // TODO: integrate in common swich
15963deb3ec6SMatthias Ringwald     if (event->type == CH_EVT_READY_TO_SEND){
15973deb3ec6SMatthias Ringwald         if (channel->state_var & RFCOMM_CHANNEL_STATE_VAR_SEND_RPN_RSP){
15983deb3ec6SMatthias Ringwald             log_info("Sending Remote Port Negotiation RSP for #%u", channel->dlci);
15993deb3ec6SMatthias Ringwald             rfcomm_channel_state_remove(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_RPN_RSP);
16003deb3ec6SMatthias Ringwald             rfcomm_send_uih_rpn_rsp(multiplexer, channel->dlci, &channel->rpn_data);
16013deb3ec6SMatthias Ringwald             return;
16023deb3ec6SMatthias Ringwald         }
16033deb3ec6SMatthias Ringwald         if (channel->state_var & RFCOMM_CHANNEL_STATE_VAR_SEND_MSC_RSP){
16043deb3ec6SMatthias Ringwald             log_info("Sending MSC RSP for #%u", channel->dlci);
16053deb3ec6SMatthias Ringwald             rfcomm_channel_state_remove(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_MSC_RSP);
16063deb3ec6SMatthias Ringwald             rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_SENT_MSC_RSP);
16073deb3ec6SMatthias Ringwald             rfcomm_send_uih_msc_rsp(multiplexer, channel->dlci, 0x8d);  // ea=1,fc=0,rtc=1,rtr=1,ic=0,dv=1
16083deb3ec6SMatthias Ringwald             return;
16093deb3ec6SMatthias Ringwald         }
16103deb3ec6SMatthias Ringwald         if (channel->rls_line_status != RFCOMM_RLS_STATUS_INVALID){
16113deb3ec6SMatthias Ringwald             log_info("Sending RLS RSP 0x%0x", channel->rls_line_status);
16123deb3ec6SMatthias Ringwald             uint8_t line_status = channel->rls_line_status;
16133deb3ec6SMatthias Ringwald             channel->rls_line_status = RFCOMM_RLS_STATUS_INVALID;
16143deb3ec6SMatthias Ringwald             rfcomm_send_uih_rls_rsp(multiplexer, channel->dlci, line_status);
16153deb3ec6SMatthias Ringwald             return;
16163deb3ec6SMatthias Ringwald         }
16173deb3ec6SMatthias Ringwald     }
16183deb3ec6SMatthias Ringwald 
16193deb3ec6SMatthias Ringwald     // emit MSC status to app
16203deb3ec6SMatthias Ringwald     if (event->type == CH_EVT_RCVD_MSC_CMD){
16213deb3ec6SMatthias Ringwald         // notify client about new settings
16223deb3ec6SMatthias Ringwald         rfcomm_channel_event_msc_t *event_msc = (rfcomm_channel_event_msc_t*) event;
16233deb3ec6SMatthias Ringwald         uint8_t modem_status_event[2+1];
16243deb3ec6SMatthias Ringwald         modem_status_event[0] = RFCOMM_EVENT_REMOTE_MODEM_STATUS;
16253deb3ec6SMatthias Ringwald         modem_status_event[1] = 1;
16263deb3ec6SMatthias Ringwald         modem_status_event[2] = event_msc->modem_status;
1627fc376368SMatthias Ringwald         (channel->packet_handler)(HCI_EVENT_PACKET, channel->rfcomm_cid, (uint8_t*)&modem_status_event, sizeof(modem_status_event));
16283deb3ec6SMatthias Ringwald         // no return, MSC_CMD will be handled by state machine below
16293deb3ec6SMatthias Ringwald     }
16303deb3ec6SMatthias Ringwald 
16313deb3ec6SMatthias Ringwald     rfcomm_channel_event_pn_t * event_pn = (rfcomm_channel_event_pn_t*) event;
16323deb3ec6SMatthias Ringwald 
16333deb3ec6SMatthias Ringwald     switch (channel->state) {
16343deb3ec6SMatthias Ringwald         case RFCOMM_CHANNEL_CLOSED:
16353deb3ec6SMatthias Ringwald             switch (event->type){
16363deb3ec6SMatthias Ringwald                 case CH_EVT_RCVD_SABM:
16373deb3ec6SMatthias Ringwald                     log_info("-> Inform app");
16383deb3ec6SMatthias Ringwald                     rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_RCVD_SABM);
16393deb3ec6SMatthias Ringwald                     channel->state = RFCOMM_CHANNEL_INCOMING_SETUP;
16403deb3ec6SMatthias Ringwald                     rfcomm_emit_connection_request(channel);
16413deb3ec6SMatthias Ringwald                     break;
16423deb3ec6SMatthias Ringwald                 case CH_EVT_RCVD_PN:
16433deb3ec6SMatthias Ringwald                     rfcomm_channel_accept_pn(channel, event_pn);
16443deb3ec6SMatthias Ringwald                     log_info("-> Inform app");
16453deb3ec6SMatthias Ringwald                     rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_RCVD_PN);
16463deb3ec6SMatthias Ringwald                     channel->state = RFCOMM_CHANNEL_INCOMING_SETUP;
16473deb3ec6SMatthias Ringwald                     rfcomm_emit_connection_request(channel);
16483deb3ec6SMatthias Ringwald                     break;
16493deb3ec6SMatthias Ringwald                 default:
16503deb3ec6SMatthias Ringwald                     break;
16513deb3ec6SMatthias Ringwald             }
16523deb3ec6SMatthias Ringwald             break;
16533deb3ec6SMatthias Ringwald 
16543deb3ec6SMatthias Ringwald         case RFCOMM_CHANNEL_INCOMING_SETUP:
16553deb3ec6SMatthias Ringwald             switch (event->type){
16563deb3ec6SMatthias Ringwald                 case CH_EVT_RCVD_SABM:
16573deb3ec6SMatthias Ringwald                     rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_RCVD_SABM);
16583deb3ec6SMatthias Ringwald                     if (channel->state_var & RFCOMM_CHANNEL_STATE_VAR_CLIENT_ACCEPTED) {
16593deb3ec6SMatthias Ringwald                         rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_UA);
16603deb3ec6SMatthias Ringwald                     }
16613deb3ec6SMatthias Ringwald                     break;
16623deb3ec6SMatthias Ringwald                 case CH_EVT_RCVD_PN:
16633deb3ec6SMatthias Ringwald                     rfcomm_channel_accept_pn(channel, event_pn);
16643deb3ec6SMatthias Ringwald                     rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_RCVD_PN);
16653deb3ec6SMatthias Ringwald                     if (channel->state_var & RFCOMM_CHANNEL_STATE_VAR_CLIENT_ACCEPTED) {
16663deb3ec6SMatthias Ringwald                         rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_PN_RSP);
16673deb3ec6SMatthias Ringwald                     }
16683deb3ec6SMatthias Ringwald                     break;
16693deb3ec6SMatthias Ringwald                 case CH_EVT_READY_TO_SEND:
16703deb3ec6SMatthias Ringwald                     // if / else if is used to check for state transition after sending
16713deb3ec6SMatthias Ringwald                     if (channel->state_var & RFCOMM_CHANNEL_STATE_VAR_SEND_PN_RSP){
16723deb3ec6SMatthias Ringwald                         log_info("Sending UIH Parameter Negotiation Respond for #%u", channel->dlci);
16733deb3ec6SMatthias Ringwald                         rfcomm_channel_state_remove(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_PN_RSP);
16743deb3ec6SMatthias Ringwald                         rfcomm_send_uih_pn_response(multiplexer, channel->dlci, channel->pn_priority, channel->max_frame_size);
16753deb3ec6SMatthias Ringwald                     } else if (channel->state_var & RFCOMM_CHANNEL_STATE_VAR_SEND_UA){
16763deb3ec6SMatthias Ringwald                         log_info("Sending UA #%u", channel->dlci);
16773deb3ec6SMatthias Ringwald                         rfcomm_channel_state_remove(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_UA);
16783deb3ec6SMatthias Ringwald                         rfcomm_send_ua(multiplexer, channel->dlci);
16793deb3ec6SMatthias Ringwald                     }
16803deb3ec6SMatthias Ringwald                     if (rfcomm_channel_ready_for_incoming_dlc_setup(channel)){
16813deb3ec6SMatthias Ringwald                         log_info("Incomping setup done, requesting send MSC CMD and send Credits");
16823deb3ec6SMatthias Ringwald                         rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_MSC_CMD);
16833deb3ec6SMatthias Ringwald                         rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_CREDITS);
16843deb3ec6SMatthias Ringwald                         channel->state = RFCOMM_CHANNEL_DLC_SETUP;
16853deb3ec6SMatthias Ringwald                     }
16863deb3ec6SMatthias Ringwald                     break;
16873deb3ec6SMatthias Ringwald                 default:
16883deb3ec6SMatthias Ringwald                     break;
16893deb3ec6SMatthias Ringwald             }
16903deb3ec6SMatthias Ringwald             break;
16913deb3ec6SMatthias Ringwald 
16923deb3ec6SMatthias Ringwald         case RFCOMM_CHANNEL_W4_MULTIPLEXER:
16933deb3ec6SMatthias Ringwald             switch (event->type) {
16943deb3ec6SMatthias Ringwald                 case CH_EVT_MULTIPLEXER_READY:
16953deb3ec6SMatthias Ringwald                     log_info("Muliplexer opened, sending UIH PN next");
16963deb3ec6SMatthias Ringwald                     channel->state = RFCOMM_CHANNEL_SEND_UIH_PN;
16973deb3ec6SMatthias Ringwald                     break;
16983deb3ec6SMatthias Ringwald                 default:
16993deb3ec6SMatthias Ringwald                     break;
17003deb3ec6SMatthias Ringwald             }
17013deb3ec6SMatthias Ringwald             break;
17023deb3ec6SMatthias Ringwald 
17033deb3ec6SMatthias Ringwald         case RFCOMM_CHANNEL_SEND_UIH_PN:
17043deb3ec6SMatthias Ringwald             switch (event->type) {
17053deb3ec6SMatthias Ringwald                 case CH_EVT_READY_TO_SEND:
17063deb3ec6SMatthias Ringwald                     log_info("Sending UIH Parameter Negotiation Command for #%u (channel 0x%p)", channel->dlci, channel );
17073deb3ec6SMatthias Ringwald                     channel->state = RFCOMM_CHANNEL_W4_PN_RSP;
17083deb3ec6SMatthias Ringwald                     rfcomm_send_uih_pn_command(multiplexer, channel->dlci, channel->max_frame_size);
17093deb3ec6SMatthias Ringwald                     break;
17103deb3ec6SMatthias Ringwald                 default:
17113deb3ec6SMatthias Ringwald                     break;
17123deb3ec6SMatthias Ringwald             }
17133deb3ec6SMatthias Ringwald             break;
17143deb3ec6SMatthias Ringwald 
17153deb3ec6SMatthias Ringwald         case RFCOMM_CHANNEL_W4_PN_RSP:
17163deb3ec6SMatthias Ringwald             switch (event->type){
17173deb3ec6SMatthias Ringwald                 case CH_EVT_RCVD_PN_RSP:
17183deb3ec6SMatthias Ringwald                     // update max frame size
17193deb3ec6SMatthias Ringwald                     if (channel->max_frame_size > event_pn->max_frame_size) {
17203deb3ec6SMatthias Ringwald                         channel->max_frame_size = event_pn->max_frame_size;
17213deb3ec6SMatthias Ringwald                     }
17223deb3ec6SMatthias Ringwald                     // new credits
17233deb3ec6SMatthias Ringwald                     channel->credits_outgoing = event_pn->credits_outgoing;
17243deb3ec6SMatthias Ringwald                     channel->state = RFCOMM_CHANNEL_SEND_SABM_W4_UA;
17253deb3ec6SMatthias Ringwald                     break;
17263deb3ec6SMatthias Ringwald                 default:
17273deb3ec6SMatthias Ringwald                     break;
17283deb3ec6SMatthias Ringwald             }
17293deb3ec6SMatthias Ringwald             break;
17303deb3ec6SMatthias Ringwald 
17313deb3ec6SMatthias Ringwald         case RFCOMM_CHANNEL_SEND_SABM_W4_UA:
17323deb3ec6SMatthias Ringwald             switch (event->type) {
17333deb3ec6SMatthias Ringwald                 case CH_EVT_READY_TO_SEND:
17343deb3ec6SMatthias Ringwald                     log_info("Sending SABM #%u", channel->dlci);
17353deb3ec6SMatthias Ringwald                     channel->state = RFCOMM_CHANNEL_W4_UA;
17363deb3ec6SMatthias Ringwald                     rfcomm_send_sabm(multiplexer, channel->dlci);
17373deb3ec6SMatthias Ringwald                     break;
17383deb3ec6SMatthias Ringwald                 default:
17393deb3ec6SMatthias Ringwald                     break;
17403deb3ec6SMatthias Ringwald             }
17413deb3ec6SMatthias Ringwald             break;
17423deb3ec6SMatthias Ringwald 
17433deb3ec6SMatthias Ringwald         case RFCOMM_CHANNEL_W4_UA:
17443deb3ec6SMatthias Ringwald             switch (event->type){
17453deb3ec6SMatthias Ringwald                 case CH_EVT_RCVD_UA:
17463deb3ec6SMatthias Ringwald                     channel->state = RFCOMM_CHANNEL_DLC_SETUP;
17473deb3ec6SMatthias Ringwald                     rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_MSC_CMD);
17483deb3ec6SMatthias Ringwald                     rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_CREDITS);
17493deb3ec6SMatthias Ringwald                     break;
17503deb3ec6SMatthias Ringwald                 default:
17513deb3ec6SMatthias Ringwald                     break;
17523deb3ec6SMatthias Ringwald             }
17533deb3ec6SMatthias Ringwald             break;
17543deb3ec6SMatthias Ringwald 
17553deb3ec6SMatthias Ringwald         case RFCOMM_CHANNEL_DLC_SETUP:
17563deb3ec6SMatthias Ringwald             switch (event->type){
17573deb3ec6SMatthias Ringwald                 case CH_EVT_RCVD_MSC_CMD:
17583deb3ec6SMatthias Ringwald                     rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_RCVD_MSC_CMD);
17593deb3ec6SMatthias Ringwald                     rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_MSC_RSP);
17603deb3ec6SMatthias Ringwald                     break;
17613deb3ec6SMatthias Ringwald                 case CH_EVT_RCVD_MSC_RSP:
17623deb3ec6SMatthias Ringwald                     rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_RCVD_MSC_RSP);
17633deb3ec6SMatthias Ringwald                     break;
17643deb3ec6SMatthias Ringwald 
17653deb3ec6SMatthias Ringwald                 case CH_EVT_READY_TO_SEND:
17663deb3ec6SMatthias Ringwald                     if (channel->state_var & RFCOMM_CHANNEL_STATE_VAR_SEND_MSC_CMD){
17673deb3ec6SMatthias Ringwald                         log_info("Sending MSC CMD for #%u", channel->dlci);
17683deb3ec6SMatthias Ringwald                         rfcomm_channel_state_remove(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_MSC_CMD);
17693deb3ec6SMatthias Ringwald                         rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_SENT_MSC_CMD);
17703deb3ec6SMatthias Ringwald                         rfcomm_send_uih_msc_cmd(multiplexer, channel->dlci , 0x8d);  // ea=1,fc=0,rtc=1,rtr=1,ic=0,dv=1
17713deb3ec6SMatthias Ringwald                         break;
17723deb3ec6SMatthias Ringwald                     }
17733deb3ec6SMatthias Ringwald                     if (channel->state_var & RFCOMM_CHANNEL_STATE_VAR_SEND_CREDITS){
17743deb3ec6SMatthias Ringwald                         log_info("Providing credits for #%u", channel->dlci);
17753deb3ec6SMatthias Ringwald                         rfcomm_channel_state_remove(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_CREDITS);
17763deb3ec6SMatthias Ringwald                         rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_SENT_CREDITS);
17773deb3ec6SMatthias Ringwald 
17783deb3ec6SMatthias Ringwald                         if (channel->new_credits_incoming) {
17793deb3ec6SMatthias Ringwald                             uint8_t new_credits = channel->new_credits_incoming;
17803deb3ec6SMatthias Ringwald                             channel->new_credits_incoming = 0;
17813deb3ec6SMatthias Ringwald                             rfcomm_channel_send_credits(channel, new_credits);
17823deb3ec6SMatthias Ringwald                         }
17833deb3ec6SMatthias Ringwald                         break;
17843deb3ec6SMatthias Ringwald 
17853deb3ec6SMatthias Ringwald                     }
17863deb3ec6SMatthias Ringwald                     break;
17873deb3ec6SMatthias Ringwald                 default:
17883deb3ec6SMatthias Ringwald                     break;
17893deb3ec6SMatthias Ringwald             }
17903deb3ec6SMatthias Ringwald             // finally done?
17913deb3ec6SMatthias Ringwald             if (rfcomm_channel_ready_for_open(channel)){
17923deb3ec6SMatthias Ringwald                 channel->state = RFCOMM_CHANNEL_OPEN;
17933deb3ec6SMatthias Ringwald                 rfcomm_channel_opened(channel);
17943deb3ec6SMatthias Ringwald             }
17953deb3ec6SMatthias Ringwald             break;
17963deb3ec6SMatthias Ringwald 
17973deb3ec6SMatthias Ringwald         case RFCOMM_CHANNEL_OPEN:
17983deb3ec6SMatthias Ringwald             switch (event->type){
17993deb3ec6SMatthias Ringwald                 case CH_EVT_RCVD_MSC_CMD:
18003deb3ec6SMatthias Ringwald                     rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_MSC_RSP);
18013deb3ec6SMatthias Ringwald                     break;
18023deb3ec6SMatthias Ringwald                 case CH_EVT_READY_TO_SEND:
18033deb3ec6SMatthias Ringwald                     if (channel->new_credits_incoming) {
18043deb3ec6SMatthias Ringwald                         uint8_t new_credits = channel->new_credits_incoming;
18053deb3ec6SMatthias Ringwald                         channel->new_credits_incoming = 0;
18063deb3ec6SMatthias Ringwald                         rfcomm_channel_send_credits(channel, new_credits);
18073deb3ec6SMatthias Ringwald                         break;
18083deb3ec6SMatthias Ringwald                     }
18093deb3ec6SMatthias Ringwald                     break;
1810b31d33b2SMatthias Ringwald                 case CH_EVT_RCVD_CREDITS:
1811b31d33b2SMatthias Ringwald                     rfcomm_notify_channel_can_send();
18123deb3ec6SMatthias Ringwald                     break;
18133deb3ec6SMatthias Ringwald                 default:
18143deb3ec6SMatthias Ringwald                     break;
18153deb3ec6SMatthias Ringwald             }
18163deb3ec6SMatthias Ringwald             break;
18173deb3ec6SMatthias Ringwald 
18183deb3ec6SMatthias Ringwald         case RFCOMM_CHANNEL_SEND_DM:
18193deb3ec6SMatthias Ringwald             switch (event->type) {
18203deb3ec6SMatthias Ringwald                 case CH_EVT_READY_TO_SEND:
18213deb3ec6SMatthias Ringwald                     log_info("Sending DM_PF for #%u", channel->dlci);
18223deb3ec6SMatthias Ringwald                     // don't emit channel closed - channel was never open
18233deb3ec6SMatthias Ringwald                     channel->state = RFCOMM_CHANNEL_CLOSED;
18243deb3ec6SMatthias Ringwald                     rfcomm_send_dm_pf(multiplexer, channel->dlci);
18253deb3ec6SMatthias Ringwald                     rfcomm_channel_finalize(channel);
18263deb3ec6SMatthias Ringwald                     break;
18273deb3ec6SMatthias Ringwald                 default:
18283deb3ec6SMatthias Ringwald                     break;
18293deb3ec6SMatthias Ringwald             }
18303deb3ec6SMatthias Ringwald             break;
18313deb3ec6SMatthias Ringwald 
18323deb3ec6SMatthias Ringwald         case RFCOMM_CHANNEL_SEND_DISC:
18333deb3ec6SMatthias Ringwald             switch (event->type) {
18343deb3ec6SMatthias Ringwald                 case CH_EVT_READY_TO_SEND:
18353deb3ec6SMatthias Ringwald                     channel->state = RFCOMM_CHANNEL_W4_UA_AFTER_UA;
18363deb3ec6SMatthias Ringwald                     rfcomm_send_disc(multiplexer, channel->dlci);
18373deb3ec6SMatthias Ringwald                     break;
18383deb3ec6SMatthias Ringwald                 default:
18393deb3ec6SMatthias Ringwald                     break;
18403deb3ec6SMatthias Ringwald             }
18413deb3ec6SMatthias Ringwald             break;
18423deb3ec6SMatthias Ringwald 
18433deb3ec6SMatthias Ringwald         case RFCOMM_CHANNEL_W4_UA_AFTER_UA:
18443deb3ec6SMatthias Ringwald             switch (event->type){
18453deb3ec6SMatthias Ringwald                 case CH_EVT_RCVD_UA:
18463deb3ec6SMatthias Ringwald                     channel->state = RFCOMM_CHANNEL_CLOSED;
18473deb3ec6SMatthias Ringwald                     rfcomm_emit_channel_closed(channel);
18483deb3ec6SMatthias Ringwald                     rfcomm_channel_finalize(channel);
18493deb3ec6SMatthias Ringwald                     break;
18503deb3ec6SMatthias Ringwald                 default:
18513deb3ec6SMatthias Ringwald                     break;
18523deb3ec6SMatthias Ringwald             }
18533deb3ec6SMatthias Ringwald             break;
18543deb3ec6SMatthias Ringwald 
18553deb3ec6SMatthias Ringwald         case RFCOMM_CHANNEL_SEND_UA_AFTER_DISC:
18563deb3ec6SMatthias Ringwald             switch (event->type) {
18573deb3ec6SMatthias Ringwald                 case CH_EVT_READY_TO_SEND:
18583deb3ec6SMatthias Ringwald                     log_info("Sending UA after DISC for #%u", channel->dlci);
18593deb3ec6SMatthias Ringwald                     channel->state = RFCOMM_CHANNEL_CLOSED;
18603deb3ec6SMatthias Ringwald                     rfcomm_send_ua(multiplexer, channel->dlci);
18613deb3ec6SMatthias Ringwald                     rfcomm_channel_finalize(channel);
18623deb3ec6SMatthias Ringwald                     break;
18633deb3ec6SMatthias Ringwald                 default:
18643deb3ec6SMatthias Ringwald                     break;
18653deb3ec6SMatthias Ringwald             }
18663deb3ec6SMatthias Ringwald             break;
18673deb3ec6SMatthias Ringwald 
18683deb3ec6SMatthias Ringwald         default:
18693deb3ec6SMatthias Ringwald             break;
18703deb3ec6SMatthias Ringwald     }
18713deb3ec6SMatthias Ringwald }
18723deb3ec6SMatthias Ringwald 
18733deb3ec6SMatthias Ringwald 
18743deb3ec6SMatthias Ringwald // MARK: RFCOMM RUN
18753deb3ec6SMatthias Ringwald // process outstanding signaling tasks
18763deb3ec6SMatthias Ringwald static void rfcomm_run(void){
18773deb3ec6SMatthias Ringwald 
1878665d90f2SMatthias Ringwald     btstack_linked_item_t *it;
1879665d90f2SMatthias Ringwald     btstack_linked_item_t *next;
18803deb3ec6SMatthias Ringwald 
1881665d90f2SMatthias Ringwald     for (it = (btstack_linked_item_t *) rfcomm_multiplexers; it ; it = next){
18823deb3ec6SMatthias Ringwald 
18833deb3ec6SMatthias Ringwald         next = it->next;    // be prepared for removal of channel in state machine
18843deb3ec6SMatthias Ringwald 
18853deb3ec6SMatthias Ringwald         rfcomm_multiplexer_t * multiplexer = ((rfcomm_multiplexer_t *) it);
18863deb3ec6SMatthias Ringwald 
18873deb3ec6SMatthias Ringwald         if (!l2cap_can_send_packet_now(multiplexer->l2cap_cid)) {
18883deb3ec6SMatthias Ringwald             // log_info("rfcomm_run A cannot send l2cap packet for #%u, credits %u", multiplexer->l2cap_cid, multiplexer->l2cap_credits);
18893deb3ec6SMatthias Ringwald             continue;
18903deb3ec6SMatthias Ringwald         }
18913deb3ec6SMatthias Ringwald         // log_info("rfcomm_run: multi 0x%08x, state %u", (int) multiplexer, multiplexer->state);
18923deb3ec6SMatthias Ringwald 
18933deb3ec6SMatthias Ringwald         rfcomm_multiplexer_state_machine(multiplexer, MULT_EV_READY_TO_SEND);
18943deb3ec6SMatthias Ringwald     }
18953deb3ec6SMatthias Ringwald 
1896665d90f2SMatthias Ringwald     for (it = (btstack_linked_item_t *) rfcomm_channels; it ; it = next){
18973deb3ec6SMatthias Ringwald 
18983deb3ec6SMatthias Ringwald         next = it->next;    // be prepared for removal of channel in state machine
18993deb3ec6SMatthias Ringwald 
19003deb3ec6SMatthias Ringwald         rfcomm_channel_t * channel = ((rfcomm_channel_t *) it);
19013deb3ec6SMatthias Ringwald         rfcomm_multiplexer_t * multiplexer = channel->multiplexer;
19023deb3ec6SMatthias Ringwald 
19033deb3ec6SMatthias Ringwald         if (!l2cap_can_send_packet_now(multiplexer->l2cap_cid)) {
19043deb3ec6SMatthias Ringwald             // log_info("rfcomm_run B cannot send l2cap packet for #%u, credits %u", multiplexer->l2cap_cid, multiplexer->l2cap_credits);
19053deb3ec6SMatthias Ringwald             continue;
19063deb3ec6SMatthias Ringwald         }
19073deb3ec6SMatthias Ringwald 
19083deb3ec6SMatthias Ringwald         rfcomm_channel_event_t event = { CH_EVT_READY_TO_SEND };
19093deb3ec6SMatthias Ringwald         rfcomm_channel_state_machine(channel, &event);
19103deb3ec6SMatthias Ringwald     }
19113deb3ec6SMatthias Ringwald }
19123deb3ec6SMatthias Ringwald 
19133deb3ec6SMatthias Ringwald // MARK: RFCOMM BTstack API
19143deb3ec6SMatthias Ringwald 
19153deb3ec6SMatthias Ringwald void rfcomm_init(void){
19163deb3ec6SMatthias Ringwald     rfcomm_client_cid_generator = 0;
19173deb3ec6SMatthias Ringwald     rfcomm_multiplexers = NULL;
19183deb3ec6SMatthias Ringwald     rfcomm_services     = NULL;
19193deb3ec6SMatthias Ringwald     rfcomm_channels     = NULL;
19203deb3ec6SMatthias Ringwald     rfcomm_security_level = LEVEL_2;
19213deb3ec6SMatthias Ringwald }
19223deb3ec6SMatthias Ringwald 
19233deb3ec6SMatthias Ringwald void rfcomm_set_required_security_level(gap_security_level_t security_level){
19243deb3ec6SMatthias Ringwald     rfcomm_security_level = security_level;
19253deb3ec6SMatthias Ringwald }
19263deb3ec6SMatthias Ringwald 
19273deb3ec6SMatthias Ringwald int rfcomm_can_send_packet_now(uint16_t rfcomm_cid){
19283deb3ec6SMatthias Ringwald     rfcomm_channel_t * channel = rfcomm_channel_for_rfcomm_cid(rfcomm_cid);
19293deb3ec6SMatthias Ringwald     if (!channel){
193028190c0bSMatthias Ringwald         log_error("rfcomm_send cid 0x%02x doesn't exist!", rfcomm_cid);
1931b31d33b2SMatthias Ringwald         return 0;
19323deb3ec6SMatthias Ringwald     }
1933b31d33b2SMatthias Ringwald     int res = rfcomm_channel_can_send(channel);
1934b31d33b2SMatthias Ringwald     if (!res){
1935b31d33b2SMatthias Ringwald         channel->waiting_for_can_send_now = 1;
1936b31d33b2SMatthias Ringwald     }
1937b31d33b2SMatthias Ringwald     return res;
19383deb3ec6SMatthias Ringwald }
19393deb3ec6SMatthias Ringwald 
1940*225a2744SMatthias Ringwald void rfcomm_request_can_send_now_event(uint16_t rfcomm_cid){
1941*225a2744SMatthias Ringwald     rfcomm_channel_t * channel = rfcomm_channel_for_rfcomm_cid(rfcomm_cid);
1942*225a2744SMatthias Ringwald     if (!channel){
1943*225a2744SMatthias Ringwald         log_error("rfcomm_send cid 0x%02x doesn't exist!", rfcomm_cid);
1944*225a2744SMatthias Ringwald         return;
1945*225a2744SMatthias Ringwald     }
1946*225a2744SMatthias Ringwald     channel->waiting_for_can_send_now = 1;
1947*225a2744SMatthias Ringwald     rfcomm_notify_channel_can_send();
1948*225a2744SMatthias Ringwald }
1949*225a2744SMatthias Ringwald 
19503deb3ec6SMatthias Ringwald static int rfcomm_assert_send_valid(rfcomm_channel_t * channel , uint16_t len){
19513deb3ec6SMatthias Ringwald     if (len > channel->max_frame_size){
195228190c0bSMatthias Ringwald         log_error("rfcomm_send cid 0x%02x, rfcomm data lenght exceeds MTU!", channel->rfcomm_cid);
19533deb3ec6SMatthias Ringwald         return RFCOMM_DATA_LEN_EXCEEDS_MTU;
19543deb3ec6SMatthias Ringwald     }
19553deb3ec6SMatthias Ringwald 
19563deb3ec6SMatthias Ringwald     if (!channel->credits_outgoing){
195728190c0bSMatthias Ringwald         log_info("rfcomm_send cid 0x%02x, no rfcomm outgoing credits!", channel->rfcomm_cid);
19583deb3ec6SMatthias Ringwald         return RFCOMM_NO_OUTGOING_CREDITS;
19593deb3ec6SMatthias Ringwald     }
19603deb3ec6SMatthias Ringwald 
19613deb3ec6SMatthias Ringwald     if ((channel->multiplexer->fcon & 1) == 0){
196228190c0bSMatthias Ringwald         log_info("rfcomm_send cid 0x%02x, aggregate flow off!", channel->rfcomm_cid);
19633deb3ec6SMatthias Ringwald         return RFCOMM_AGGREGATE_FLOW_OFF;
19643deb3ec6SMatthias Ringwald     }
19653deb3ec6SMatthias Ringwald     return 0;
19663deb3ec6SMatthias Ringwald }
19673deb3ec6SMatthias Ringwald 
19683deb3ec6SMatthias Ringwald // pre: rfcomm_can_send_packet_now(rfcomm_cid) == true
19693deb3ec6SMatthias Ringwald int rfcomm_reserve_packet_buffer(void){
19703deb3ec6SMatthias Ringwald     return l2cap_reserve_packet_buffer();
19713deb3ec6SMatthias Ringwald }
19723deb3ec6SMatthias Ringwald 
19733deb3ec6SMatthias Ringwald void rfcomm_release_packet_buffer(void){
19743deb3ec6SMatthias Ringwald     l2cap_release_packet_buffer();
19753deb3ec6SMatthias Ringwald }
19763deb3ec6SMatthias Ringwald 
19773deb3ec6SMatthias Ringwald uint8_t * rfcomm_get_outgoing_buffer(void){
19783deb3ec6SMatthias Ringwald     uint8_t * rfcomm_out_buffer = l2cap_get_outgoing_buffer();
19793deb3ec6SMatthias Ringwald     // address + control + length (16) + no credit field
19803deb3ec6SMatthias Ringwald     return &rfcomm_out_buffer[4];
19813deb3ec6SMatthias Ringwald }
19823deb3ec6SMatthias Ringwald 
19833deb3ec6SMatthias Ringwald uint16_t rfcomm_get_max_frame_size(uint16_t rfcomm_cid){
19843deb3ec6SMatthias Ringwald     rfcomm_channel_t * channel = rfcomm_channel_for_rfcomm_cid(rfcomm_cid);
19853deb3ec6SMatthias Ringwald     if (!channel){
19863deb3ec6SMatthias Ringwald         log_error("rfcomm_get_max_frame_size cid 0x%02x doesn't exist!", rfcomm_cid);
19873deb3ec6SMatthias Ringwald         return 0;
19883deb3ec6SMatthias Ringwald     }
19893deb3ec6SMatthias Ringwald     return channel->max_frame_size;
19903deb3ec6SMatthias Ringwald }
19913deb3ec6SMatthias Ringwald int rfcomm_send_prepared(uint16_t rfcomm_cid, uint16_t len){
19923deb3ec6SMatthias Ringwald     rfcomm_channel_t * channel = rfcomm_channel_for_rfcomm_cid(rfcomm_cid);
19933deb3ec6SMatthias Ringwald     if (!channel){
19943deb3ec6SMatthias Ringwald         log_error("rfcomm_send_prepared cid 0x%02x doesn't exist!", rfcomm_cid);
19953deb3ec6SMatthias Ringwald         return 0;
19963deb3ec6SMatthias Ringwald     }
19973deb3ec6SMatthias Ringwald 
19983deb3ec6SMatthias Ringwald     int err = rfcomm_assert_send_valid(channel, len);
19993deb3ec6SMatthias Ringwald     if (err) return err;
200068d15bfcSMatthias Ringwald     if (!l2cap_can_send_prepared_packet_now(channel->multiplexer->l2cap_cid)){
200178707112SMatthias Ringwald         log_error("rfcomm_send_prepared: l2cap cannot send now");
200278707112SMatthias Ringwald         return BTSTACK_ACL_BUFFERS_FULL;
200378707112SMatthias Ringwald     }
20043deb3ec6SMatthias Ringwald 
20053deb3ec6SMatthias Ringwald     // send might cause l2cap to emit new credits, update counters first
20063deb3ec6SMatthias Ringwald     channel->credits_outgoing--;
20073deb3ec6SMatthias Ringwald 
20083deb3ec6SMatthias Ringwald     int result = rfcomm_send_uih_prepared(channel->multiplexer, channel->dlci, len);
20093deb3ec6SMatthias Ringwald 
20103deb3ec6SMatthias Ringwald     if (result != 0) {
20113deb3ec6SMatthias Ringwald         channel->credits_outgoing++;
201278707112SMatthias Ringwald         log_error("rfcomm_send_prepared: error %d", result);
20133deb3ec6SMatthias Ringwald         return result;
20143deb3ec6SMatthias Ringwald     }
20153deb3ec6SMatthias Ringwald 
20163deb3ec6SMatthias Ringwald     return result;
20173deb3ec6SMatthias Ringwald }
20183deb3ec6SMatthias Ringwald 
201928190c0bSMatthias Ringwald int rfcomm_send(uint16_t rfcomm_cid, uint8_t *data, uint16_t len){
20203deb3ec6SMatthias Ringwald     rfcomm_channel_t * channel = rfcomm_channel_for_rfcomm_cid(rfcomm_cid);
20213deb3ec6SMatthias Ringwald     if (!channel){
202228190c0bSMatthias Ringwald         log_error("rfcomm_send cid 0x%02x doesn't exist!", rfcomm_cid);
20233deb3ec6SMatthias Ringwald         return 1;
20243deb3ec6SMatthias Ringwald     }
20253deb3ec6SMatthias Ringwald 
20263deb3ec6SMatthias Ringwald     int err = rfcomm_assert_send_valid(channel, len);
20273deb3ec6SMatthias Ringwald     if (err) return err;
202868d15bfcSMatthias Ringwald     if (!l2cap_can_send_packet_now(channel->multiplexer->l2cap_cid)){
202978707112SMatthias Ringwald         log_error("rfcomm_send_internal: l2cap cannot send now");
203078707112SMatthias Ringwald         return BTSTACK_ACL_BUFFERS_FULL;
203178707112SMatthias Ringwald     }
20323deb3ec6SMatthias Ringwald 
20333deb3ec6SMatthias Ringwald     rfcomm_reserve_packet_buffer();
20343deb3ec6SMatthias Ringwald     uint8_t * rfcomm_payload = rfcomm_get_outgoing_buffer();
20353deb3ec6SMatthias Ringwald     memcpy(rfcomm_payload, data, len);
203678707112SMatthias Ringwald     err = rfcomm_send_prepared(rfcomm_cid, len);
203778707112SMatthias Ringwald     if (err){
203878707112SMatthias Ringwald         rfcomm_release_packet_buffer();
203978707112SMatthias Ringwald     }
204078707112SMatthias Ringwald     return err;
20413deb3ec6SMatthias Ringwald }
20423deb3ec6SMatthias Ringwald 
20433deb3ec6SMatthias Ringwald // Sends Local Lnie Status, see LINE_STATUS_..
20443deb3ec6SMatthias Ringwald int rfcomm_send_local_line_status(uint16_t rfcomm_cid, uint8_t line_status){
20453deb3ec6SMatthias Ringwald     rfcomm_channel_t * channel = rfcomm_channel_for_rfcomm_cid(rfcomm_cid);
20463deb3ec6SMatthias Ringwald     if (!channel){
20473deb3ec6SMatthias Ringwald         log_error("rfcomm_send_local_line_status cid 0x%02x doesn't exist!", rfcomm_cid);
20483deb3ec6SMatthias Ringwald         return 0;
20493deb3ec6SMatthias Ringwald     }
20503deb3ec6SMatthias Ringwald     return rfcomm_send_uih_rls_cmd(channel->multiplexer, channel->dlci, line_status);
20513deb3ec6SMatthias Ringwald }
20523deb3ec6SMatthias Ringwald 
20533deb3ec6SMatthias Ringwald // Sned local modem status. see MODEM_STAUS_..
20543deb3ec6SMatthias Ringwald int rfcomm_send_modem_status(uint16_t rfcomm_cid, uint8_t modem_status){
20553deb3ec6SMatthias Ringwald     rfcomm_channel_t * channel = rfcomm_channel_for_rfcomm_cid(rfcomm_cid);
20563deb3ec6SMatthias Ringwald     if (!channel){
20573deb3ec6SMatthias Ringwald         log_error("rfcomm_send_modem_status cid 0x%02x doesn't exist!", rfcomm_cid);
20583deb3ec6SMatthias Ringwald         return 0;
20593deb3ec6SMatthias Ringwald     }
20603deb3ec6SMatthias Ringwald     return rfcomm_send_uih_msc_cmd(channel->multiplexer, channel->dlci, modem_status);
20613deb3ec6SMatthias Ringwald }
20623deb3ec6SMatthias Ringwald 
20633deb3ec6SMatthias Ringwald // Configure remote port
20643deb3ec6SMatthias 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){
20653deb3ec6SMatthias Ringwald     rfcomm_channel_t * channel = rfcomm_channel_for_rfcomm_cid(rfcomm_cid);
20663deb3ec6SMatthias Ringwald     if (!channel){
20673deb3ec6SMatthias Ringwald         log_error("rfcomm_send_port_configuration cid 0x%02x doesn't exist!", rfcomm_cid);
20683deb3ec6SMatthias Ringwald         return 0;
20693deb3ec6SMatthias Ringwald     }
20703deb3ec6SMatthias Ringwald     rfcomm_rpn_data_t rpn_data;
20713deb3ec6SMatthias Ringwald     rpn_data.baud_rate = baud_rate;
20723deb3ec6SMatthias Ringwald     rpn_data.flags = data_bits | (stop_bits << 2) | (parity << 3);
20733deb3ec6SMatthias Ringwald     rpn_data.flow_control = flow_control;
20743deb3ec6SMatthias Ringwald     rpn_data.xon = 0;
20753deb3ec6SMatthias Ringwald     rpn_data.xoff = 0;
20763deb3ec6SMatthias Ringwald     rpn_data.parameter_mask_0 = 0x1f;   // all but xon/xoff
20773deb3ec6SMatthias Ringwald     rpn_data.parameter_mask_1 = 0x3f;   // all flow control options
20783deb3ec6SMatthias Ringwald     return rfcomm_send_uih_rpn_cmd(channel->multiplexer, channel->dlci, &rpn_data);
20793deb3ec6SMatthias Ringwald }
20803deb3ec6SMatthias Ringwald 
20813deb3ec6SMatthias Ringwald // Query remote port
20823deb3ec6SMatthias Ringwald int rfcomm_query_port_configuration(uint16_t rfcomm_cid){
20833deb3ec6SMatthias Ringwald     rfcomm_channel_t * channel = rfcomm_channel_for_rfcomm_cid(rfcomm_cid);
20843deb3ec6SMatthias Ringwald     if (!channel){
20853deb3ec6SMatthias Ringwald         log_error("rfcomm_query_port_configuration cid 0x%02x doesn't exist!", rfcomm_cid);
20863deb3ec6SMatthias Ringwald         return 0;
20873deb3ec6SMatthias Ringwald     }
20883deb3ec6SMatthias Ringwald     return rfcomm_send_uih_rpn_req(channel->multiplexer, channel->dlci);
20893deb3ec6SMatthias Ringwald }
20903deb3ec6SMatthias Ringwald 
2091aa4dd815SMatthias Ringwald 
2092ccb8ddfbSMatthias 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){
20935d1e858fSMatthias Ringwald     log_info("RFCOMM_CREATE_CHANNEL addr %s channel #%u init credits %u",  bd_addr_to_str(addr), server_channel, initial_credits);
20945d1e858fSMatthias Ringwald 
20955d1e858fSMatthias Ringwald     // create new multiplexer if necessary
20965d1e858fSMatthias Ringwald     uint8_t status = 0;
20975d1e858fSMatthias Ringwald     int new_multiplexer = 0;
20985d1e858fSMatthias Ringwald     rfcomm_channel_t * channel = NULL;
20995d1e858fSMatthias Ringwald     rfcomm_multiplexer_t * multiplexer = rfcomm_multiplexer_for_addr(addr);
21005d1e858fSMatthias Ringwald     if (!multiplexer) {
21015d1e858fSMatthias Ringwald         multiplexer = rfcomm_multiplexer_create_for_addr(addr);
21025d1e858fSMatthias Ringwald         if (!multiplexer){
21035d1e858fSMatthias Ringwald             status = BTSTACK_MEMORY_ALLOC_FAILED;
21045d1e858fSMatthias Ringwald             goto fail;
21055d1e858fSMatthias Ringwald         }
21065d1e858fSMatthias Ringwald         multiplexer->outgoing = 1;
21075d1e858fSMatthias Ringwald         multiplexer->state = RFCOMM_MULTIPLEXER_W4_CONNECT;
21085d1e858fSMatthias Ringwald         new_multiplexer = 1;
21095d1e858fSMatthias Ringwald     }
21105d1e858fSMatthias Ringwald 
21115d1e858fSMatthias Ringwald     // prepare channel
21125d1e858fSMatthias Ringwald     channel = rfcomm_channel_create(multiplexer, NULL, server_channel);
21135d1e858fSMatthias Ringwald     if (!channel){
21145d1e858fSMatthias Ringwald         status = BTSTACK_MEMORY_ALLOC_FAILED;
21155d1e858fSMatthias Ringwald         goto fail;
21165d1e858fSMatthias Ringwald     }
2117ccb8ddfbSMatthias Ringwald 
21185d1e858fSMatthias Ringwald     // rfcomm_cid is already assigned by rfcomm_channel_create
21195d1e858fSMatthias Ringwald     channel->incoming_flow_control = incoming_flow_control;
21205d1e858fSMatthias Ringwald     channel->new_credits_incoming  = initial_credits;
2121ccb8ddfbSMatthias Ringwald     channel->packet_handler = packet_handler;
21225d1e858fSMatthias Ringwald 
21235d1e858fSMatthias Ringwald     // return rfcomm_cid
2124432fe57eSMatthias Ringwald     if (out_rfcomm_cid){
21255d1e858fSMatthias Ringwald         *out_rfcomm_cid = channel->rfcomm_cid;
2126432fe57eSMatthias Ringwald     }
21275d1e858fSMatthias Ringwald 
21285d1e858fSMatthias Ringwald     // start multiplexer setup
21295d1e858fSMatthias Ringwald     if (multiplexer->state != RFCOMM_MULTIPLEXER_OPEN) {
21305d1e858fSMatthias Ringwald         channel->state = RFCOMM_CHANNEL_W4_MULTIPLEXER;
21315d1e858fSMatthias Ringwald         uint16_t l2cap_cid = 0;
21325d1e858fSMatthias Ringwald         status = l2cap_create_channel(rfcomm_packet_handler, addr, PSM_RFCOMM, l2cap_max_mtu(), &l2cap_cid);
21335d1e858fSMatthias Ringwald         if (status) goto fail;
21345d1e858fSMatthias Ringwald         multiplexer->l2cap_cid = l2cap_cid;
21355d1e858fSMatthias Ringwald         return 0;
21365d1e858fSMatthias Ringwald     }
21375d1e858fSMatthias Ringwald 
21385d1e858fSMatthias Ringwald     channel->state = RFCOMM_CHANNEL_SEND_UIH_PN;
21395d1e858fSMatthias Ringwald 
21405d1e858fSMatthias Ringwald     // start connecting, if multiplexer is already up and running
21415d1e858fSMatthias Ringwald     rfcomm_run();
21425d1e858fSMatthias Ringwald     return 0;
21435d1e858fSMatthias Ringwald 
21445d1e858fSMatthias Ringwald fail:
21455d1e858fSMatthias Ringwald     if (new_multiplexer) btstack_memory_rfcomm_multiplexer_free(multiplexer);
21465d1e858fSMatthias Ringwald     if (channel)         btstack_memory_rfcomm_channel_free(channel);
21475d1e858fSMatthias Ringwald     return status;
21485d1e858fSMatthias Ringwald }
21495d1e858fSMatthias Ringwald 
2150ccb8ddfbSMatthias 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){
2151ccb8ddfbSMatthias Ringwald     return rfcomm_channel_create_internal(packet_handler, addr, server_channel, 1, initial_credits, out_rfcomm_cid);
21525d1e858fSMatthias Ringwald }
21535d1e858fSMatthias Ringwald 
2154ccb8ddfbSMatthias 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){
2155ccb8ddfbSMatthias Ringwald     return rfcomm_channel_create_internal(packet_handler, addr, server_channel, 0, RFCOMM_CREDITS, out_rfcomm_cid);
21565d1e858fSMatthias Ringwald }
21575d1e858fSMatthias Ringwald 
215828190c0bSMatthias Ringwald void rfcomm_disconnect(uint16_t rfcomm_cid){
21593deb3ec6SMatthias Ringwald     log_info("RFCOMM_DISCONNECT cid 0x%02x", rfcomm_cid);
21603deb3ec6SMatthias Ringwald     rfcomm_channel_t * channel = rfcomm_channel_for_rfcomm_cid(rfcomm_cid);
21613deb3ec6SMatthias Ringwald     if (channel) {
21623deb3ec6SMatthias Ringwald         channel->state = RFCOMM_CHANNEL_SEND_DISC;
21633deb3ec6SMatthias Ringwald     }
21643deb3ec6SMatthias Ringwald 
21653deb3ec6SMatthias Ringwald     // process
21663deb3ec6SMatthias Ringwald     rfcomm_run();
21673deb3ec6SMatthias Ringwald }
21683deb3ec6SMatthias Ringwald 
2169ccb8ddfbSMatthias Ringwald static uint8_t rfcomm_register_service_internal(btstack_packet_handler_t packet_handler,
2170ccb8ddfbSMatthias Ringwald     uint8_t channel, uint16_t max_frame_size, uint8_t incoming_flow_control, uint8_t initial_credits){
2171ccb8ddfbSMatthias Ringwald 
2172ccb8ddfbSMatthias Ringwald     log_info("RFCOMM_REGISTER_SERVICE channel #%u mtu %u flow_control %u credits %u",
21733deb3ec6SMatthias Ringwald              channel, max_frame_size, incoming_flow_control, initial_credits);
2174457b5cb1SMatthias Ringwald 
21753deb3ec6SMatthias Ringwald     // check if already registered
21763deb3ec6SMatthias Ringwald     rfcomm_service_t * service = rfcomm_service_for_channel(channel);
21773deb3ec6SMatthias Ringwald     if (service){
2178457b5cb1SMatthias Ringwald         return RFCOMM_CHANNEL_ALREADY_REGISTERED;
21793deb3ec6SMatthias Ringwald     }
21803deb3ec6SMatthias Ringwald 
21813deb3ec6SMatthias Ringwald     // alloc structure
21823deb3ec6SMatthias Ringwald     service = btstack_memory_rfcomm_service_get();
21833deb3ec6SMatthias Ringwald     if (!service) {
2184457b5cb1SMatthias Ringwald         return BTSTACK_MEMORY_ALLOC_FAILED;
21853deb3ec6SMatthias Ringwald     }
21863deb3ec6SMatthias Ringwald 
21873deb3ec6SMatthias Ringwald     // register with l2cap if not registered before, max MTU
2188665d90f2SMatthias Ringwald     if (btstack_linked_list_empty(&rfcomm_services)){
2189be2053a6SMatthias Ringwald         l2cap_register_service(rfcomm_packet_handler, PSM_RFCOMM, 0xffff, rfcomm_security_level);
21903deb3ec6SMatthias Ringwald     }
21913deb3ec6SMatthias Ringwald 
21923deb3ec6SMatthias Ringwald     // fill in
2193ccb8ddfbSMatthias Ringwald     service->packet_handler = packet_handler;
21943deb3ec6SMatthias Ringwald     service->server_channel = channel;
21953deb3ec6SMatthias Ringwald     service->max_frame_size = max_frame_size;
21963deb3ec6SMatthias Ringwald     service->incoming_flow_control = incoming_flow_control;
21973deb3ec6SMatthias Ringwald     service->incoming_initial_credits = initial_credits;
21983deb3ec6SMatthias Ringwald 
21993deb3ec6SMatthias Ringwald     // add to services list
2200665d90f2SMatthias Ringwald     btstack_linked_list_add(&rfcomm_services, (btstack_linked_item_t *) service);
22013deb3ec6SMatthias Ringwald 
2202457b5cb1SMatthias Ringwald     return 0;
22033deb3ec6SMatthias Ringwald }
22043deb3ec6SMatthias Ringwald 
2205ccb8ddfbSMatthias Ringwald uint8_t rfcomm_register_service_with_initial_credits(btstack_packet_handler_t packet_handler,
2206ccb8ddfbSMatthias Ringwald     uint8_t channel, uint16_t max_frame_size, uint8_t initial_credits){
2207ccb8ddfbSMatthias Ringwald 
2208ccb8ddfbSMatthias Ringwald     return rfcomm_register_service_internal(packet_handler, channel, max_frame_size, 1, initial_credits);
22093deb3ec6SMatthias Ringwald }
22103deb3ec6SMatthias Ringwald 
2211ccb8ddfbSMatthias Ringwald uint8_t rfcomm_register_service(btstack_packet_handler_t packet_handler, uint8_t channel,
2212ccb8ddfbSMatthias Ringwald     uint16_t max_frame_size){
2213ccb8ddfbSMatthias Ringwald 
2214ccb8ddfbSMatthias Ringwald     return rfcomm_register_service_internal(packet_handler, channel, max_frame_size, 0,RFCOMM_CREDITS);
22153deb3ec6SMatthias Ringwald }
22163deb3ec6SMatthias Ringwald 
2217457b5cb1SMatthias Ringwald void rfcomm_unregister_service(uint8_t service_channel){
22183deb3ec6SMatthias Ringwald     log_info("RFCOMM_UNREGISTER_SERVICE #%u", service_channel);
22193deb3ec6SMatthias Ringwald     rfcomm_service_t *service = rfcomm_service_for_channel(service_channel);
22203deb3ec6SMatthias Ringwald     if (!service) return;
2221665d90f2SMatthias Ringwald     btstack_linked_list_remove(&rfcomm_services, (btstack_linked_item_t *) service);
22223deb3ec6SMatthias Ringwald     btstack_memory_rfcomm_service_free(service);
22233deb3ec6SMatthias Ringwald 
22243deb3ec6SMatthias Ringwald     // unregister if no services active
2225665d90f2SMatthias Ringwald     if (btstack_linked_list_empty(&rfcomm_services)){
22263deb3ec6SMatthias Ringwald         // bt_send_cmd(&l2cap_unregister_service, PSM_RFCOMM);
222702f83142SMatthias Ringwald         l2cap_unregister_service(PSM_RFCOMM);
22283deb3ec6SMatthias Ringwald     }
22293deb3ec6SMatthias Ringwald }
22303deb3ec6SMatthias Ringwald 
223128190c0bSMatthias Ringwald void rfcomm_accept_connection(uint16_t rfcomm_cid){
22323deb3ec6SMatthias Ringwald     log_info("RFCOMM_ACCEPT_CONNECTION cid 0x%02x", rfcomm_cid);
22333deb3ec6SMatthias Ringwald     rfcomm_channel_t * channel = rfcomm_channel_for_rfcomm_cid(rfcomm_cid);
22343deb3ec6SMatthias Ringwald     if (!channel) return;
22353deb3ec6SMatthias Ringwald     switch (channel->state) {
22363deb3ec6SMatthias Ringwald         case RFCOMM_CHANNEL_INCOMING_SETUP:
22373deb3ec6SMatthias Ringwald             rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_CLIENT_ACCEPTED);
22383deb3ec6SMatthias Ringwald             if (channel->state_var & RFCOMM_CHANNEL_STATE_VAR_RCVD_PN){
22393deb3ec6SMatthias Ringwald                 rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_PN_RSP);
22403deb3ec6SMatthias Ringwald             }
22413deb3ec6SMatthias Ringwald             if (channel->state_var & RFCOMM_CHANNEL_STATE_VAR_RCVD_SABM){
22423deb3ec6SMatthias Ringwald                 rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_UA);
22433deb3ec6SMatthias Ringwald             }
22443deb3ec6SMatthias Ringwald             // at least one of { PN RSP, UA } needs to be sent
22453deb3ec6SMatthias Ringwald             // state transistion incoming setup -> dlc setup happens in rfcomm_run after these have been sent
22463deb3ec6SMatthias Ringwald             break;
22473deb3ec6SMatthias Ringwald         default:
22483deb3ec6SMatthias Ringwald             break;
22493deb3ec6SMatthias Ringwald     }
22503deb3ec6SMatthias Ringwald 
22513deb3ec6SMatthias Ringwald     // process
22523deb3ec6SMatthias Ringwald     rfcomm_run();
22533deb3ec6SMatthias Ringwald }
22543deb3ec6SMatthias Ringwald 
225528190c0bSMatthias Ringwald void rfcomm_decline_connection(uint16_t rfcomm_cid){
22563deb3ec6SMatthias Ringwald     log_info("RFCOMM_DECLINE_CONNECTION cid 0x%02x", rfcomm_cid);
22573deb3ec6SMatthias Ringwald     rfcomm_channel_t * channel = rfcomm_channel_for_rfcomm_cid(rfcomm_cid);
22583deb3ec6SMatthias Ringwald     if (!channel) return;
22593deb3ec6SMatthias Ringwald     switch (channel->state) {
22603deb3ec6SMatthias Ringwald         case RFCOMM_CHANNEL_INCOMING_SETUP:
22613deb3ec6SMatthias Ringwald             channel->state = RFCOMM_CHANNEL_SEND_DM;
22623deb3ec6SMatthias Ringwald             break;
22633deb3ec6SMatthias Ringwald         default:
22643deb3ec6SMatthias Ringwald             break;
22653deb3ec6SMatthias Ringwald     }
22663deb3ec6SMatthias Ringwald 
22673deb3ec6SMatthias Ringwald     // process
22683deb3ec6SMatthias Ringwald     rfcomm_run();
22693deb3ec6SMatthias Ringwald }
22703deb3ec6SMatthias Ringwald 
22713deb3ec6SMatthias Ringwald void rfcomm_grant_credits(uint16_t rfcomm_cid, uint8_t credits){
22723deb3ec6SMatthias Ringwald     log_info("RFCOMM_GRANT_CREDITS cid 0x%02x credits %u", rfcomm_cid, credits);
22733deb3ec6SMatthias Ringwald     rfcomm_channel_t * channel = rfcomm_channel_for_rfcomm_cid(rfcomm_cid);
22743deb3ec6SMatthias Ringwald     if (!channel) return;
22753deb3ec6SMatthias Ringwald     if (!channel->incoming_flow_control) return;
22763deb3ec6SMatthias Ringwald     channel->new_credits_incoming += credits;
22773deb3ec6SMatthias Ringwald 
22783deb3ec6SMatthias Ringwald     // process
22793deb3ec6SMatthias Ringwald     rfcomm_run();
22803deb3ec6SMatthias Ringwald }
22813deb3ec6SMatthias Ringwald 
22823deb3ec6SMatthias Ringwald 
2283b1c4ef5fSMatthias Ringwald /*
2284b1c4ef5fSMatthias Ringwald  * CRC (reversed crc) lookup table as calculated by the table generator in ETSI TS 101 369 V6.3.0.
2285b1c4ef5fSMatthias Ringwald  */
2286b1c4ef5fSMatthias Ringwald static const uint8_t crc8table[256] = {    /* reversed, 8-bit, poly=0x07 */
2287b1c4ef5fSMatthias Ringwald     0x00, 0x91, 0xE3, 0x72, 0x07, 0x96, 0xE4, 0x75, 0x0E, 0x9F, 0xED, 0x7C, 0x09, 0x98, 0xEA, 0x7B,
2288b1c4ef5fSMatthias Ringwald     0x1C, 0x8D, 0xFF, 0x6E, 0x1B, 0x8A, 0xF8, 0x69, 0x12, 0x83, 0xF1, 0x60, 0x15, 0x84, 0xF6, 0x67,
2289b1c4ef5fSMatthias Ringwald     0x38, 0xA9, 0xDB, 0x4A, 0x3F, 0xAE, 0xDC, 0x4D, 0x36, 0xA7, 0xD5, 0x44, 0x31, 0xA0, 0xD2, 0x43,
2290b1c4ef5fSMatthias Ringwald     0x24, 0xB5, 0xC7, 0x56, 0x23, 0xB2, 0xC0, 0x51, 0x2A, 0xBB, 0xC9, 0x58, 0x2D, 0xBC, 0xCE, 0x5F,
2291b1c4ef5fSMatthias Ringwald     0x70, 0xE1, 0x93, 0x02, 0x77, 0xE6, 0x94, 0x05, 0x7E, 0xEF, 0x9D, 0x0C, 0x79, 0xE8, 0x9A, 0x0B,
2292b1c4ef5fSMatthias Ringwald     0x6C, 0xFD, 0x8F, 0x1E, 0x6B, 0xFA, 0x88, 0x19, 0x62, 0xF3, 0x81, 0x10, 0x65, 0xF4, 0x86, 0x17,
2293b1c4ef5fSMatthias Ringwald     0x48, 0xD9, 0xAB, 0x3A, 0x4F, 0xDE, 0xAC, 0x3D, 0x46, 0xD7, 0xA5, 0x34, 0x41, 0xD0, 0xA2, 0x33,
2294b1c4ef5fSMatthias Ringwald     0x54, 0xC5, 0xB7, 0x26, 0x53, 0xC2, 0xB0, 0x21, 0x5A, 0xCB, 0xB9, 0x28, 0x5D, 0xCC, 0xBE, 0x2F,
2295b1c4ef5fSMatthias Ringwald     0xE0, 0x71, 0x03, 0x92, 0xE7, 0x76, 0x04, 0x95, 0xEE, 0x7F, 0x0D, 0x9C, 0xE9, 0x78, 0x0A, 0x9B,
2296b1c4ef5fSMatthias Ringwald     0xFC, 0x6D, 0x1F, 0x8E, 0xFB, 0x6A, 0x18, 0x89, 0xF2, 0x63, 0x11, 0x80, 0xF5, 0x64, 0x16, 0x87,
2297b1c4ef5fSMatthias Ringwald     0xD8, 0x49, 0x3B, 0xAA, 0xDF, 0x4E, 0x3C, 0xAD, 0xD6, 0x47, 0x35, 0xA4, 0xD1, 0x40, 0x32, 0xA3,
2298b1c4ef5fSMatthias Ringwald     0xC4, 0x55, 0x27, 0xB6, 0xC3, 0x52, 0x20, 0xB1, 0xCA, 0x5B, 0x29, 0xB8, 0xCD, 0x5C, 0x2E, 0xBF,
2299b1c4ef5fSMatthias Ringwald     0x90, 0x01, 0x73, 0xE2, 0x97, 0x06, 0x74, 0xE5, 0x9E, 0x0F, 0x7D, 0xEC, 0x99, 0x08, 0x7A, 0xEB,
2300b1c4ef5fSMatthias Ringwald     0x8C, 0x1D, 0x6F, 0xFE, 0x8B, 0x1A, 0x68, 0xF9, 0x82, 0x13, 0x61, 0xF0, 0x85, 0x14, 0x66, 0xF7,
2301b1c4ef5fSMatthias Ringwald     0xA8, 0x39, 0x4B, 0xDA, 0xAF, 0x3E, 0x4C, 0xDD, 0xA6, 0x37, 0x45, 0xD4, 0xA1, 0x30, 0x42, 0xD3,
2302b1c4ef5fSMatthias Ringwald     0xB4, 0x25, 0x57, 0xC6, 0xB3, 0x22, 0x50, 0xC1, 0xBA, 0x2B, 0x59, 0xC8, 0xBD, 0x2C, 0x5E, 0xCF
2303b1c4ef5fSMatthias Ringwald };
2304b1c4ef5fSMatthias Ringwald 
2305b1c4ef5fSMatthias Ringwald #define CRC8_INIT  0xFF          // Initial FCS value
2306b1c4ef5fSMatthias Ringwald #define CRC8_OK    0xCF          // Good final FCS value
2307b1c4ef5fSMatthias Ringwald /*-----------------------------------------------------------------------------------*/
2308b1c4ef5fSMatthias Ringwald static uint8_t crc8(uint8_t *data, uint16_t len)
2309b1c4ef5fSMatthias Ringwald {
2310b1c4ef5fSMatthias Ringwald     uint16_t count;
2311b1c4ef5fSMatthias Ringwald     uint8_t crc = CRC8_INIT;
2312b1c4ef5fSMatthias Ringwald     for (count = 0; count < len; count++)
2313b1c4ef5fSMatthias Ringwald         crc = crc8table[crc ^ data[count]];
2314b1c4ef5fSMatthias Ringwald     return crc;
2315b1c4ef5fSMatthias Ringwald }
2316b1c4ef5fSMatthias Ringwald 
2317b1c4ef5fSMatthias Ringwald /*-----------------------------------------------------------------------------------*/
2318b1c4ef5fSMatthias Ringwald uint8_t crc8_check(uint8_t *data, uint16_t len, uint8_t check_sum)
2319b1c4ef5fSMatthias Ringwald {
2320b1c4ef5fSMatthias Ringwald     uint8_t crc;
2321b1c4ef5fSMatthias Ringwald 
2322b1c4ef5fSMatthias Ringwald     crc = crc8(data, len);
2323b1c4ef5fSMatthias Ringwald 
2324b1c4ef5fSMatthias Ringwald     crc = crc8table[crc ^ check_sum];
2325b1c4ef5fSMatthias Ringwald     if (crc == CRC8_OK)
2326b1c4ef5fSMatthias Ringwald         return 0;               /* Valid */
2327b1c4ef5fSMatthias Ringwald     else
2328b1c4ef5fSMatthias Ringwald         return 1;               /* Failed */
2329b1c4ef5fSMatthias Ringwald 
2330b1c4ef5fSMatthias Ringwald }
2331b1c4ef5fSMatthias Ringwald 
2332b1c4ef5fSMatthias Ringwald /*-----------------------------------------------------------------------------------*/
2333b1c4ef5fSMatthias Ringwald uint8_t crc8_calc(uint8_t *data, uint16_t len)
2334b1c4ef5fSMatthias Ringwald {
2335b1c4ef5fSMatthias Ringwald     /* Ones complement */
2336b1c4ef5fSMatthias Ringwald     return 0xFF - crc8(data, len);
2337b1c4ef5fSMatthias Ringwald }
2338b1c4ef5fSMatthias Ringwald 
2339b1c4ef5fSMatthias Ringwald 
23403deb3ec6SMatthias Ringwald 
23413deb3ec6SMatthias Ringwald 
2342