xref: /btstack/src/classic/rfcomm.c (revision d9d230549a3778668cfadaaad2aa1afc2922338b)
13deb3ec6SMatthias Ringwald /*
23deb3ec6SMatthias Ringwald  * Copyright (C) 2014 BlueKitchen GmbH
33deb3ec6SMatthias Ringwald  *
43deb3ec6SMatthias Ringwald  * Redistribution and use in source and binary forms, with or without
53deb3ec6SMatthias Ringwald  * modification, are permitted provided that the following conditions
63deb3ec6SMatthias Ringwald  * are met:
73deb3ec6SMatthias Ringwald  *
83deb3ec6SMatthias Ringwald  * 1. Redistributions of source code must retain the above copyright
93deb3ec6SMatthias Ringwald  *    notice, this list of conditions and the following disclaimer.
103deb3ec6SMatthias Ringwald  * 2. Redistributions in binary form must reproduce the above copyright
113deb3ec6SMatthias Ringwald  *    notice, this list of conditions and the following disclaimer in the
123deb3ec6SMatthias Ringwald  *    documentation and/or other materials provided with the distribution.
133deb3ec6SMatthias Ringwald  * 3. Neither the name of the copyright holders nor the names of
143deb3ec6SMatthias Ringwald  *    contributors may be used to endorse or promote products derived
153deb3ec6SMatthias Ringwald  *    from this software without specific prior written permission.
163deb3ec6SMatthias Ringwald  * 4. Any redistribution, use, or modification is done solely for
173deb3ec6SMatthias Ringwald  *    personal benefit and not for any commercial purpose or for
183deb3ec6SMatthias Ringwald  *    monetary gain.
193deb3ec6SMatthias Ringwald  *
203deb3ec6SMatthias Ringwald  * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
213deb3ec6SMatthias Ringwald  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
223deb3ec6SMatthias Ringwald  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
233deb3ec6SMatthias Ringwald  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
243deb3ec6SMatthias Ringwald  * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
253deb3ec6SMatthias Ringwald  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
263deb3ec6SMatthias Ringwald  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
273deb3ec6SMatthias Ringwald  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
283deb3ec6SMatthias Ringwald  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
293deb3ec6SMatthias Ringwald  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
303deb3ec6SMatthias Ringwald  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
313deb3ec6SMatthias Ringwald  * SUCH DAMAGE.
323deb3ec6SMatthias Ringwald  *
333deb3ec6SMatthias Ringwald  * Please inquire about commercial licensing options at
343deb3ec6SMatthias Ringwald  * [email protected]
353deb3ec6SMatthias Ringwald  *
363deb3ec6SMatthias Ringwald  */
373deb3ec6SMatthias Ringwald 
383deb3ec6SMatthias Ringwald /*
393deb3ec6SMatthias Ringwald  *  rfcomm.c
403deb3ec6SMatthias Ringwald  */
413deb3ec6SMatthias Ringwald 
423deb3ec6SMatthias Ringwald #include <stdio.h>
433deb3ec6SMatthias Ringwald #include <stdlib.h>
443deb3ec6SMatthias Ringwald #include <string.h> // memcpy
453deb3ec6SMatthias Ringwald #include <stdint.h>
463deb3ec6SMatthias Ringwald 
4716ece135SMatthias Ringwald #include "btstack_debug.h"
480e2df43fSMatthias Ringwald #include "btstack_event.h"
49e628322dSMatthias Ringwald #include "btstack_memory.h"
50e628322dSMatthias Ringwald #include "btstack_util.h"
5159c6af15SMatthias Ringwald #include "classic/core.h"
523edc84c5SMatthias Ringwald #include "classic/rfcomm.h"
53e628322dSMatthias Ringwald #include "hci.h"
54e628322dSMatthias Ringwald #include "hci_cmd.h"
55e628322dSMatthias Ringwald #include "hci_dump.h"
56e628322dSMatthias Ringwald #include "l2cap.h"
573deb3ec6SMatthias Ringwald 
583deb3ec6SMatthias Ringwald // workaround for missing PRIxPTR on mspgcc (16/20-bit MCU)
593deb3ec6SMatthias Ringwald #ifndef PRIxPTR
603deb3ec6SMatthias Ringwald #if defined(__MSP430X__)  &&  defined(__MSP430X_LARGE__)
613deb3ec6SMatthias Ringwald #define PRIxPTR "lx"
623deb3ec6SMatthias Ringwald #else
633deb3ec6SMatthias Ringwald #define PRIxPTR "x"
643deb3ec6SMatthias Ringwald #endif
653deb3ec6SMatthias Ringwald #endif
663deb3ec6SMatthias Ringwald 
673deb3ec6SMatthias Ringwald #define RFCOMM_MULIPLEXER_TIMEOUT_MS 60000
683deb3ec6SMatthias Ringwald 
693deb3ec6SMatthias Ringwald #define RFCOMM_CREDITS 10
703deb3ec6SMatthias Ringwald 
713deb3ec6SMatthias Ringwald // FCS calc
723deb3ec6SMatthias Ringwald #define BT_RFCOMM_CODE_WORD         0xE0 // pol = x8+x2+x1+1
733deb3ec6SMatthias Ringwald #define BT_RFCOMM_CRC_CHECK_LEN     3
743deb3ec6SMatthias Ringwald #define BT_RFCOMM_UIHCRC_CHECK_LEN  2
753deb3ec6SMatthias Ringwald 
76e628322dSMatthias Ringwald 
77e628322dSMatthias Ringwald typedef enum {
78e628322dSMatthias Ringwald     CH_EVT_RCVD_SABM = 1,
79e628322dSMatthias Ringwald     CH_EVT_RCVD_UA,
80e628322dSMatthias Ringwald     CH_EVT_RCVD_PN,
81e628322dSMatthias Ringwald     CH_EVT_RCVD_PN_RSP,
82e628322dSMatthias Ringwald     CH_EVT_RCVD_DISC,
83e628322dSMatthias Ringwald     CH_EVT_RCVD_DM,
84e628322dSMatthias Ringwald     CH_EVT_RCVD_MSC_CMD,
85e628322dSMatthias Ringwald     CH_EVT_RCVD_MSC_RSP,
86e628322dSMatthias Ringwald     CH_EVT_RCVD_NSC_RSP,
87e628322dSMatthias Ringwald     CH_EVT_RCVD_RLS_CMD,
88e628322dSMatthias Ringwald     CH_EVT_RCVD_RLS_RSP,
89e628322dSMatthias Ringwald     CH_EVT_RCVD_RPN_CMD,
90e628322dSMatthias Ringwald     CH_EVT_RCVD_RPN_REQ,
91e628322dSMatthias Ringwald     CH_EVT_RCVD_CREDITS,
92e628322dSMatthias Ringwald     CH_EVT_MULTIPLEXER_READY,
93e628322dSMatthias Ringwald     CH_EVT_READY_TO_SEND,
94e628322dSMatthias Ringwald } RFCOMM_CHANNEL_EVENT;
95e628322dSMatthias Ringwald 
96e628322dSMatthias Ringwald typedef struct rfcomm_channel_event {
97e628322dSMatthias Ringwald     RFCOMM_CHANNEL_EVENT type;
98e628322dSMatthias Ringwald     uint16_t dummy; // force rfcomm_channel_event to be 2-byte aligned -> avoid -Wcast-align warning
99e628322dSMatthias Ringwald } rfcomm_channel_event_t;
100e628322dSMatthias Ringwald 
101e628322dSMatthias Ringwald typedef struct rfcomm_channel_event_pn {
102e628322dSMatthias Ringwald     rfcomm_channel_event_t super;
103e628322dSMatthias Ringwald     uint16_t max_frame_size;
104e628322dSMatthias Ringwald     uint8_t  priority;
105e628322dSMatthias Ringwald     uint8_t  credits_outgoing;
106e628322dSMatthias Ringwald } rfcomm_channel_event_pn_t;
107e628322dSMatthias Ringwald 
108e628322dSMatthias Ringwald typedef struct rfcomm_channel_event_rpn {
109e628322dSMatthias Ringwald     rfcomm_channel_event_t super;
110e628322dSMatthias Ringwald     rfcomm_rpn_data_t data;
111e628322dSMatthias Ringwald } rfcomm_channel_event_rpn_t;
112e628322dSMatthias Ringwald 
113e628322dSMatthias Ringwald typedef struct rfcomm_channel_event_rls {
114e628322dSMatthias Ringwald     rfcomm_channel_event_t super;
115e628322dSMatthias Ringwald     uint8_t line_status;
116e628322dSMatthias Ringwald } rfcomm_channel_event_rls_t;
117e628322dSMatthias Ringwald 
118e628322dSMatthias Ringwald typedef struct rfcomm_channel_event_msc {
119e628322dSMatthias Ringwald     rfcomm_channel_event_t super;
120e628322dSMatthias Ringwald     uint8_t modem_status;
121e628322dSMatthias Ringwald } rfcomm_channel_event_msc_t;
122e628322dSMatthias Ringwald 
1233deb3ec6SMatthias Ringwald 
1243deb3ec6SMatthias Ringwald // global rfcomm data
1253deb3ec6SMatthias Ringwald static uint16_t      rfcomm_client_cid_generator;  // used for client channel IDs
1263deb3ec6SMatthias Ringwald 
1273deb3ec6SMatthias Ringwald // linked lists for all
1288f2a52f4SMatthias Ringwald static btstack_linked_list_t rfcomm_multiplexers = NULL;
1298f2a52f4SMatthias Ringwald static btstack_linked_list_t rfcomm_channels = NULL;
1308f2a52f4SMatthias Ringwald static btstack_linked_list_t rfcomm_services = NULL;
1313deb3ec6SMatthias Ringwald 
1323deb3ec6SMatthias Ringwald static gap_security_level_t rfcomm_security_level;
1333deb3ec6SMatthias Ringwald 
134b31d33b2SMatthias Ringwald static int  rfcomm_channel_can_send(rfcomm_channel_t * channel);
135b31d33b2SMatthias Ringwald static int  rfcomm_channel_ready_for_open(rfcomm_channel_t *channel);
13662b5b741SMatthias Ringwald static int rfcomm_channel_ready_to_send(rfcomm_channel_t * channel);
1373232fa30SMatthias Ringwald static void rfcomm_channel_state_machine_with_channel(rfcomm_channel_t *channel, const rfcomm_channel_event_t *event);
1383232fa30SMatthias Ringwald static void rfcomm_channel_state_machine_with_dlci(rfcomm_multiplexer_t * multiplexer, uint8_t dlci, const rfcomm_channel_event_t *event);
139b31d33b2SMatthias Ringwald static void rfcomm_emit_can_send_now(rfcomm_channel_t *channel);
140b35818ceSMatthias Ringwald static int rfcomm_multiplexer_ready_to_send(rfcomm_multiplexer_t * multiplexer);
1413deb3ec6SMatthias Ringwald static void rfcomm_multiplexer_state_machine(rfcomm_multiplexer_t * multiplexer, RFCOMM_MULTIPLEXER_EVENT event);
1423deb3ec6SMatthias Ringwald 
1433deb3ec6SMatthias Ringwald // MARK: RFCOMM CLIENT EVENTS
1443deb3ec6SMatthias Ringwald 
1453deb3ec6SMatthias Ringwald // data: event (8), len(8), address(48), channel (8), rfcomm_cid (16)
1463deb3ec6SMatthias Ringwald static void rfcomm_emit_connection_request(rfcomm_channel_t *channel) {
1473deb3ec6SMatthias Ringwald     log_info("RFCOMM_EVENT_INCOMING_CONNECTION addr %s channel #%u cid 0x%02x",
1483deb3ec6SMatthias Ringwald              bd_addr_to_str(channel->multiplexer->remote_addr), channel->dlci>>1, channel->rfcomm_cid);
1493deb3ec6SMatthias Ringwald     uint8_t event[11];
1503deb3ec6SMatthias Ringwald     event[0] = RFCOMM_EVENT_INCOMING_CONNECTION;
1513deb3ec6SMatthias Ringwald     event[1] = sizeof(event) - 2;
152724d70a2SMatthias Ringwald     reverse_bd_addr(channel->multiplexer->remote_addr, &event[2]);
1533deb3ec6SMatthias Ringwald     event[8] = channel->dlci >> 1;
154f8fbdce0SMatthias Ringwald     little_endian_store_16(event, 9, channel->rfcomm_cid);
1553deb3ec6SMatthias Ringwald     hci_dump_packet(HCI_EVENT_PACKET, 0, event, sizeof(event));
156b31d33b2SMatthias Ringwald 	(channel->packet_handler)(HCI_EVENT_PACKET, 0, event, sizeof(event));
1573deb3ec6SMatthias Ringwald }
1583deb3ec6SMatthias Ringwald 
1593deb3ec6SMatthias Ringwald // API Change: BTstack-0.3.50x uses
1603deb3ec6SMatthias Ringwald // data: event(8), len(8), status (8), address (48), server channel(8), rfcomm_cid(16), max frame size(16)
1613deb3ec6SMatthias Ringwald // next Cydia release will use SVN version of this
1623deb3ec6SMatthias Ringwald // data: event(8), len(8), status (8), address (48), handle (16), server channel(8), rfcomm_cid(16), max frame size(16)
1633deb3ec6SMatthias Ringwald static void rfcomm_emit_channel_opened(rfcomm_channel_t *channel, uint8_t status) {
164f8f6a918SMatthias Ringwald     log_info("RFCOMM_EVENT_CHANNEL_OPENED status 0x%x addr %s handle 0x%x channel #%u cid 0x%02x mtu %u",
1653deb3ec6SMatthias Ringwald              status, bd_addr_to_str(channel->multiplexer->remote_addr), channel->multiplexer->con_handle,
1663deb3ec6SMatthias Ringwald              channel->dlci>>1, channel->rfcomm_cid, channel->max_frame_size);
167bab5f4f0SMatthias Ringwald     uint8_t event[18];
1683deb3ec6SMatthias Ringwald     uint8_t pos = 0;
169f8f6a918SMatthias Ringwald     event[pos++] = RFCOMM_EVENT_CHANNEL_OPENED;  // 0
1705d1e858fSMatthias Ringwald     event[pos++] = sizeof(event) - 2;                   // 1
1715d1e858fSMatthias Ringwald     event[pos++] = status;                              // 2
172724d70a2SMatthias Ringwald     reverse_bd_addr(channel->multiplexer->remote_addr, &event[pos]); pos += 6; // 3
173f8fbdce0SMatthias Ringwald     little_endian_store_16(event,  pos, channel->multiplexer->con_handle);   pos += 2; // 9
1745d1e858fSMatthias Ringwald 	event[pos++] = channel->dlci >> 1;                                      // 11
175f8fbdce0SMatthias Ringwald 	little_endian_store_16(event, pos, channel->rfcomm_cid); pos += 2;                 // 12 - channel ID
176f8fbdce0SMatthias Ringwald 	little_endian_store_16(event, pos, channel->max_frame_size); pos += 2;   // max frame size
177bab5f4f0SMatthias Ringwald     event[pos++] = channel->service ? 1 : 0;    // linked to service -> incoming
1783deb3ec6SMatthias Ringwald     hci_dump_packet(HCI_EVENT_PACKET, 0, event, sizeof(event));
179b31d33b2SMatthias Ringwald 	(channel->packet_handler)(HCI_EVENT_PACKET, 0, event, pos);
180b31d33b2SMatthias Ringwald 
181b31d33b2SMatthias Ringwald     // if channel opened successfully, also send can send now if possible
182b31d33b2SMatthias Ringwald     if (status) return;
183b31d33b2SMatthias Ringwald     if (rfcomm_channel_can_send(channel)){
184b31d33b2SMatthias Ringwald         rfcomm_emit_can_send_now(channel);
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) {
221*d9d23054SMatthias Ringwald     log_debug("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
77367a68729SMatthias Ringwald             switch(channel->state){
77467a68729SMatthias Ringwald                 case RFCOMM_CHANNEL_OPEN:
7753deb3ec6SMatthias Ringwald                     rfcomm_emit_channel_closed(channel);
77667a68729SMatthias Ringwald                     break;
77767a68729SMatthias Ringwald                 case RFCOMM_CHANNEL_SEND_UA_AFTER_DISC:
77867a68729SMatthias Ringwald                     // remote didn't wait until we send the UA disc
77967a68729SMatthias Ringwald                     break;
78067a68729SMatthias Ringwald                 default:
7813deb3ec6SMatthias Ringwald                     rfcomm_emit_channel_opened(channel, RFCOMM_MULTIPLEXER_STOPPED);
78267a68729SMatthias Ringwald                     break;
7833deb3ec6SMatthias Ringwald             }
7843deb3ec6SMatthias Ringwald             // remove from list
7853deb3ec6SMatthias Ringwald             it->next = it->next->next;
7863deb3ec6SMatthias Ringwald             // free channel struct
7873deb3ec6SMatthias Ringwald             btstack_memory_rfcomm_channel_free(channel);
7883deb3ec6SMatthias Ringwald         } else {
7893deb3ec6SMatthias Ringwald             it = it->next;
7903deb3ec6SMatthias Ringwald         }
7913deb3ec6SMatthias Ringwald     }
7923deb3ec6SMatthias Ringwald 
7933deb3ec6SMatthias Ringwald     // remove mutliplexer
7943deb3ec6SMatthias Ringwald     rfcomm_multiplexer_free(multiplexer);
7953deb3ec6SMatthias Ringwald }
7963deb3ec6SMatthias Ringwald 
797ec820d77SMatthias Ringwald static void rfcomm_multiplexer_timer_handler(btstack_timer_source_t *timer){
798c5b64319SMatthias Ringwald     rfcomm_multiplexer_t * multiplexer = (rfcomm_multiplexer_t*) btstack_run_loop_get_timer_context(timer);
7993deb3ec6SMatthias Ringwald     if (rfcomm_multiplexer_has_channels(multiplexer)) return;
8003deb3ec6SMatthias Ringwald 
8013deb3ec6SMatthias Ringwald     log_info("rfcomm_multiplexer_timer_handler timeout: shutting down multiplexer! (no channels)");
8023deb3ec6SMatthias Ringwald     uint16_t l2cap_cid = multiplexer->l2cap_cid;
8033deb3ec6SMatthias Ringwald     rfcomm_multiplexer_finalize(multiplexer);
804ce8f182eSMatthias Ringwald     l2cap_disconnect(l2cap_cid, 0x13);
8053deb3ec6SMatthias Ringwald }
8063deb3ec6SMatthias Ringwald 
8073deb3ec6SMatthias Ringwald static void rfcomm_multiplexer_prepare_idle_timer(rfcomm_multiplexer_t * multiplexer){
8083deb3ec6SMatthias Ringwald     if (multiplexer->timer_active) {
809528a4a3bSMatthias Ringwald         btstack_run_loop_remove_timer(&multiplexer->timer);
8103deb3ec6SMatthias Ringwald         multiplexer->timer_active = 0;
8113deb3ec6SMatthias Ringwald     }
8123deb3ec6SMatthias Ringwald     if (rfcomm_multiplexer_has_channels(multiplexer)) return;
8133deb3ec6SMatthias Ringwald 
8143deb3ec6SMatthias Ringwald     // start idle timer for multiplexer timeout check as there are no rfcomm channels yet
815528a4a3bSMatthias Ringwald     btstack_run_loop_set_timer(&multiplexer->timer, RFCOMM_MULIPLEXER_TIMEOUT_MS);
81691a977e8SMatthias Ringwald     btstack_run_loop_set_timer_handler(&multiplexer->timer, rfcomm_multiplexer_timer_handler);
81791a977e8SMatthias Ringwald     btstack_run_loop_set_timer_context(&multiplexer->timer, multiplexer);
818528a4a3bSMatthias Ringwald     btstack_run_loop_add_timer(&multiplexer->timer);
8193deb3ec6SMatthias Ringwald     multiplexer->timer_active = 1;
8203deb3ec6SMatthias Ringwald }
8213deb3ec6SMatthias Ringwald 
8223deb3ec6SMatthias Ringwald static void rfcomm_multiplexer_opened(rfcomm_multiplexer_t *multiplexer){
8233deb3ec6SMatthias Ringwald     log_info("Multiplexer up and running");
8243deb3ec6SMatthias Ringwald     multiplexer->state = RFCOMM_MULTIPLEXER_OPEN;
8253deb3ec6SMatthias Ringwald 
82662b5b741SMatthias Ringwald     const rfcomm_channel_event_t event = { CH_EVT_MULTIPLEXER_READY };
8273deb3ec6SMatthias Ringwald 
8283deb3ec6SMatthias Ringwald     // transition of channels that wait for multiplexer
829665d90f2SMatthias Ringwald     btstack_linked_item_t *it;
830665d90f2SMatthias Ringwald     for (it = (btstack_linked_item_t *) rfcomm_channels; it ; it = it->next){
8313deb3ec6SMatthias Ringwald         rfcomm_channel_t * channel = ((rfcomm_channel_t *) it);
8323deb3ec6SMatthias Ringwald         if (channel->multiplexer != multiplexer) continue;
8333232fa30SMatthias Ringwald         rfcomm_channel_state_machine_with_channel(channel, &event);
83462b5b741SMatthias Ringwald         if (rfcomm_channel_ready_to_send(channel)){
83562b5b741SMatthias Ringwald             l2cap_request_can_send_now_event(multiplexer->l2cap_cid);
83662b5b741SMatthias Ringwald         }
8373deb3ec6SMatthias Ringwald     }
8383deb3ec6SMatthias Ringwald     rfcomm_multiplexer_prepare_idle_timer(multiplexer);
839b35818ceSMatthias Ringwald 
840b35818ceSMatthias Ringwald     // request can send now for multiplexer if ready
841b35818ceSMatthias Ringwald     if (rfcomm_multiplexer_ready_to_send(multiplexer)){
842b35818ceSMatthias Ringwald         l2cap_request_can_send_now_event(multiplexer->l2cap_cid);
843b35818ceSMatthias Ringwald     }
8443deb3ec6SMatthias Ringwald }
8453deb3ec6SMatthias Ringwald 
846b35818ceSMatthias Ringwald static void rfcomm_handle_can_send_now(uint16_t l2cap_cid){
847b35818ceSMatthias Ringwald 
848e9a7c22dSMatthias Ringwald     log_debug("rfcomm_handle_can_send_now enter: %u", l2cap_cid);
84962b5b741SMatthias Ringwald 
850e9a7c22dSMatthias Ringwald     btstack_linked_list_iterator_t it;
851e9a7c22dSMatthias Ringwald     int token_consumed = 0;
852e9a7c22dSMatthias Ringwald 
853e9a7c22dSMatthias Ringwald     // forward token to multiplexer
854b35818ceSMatthias Ringwald     btstack_linked_list_iterator_init(&it, &rfcomm_multiplexers);
855e9a7c22dSMatthias Ringwald     while (!token_consumed && btstack_linked_list_iterator_has_next(&it)){
856b35818ceSMatthias Ringwald         rfcomm_multiplexer_t * multiplexer = (rfcomm_multiplexer_t *) btstack_linked_list_iterator_next(&it);
857b35818ceSMatthias Ringwald         if (multiplexer->l2cap_cid != l2cap_cid) continue;
858b35818ceSMatthias Ringwald         if (rfcomm_multiplexer_ready_to_send(multiplexer)){
859e9a7c22dSMatthias Ringwald             log_debug("rfcomm_handle_can_send_now enter: multiplexer token");
860e9a7c22dSMatthias Ringwald             token_consumed = 1;
861b35818ceSMatthias Ringwald             rfcomm_multiplexer_state_machine(multiplexer, MULT_EV_READY_TO_SEND);
862b35818ceSMatthias Ringwald         }
863b35818ceSMatthias Ringwald     }
864b35818ceSMatthias Ringwald 
865e9a7c22dSMatthias Ringwald     // forward token to channel state machine
86662b5b741SMatthias Ringwald     btstack_linked_list_iterator_init(&it, &rfcomm_channels);
867e9a7c22dSMatthias Ringwald     while (!token_consumed && btstack_linked_list_iterator_has_next(&it)){
86862b5b741SMatthias Ringwald         rfcomm_channel_t * channel = (rfcomm_channel_t *) btstack_linked_list_iterator_next(&it);
86962b5b741SMatthias Ringwald         if (channel->multiplexer->l2cap_cid != l2cap_cid) continue;
87062b5b741SMatthias Ringwald         // channel state machine
87162b5b741SMatthias Ringwald         if (rfcomm_channel_ready_to_send(channel)){
872e9a7c22dSMatthias Ringwald             log_debug("rfcomm_handle_can_send_now enter: channel token");
873e9a7c22dSMatthias Ringwald             token_consumed = 1;
87462b5b741SMatthias Ringwald             const rfcomm_channel_event_t event = { CH_EVT_READY_TO_SEND };
8753232fa30SMatthias Ringwald             rfcomm_channel_state_machine_with_channel(channel, &event);
87662b5b741SMatthias Ringwald         }
8775ef5325cSMatthias Ringwald     }
8785ef5325cSMatthias Ringwald 
879e9a7c22dSMatthias Ringwald     // forward token to client
8805ef5325cSMatthias Ringwald     btstack_linked_list_iterator_init(&it, &rfcomm_channels);
881e9a7c22dSMatthias Ringwald     while (!token_consumed && btstack_linked_list_iterator_has_next(&it)){
8825ef5325cSMatthias Ringwald         rfcomm_channel_t * channel = (rfcomm_channel_t *) btstack_linked_list_iterator_next(&it);
8835ef5325cSMatthias Ringwald         if (channel->multiplexer->l2cap_cid != l2cap_cid) continue;
88462b5b741SMatthias Ringwald         // client waiting for can send now
88562b5b741SMatthias Ringwald         if (!channel->waiting_for_can_send_now)    continue;
88662b5b741SMatthias Ringwald         if (!channel->credits_outgoing)            continue;
88762b5b741SMatthias Ringwald         if ((channel->multiplexer->fcon & 1) == 0) continue;
88862b5b741SMatthias Ringwald 
889e9a7c22dSMatthias Ringwald         log_debug("rfcomm_handle_can_send_now enter: client token");
890e9a7c22dSMatthias Ringwald         token_consumed = 1;
89162b5b741SMatthias Ringwald         channel->waiting_for_can_send_now = 0;
89262b5b741SMatthias Ringwald         rfcomm_emit_can_send_now(channel);
89362b5b741SMatthias Ringwald     }
894e9a7c22dSMatthias Ringwald 
895e9a7c22dSMatthias Ringwald     // if token was consumed, request another one
896e9a7c22dSMatthias Ringwald     if (token_consumed) {
897e9a7c22dSMatthias Ringwald         l2cap_request_can_send_now_event(l2cap_cid);
89862b5b741SMatthias Ringwald     }
899e9a7c22dSMatthias Ringwald 
900e9a7c22dSMatthias Ringwald     log_debug("rfcomm_handle_can_send_now exit");
901b35818ceSMatthias Ringwald }
9023deb3ec6SMatthias Ringwald 
903f7d61b10SMatthias Ringwald static void rfcomm_multiplexer_set_state_and_request_can_send_now_event(rfcomm_multiplexer_t * multiplexer, RFCOMM_MULTIPLEXER_STATE state){
904f7d61b10SMatthias Ringwald     multiplexer->state = state;
905f7d61b10SMatthias Ringwald     l2cap_request_can_send_now_event(multiplexer->l2cap_cid);
906f7d61b10SMatthias Ringwald }
907f7d61b10SMatthias Ringwald 
9083deb3ec6SMatthias Ringwald /**
9093deb3ec6SMatthias Ringwald  * @return handled packet
9103deb3ec6SMatthias Ringwald  */
9110d78ab98SMatthias Ringwald static int rfcomm_hci_event_handler(uint8_t *packet, uint16_t size){
9129ec2630cSMatthias Ringwald     UNUSED(size);
9139ec2630cSMatthias Ringwald 
9143deb3ec6SMatthias Ringwald     bd_addr_t event_addr;
9153deb3ec6SMatthias Ringwald     uint16_t  psm;
9163deb3ec6SMatthias Ringwald     uint16_t l2cap_cid;
9173deb3ec6SMatthias Ringwald     hci_con_handle_t con_handle;
9183deb3ec6SMatthias Ringwald     rfcomm_multiplexer_t *multiplexer = NULL;
9193deb3ec6SMatthias Ringwald     uint8_t status;
9203deb3ec6SMatthias Ringwald 
9210e2df43fSMatthias Ringwald     switch (hci_event_packet_get_type(packet)) {
9223deb3ec6SMatthias Ringwald 
9233deb3ec6SMatthias Ringwald         // accept incoming PSM_RFCOMM connection if no multiplexer exists yet
9243deb3ec6SMatthias Ringwald         case L2CAP_EVENT_INCOMING_CONNECTION:
9253deb3ec6SMatthias Ringwald             // data: event(8), len(8), address(48), handle (16),  psm (16), source cid(16) dest cid(16)
926724d70a2SMatthias Ringwald             reverse_bd_addr(&packet[2], event_addr);
927f8fbdce0SMatthias Ringwald             con_handle = little_endian_read_16(packet,  8);
928f8fbdce0SMatthias Ringwald             psm        = little_endian_read_16(packet, 10);
929f8fbdce0SMatthias Ringwald             l2cap_cid  = little_endian_read_16(packet, 12);
9303deb3ec6SMatthias Ringwald 
9313deb3ec6SMatthias Ringwald             if (psm != PSM_RFCOMM) break;
9323deb3ec6SMatthias Ringwald 
9333deb3ec6SMatthias Ringwald             multiplexer = rfcomm_multiplexer_for_addr(event_addr);
9343deb3ec6SMatthias Ringwald 
9353deb3ec6SMatthias Ringwald             if (multiplexer) {
9363deb3ec6SMatthias Ringwald                 log_info("INCOMING_CONNECTION (l2cap_cid 0x%02x) for PSM_RFCOMM => decline - multiplexer already exists", l2cap_cid);
9377ef6a7bbSMatthias Ringwald                 l2cap_decline_connection(l2cap_cid);
9383deb3ec6SMatthias Ringwald                 return 1;
9393deb3ec6SMatthias Ringwald             }
9403deb3ec6SMatthias Ringwald 
9413deb3ec6SMatthias Ringwald             // create and inititialize new multiplexer instance (incoming)
9423deb3ec6SMatthias Ringwald             multiplexer = rfcomm_multiplexer_create_for_addr(event_addr);
9433deb3ec6SMatthias Ringwald             if (!multiplexer){
9443deb3ec6SMatthias Ringwald                 log_info("INCOMING_CONNECTION (l2cap_cid 0x%02x) for PSM_RFCOMM => decline - no memory left", l2cap_cid);
9457ef6a7bbSMatthias Ringwald                 l2cap_decline_connection(l2cap_cid);
9463deb3ec6SMatthias Ringwald                 return 1;
9473deb3ec6SMatthias Ringwald             }
9483deb3ec6SMatthias Ringwald 
9493deb3ec6SMatthias Ringwald             multiplexer->con_handle = con_handle;
9503deb3ec6SMatthias Ringwald             multiplexer->l2cap_cid = l2cap_cid;
9510d78ab98SMatthias Ringwald             //
9523deb3ec6SMatthias Ringwald             multiplexer->state = RFCOMM_MULTIPLEXER_W4_SABM_0;
9533deb3ec6SMatthias Ringwald             log_info("L2CAP_EVENT_INCOMING_CONNECTION (l2cap_cid 0x%02x) for PSM_RFCOMM => accept", l2cap_cid);
954ce8f182eSMatthias Ringwald             l2cap_accept_connection(l2cap_cid);
9553deb3ec6SMatthias Ringwald             return 1;
9563deb3ec6SMatthias Ringwald 
9573deb3ec6SMatthias Ringwald         // l2cap connection opened -> store l2cap_cid, remote_addr
9583deb3ec6SMatthias Ringwald         case L2CAP_EVENT_CHANNEL_OPENED:
9593deb3ec6SMatthias Ringwald 
960f8fbdce0SMatthias Ringwald             if (little_endian_read_16(packet, 11) != PSM_RFCOMM) break;
9613deb3ec6SMatthias Ringwald 
9623deb3ec6SMatthias Ringwald             status = packet[2];
9633deb3ec6SMatthias Ringwald             log_info("L2CAP_EVENT_CHANNEL_OPENED for PSM_RFCOMM, status %u", status);
9643deb3ec6SMatthias Ringwald 
9653deb3ec6SMatthias Ringwald             // get multiplexer for remote addr
966f8fbdce0SMatthias Ringwald             con_handle = little_endian_read_16(packet, 9);
967f8fbdce0SMatthias Ringwald             l2cap_cid = little_endian_read_16(packet, 13);
968724d70a2SMatthias Ringwald             reverse_bd_addr(&packet[3], event_addr);
9693deb3ec6SMatthias Ringwald             multiplexer = rfcomm_multiplexer_for_addr(event_addr);
9703deb3ec6SMatthias Ringwald             if (!multiplexer) {
9713deb3ec6SMatthias Ringwald                 log_error("L2CAP_EVENT_CHANNEL_OPENED but no multiplexer prepared");
9723deb3ec6SMatthias Ringwald                 return 1;
9733deb3ec6SMatthias Ringwald             }
9743deb3ec6SMatthias Ringwald 
9753deb3ec6SMatthias Ringwald             // on l2cap open error discard everything
9763deb3ec6SMatthias Ringwald             if (status){
9773deb3ec6SMatthias Ringwald 
9783deb3ec6SMatthias Ringwald                 // remove (potential) timer
9793deb3ec6SMatthias Ringwald                 rfcomm_multiplexer_stop_timer(multiplexer);
9803deb3ec6SMatthias Ringwald 
9813deb3ec6SMatthias Ringwald                 // emit rfcomm_channel_opened with status and free channel
982665d90f2SMatthias Ringwald                 btstack_linked_item_t * it = (btstack_linked_item_t *) &rfcomm_channels;
9833deb3ec6SMatthias Ringwald                 while (it->next) {
9843deb3ec6SMatthias Ringwald                     rfcomm_channel_t * channel = (rfcomm_channel_t *) it->next;
9853deb3ec6SMatthias Ringwald                     if (channel->multiplexer == multiplexer){
9863deb3ec6SMatthias Ringwald                         rfcomm_emit_channel_opened(channel, status);
9873deb3ec6SMatthias Ringwald                         it->next = it->next->next;
9883deb3ec6SMatthias Ringwald                         btstack_memory_rfcomm_channel_free(channel);
9893deb3ec6SMatthias Ringwald                     } else {
9903deb3ec6SMatthias Ringwald                         it = it->next;
9913deb3ec6SMatthias Ringwald                     }
9923deb3ec6SMatthias Ringwald                 }
9933deb3ec6SMatthias Ringwald 
9943deb3ec6SMatthias Ringwald                 // free multiplexer
9953deb3ec6SMatthias Ringwald                 rfcomm_multiplexer_free(multiplexer);
9963deb3ec6SMatthias Ringwald                 return 1;
9973deb3ec6SMatthias Ringwald             }
9983deb3ec6SMatthias Ringwald 
9990d78ab98SMatthias Ringwald             // following could be: rfcom_multiplexer_state_machein(..., EVENT_L2CAP_OPENED)
10000d78ab98SMatthias Ringwald 
10013deb3ec6SMatthias Ringwald             if (multiplexer->state == RFCOMM_MULTIPLEXER_W4_CONNECT) {
10023deb3ec6SMatthias Ringwald                 log_info("L2CAP_EVENT_CHANNEL_OPENED: outgoing connection");
10033deb3ec6SMatthias Ringwald                 // wrong remote addr
1004058e3d6bSMatthias Ringwald                 if (bd_addr_cmp(event_addr, multiplexer->remote_addr)) break;
10053deb3ec6SMatthias Ringwald                 multiplexer->l2cap_cid = l2cap_cid;
10063deb3ec6SMatthias Ringwald                 multiplexer->con_handle = con_handle;
10073deb3ec6SMatthias Ringwald                 // send SABM #0
1008f7d61b10SMatthias Ringwald                 rfcomm_multiplexer_set_state_and_request_can_send_now_event(multiplexer, RFCOMM_MULTIPLEXER_SEND_SABM_0);
1009b35818ceSMatthias Ringwald 
10103deb3ec6SMatthias Ringwald             } else { // multiplexer->state == RFCOMM_MULTIPLEXER_W4_SABM_0
10113deb3ec6SMatthias Ringwald 
10123deb3ec6SMatthias Ringwald                 // set max frame size based on l2cap MTU
1013f8fbdce0SMatthias Ringwald                 multiplexer->max_frame_size = rfcomm_max_frame_size_for_l2cap_mtu(little_endian_read_16(packet, 17));
10143deb3ec6SMatthias Ringwald             }
10153deb3ec6SMatthias Ringwald             return 1;
10163deb3ec6SMatthias Ringwald 
10173deb3ec6SMatthias Ringwald             // l2cap disconnect -> state = RFCOMM_MULTIPLEXER_CLOSED;
10183deb3ec6SMatthias Ringwald 
1019b31d33b2SMatthias Ringwald         // Notify channel packet handler if they can send now
1020b31d33b2SMatthias Ringwald         case L2CAP_EVENT_CAN_SEND_NOW:
1021b35818ceSMatthias Ringwald             l2cap_cid = l2cap_event_can_send_now_get_local_cid(packet);
1022b35818ceSMatthias Ringwald             rfcomm_handle_can_send_now(l2cap_cid);
10230d78ab98SMatthias Ringwald             return 1;
10243deb3ec6SMatthias Ringwald 
10253deb3ec6SMatthias Ringwald         case L2CAP_EVENT_CHANNEL_CLOSED:
10263deb3ec6SMatthias Ringwald             // data: event (8), len(8), channel (16)
1027f8fbdce0SMatthias Ringwald             l2cap_cid = little_endian_read_16(packet, 2);
10283deb3ec6SMatthias Ringwald             multiplexer = rfcomm_multiplexer_for_l2cap_cid(l2cap_cid);
10293deb3ec6SMatthias Ringwald             log_info("L2CAP_EVENT_CHANNEL_CLOSED cid 0x%0x, mult %p", l2cap_cid, multiplexer);
10303deb3ec6SMatthias Ringwald             if (!multiplexer) break;
10313deb3ec6SMatthias Ringwald             log_info("L2CAP_EVENT_CHANNEL_CLOSED state %u", multiplexer->state);
10327d20d6a4SMatthias Ringwald             // no need to call l2cap_disconnect here, as it's already closed
10333deb3ec6SMatthias Ringwald             rfcomm_multiplexer_finalize(multiplexer);
1034d5499c6fSMatthias Ringwald             return 1;
1035d5499c6fSMatthias Ringwald 
10363deb3ec6SMatthias Ringwald         default:
10373deb3ec6SMatthias Ringwald             break;
10383deb3ec6SMatthias Ringwald     }
10393deb3ec6SMatthias Ringwald     return 0;
10403deb3ec6SMatthias Ringwald }
10413deb3ec6SMatthias Ringwald 
10423deb3ec6SMatthias Ringwald static int rfcomm_multiplexer_l2cap_packet_handler(uint16_t channel, uint8_t *packet, uint16_t size){
10439ec2630cSMatthias Ringwald     UNUSED(size);
10443deb3ec6SMatthias Ringwald 
10453deb3ec6SMatthias Ringwald     // get or create a multiplexer for a certain device
10463deb3ec6SMatthias Ringwald     rfcomm_multiplexer_t *multiplexer = rfcomm_multiplexer_for_l2cap_cid(channel);
10473deb3ec6SMatthias Ringwald     if (!multiplexer) return 0;
10483deb3ec6SMatthias Ringwald 
10493deb3ec6SMatthias Ringwald     uint16_t l2cap_cid = multiplexer->l2cap_cid;
10503deb3ec6SMatthias Ringwald 
10513deb3ec6SMatthias Ringwald 	// but only care for multiplexer control channel
10523deb3ec6SMatthias Ringwald     uint8_t frame_dlci = packet[0] >> 2;
10533deb3ec6SMatthias Ringwald     if (frame_dlci) return 0;
10543deb3ec6SMatthias Ringwald     const uint8_t length_offset = (packet[2] & 1) ^ 1;  // to be used for pos >= 3
10553deb3ec6SMatthias Ringwald     const uint8_t credit_offset = ((packet[1] & BT_RFCOMM_UIH_PF) == BT_RFCOMM_UIH_PF) ? 1 : 0;   // credits for uih_pf frames
10563deb3ec6SMatthias Ringwald     const uint8_t payload_offset = 3 + length_offset + credit_offset;
10573deb3ec6SMatthias Ringwald     switch (packet[1]){
10583deb3ec6SMatthias Ringwald 
10593deb3ec6SMatthias Ringwald         case BT_RFCOMM_SABM:
10603deb3ec6SMatthias Ringwald             if (multiplexer->state == RFCOMM_MULTIPLEXER_W4_SABM_0){
10613deb3ec6SMatthias Ringwald                 log_info("Received SABM #0");
10623deb3ec6SMatthias Ringwald                 multiplexer->outgoing = 0;
1063f7d61b10SMatthias Ringwald                 rfcomm_multiplexer_set_state_and_request_can_send_now_event(multiplexer, RFCOMM_MULTIPLEXER_SEND_UA_0);
10643deb3ec6SMatthias Ringwald                 return 1;
10653deb3ec6SMatthias Ringwald             }
10663deb3ec6SMatthias Ringwald             break;
10673deb3ec6SMatthias Ringwald 
10683deb3ec6SMatthias Ringwald         case BT_RFCOMM_UA:
10693deb3ec6SMatthias Ringwald             if (multiplexer->state == RFCOMM_MULTIPLEXER_W4_UA_0) {
10703deb3ec6SMatthias Ringwald                 // UA #0 -> send UA #0, state = RFCOMM_MULTIPLEXER_OPEN
10713deb3ec6SMatthias Ringwald                 log_info("Received UA #0 ");
10723deb3ec6SMatthias Ringwald                 rfcomm_multiplexer_opened(multiplexer);
10733deb3ec6SMatthias Ringwald                 return 1;
10743deb3ec6SMatthias Ringwald             }
10753deb3ec6SMatthias Ringwald             break;
10763deb3ec6SMatthias Ringwald 
10773deb3ec6SMatthias Ringwald         case BT_RFCOMM_DISC:
10783deb3ec6SMatthias Ringwald             // DISC #0 -> send UA #0, close multiplexer
10793deb3ec6SMatthias Ringwald             log_info("Received DISC #0, (ougoing = %u)", multiplexer->outgoing);
1080f7d61b10SMatthias Ringwald             rfcomm_multiplexer_set_state_and_request_can_send_now_event(multiplexer, RFCOMM_MULTIPLEXER_SEND_UA_0_AND_DISC);
10813deb3ec6SMatthias Ringwald             return 1;
10823deb3ec6SMatthias Ringwald 
10833deb3ec6SMatthias Ringwald         case BT_RFCOMM_DM:
10843deb3ec6SMatthias Ringwald             // DM #0 - we shouldn't get this, just give up
10853deb3ec6SMatthias Ringwald             log_info("Received DM #0");
10863deb3ec6SMatthias Ringwald             log_info("-> Closing down multiplexer");
10873deb3ec6SMatthias Ringwald             rfcomm_multiplexer_finalize(multiplexer);
1088ce8f182eSMatthias Ringwald             l2cap_disconnect(l2cap_cid, 0x13);
10893deb3ec6SMatthias Ringwald             return 1;
10903deb3ec6SMatthias Ringwald 
10913deb3ec6SMatthias Ringwald         case BT_RFCOMM_UIH:
10923deb3ec6SMatthias Ringwald             if (packet[payload_offset] == BT_RFCOMM_CLD_CMD){
10933deb3ec6SMatthias Ringwald                 // Multiplexer close down (CLD) -> close mutliplexer
10943deb3ec6SMatthias Ringwald                 log_info("Received Multiplexer close down command");
10953deb3ec6SMatthias Ringwald                 log_info("-> Closing down multiplexer");
10963deb3ec6SMatthias Ringwald                 rfcomm_multiplexer_finalize(multiplexer);
1097ce8f182eSMatthias Ringwald                 l2cap_disconnect(l2cap_cid, 0x13);
10983deb3ec6SMatthias Ringwald                 return 1;
10993deb3ec6SMatthias Ringwald             }
11003deb3ec6SMatthias Ringwald             switch (packet[payload_offset]){
11013deb3ec6SMatthias Ringwald                 case BT_RFCOMM_CLD_CMD:
11023deb3ec6SMatthias Ringwald                      // Multiplexer close down (CLD) -> close mutliplexer
11033deb3ec6SMatthias Ringwald                     log_info("Received Multiplexer close down command");
11043deb3ec6SMatthias Ringwald                     log_info("-> Closing down multiplexer");
11053deb3ec6SMatthias Ringwald                     rfcomm_multiplexer_finalize(multiplexer);
1106ce8f182eSMatthias Ringwald                     l2cap_disconnect(l2cap_cid, 0x13);
11073deb3ec6SMatthias Ringwald                     return 1;
11083deb3ec6SMatthias Ringwald 
11093deb3ec6SMatthias Ringwald                 case BT_RFCOMM_FCON_CMD:
11103deb3ec6SMatthias Ringwald                     multiplexer->fcon = 0x81;
1111b35818ceSMatthias Ringwald                     l2cap_request_can_send_now_event(multiplexer->l2cap_cid);
1112b35818ceSMatthias Ringwald                     return 1;
11133deb3ec6SMatthias Ringwald 
11143deb3ec6SMatthias Ringwald                 case BT_RFCOMM_FCOFF_CMD:
11153deb3ec6SMatthias Ringwald                     multiplexer->fcon = 0x80;
1116b35818ceSMatthias Ringwald                     l2cap_request_can_send_now_event(multiplexer->l2cap_cid);
1117b35818ceSMatthias Ringwald                     return 1;
11183deb3ec6SMatthias Ringwald 
11193deb3ec6SMatthias Ringwald                 case BT_RFCOMM_TEST_CMD: {
11203deb3ec6SMatthias Ringwald                     log_info("Received test command");
11213deb3ec6SMatthias Ringwald                     int len = packet[payload_offset+1] >> 1; // length < 125
11223deb3ec6SMatthias Ringwald                     if (len > RFCOMM_TEST_DATA_MAX_LEN){
11233deb3ec6SMatthias Ringwald                         len = RFCOMM_TEST_DATA_MAX_LEN;
11243deb3ec6SMatthias Ringwald                     }
11253deb3ec6SMatthias Ringwald                     multiplexer->test_data_len = len;
11263deb3ec6SMatthias Ringwald                     memcpy(multiplexer->test_data, &packet[payload_offset + 2], len);
1127b35818ceSMatthias Ringwald                     l2cap_request_can_send_now_event(multiplexer->l2cap_cid);
11283deb3ec6SMatthias Ringwald                     return 1;
11293deb3ec6SMatthias Ringwald                 }
11303deb3ec6SMatthias Ringwald                 default:
11313deb3ec6SMatthias Ringwald                     break;
11323deb3ec6SMatthias Ringwald             }
11333deb3ec6SMatthias Ringwald             break;
11343deb3ec6SMatthias Ringwald 
11353deb3ec6SMatthias Ringwald         default:
11363deb3ec6SMatthias Ringwald             break;
11373deb3ec6SMatthias Ringwald 
11383deb3ec6SMatthias Ringwald     }
11393deb3ec6SMatthias Ringwald     return 0;
11403deb3ec6SMatthias Ringwald }
11413deb3ec6SMatthias Ringwald 
1142b35818ceSMatthias Ringwald static int rfcomm_multiplexer_ready_to_send(rfcomm_multiplexer_t * multiplexer){
1143b35818ceSMatthias Ringwald     if (multiplexer->send_dm_for_dlci) return 1;
1144b35818ceSMatthias Ringwald     if (multiplexer->nsc_command) return 1;
1145b35818ceSMatthias Ringwald     if (multiplexer->fcon & 0x80) return 1;
1146b35818ceSMatthias Ringwald     switch (multiplexer->state){
1147b35818ceSMatthias Ringwald         case RFCOMM_MULTIPLEXER_SEND_SABM_0:
1148b35818ceSMatthias Ringwald         case RFCOMM_MULTIPLEXER_SEND_UA_0:
1149b35818ceSMatthias Ringwald         case RFCOMM_MULTIPLEXER_SEND_UA_0_AND_DISC:
1150b35818ceSMatthias Ringwald             return 1;
1151b35818ceSMatthias Ringwald         case RFCOMM_MULTIPLEXER_OPEN:
1152b35818ceSMatthias Ringwald             if (multiplexer->test_data_len) {
1153b35818ceSMatthias Ringwald                 return 1;
1154b35818ceSMatthias Ringwald             }
1155b35818ceSMatthias Ringwald             break;
1156b35818ceSMatthias Ringwald         default:
1157b35818ceSMatthias Ringwald             break;
1158b35818ceSMatthias Ringwald     }
1159b35818ceSMatthias Ringwald     return 0;
1160b35818ceSMatthias Ringwald }
1161b35818ceSMatthias Ringwald 
11623deb3ec6SMatthias Ringwald static void rfcomm_multiplexer_state_machine(rfcomm_multiplexer_t * multiplexer, RFCOMM_MULTIPLEXER_EVENT event){
11633deb3ec6SMatthias Ringwald 
1164f7d61b10SMatthias Ringwald     if (event != MULT_EV_READY_TO_SEND) return;
1165f7d61b10SMatthias Ringwald 
11663deb3ec6SMatthias Ringwald     uint16_t l2cap_cid = multiplexer->l2cap_cid;
11673deb3ec6SMatthias Ringwald 
11683deb3ec6SMatthias Ringwald     // process stored DM responses
11693deb3ec6SMatthias Ringwald     if (multiplexer->send_dm_for_dlci){
11703deb3ec6SMatthias Ringwald         uint8_t dlci = multiplexer->send_dm_for_dlci;
11713deb3ec6SMatthias Ringwald         multiplexer->send_dm_for_dlci = 0;
11723deb3ec6SMatthias Ringwald         rfcomm_send_dm_pf(multiplexer, dlci);
11733deb3ec6SMatthias Ringwald         return;
11743deb3ec6SMatthias Ringwald     }
11753deb3ec6SMatthias Ringwald 
11763deb3ec6SMatthias Ringwald     if (multiplexer->nsc_command){
11773deb3ec6SMatthias Ringwald         uint8_t command = multiplexer->nsc_command;
11783deb3ec6SMatthias Ringwald         multiplexer->nsc_command = 0;
11793deb3ec6SMatthias Ringwald         rfcomm_send_uih_nsc_rsp(multiplexer, command);
11803deb3ec6SMatthias Ringwald         return;
11813deb3ec6SMatthias Ringwald     }
11823deb3ec6SMatthias Ringwald 
11833deb3ec6SMatthias Ringwald     if (multiplexer->fcon & 0x80){
11843deb3ec6SMatthias Ringwald         multiplexer->fcon &= 0x01;
11853deb3ec6SMatthias Ringwald         rfcomm_send_uih_fc_rsp(multiplexer, multiplexer->fcon);
1186f7d61b10SMatthias Ringwald 
11873deb3ec6SMatthias Ringwald         if (multiplexer->fcon == 0) return;
11883deb3ec6SMatthias Ringwald         // trigger client to send again after sending FCon Response
1189b31d33b2SMatthias Ringwald         rfcomm_notify_channel_can_send();
11903deb3ec6SMatthias Ringwald         return;
11913deb3ec6SMatthias Ringwald     }
11923deb3ec6SMatthias Ringwald 
11933deb3ec6SMatthias Ringwald     switch (multiplexer->state) {
11943deb3ec6SMatthias Ringwald         case RFCOMM_MULTIPLEXER_SEND_SABM_0:
11953deb3ec6SMatthias Ringwald             log_info("Sending SABM #0 - (multi 0x%p)", multiplexer);
11963deb3ec6SMatthias Ringwald             multiplexer->state = RFCOMM_MULTIPLEXER_W4_UA_0;
11973deb3ec6SMatthias Ringwald             rfcomm_send_sabm(multiplexer, 0);
11983deb3ec6SMatthias Ringwald             break;
11993deb3ec6SMatthias Ringwald         case RFCOMM_MULTIPLEXER_SEND_UA_0:
12003deb3ec6SMatthias Ringwald             log_info("Sending UA #0");
12013deb3ec6SMatthias Ringwald             multiplexer->state = RFCOMM_MULTIPLEXER_OPEN;
12023deb3ec6SMatthias Ringwald             rfcomm_send_ua(multiplexer, 0);
1203f7d61b10SMatthias Ringwald 
12043deb3ec6SMatthias Ringwald             rfcomm_multiplexer_opened(multiplexer);
12053deb3ec6SMatthias Ringwald             break;
12063deb3ec6SMatthias Ringwald         case RFCOMM_MULTIPLEXER_SEND_UA_0_AND_DISC:
12073deb3ec6SMatthias Ringwald             // try to detect authentication errors: drop link key if multiplexer closed before first channel got opened
12083deb3ec6SMatthias Ringwald             if (!multiplexer->at_least_one_connection){
12093deb3ec6SMatthias Ringwald                 log_info("TODO: no connections established - delete link key prophylactically");
12103deb3ec6SMatthias Ringwald                 // hci_send_cmd(&hci_delete_stored_link_key, multiplexer->remote_addr);
12113deb3ec6SMatthias Ringwald             }
12123deb3ec6SMatthias Ringwald             log_info("Sending UA #0");
12133deb3ec6SMatthias Ringwald             log_info("Closing down multiplexer");
12143deb3ec6SMatthias Ringwald             multiplexer->state = RFCOMM_MULTIPLEXER_CLOSED;
12153deb3ec6SMatthias Ringwald             rfcomm_send_ua(multiplexer, 0);
1216f7d61b10SMatthias Ringwald 
12173deb3ec6SMatthias Ringwald             rfcomm_multiplexer_finalize(multiplexer);
1218ce8f182eSMatthias Ringwald             l2cap_disconnect(l2cap_cid, 0x13);
12193deb3ec6SMatthias Ringwald             break;
12203deb3ec6SMatthias Ringwald         case RFCOMM_MULTIPLEXER_OPEN:
12213deb3ec6SMatthias Ringwald             // respond to test command
12223deb3ec6SMatthias Ringwald             if (multiplexer->test_data_len){
12233deb3ec6SMatthias Ringwald                 int len = multiplexer->test_data_len;
12243deb3ec6SMatthias Ringwald                 log_info("Sending TEST Response with %u bytes", len);
12253deb3ec6SMatthias Ringwald                 multiplexer->test_data_len = 0;
12263deb3ec6SMatthias Ringwald                 rfcomm_send_uih_test_rsp(multiplexer, multiplexer->test_data, len);
12273deb3ec6SMatthias Ringwald                 return;
12283deb3ec6SMatthias Ringwald             }
12293deb3ec6SMatthias Ringwald             break;
12303deb3ec6SMatthias Ringwald         default:
12313deb3ec6SMatthias Ringwald             break;
12323deb3ec6SMatthias Ringwald     }
12333deb3ec6SMatthias Ringwald }
12343deb3ec6SMatthias Ringwald 
12353deb3ec6SMatthias Ringwald // MARK: RFCOMM CHANNEL
12363deb3ec6SMatthias Ringwald 
12373deb3ec6SMatthias Ringwald static void rfcomm_channel_send_credits(rfcomm_channel_t *channel, uint8_t credits){
12383deb3ec6SMatthias Ringwald     channel->credits_incoming += credits;
1239ec3f4248SMatthias Ringwald     rfcomm_send_uih_credits(channel->multiplexer, channel->dlci, credits);
12403deb3ec6SMatthias Ringwald }
12413deb3ec6SMatthias Ringwald 
1242b31d33b2SMatthias Ringwald static int rfcomm_channel_can_send(rfcomm_channel_t * channel){
1243b31d33b2SMatthias Ringwald     if (!channel->credits_outgoing) return 0;
1244b31d33b2SMatthias Ringwald     if ((channel->multiplexer->fcon & 1) == 0) return 0;
1245b31d33b2SMatthias Ringwald     return l2cap_can_send_packet_now(channel->multiplexer->l2cap_cid);
1246b31d33b2SMatthias Ringwald }
1247b31d33b2SMatthias Ringwald 
12483deb3ec6SMatthias Ringwald static void rfcomm_channel_opened(rfcomm_channel_t *rfChannel){
12493deb3ec6SMatthias Ringwald 
12503deb3ec6SMatthias Ringwald     log_info("rfcomm_channel_opened!");
12513deb3ec6SMatthias Ringwald 
12523deb3ec6SMatthias Ringwald     rfChannel->state = RFCOMM_CHANNEL_OPEN;
12533deb3ec6SMatthias Ringwald     rfcomm_emit_channel_opened(rfChannel, 0);
12543deb3ec6SMatthias Ringwald     rfcomm_emit_port_configuration(rfChannel);
12553deb3ec6SMatthias Ringwald 
12563deb3ec6SMatthias Ringwald     // remove (potential) timer
12573deb3ec6SMatthias Ringwald     rfcomm_multiplexer_t *multiplexer = rfChannel->multiplexer;
12583deb3ec6SMatthias Ringwald     if (multiplexer->timer_active) {
1259528a4a3bSMatthias Ringwald         btstack_run_loop_remove_timer(&multiplexer->timer);
12603deb3ec6SMatthias Ringwald         multiplexer->timer_active = 0;
12613deb3ec6SMatthias Ringwald     }
12623deb3ec6SMatthias Ringwald     // hack for problem detecting authentication failure
12633deb3ec6SMatthias Ringwald     multiplexer->at_least_one_connection = 1;
12643deb3ec6SMatthias Ringwald 
126562b5b741SMatthias Ringwald     // request can send now if channel ready
126662b5b741SMatthias Ringwald     if (rfcomm_channel_ready_to_send(rfChannel)){
126762b5b741SMatthias Ringwald         l2cap_request_can_send_now_event(multiplexer->l2cap_cid);
126862b5b741SMatthias Ringwald     }
12693deb3ec6SMatthias Ringwald }
12703deb3ec6SMatthias Ringwald 
12713deb3ec6SMatthias Ringwald static void rfcomm_channel_packet_handler_uih(rfcomm_multiplexer_t *multiplexer, uint8_t * packet, uint16_t size){
12723deb3ec6SMatthias Ringwald     const uint8_t frame_dlci = packet[0] >> 2;
12733deb3ec6SMatthias Ringwald     const uint8_t length_offset = (packet[2] & 1) ^ 1;  // to be used for pos >= 3
12743deb3ec6SMatthias Ringwald     const uint8_t credit_offset = ((packet[1] & BT_RFCOMM_UIH_PF) == BT_RFCOMM_UIH_PF) ? 1 : 0;   // credits for uih_pf frames
12753deb3ec6SMatthias Ringwald     const uint8_t payload_offset = 3 + length_offset + credit_offset;
12763deb3ec6SMatthias Ringwald 
12773deb3ec6SMatthias Ringwald     rfcomm_channel_t * channel = rfcomm_channel_for_multiplexer_and_dlci(multiplexer, frame_dlci);
12783deb3ec6SMatthias Ringwald     if (!channel) return;
12793deb3ec6SMatthias Ringwald 
12803deb3ec6SMatthias Ringwald     // handle new outgoing credits
12813deb3ec6SMatthias Ringwald     if (packet[1] == BT_RFCOMM_UIH_PF) {
12823deb3ec6SMatthias Ringwald 
12833deb3ec6SMatthias Ringwald         // add them
12843deb3ec6SMatthias Ringwald         uint16_t new_credits = packet[3+length_offset];
12853deb3ec6SMatthias Ringwald         channel->credits_outgoing += new_credits;
12863deb3ec6SMatthias Ringwald         log_info( "RFCOMM data UIH_PF, new credits: %u, now %u", new_credits, channel->credits_outgoing);
12873deb3ec6SMatthias Ringwald 
12883deb3ec6SMatthias Ringwald         // notify channel statemachine
12893deb3ec6SMatthias Ringwald         rfcomm_channel_event_t channel_event = { CH_EVT_RCVD_CREDITS };
12903232fa30SMatthias Ringwald         rfcomm_channel_state_machine_with_channel(channel, &channel_event);
12913232fa30SMatthias Ringwald         if (rfcomm_channel_ready_to_send(channel)){
129262b5b741SMatthias Ringwald             l2cap_request_can_send_now_event(multiplexer->l2cap_cid);
129362b5b741SMatthias Ringwald         }
12943deb3ec6SMatthias Ringwald     }
12953deb3ec6SMatthias Ringwald 
12963deb3ec6SMatthias Ringwald     // contains payload?
12973deb3ec6SMatthias Ringwald     if (size - 1 > payload_offset){
12983deb3ec6SMatthias Ringwald 
12993deb3ec6SMatthias Ringwald         // log_info( "RFCOMM data UIH_PF, size %u, channel %p", size-payload_offset-1, rfChannel->connection);
13003deb3ec6SMatthias Ringwald 
13013deb3ec6SMatthias Ringwald         // decrease incoming credit counter
13023deb3ec6SMatthias Ringwald         if (channel->credits_incoming > 0){
13033deb3ec6SMatthias Ringwald             channel->credits_incoming--;
13043deb3ec6SMatthias Ringwald         }
13053deb3ec6SMatthias Ringwald 
13063deb3ec6SMatthias Ringwald         // deliver payload
1307fc376368SMatthias Ringwald         (channel->packet_handler)(RFCOMM_DATA_PACKET, channel->rfcomm_cid,
13083deb3ec6SMatthias Ringwald                               &packet[payload_offset], size-payload_offset-1);
13093deb3ec6SMatthias Ringwald     }
13103deb3ec6SMatthias Ringwald 
13113deb3ec6SMatthias Ringwald     // automatically provide new credits to remote device, if no incoming flow control
13123deb3ec6SMatthias Ringwald     if (!channel->incoming_flow_control && channel->credits_incoming < 5){
13133deb3ec6SMatthias Ringwald         channel->new_credits_incoming = RFCOMM_CREDITS;
131462b5b741SMatthias Ringwald         l2cap_request_can_send_now_event(multiplexer->l2cap_cid);
13153deb3ec6SMatthias Ringwald     }
13163deb3ec6SMatthias Ringwald }
13173deb3ec6SMatthias Ringwald 
13183deb3ec6SMatthias Ringwald static void rfcomm_channel_accept_pn(rfcomm_channel_t *channel, rfcomm_channel_event_pn_t *event){
13193deb3ec6SMatthias Ringwald     // priority of client request
13203deb3ec6SMatthias Ringwald     channel->pn_priority = event->priority;
13213deb3ec6SMatthias Ringwald 
13223deb3ec6SMatthias Ringwald     // new credits
13233deb3ec6SMatthias Ringwald     channel->credits_outgoing = event->credits_outgoing;
13243deb3ec6SMatthias Ringwald 
13253deb3ec6SMatthias Ringwald     // negotiate max frame size
13263deb3ec6SMatthias Ringwald     if (channel->max_frame_size > channel->multiplexer->max_frame_size) {
13273deb3ec6SMatthias Ringwald         channel->max_frame_size = channel->multiplexer->max_frame_size;
13283deb3ec6SMatthias Ringwald     }
13293deb3ec6SMatthias Ringwald     if (channel->max_frame_size > event->max_frame_size) {
13303deb3ec6SMatthias Ringwald         channel->max_frame_size = event->max_frame_size;
13313deb3ec6SMatthias Ringwald     }
13323deb3ec6SMatthias Ringwald 
13333deb3ec6SMatthias Ringwald }
13343deb3ec6SMatthias Ringwald 
13353deb3ec6SMatthias Ringwald static void rfcomm_channel_finalize(rfcomm_channel_t *channel){
13363deb3ec6SMatthias Ringwald 
13373deb3ec6SMatthias Ringwald     rfcomm_multiplexer_t *multiplexer = channel->multiplexer;
13383deb3ec6SMatthias Ringwald 
13393deb3ec6SMatthias Ringwald     // remove from list
1340665d90f2SMatthias Ringwald     btstack_linked_list_remove( &rfcomm_channels, (btstack_linked_item_t *) channel);
13413deb3ec6SMatthias Ringwald 
13423deb3ec6SMatthias Ringwald     // free channel
13433deb3ec6SMatthias Ringwald     btstack_memory_rfcomm_channel_free(channel);
13443deb3ec6SMatthias Ringwald 
13453deb3ec6SMatthias Ringwald     // update multiplexer timeout after channel was removed from list
13463deb3ec6SMatthias Ringwald     rfcomm_multiplexer_prepare_idle_timer(multiplexer);
13473deb3ec6SMatthias Ringwald }
13483deb3ec6SMatthias Ringwald 
13493232fa30SMatthias Ringwald static void rfcomm_channel_state_machine_with_dlci(rfcomm_multiplexer_t * multiplexer, uint8_t dlci, const rfcomm_channel_event_t *event){
13503deb3ec6SMatthias Ringwald 
13513deb3ec6SMatthias Ringwald     // TODO: if client max frame size is smaller than RFCOMM_DEFAULT_SIZE, send PN
13523deb3ec6SMatthias Ringwald 
13533deb3ec6SMatthias Ringwald 
13543deb3ec6SMatthias Ringwald     // lookup existing channel
13553deb3ec6SMatthias Ringwald     rfcomm_channel_t * channel = rfcomm_channel_for_multiplexer_and_dlci(multiplexer, dlci);
13563deb3ec6SMatthias Ringwald 
13573232fa30SMatthias Ringwald     // log_info("rfcomm_channel_state_machine_with_dlci lookup dlci #%u = 0x%08x - event %u", dlci, (int) channel, event->type);
13583deb3ec6SMatthias Ringwald 
13593deb3ec6SMatthias Ringwald     if (channel) {
13603232fa30SMatthias Ringwald         rfcomm_channel_state_machine_with_channel(channel, event);
13613232fa30SMatthias Ringwald         if (rfcomm_channel_ready_to_send(channel)){
13623232fa30SMatthias Ringwald             l2cap_request_can_send_now_event(multiplexer->l2cap_cid);
13633232fa30SMatthias Ringwald         }
13643deb3ec6SMatthias Ringwald         return;
13653deb3ec6SMatthias Ringwald     }
13663deb3ec6SMatthias Ringwald 
13673deb3ec6SMatthias Ringwald     // service registered?
13683deb3ec6SMatthias Ringwald     rfcomm_service_t * service = rfcomm_service_for_channel(dlci >> 1);
13693232fa30SMatthias Ringwald     // log_info("rfcomm_channel_state_machine_with_dlci service dlci #%u = 0x%08x", dlci, (int) service);
13703deb3ec6SMatthias Ringwald     if (!service) {
13713deb3ec6SMatthias Ringwald         // discard request by sending disconnected mode
13723deb3ec6SMatthias Ringwald         multiplexer->send_dm_for_dlci = dlci;
137362b5b741SMatthias Ringwald         l2cap_request_can_send_now_event(multiplexer->l2cap_cid);
13743deb3ec6SMatthias Ringwald         return;
13753deb3ec6SMatthias Ringwald     }
13763deb3ec6SMatthias Ringwald 
13773deb3ec6SMatthias Ringwald     // create channel for some events
13783deb3ec6SMatthias Ringwald     switch (event->type) {
13793deb3ec6SMatthias Ringwald         case CH_EVT_RCVD_SABM:
13803deb3ec6SMatthias Ringwald         case CH_EVT_RCVD_PN:
13813deb3ec6SMatthias Ringwald         case CH_EVT_RCVD_RPN_REQ:
13823deb3ec6SMatthias Ringwald         case CH_EVT_RCVD_RPN_CMD:
13833deb3ec6SMatthias Ringwald             // setup incoming channel
13843deb3ec6SMatthias Ringwald             channel = rfcomm_channel_create(multiplexer, service, dlci >> 1);
13853deb3ec6SMatthias Ringwald             if (!channel){
13863deb3ec6SMatthias Ringwald                 // discard request by sending disconnected mode
13873deb3ec6SMatthias Ringwald                 multiplexer->send_dm_for_dlci = dlci;
138862b5b741SMatthias Ringwald                 l2cap_request_can_send_now_event(multiplexer->l2cap_cid);
13893deb3ec6SMatthias Ringwald             }
13903deb3ec6SMatthias Ringwald             break;
13913deb3ec6SMatthias Ringwald         default:
13923deb3ec6SMatthias Ringwald             break;
13933deb3ec6SMatthias Ringwald     }
13943deb3ec6SMatthias Ringwald 
13953deb3ec6SMatthias Ringwald     if (!channel) {
13963deb3ec6SMatthias Ringwald         // discard request by sending disconnected mode
13973deb3ec6SMatthias Ringwald         multiplexer->send_dm_for_dlci = dlci;
139862b5b741SMatthias Ringwald         l2cap_request_can_send_now_event(multiplexer->l2cap_cid);
13993deb3ec6SMatthias Ringwald         return;
14003deb3ec6SMatthias Ringwald     }
140162b5b741SMatthias Ringwald 
14023232fa30SMatthias Ringwald     rfcomm_channel_state_machine_with_channel(channel, event);
14033232fa30SMatthias Ringwald     if (rfcomm_channel_ready_to_send(channel)){
14043232fa30SMatthias Ringwald         l2cap_request_can_send_now_event(multiplexer->l2cap_cid);
14053232fa30SMatthias Ringwald     }
14063deb3ec6SMatthias Ringwald }
14073deb3ec6SMatthias Ringwald 
14083deb3ec6SMatthias Ringwald static void rfcomm_channel_packet_handler(rfcomm_multiplexer_t * multiplexer,  uint8_t *packet, uint16_t size){
14099ec2630cSMatthias Ringwald     UNUSED(size);
14103deb3ec6SMatthias Ringwald 
14113deb3ec6SMatthias Ringwald     // rfcomm: (0) addr [76543 server channel] [2 direction: initiator uses 1] [1 C/R: CMD by initiator = 1] [0 EA=1]
14123deb3ec6SMatthias Ringwald     const uint8_t frame_dlci = packet[0] >> 2;
14133deb3ec6SMatthias Ringwald     uint8_t message_dlci; // used by commands in UIH(_PF) packets
14143deb3ec6SMatthias Ringwald 	uint8_t message_len;  //   "
14153deb3ec6SMatthias Ringwald 
14163deb3ec6SMatthias Ringwald     // rfcomm: (1) command/control
14173deb3ec6SMatthias Ringwald     // -- credits_offset = 1 if command == BT_RFCOMM_UIH_PF
14183deb3ec6SMatthias Ringwald     const uint8_t credit_offset = ((packet[1] & BT_RFCOMM_UIH_PF) == BT_RFCOMM_UIH_PF) ? 1 : 0;   // credits for uih_pf frames
14193deb3ec6SMatthias Ringwald     // rfcomm: (2) length. if bit 0 is cleared, 2 byte length is used. (little endian)
14203deb3ec6SMatthias Ringwald     const uint8_t length_offset = (packet[2] & 1) ^ 1;  // to be used for pos >= 3
14213deb3ec6SMatthias Ringwald     // rfcomm: (3+length_offset) credits if credits_offset == 1
14223deb3ec6SMatthias Ringwald     // rfcomm: (3+length_offest+credits_offset)
14233deb3ec6SMatthias Ringwald     const uint8_t payload_offset = 3 + length_offset + credit_offset;
14243deb3ec6SMatthias Ringwald 
14253deb3ec6SMatthias Ringwald     rfcomm_channel_event_t event;
14263deb3ec6SMatthias Ringwald     rfcomm_channel_event_pn_t event_pn;
14273deb3ec6SMatthias Ringwald     rfcomm_channel_event_rpn_t event_rpn;
14283deb3ec6SMatthias Ringwald     rfcomm_channel_event_msc_t event_msc;
14293deb3ec6SMatthias Ringwald 
14303deb3ec6SMatthias Ringwald     // switch by rfcomm message type
14313deb3ec6SMatthias Ringwald     switch(packet[1]) {
14323deb3ec6SMatthias Ringwald 
14333deb3ec6SMatthias Ringwald         case BT_RFCOMM_SABM:
14343deb3ec6SMatthias Ringwald             event.type = CH_EVT_RCVD_SABM;
14353deb3ec6SMatthias Ringwald             log_info("Received SABM #%u", frame_dlci);
14363232fa30SMatthias Ringwald             rfcomm_channel_state_machine_with_dlci(multiplexer, frame_dlci, &event);
14373deb3ec6SMatthias Ringwald             break;
14383deb3ec6SMatthias Ringwald 
14393deb3ec6SMatthias Ringwald         case BT_RFCOMM_UA:
14403deb3ec6SMatthias Ringwald             event.type = CH_EVT_RCVD_UA;
14413deb3ec6SMatthias Ringwald             log_info("Received UA #%u",frame_dlci);
14423232fa30SMatthias Ringwald             rfcomm_channel_state_machine_with_dlci(multiplexer, frame_dlci, &event);
14433deb3ec6SMatthias Ringwald             break;
14443deb3ec6SMatthias Ringwald 
14453deb3ec6SMatthias Ringwald         case BT_RFCOMM_DISC:
14463deb3ec6SMatthias Ringwald             event.type = CH_EVT_RCVD_DISC;
14473232fa30SMatthias Ringwald             rfcomm_channel_state_machine_with_dlci(multiplexer, frame_dlci, &event);
14483deb3ec6SMatthias Ringwald             break;
14493deb3ec6SMatthias Ringwald 
14503deb3ec6SMatthias Ringwald         case BT_RFCOMM_DM:
14513deb3ec6SMatthias Ringwald         case BT_RFCOMM_DM_PF:
14523deb3ec6SMatthias Ringwald             event.type = CH_EVT_RCVD_DM;
14533232fa30SMatthias Ringwald             rfcomm_channel_state_machine_with_dlci(multiplexer, frame_dlci, &event);
14543deb3ec6SMatthias Ringwald             break;
14553deb3ec6SMatthias Ringwald 
14563deb3ec6SMatthias Ringwald         case BT_RFCOMM_UIH_PF:
14573deb3ec6SMatthias Ringwald         case BT_RFCOMM_UIH:
14583deb3ec6SMatthias Ringwald 
14593deb3ec6SMatthias Ringwald             message_len  = packet[payload_offset+1] >> 1;
14603deb3ec6SMatthias Ringwald 
14613deb3ec6SMatthias Ringwald             switch (packet[payload_offset]) {
14623deb3ec6SMatthias Ringwald                 case BT_RFCOMM_PN_CMD:
14633deb3ec6SMatthias Ringwald                     message_dlci = packet[payload_offset+2];
14643deb3ec6SMatthias Ringwald                     event_pn.super.type = CH_EVT_RCVD_PN;
14653deb3ec6SMatthias Ringwald                     event_pn.priority = packet[payload_offset+4];
1466f8fbdce0SMatthias Ringwald                     event_pn.max_frame_size = little_endian_read_16(packet, payload_offset+6);
14673deb3ec6SMatthias Ringwald                     event_pn.credits_outgoing = packet[payload_offset+9];
14683deb3ec6SMatthias Ringwald                     log_info("Received UIH Parameter Negotiation Command for #%u, credits %u",
14693deb3ec6SMatthias Ringwald                         message_dlci, event_pn.credits_outgoing);
14703232fa30SMatthias Ringwald                     rfcomm_channel_state_machine_with_dlci(multiplexer, message_dlci, (rfcomm_channel_event_t*) &event_pn);
14713deb3ec6SMatthias Ringwald                     break;
14723deb3ec6SMatthias Ringwald 
14733deb3ec6SMatthias Ringwald                 case BT_RFCOMM_PN_RSP:
14743deb3ec6SMatthias Ringwald                     message_dlci = packet[payload_offset+2];
14753deb3ec6SMatthias Ringwald                     event_pn.super.type = CH_EVT_RCVD_PN_RSP;
14763deb3ec6SMatthias Ringwald                     event_pn.priority = packet[payload_offset+4];
1477f8fbdce0SMatthias Ringwald                     event_pn.max_frame_size = little_endian_read_16(packet, payload_offset+6);
14783deb3ec6SMatthias Ringwald                     event_pn.credits_outgoing = packet[payload_offset+9];
14793deb3ec6SMatthias Ringwald                     log_info("Received UIH Parameter Negotiation Response max frame %u, credits %u",
14803deb3ec6SMatthias Ringwald                             event_pn.max_frame_size, event_pn.credits_outgoing);
14813232fa30SMatthias Ringwald                     rfcomm_channel_state_machine_with_dlci(multiplexer, message_dlci, (rfcomm_channel_event_t*) &event_pn);
14823deb3ec6SMatthias Ringwald                     break;
14833deb3ec6SMatthias Ringwald 
14843deb3ec6SMatthias Ringwald                 case BT_RFCOMM_MSC_CMD:
14853deb3ec6SMatthias Ringwald                     message_dlci = packet[payload_offset+2] >> 2;
14863deb3ec6SMatthias Ringwald                     event_msc.super.type = CH_EVT_RCVD_MSC_CMD;
14873deb3ec6SMatthias Ringwald                     event_msc.modem_status = packet[payload_offset+3];
14883deb3ec6SMatthias Ringwald                     log_info("Received MSC CMD for #%u, ", message_dlci);
14893232fa30SMatthias Ringwald                     rfcomm_channel_state_machine_with_dlci(multiplexer, message_dlci, (rfcomm_channel_event_t*) &event_msc);
14903deb3ec6SMatthias Ringwald                     break;
14913deb3ec6SMatthias Ringwald 
14923deb3ec6SMatthias Ringwald                 case BT_RFCOMM_MSC_RSP:
14933deb3ec6SMatthias Ringwald                     message_dlci = packet[payload_offset+2] >> 2;
14943deb3ec6SMatthias Ringwald                     event.type = CH_EVT_RCVD_MSC_RSP;
14953deb3ec6SMatthias Ringwald                     log_info("Received MSC RSP for #%u", message_dlci);
14963232fa30SMatthias Ringwald                     rfcomm_channel_state_machine_with_dlci(multiplexer, message_dlci, &event);
14973deb3ec6SMatthias Ringwald                     break;
14983deb3ec6SMatthias Ringwald 
14993deb3ec6SMatthias Ringwald                 case BT_RFCOMM_RPN_CMD:
15003deb3ec6SMatthias Ringwald                     message_dlci = packet[payload_offset+2] >> 2;
15013deb3ec6SMatthias Ringwald                     switch (message_len){
15023deb3ec6SMatthias Ringwald                         case 1:
15033deb3ec6SMatthias Ringwald                             log_info("Received Remote Port Negotiation Request for #%u", message_dlci);
15043deb3ec6SMatthias Ringwald                             event.type = CH_EVT_RCVD_RPN_REQ;
15053232fa30SMatthias Ringwald                             rfcomm_channel_state_machine_with_dlci(multiplexer, message_dlci, &event);
15063deb3ec6SMatthias Ringwald                             break;
15073deb3ec6SMatthias Ringwald                         case 8:
15083deb3ec6SMatthias Ringwald                             log_info("Received Remote Port Negotiation Update for #%u", message_dlci);
15093deb3ec6SMatthias Ringwald                             event_rpn.super.type = CH_EVT_RCVD_RPN_CMD;
15103deb3ec6SMatthias Ringwald                             event_rpn.data = *(rfcomm_rpn_data_t*) &packet[payload_offset+3];
15113232fa30SMatthias Ringwald                             rfcomm_channel_state_machine_with_dlci(multiplexer, message_dlci, (rfcomm_channel_event_t*) &event_rpn);
15123deb3ec6SMatthias Ringwald                             break;
15133deb3ec6SMatthias Ringwald                         default:
15143deb3ec6SMatthias Ringwald                             break;
15153deb3ec6SMatthias Ringwald                     }
15163deb3ec6SMatthias Ringwald                     break;
15173deb3ec6SMatthias Ringwald 
15183deb3ec6SMatthias Ringwald                 case BT_RFCOMM_RPN_RSP:
15193deb3ec6SMatthias Ringwald                     log_info("Received RPN response");
15203deb3ec6SMatthias Ringwald                     break;
15213deb3ec6SMatthias Ringwald 
15223deb3ec6SMatthias Ringwald                 case BT_RFCOMM_RLS_CMD: {
15233deb3ec6SMatthias Ringwald                     log_info("Received RLS command");
15243deb3ec6SMatthias Ringwald                     message_dlci = packet[payload_offset+2] >> 2;
15253deb3ec6SMatthias Ringwald                     rfcomm_channel_event_rls_t event_rls;
15263deb3ec6SMatthias Ringwald                     event_rls.super.type = CH_EVT_RCVD_RLS_CMD;
15273deb3ec6SMatthias Ringwald                     event_rls.line_status = packet[payload_offset+3];
15283232fa30SMatthias Ringwald                     rfcomm_channel_state_machine_with_dlci(multiplexer, message_dlci, (rfcomm_channel_event_t*) &event_rls);
15293deb3ec6SMatthias Ringwald                     break;
15303deb3ec6SMatthias Ringwald                 }
15313deb3ec6SMatthias Ringwald 
15323deb3ec6SMatthias Ringwald                 case BT_RFCOMM_RLS_RSP:
15333deb3ec6SMatthias Ringwald                     log_info("Received RLS response");
15343deb3ec6SMatthias Ringwald                     break;
15353deb3ec6SMatthias Ringwald 
15363deb3ec6SMatthias Ringwald                 // Following commands are handled by rfcomm_multiplexer_l2cap_packet_handler
15373deb3ec6SMatthias Ringwald                 // case BT_RFCOMM_TEST_CMD:
15383deb3ec6SMatthias Ringwald                 // case BT_RFCOMM_FCOFF_CMD:
15393deb3ec6SMatthias Ringwald                 // case BT_RFCOMM_FCON_CMD:
15403deb3ec6SMatthias Ringwald                 // everything else is an not supported command
15413deb3ec6SMatthias Ringwald                 default: {
15423deb3ec6SMatthias Ringwald                     log_error("Received unknown UIH command packet - 0x%02x", packet[payload_offset]);
15433deb3ec6SMatthias Ringwald                     multiplexer->nsc_command = packet[payload_offset];
15443deb3ec6SMatthias Ringwald                     break;
15453deb3ec6SMatthias Ringwald                 }
15463deb3ec6SMatthias Ringwald             }
15473deb3ec6SMatthias Ringwald             break;
15483deb3ec6SMatthias Ringwald 
15493deb3ec6SMatthias Ringwald         default:
15503deb3ec6SMatthias Ringwald             log_error("Received unknown RFCOMM message type %x", packet[1]);
15513deb3ec6SMatthias Ringwald             break;
15523deb3ec6SMatthias Ringwald     }
15533deb3ec6SMatthias Ringwald 
15543deb3ec6SMatthias Ringwald     // trigger next action - example W4_PN_RSP: transition to SEND_SABM which only depends on "can send"
155562b5b741SMatthias Ringwald     if (rfcomm_multiplexer_ready_to_send(multiplexer)){
155662b5b741SMatthias Ringwald         l2cap_request_can_send_now_event(multiplexer->l2cap_cid);
155762b5b741SMatthias Ringwald     }
15583deb3ec6SMatthias Ringwald }
15593deb3ec6SMatthias Ringwald 
1560457b5cb1SMatthias Ringwald static void rfcomm_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
15613deb3ec6SMatthias Ringwald 
15620d78ab98SMatthias Ringwald     if (packet_type == HCI_EVENT_PACKET){
15630d78ab98SMatthias Ringwald         rfcomm_hci_event_handler(packet, size);
15640d78ab98SMatthias Ringwald         return;
15653deb3ec6SMatthias Ringwald     }
15663deb3ec6SMatthias Ringwald 
15670d78ab98SMatthias Ringwald     // we only handle l2cap packets for:
15680d78ab98SMatthias Ringwald     if (packet_type != L2CAP_DATA_PACKET) return;
15690d78ab98SMatthias Ringwald 
15700d78ab98SMatthias Ringwald     //  - multiplexer itself
15710d78ab98SMatthias Ringwald     int handled = rfcomm_multiplexer_l2cap_packet_handler(channel, packet, size);
15720d78ab98SMatthias Ringwald 
1573b35818ceSMatthias Ringwald     if (handled) return;
15743deb3ec6SMatthias Ringwald 
15750d78ab98SMatthias Ringwald     // - channel over open mutliplexer
15763deb3ec6SMatthias Ringwald     rfcomm_multiplexer_t * multiplexer = rfcomm_multiplexer_for_l2cap_cid(channel);
1577fc376368SMatthias Ringwald     if (!multiplexer || multiplexer->state != RFCOMM_MULTIPLEXER_OPEN) return;
15783deb3ec6SMatthias Ringwald 
15793deb3ec6SMatthias Ringwald     // channel data ?
15803deb3ec6SMatthias Ringwald     // rfcomm: (0) addr [76543 server channel] [2 direction: initiator uses 1] [1 C/R: CMD by initiator = 1] [0 EA=1]
15813deb3ec6SMatthias Ringwald     const uint8_t frame_dlci = packet[0] >> 2;
15823deb3ec6SMatthias Ringwald 
15833deb3ec6SMatthias Ringwald     if (frame_dlci && (packet[1] == BT_RFCOMM_UIH || packet[1] == BT_RFCOMM_UIH_PF)) {
15843deb3ec6SMatthias Ringwald         rfcomm_channel_packet_handler_uih(multiplexer, packet, size);
15853deb3ec6SMatthias Ringwald         return;
15863deb3ec6SMatthias Ringwald     }
15873deb3ec6SMatthias Ringwald 
15883deb3ec6SMatthias Ringwald     rfcomm_channel_packet_handler(multiplexer, packet, size);
15893deb3ec6SMatthias Ringwald }
15903deb3ec6SMatthias Ringwald 
15913deb3ec6SMatthias Ringwald static int rfcomm_channel_ready_for_open(rfcomm_channel_t *channel){
15923deb3ec6SMatthias Ringwald     // note: exchanging MSC isn't neccessary to consider channel open
15933deb3ec6SMatthias Ringwald     // note: having outgoing credits is also not necessary to consider channel open
15943deb3ec6SMatthias 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);
15953deb3ec6SMatthias Ringwald     // if ((channel->state_var & RFCOMM_CHANNEL_STATE_VAR_SENT_MSC_RSP) == 0) return 0;
15963deb3ec6SMatthias Ringwald     // if (channel->credits_outgoing == 0) return 0;
15971e35c04dSMatthias Ringwald     log_info("rfcomm_channel_ready_for_open state %u, flags needed %04x, current %04x, rf credits %u",
15981e35c04dSMatthias Ringwald          channel->state, RFCOMM_CHANNEL_STATE_VAR_RCVD_MSC_RSP, channel->state_var, channel->credits_outgoing);
15993deb3ec6SMatthias Ringwald     if ((channel->state_var & RFCOMM_CHANNEL_STATE_VAR_RCVD_MSC_RSP) == 0) return 0;
16003deb3ec6SMatthias Ringwald     if ((channel->state_var & RFCOMM_CHANNEL_STATE_VAR_SENT_CREDITS) == 0) return 0;
16013deb3ec6SMatthias Ringwald 
16023deb3ec6SMatthias Ringwald     return 1;
16033deb3ec6SMatthias Ringwald }
16043deb3ec6SMatthias Ringwald 
16053deb3ec6SMatthias Ringwald static int rfcomm_channel_ready_for_incoming_dlc_setup(rfcomm_channel_t * channel){
16063deb3ec6SMatthias Ringwald     log_info("rfcomm_channel_ready_for_incoming_dlc_setup state var %04x", channel->state_var);
16073deb3ec6SMatthias Ringwald     // Client accept and SABM/UA is required, PN RSP is needed if PN was received
16083deb3ec6SMatthias Ringwald     if ((channel->state_var & RFCOMM_CHANNEL_STATE_VAR_CLIENT_ACCEPTED) == 0) return 0;
16093deb3ec6SMatthias Ringwald     if ((channel->state_var & RFCOMM_CHANNEL_STATE_VAR_RCVD_SABM      ) == 0) return 0;
16103deb3ec6SMatthias Ringwald     if ((channel->state_var & RFCOMM_CHANNEL_STATE_VAR_SEND_UA        ) != 0) return 0;
16113deb3ec6SMatthias Ringwald     if ((channel->state_var & RFCOMM_CHANNEL_STATE_VAR_SEND_PN_RSP    ) != 0) return 0;
16123deb3ec6SMatthias Ringwald     return 1;
16133deb3ec6SMatthias Ringwald }
16143deb3ec6SMatthias Ringwald 
16153deb3ec6SMatthias Ringwald inline static void rfcomm_channel_state_add(rfcomm_channel_t *channel, RFCOMM_CHANNEL_STATE_VAR event){
16163deb3ec6SMatthias Ringwald     channel->state_var = (RFCOMM_CHANNEL_STATE_VAR) (channel->state_var | event);
16173deb3ec6SMatthias Ringwald }
16183deb3ec6SMatthias Ringwald inline static void rfcomm_channel_state_remove(rfcomm_channel_t *channel, RFCOMM_CHANNEL_STATE_VAR event){
16193deb3ec6SMatthias Ringwald     channel->state_var = (RFCOMM_CHANNEL_STATE_VAR) (channel->state_var & ~event);
16203deb3ec6SMatthias Ringwald }
16213deb3ec6SMatthias Ringwald 
162262b5b741SMatthias Ringwald static int rfcomm_channel_ready_to_send(rfcomm_channel_t * channel){
162362b5b741SMatthias Ringwald     switch (channel->state){
162462b5b741SMatthias Ringwald         case RFCOMM_CHANNEL_SEND_UIH_PN:
162562b5b741SMatthias Ringwald             log_debug("ch-ready: state %u", channel->state);
162662b5b741SMatthias Ringwald             return 1;
162762b5b741SMatthias Ringwald         case RFCOMM_CHANNEL_SEND_SABM_W4_UA:
162862b5b741SMatthias Ringwald             log_debug("ch-ready: state %u", channel->state);
162962b5b741SMatthias Ringwald             return 1;
163062b5b741SMatthias Ringwald         case RFCOMM_CHANNEL_SEND_UA_AFTER_DISC:
163162b5b741SMatthias Ringwald             log_debug("ch-ready: state %u", channel->state);
163262b5b741SMatthias Ringwald             return 1;
163362b5b741SMatthias Ringwald         case RFCOMM_CHANNEL_SEND_DISC:
163462b5b741SMatthias Ringwald             log_debug("ch-ready: state %u", channel->state);
163562b5b741SMatthias Ringwald             return 1;
163662b5b741SMatthias Ringwald         case RFCOMM_CHANNEL_SEND_DM:
163762b5b741SMatthias Ringwald             log_debug("ch-ready: state %u", channel->state);
163862b5b741SMatthias Ringwald             return 1;
163962b5b741SMatthias Ringwald         case RFCOMM_CHANNEL_OPEN:
164062b5b741SMatthias Ringwald             if (channel->new_credits_incoming) {
164162b5b741SMatthias Ringwald                 log_debug("ch-ready: channel open & new_credits_incoming") ;
164262b5b741SMatthias Ringwald                 return 1;
164362b5b741SMatthias Ringwald             }
164462b5b741SMatthias Ringwald             break;
16458ed5c2eaSMatthias Ringwald         case RFCOMM_CHANNEL_DLC_SETUP:
16468ed5c2eaSMatthias Ringwald             if (channel->state_var & (
16478ed5c2eaSMatthias Ringwald                 RFCOMM_CHANNEL_STATE_VAR_SEND_MSC_CMD  |
16488ed5c2eaSMatthias Ringwald                 RFCOMM_CHANNEL_STATE_VAR_SEND_CREDITS
16498ed5c2eaSMatthias Ringwald              )) {
16508ed5c2eaSMatthias Ringwald                 log_debug("ch-ready: channel dlc setup & send msc cmd or send credits") ;
16518ed5c2eaSMatthias Ringwald                 return 1;
16528ed5c2eaSMatthias Ringwald             }
16538ed5c2eaSMatthias Ringwald             break;
16548ed5c2eaSMatthias Ringwald 
165562b5b741SMatthias Ringwald         default:
165662b5b741SMatthias Ringwald             break;
165762b5b741SMatthias Ringwald     }
165862b5b741SMatthias Ringwald 
165962b5b741SMatthias Ringwald     if (channel->state_var & (
166062b5b741SMatthias Ringwald         RFCOMM_CHANNEL_STATE_VAR_SEND_PN_RSP   |
166162b5b741SMatthias Ringwald         RFCOMM_CHANNEL_STATE_VAR_SEND_RPN_INFO |
166262b5b741SMatthias Ringwald         RFCOMM_CHANNEL_STATE_VAR_SEND_RPN_RSP  |
166362b5b741SMatthias Ringwald         RFCOMM_CHANNEL_STATE_VAR_SEND_UA       |
16648ed5c2eaSMatthias Ringwald         RFCOMM_CHANNEL_STATE_VAR_SEND_MSC_RSP
166562b5b741SMatthias Ringwald                              )){
166662b5b741SMatthias Ringwald         log_debug("ch-ready: state %x, state var %x", channel->state, channel->state_var);
166762b5b741SMatthias Ringwald         return 1;
166862b5b741SMatthias Ringwald     }
166962b5b741SMatthias Ringwald 
167062b5b741SMatthias Ringwald     if (channel->rls_line_status != RFCOMM_RLS_STATUS_INVALID) {
167162b5b741SMatthias Ringwald         log_debug("ch-ready: rls_line_status");
167262b5b741SMatthias Ringwald         return 1;
167362b5b741SMatthias Ringwald     }
167462b5b741SMatthias Ringwald 
167562b5b741SMatthias Ringwald     return 0;
167662b5b741SMatthias Ringwald }
167762b5b741SMatthias Ringwald 
167862b5b741SMatthias Ringwald 
16793232fa30SMatthias Ringwald static void rfcomm_channel_state_machine_with_channel(rfcomm_channel_t *channel, const rfcomm_channel_event_t *event){
16803deb3ec6SMatthias Ringwald 
16813232fa30SMatthias Ringwald     // log_info("rfcomm_channel_state_machine_with_channel: state %u, state_var %04x, event %u", channel->state, channel->state_var ,event->type);
16823deb3ec6SMatthias Ringwald 
16833deb3ec6SMatthias Ringwald     rfcomm_multiplexer_t *multiplexer = channel->multiplexer;
16843deb3ec6SMatthias Ringwald 
16853deb3ec6SMatthias Ringwald     // TODO: integrate in common switch
16863deb3ec6SMatthias Ringwald     if (event->type == CH_EVT_RCVD_DISC){
16873deb3ec6SMatthias Ringwald         rfcomm_emit_channel_closed(channel);
16883deb3ec6SMatthias Ringwald         channel->state = RFCOMM_CHANNEL_SEND_UA_AFTER_DISC;
16893deb3ec6SMatthias Ringwald         return;
16903deb3ec6SMatthias Ringwald     }
16913deb3ec6SMatthias Ringwald 
16923deb3ec6SMatthias Ringwald     // TODO: integrate in common switch
16933deb3ec6SMatthias Ringwald     if (event->type == CH_EVT_RCVD_DM){
16943deb3ec6SMatthias Ringwald         log_info("Received DM message for #%u", channel->dlci);
16953deb3ec6SMatthias Ringwald         log_info("-> Closing channel locally for #%u", channel->dlci);
16963deb3ec6SMatthias Ringwald         rfcomm_emit_channel_closed(channel);
16973deb3ec6SMatthias Ringwald         rfcomm_channel_finalize(channel);
16983deb3ec6SMatthias Ringwald         return;
16993deb3ec6SMatthias Ringwald     }
17003deb3ec6SMatthias Ringwald 
17013deb3ec6SMatthias Ringwald     // remote port negotiation command - just accept everything for now
17023deb3ec6SMatthias Ringwald     //
17033deb3ec6SMatthias Ringwald     // "The RPN command can be used before a new DLC is opened and should be used whenever the port settings change."
17043deb3ec6SMatthias Ringwald     // "The RPN command is specified as optional in TS 07.10, but it is mandatory to recognize and respond to it in RFCOMM.
17053deb3ec6SMatthias Ringwald     //   (Although the handling of individual settings are implementation-dependent.)"
17063deb3ec6SMatthias Ringwald     //
17073deb3ec6SMatthias Ringwald 
17083deb3ec6SMatthias Ringwald     // TODO: integrate in common switch
17093deb3ec6SMatthias Ringwald     if (event->type == CH_EVT_RCVD_RPN_CMD){
17103deb3ec6SMatthias Ringwald         // control port parameters
17113deb3ec6SMatthias Ringwald         rfcomm_channel_event_rpn_t *event_rpn = (rfcomm_channel_event_rpn_t*) event;
17123deb3ec6SMatthias Ringwald         rfcomm_rpn_data_update(&channel->rpn_data, &event_rpn->data);
17133deb3ec6SMatthias Ringwald         rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_RPN_RSP);
17143deb3ec6SMatthias Ringwald         // notify client about new settings
17153deb3ec6SMatthias Ringwald         rfcomm_emit_port_configuration(channel);
17163deb3ec6SMatthias Ringwald         return;
17173deb3ec6SMatthias Ringwald     }
17183deb3ec6SMatthias Ringwald 
17193deb3ec6SMatthias Ringwald     // TODO: integrate in common switch
17203deb3ec6SMatthias Ringwald     if (event->type == CH_EVT_RCVD_RPN_REQ){
17213deb3ec6SMatthias Ringwald         // no values got accepted (no values have beens sent)
17223deb3ec6SMatthias Ringwald         channel->rpn_data.parameter_mask_0 = 0x00;
17233deb3ec6SMatthias Ringwald         channel->rpn_data.parameter_mask_1 = 0x00;
17243deb3ec6SMatthias Ringwald         rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_RPN_RSP);
17253deb3ec6SMatthias Ringwald         return;
17263deb3ec6SMatthias Ringwald     }
17273deb3ec6SMatthias Ringwald 
17283deb3ec6SMatthias Ringwald     if (event->type == CH_EVT_RCVD_RLS_CMD){
17293deb3ec6SMatthias Ringwald         rfcomm_channel_event_rls_t * event_rls = (rfcomm_channel_event_rls_t*) event;
17303deb3ec6SMatthias Ringwald         channel->rls_line_status = event_rls->line_status & 0x0f;
17313deb3ec6SMatthias Ringwald         log_info("CH_EVT_RCVD_RLS_CMD setting line status to 0x%0x", channel->rls_line_status);
17323deb3ec6SMatthias Ringwald         rfcomm_emit_remote_line_status(channel, event_rls->line_status);
17333deb3ec6SMatthias Ringwald         return;
17343deb3ec6SMatthias Ringwald     }
17353deb3ec6SMatthias Ringwald 
173662b5b741SMatthias Ringwald     // TODO: integrate in common switch
17373deb3ec6SMatthias Ringwald     if (event->type == CH_EVT_READY_TO_SEND){
17383deb3ec6SMatthias Ringwald         if (channel->state_var & RFCOMM_CHANNEL_STATE_VAR_SEND_RPN_RSP){
17393deb3ec6SMatthias Ringwald             log_info("Sending Remote Port Negotiation RSP for #%u", channel->dlci);
17403deb3ec6SMatthias Ringwald             rfcomm_channel_state_remove(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_RPN_RSP);
17413deb3ec6SMatthias Ringwald             rfcomm_send_uih_rpn_rsp(multiplexer, channel->dlci, &channel->rpn_data);
17423deb3ec6SMatthias Ringwald             return;
17433deb3ec6SMatthias Ringwald         }
17443deb3ec6SMatthias Ringwald         if (channel->state_var & RFCOMM_CHANNEL_STATE_VAR_SEND_MSC_RSP){
17453deb3ec6SMatthias Ringwald             log_info("Sending MSC RSP for #%u", channel->dlci);
17463deb3ec6SMatthias Ringwald             rfcomm_channel_state_remove(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_MSC_RSP);
17473deb3ec6SMatthias Ringwald             rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_SENT_MSC_RSP);
17483deb3ec6SMatthias Ringwald             rfcomm_send_uih_msc_rsp(multiplexer, channel->dlci, 0x8d);  // ea=1,fc=0,rtc=1,rtr=1,ic=0,dv=1
17493deb3ec6SMatthias Ringwald             return;
17503deb3ec6SMatthias Ringwald         }
17513deb3ec6SMatthias Ringwald         if (channel->rls_line_status != RFCOMM_RLS_STATUS_INVALID){
17523deb3ec6SMatthias Ringwald             log_info("Sending RLS RSP 0x%0x", channel->rls_line_status);
17533deb3ec6SMatthias Ringwald             uint8_t line_status = channel->rls_line_status;
17543deb3ec6SMatthias Ringwald             channel->rls_line_status = RFCOMM_RLS_STATUS_INVALID;
17553deb3ec6SMatthias Ringwald             rfcomm_send_uih_rls_rsp(multiplexer, channel->dlci, line_status);
17563deb3ec6SMatthias Ringwald             return;
17573deb3ec6SMatthias Ringwald         }
17583deb3ec6SMatthias Ringwald     }
17593deb3ec6SMatthias Ringwald 
17603deb3ec6SMatthias Ringwald     // emit MSC status to app
17613deb3ec6SMatthias Ringwald     if (event->type == CH_EVT_RCVD_MSC_CMD){
17623deb3ec6SMatthias Ringwald         // notify client about new settings
17633deb3ec6SMatthias Ringwald         rfcomm_channel_event_msc_t *event_msc = (rfcomm_channel_event_msc_t*) event;
17643deb3ec6SMatthias Ringwald         uint8_t modem_status_event[2+1];
17653deb3ec6SMatthias Ringwald         modem_status_event[0] = RFCOMM_EVENT_REMOTE_MODEM_STATUS;
17663deb3ec6SMatthias Ringwald         modem_status_event[1] = 1;
17673deb3ec6SMatthias Ringwald         modem_status_event[2] = event_msc->modem_status;
1768fc376368SMatthias Ringwald         (channel->packet_handler)(HCI_EVENT_PACKET, channel->rfcomm_cid, (uint8_t*)&modem_status_event, sizeof(modem_status_event));
17693deb3ec6SMatthias Ringwald         // no return, MSC_CMD will be handled by state machine below
17703deb3ec6SMatthias Ringwald     }
17713deb3ec6SMatthias Ringwald 
17723deb3ec6SMatthias Ringwald     rfcomm_channel_event_pn_t * event_pn = (rfcomm_channel_event_pn_t*) event;
17733deb3ec6SMatthias Ringwald 
17743deb3ec6SMatthias Ringwald     switch (channel->state) {
17753deb3ec6SMatthias Ringwald         case RFCOMM_CHANNEL_CLOSED:
17763deb3ec6SMatthias Ringwald             switch (event->type){
17773deb3ec6SMatthias Ringwald                 case CH_EVT_RCVD_SABM:
17783deb3ec6SMatthias Ringwald                     log_info("-> Inform app");
17793deb3ec6SMatthias Ringwald                     rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_RCVD_SABM);
17803deb3ec6SMatthias Ringwald                     channel->state = RFCOMM_CHANNEL_INCOMING_SETUP;
17813deb3ec6SMatthias Ringwald                     rfcomm_emit_connection_request(channel);
17823deb3ec6SMatthias Ringwald                     break;
17833deb3ec6SMatthias Ringwald                 case CH_EVT_RCVD_PN:
17843deb3ec6SMatthias Ringwald                     rfcomm_channel_accept_pn(channel, event_pn);
17853deb3ec6SMatthias Ringwald                     log_info("-> Inform app");
17863deb3ec6SMatthias Ringwald                     rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_RCVD_PN);
17873deb3ec6SMatthias Ringwald                     channel->state = RFCOMM_CHANNEL_INCOMING_SETUP;
17883deb3ec6SMatthias Ringwald                     rfcomm_emit_connection_request(channel);
17893deb3ec6SMatthias Ringwald                     break;
17903deb3ec6SMatthias Ringwald                 default:
17913deb3ec6SMatthias Ringwald                     break;
17923deb3ec6SMatthias Ringwald             }
17933deb3ec6SMatthias Ringwald             break;
17943deb3ec6SMatthias Ringwald 
17953deb3ec6SMatthias Ringwald         case RFCOMM_CHANNEL_INCOMING_SETUP:
17963deb3ec6SMatthias Ringwald             switch (event->type){
17973deb3ec6SMatthias Ringwald                 case CH_EVT_RCVD_SABM:
17983deb3ec6SMatthias Ringwald                     rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_RCVD_SABM);
17993deb3ec6SMatthias Ringwald                     if (channel->state_var & RFCOMM_CHANNEL_STATE_VAR_CLIENT_ACCEPTED) {
18003deb3ec6SMatthias Ringwald                         rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_UA);
18013deb3ec6SMatthias Ringwald                     }
18023deb3ec6SMatthias Ringwald                     break;
18033deb3ec6SMatthias Ringwald                 case CH_EVT_RCVD_PN:
18043deb3ec6SMatthias Ringwald                     rfcomm_channel_accept_pn(channel, event_pn);
18053deb3ec6SMatthias Ringwald                     rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_RCVD_PN);
18063deb3ec6SMatthias Ringwald                     if (channel->state_var & RFCOMM_CHANNEL_STATE_VAR_CLIENT_ACCEPTED) {
18073deb3ec6SMatthias Ringwald                         rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_PN_RSP);
18083deb3ec6SMatthias Ringwald                     }
18093deb3ec6SMatthias Ringwald                     break;
18103deb3ec6SMatthias Ringwald                 case CH_EVT_READY_TO_SEND:
18113deb3ec6SMatthias Ringwald                     // if / else if is used to check for state transition after sending
18123deb3ec6SMatthias Ringwald                     if (channel->state_var & RFCOMM_CHANNEL_STATE_VAR_SEND_PN_RSP){
18133deb3ec6SMatthias Ringwald                         log_info("Sending UIH Parameter Negotiation Respond for #%u", channel->dlci);
18143deb3ec6SMatthias Ringwald                         rfcomm_channel_state_remove(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_PN_RSP);
18153deb3ec6SMatthias Ringwald                         rfcomm_send_uih_pn_response(multiplexer, channel->dlci, channel->pn_priority, channel->max_frame_size);
18163deb3ec6SMatthias Ringwald                     } else if (channel->state_var & RFCOMM_CHANNEL_STATE_VAR_SEND_UA){
18173deb3ec6SMatthias Ringwald                         log_info("Sending UA #%u", channel->dlci);
18183deb3ec6SMatthias Ringwald                         rfcomm_channel_state_remove(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_UA);
18193deb3ec6SMatthias Ringwald                         rfcomm_send_ua(multiplexer, channel->dlci);
18203deb3ec6SMatthias Ringwald                     }
18213deb3ec6SMatthias Ringwald                     if (rfcomm_channel_ready_for_incoming_dlc_setup(channel)){
18223deb3ec6SMatthias Ringwald                         log_info("Incomping setup done, requesting send MSC CMD and send Credits");
18233deb3ec6SMatthias Ringwald                         rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_MSC_CMD);
18243deb3ec6SMatthias Ringwald                         rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_CREDITS);
1825daf17d1fSMatthias Ringwald                         channel->state = RFCOMM_CHANNEL_DLC_SETUP;
18263deb3ec6SMatthias Ringwald                      }
18273deb3ec6SMatthias Ringwald                     break;
18283deb3ec6SMatthias Ringwald                 default:
18293deb3ec6SMatthias Ringwald                     break;
18303deb3ec6SMatthias Ringwald             }
18313deb3ec6SMatthias Ringwald             break;
18323deb3ec6SMatthias Ringwald 
18333deb3ec6SMatthias Ringwald         case RFCOMM_CHANNEL_W4_MULTIPLEXER:
18343deb3ec6SMatthias Ringwald             switch (event->type) {
18353deb3ec6SMatthias Ringwald                 case CH_EVT_MULTIPLEXER_READY:
18363deb3ec6SMatthias Ringwald                     log_info("Muliplexer opened, sending UIH PN next");
18373deb3ec6SMatthias Ringwald                     channel->state = RFCOMM_CHANNEL_SEND_UIH_PN;
18383deb3ec6SMatthias Ringwald                     break;
18393deb3ec6SMatthias Ringwald                 default:
18403deb3ec6SMatthias Ringwald                     break;
18413deb3ec6SMatthias Ringwald             }
18423deb3ec6SMatthias Ringwald             break;
18433deb3ec6SMatthias Ringwald 
18443deb3ec6SMatthias Ringwald         case RFCOMM_CHANNEL_SEND_UIH_PN:
18453deb3ec6SMatthias Ringwald             switch (event->type) {
18463deb3ec6SMatthias Ringwald                 case CH_EVT_READY_TO_SEND:
18473deb3ec6SMatthias Ringwald                     log_info("Sending UIH Parameter Negotiation Command for #%u (channel 0x%p)", channel->dlci, channel );
18483deb3ec6SMatthias Ringwald                     channel->state = RFCOMM_CHANNEL_W4_PN_RSP;
18493deb3ec6SMatthias Ringwald                     rfcomm_send_uih_pn_command(multiplexer, channel->dlci, channel->max_frame_size);
18503deb3ec6SMatthias Ringwald                     break;
18513deb3ec6SMatthias Ringwald                 default:
18523deb3ec6SMatthias Ringwald                     break;
18533deb3ec6SMatthias Ringwald             }
18543deb3ec6SMatthias Ringwald             break;
18553deb3ec6SMatthias Ringwald 
18563deb3ec6SMatthias Ringwald         case RFCOMM_CHANNEL_W4_PN_RSP:
18573deb3ec6SMatthias Ringwald             switch (event->type){
18583deb3ec6SMatthias Ringwald                 case CH_EVT_RCVD_PN_RSP:
18593deb3ec6SMatthias Ringwald                     // update max frame size
18603deb3ec6SMatthias Ringwald                     if (channel->max_frame_size > event_pn->max_frame_size) {
18613deb3ec6SMatthias Ringwald                         channel->max_frame_size = event_pn->max_frame_size;
18623deb3ec6SMatthias Ringwald                     }
18633deb3ec6SMatthias Ringwald                     // new credits
18643deb3ec6SMatthias Ringwald                     channel->credits_outgoing = event_pn->credits_outgoing;
18653deb3ec6SMatthias Ringwald                     channel->state = RFCOMM_CHANNEL_SEND_SABM_W4_UA;
18663deb3ec6SMatthias Ringwald                     break;
18673deb3ec6SMatthias Ringwald                 default:
18683deb3ec6SMatthias Ringwald                     break;
18693deb3ec6SMatthias Ringwald             }
18703deb3ec6SMatthias Ringwald             break;
18713deb3ec6SMatthias Ringwald 
18723deb3ec6SMatthias Ringwald         case RFCOMM_CHANNEL_SEND_SABM_W4_UA:
18733deb3ec6SMatthias Ringwald             switch (event->type) {
18743deb3ec6SMatthias Ringwald                 case CH_EVT_READY_TO_SEND:
18753deb3ec6SMatthias Ringwald                     log_info("Sending SABM #%u", channel->dlci);
18763deb3ec6SMatthias Ringwald                     channel->state = RFCOMM_CHANNEL_W4_UA;
18773deb3ec6SMatthias Ringwald                     rfcomm_send_sabm(multiplexer, channel->dlci);
18783deb3ec6SMatthias Ringwald                     break;
18793deb3ec6SMatthias Ringwald                 default:
18803deb3ec6SMatthias Ringwald                     break;
18813deb3ec6SMatthias Ringwald             }
18823deb3ec6SMatthias Ringwald             break;
18833deb3ec6SMatthias Ringwald 
18843deb3ec6SMatthias Ringwald         case RFCOMM_CHANNEL_W4_UA:
18853deb3ec6SMatthias Ringwald             switch (event->type){
18863deb3ec6SMatthias Ringwald                 case CH_EVT_RCVD_UA:
18873deb3ec6SMatthias Ringwald                     channel->state = RFCOMM_CHANNEL_DLC_SETUP;
18883deb3ec6SMatthias Ringwald                     rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_MSC_CMD);
18893deb3ec6SMatthias Ringwald                     rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_CREDITS);
18903deb3ec6SMatthias Ringwald                     break;
18913deb3ec6SMatthias Ringwald                 default:
18923deb3ec6SMatthias Ringwald                     break;
18933deb3ec6SMatthias Ringwald             }
18943deb3ec6SMatthias Ringwald             break;
18953deb3ec6SMatthias Ringwald 
18963deb3ec6SMatthias Ringwald         case RFCOMM_CHANNEL_DLC_SETUP:
18973deb3ec6SMatthias Ringwald             switch (event->type){
18983deb3ec6SMatthias Ringwald                 case CH_EVT_RCVD_MSC_CMD:
18993deb3ec6SMatthias Ringwald                     rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_RCVD_MSC_CMD);
19003deb3ec6SMatthias Ringwald                     rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_MSC_RSP);
19013deb3ec6SMatthias Ringwald                     break;
19023deb3ec6SMatthias Ringwald                 case CH_EVT_RCVD_MSC_RSP:
19033deb3ec6SMatthias Ringwald                     rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_RCVD_MSC_RSP);
19043deb3ec6SMatthias Ringwald                     break;
19053deb3ec6SMatthias Ringwald 
19063deb3ec6SMatthias Ringwald                 case CH_EVT_READY_TO_SEND:
19073deb3ec6SMatthias Ringwald                     if (channel->state_var & RFCOMM_CHANNEL_STATE_VAR_SEND_MSC_CMD){
19083deb3ec6SMatthias Ringwald                         log_info("Sending MSC CMD for #%u", channel->dlci);
19093deb3ec6SMatthias Ringwald                         rfcomm_channel_state_remove(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_MSC_CMD);
19103deb3ec6SMatthias Ringwald                         rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_SENT_MSC_CMD);
19113deb3ec6SMatthias Ringwald                         rfcomm_send_uih_msc_cmd(multiplexer, channel->dlci , 0x8d);  // ea=1,fc=0,rtc=1,rtr=1,ic=0,dv=1
19123deb3ec6SMatthias Ringwald                         break;
19133deb3ec6SMatthias Ringwald                     }
19143deb3ec6SMatthias Ringwald                     if (channel->state_var & RFCOMM_CHANNEL_STATE_VAR_SEND_CREDITS){
19153deb3ec6SMatthias Ringwald                         log_info("Providing credits for #%u", channel->dlci);
19163deb3ec6SMatthias Ringwald                         rfcomm_channel_state_remove(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_CREDITS);
19173deb3ec6SMatthias Ringwald                         rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_SENT_CREDITS);
19183deb3ec6SMatthias Ringwald 
19193deb3ec6SMatthias Ringwald                         if (channel->new_credits_incoming) {
19203deb3ec6SMatthias Ringwald                             uint8_t new_credits = channel->new_credits_incoming;
19213deb3ec6SMatthias Ringwald                             channel->new_credits_incoming = 0;
19223deb3ec6SMatthias Ringwald                             rfcomm_channel_send_credits(channel, new_credits);
19233deb3ec6SMatthias Ringwald                         }
19243deb3ec6SMatthias Ringwald                         break;
19253deb3ec6SMatthias Ringwald 
19263deb3ec6SMatthias Ringwald                     }
19273deb3ec6SMatthias Ringwald                     break;
19283deb3ec6SMatthias Ringwald                 default:
19293deb3ec6SMatthias Ringwald                     break;
19303deb3ec6SMatthias Ringwald             }
19313deb3ec6SMatthias Ringwald             // finally done?
19323deb3ec6SMatthias Ringwald             if (rfcomm_channel_ready_for_open(channel)){
19333deb3ec6SMatthias Ringwald                 channel->state = RFCOMM_CHANNEL_OPEN;
19343deb3ec6SMatthias Ringwald                 rfcomm_channel_opened(channel);
19353deb3ec6SMatthias Ringwald             }
19363deb3ec6SMatthias Ringwald             break;
19373deb3ec6SMatthias Ringwald 
19383deb3ec6SMatthias Ringwald         case RFCOMM_CHANNEL_OPEN:
19393deb3ec6SMatthias Ringwald             switch (event->type){
19403deb3ec6SMatthias Ringwald                 case CH_EVT_RCVD_MSC_CMD:
19413deb3ec6SMatthias Ringwald                     rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_MSC_RSP);
19423deb3ec6SMatthias Ringwald                     break;
19433deb3ec6SMatthias Ringwald                 case CH_EVT_READY_TO_SEND:
19443deb3ec6SMatthias Ringwald                     if (channel->new_credits_incoming) {
19453deb3ec6SMatthias Ringwald                         uint8_t new_credits = channel->new_credits_incoming;
19463deb3ec6SMatthias Ringwald                         channel->new_credits_incoming = 0;
19473deb3ec6SMatthias Ringwald                         rfcomm_channel_send_credits(channel, new_credits);
19483deb3ec6SMatthias Ringwald                         break;
19493deb3ec6SMatthias Ringwald                     }
19503deb3ec6SMatthias Ringwald                     break;
1951b31d33b2SMatthias Ringwald                 case CH_EVT_RCVD_CREDITS:
1952b31d33b2SMatthias Ringwald                     rfcomm_notify_channel_can_send();
19533deb3ec6SMatthias Ringwald                     break;
19543deb3ec6SMatthias Ringwald                 default:
19553deb3ec6SMatthias Ringwald                     break;
19563deb3ec6SMatthias Ringwald             }
19573deb3ec6SMatthias Ringwald             break;
19583deb3ec6SMatthias Ringwald 
19593deb3ec6SMatthias Ringwald         case RFCOMM_CHANNEL_SEND_DM:
19603deb3ec6SMatthias Ringwald             switch (event->type) {
19613deb3ec6SMatthias Ringwald                 case CH_EVT_READY_TO_SEND:
19623deb3ec6SMatthias Ringwald                     log_info("Sending DM_PF for #%u", channel->dlci);
19633deb3ec6SMatthias Ringwald                     // don't emit channel closed - channel was never open
19643deb3ec6SMatthias Ringwald                     channel->state = RFCOMM_CHANNEL_CLOSED;
19653deb3ec6SMatthias Ringwald                     rfcomm_send_dm_pf(multiplexer, channel->dlci);
19663deb3ec6SMatthias Ringwald                     rfcomm_channel_finalize(channel);
19673deb3ec6SMatthias Ringwald                     break;
19683deb3ec6SMatthias Ringwald                 default:
19693deb3ec6SMatthias Ringwald                     break;
19703deb3ec6SMatthias Ringwald             }
19713deb3ec6SMatthias Ringwald             break;
19723deb3ec6SMatthias Ringwald 
19733deb3ec6SMatthias Ringwald         case RFCOMM_CHANNEL_SEND_DISC:
19743deb3ec6SMatthias Ringwald             switch (event->type) {
19753deb3ec6SMatthias Ringwald                 case CH_EVT_READY_TO_SEND:
19763deb3ec6SMatthias Ringwald                     channel->state = RFCOMM_CHANNEL_W4_UA_AFTER_UA;
19773deb3ec6SMatthias Ringwald                     rfcomm_send_disc(multiplexer, channel->dlci);
19783deb3ec6SMatthias Ringwald                     break;
19793deb3ec6SMatthias Ringwald                 default:
19803deb3ec6SMatthias Ringwald                     break;
19813deb3ec6SMatthias Ringwald             }
19823deb3ec6SMatthias Ringwald             break;
19833deb3ec6SMatthias Ringwald 
19843deb3ec6SMatthias Ringwald         case RFCOMM_CHANNEL_W4_UA_AFTER_UA:
19853deb3ec6SMatthias Ringwald             switch (event->type){
19863deb3ec6SMatthias Ringwald                 case CH_EVT_RCVD_UA:
19873deb3ec6SMatthias Ringwald                     channel->state = RFCOMM_CHANNEL_CLOSED;
19883deb3ec6SMatthias Ringwald                     rfcomm_emit_channel_closed(channel);
19893deb3ec6SMatthias Ringwald                     rfcomm_channel_finalize(channel);
19903deb3ec6SMatthias Ringwald                     break;
19913deb3ec6SMatthias Ringwald                 default:
19923deb3ec6SMatthias Ringwald                     break;
19933deb3ec6SMatthias Ringwald             }
19943deb3ec6SMatthias Ringwald             break;
19953deb3ec6SMatthias Ringwald 
19963deb3ec6SMatthias Ringwald         case RFCOMM_CHANNEL_SEND_UA_AFTER_DISC:
19973deb3ec6SMatthias Ringwald             switch (event->type) {
19983deb3ec6SMatthias Ringwald                 case CH_EVT_READY_TO_SEND:
19993deb3ec6SMatthias Ringwald                     log_info("Sending UA after DISC for #%u", channel->dlci);
20003deb3ec6SMatthias Ringwald                     channel->state = RFCOMM_CHANNEL_CLOSED;
20013deb3ec6SMatthias Ringwald                     rfcomm_send_ua(multiplexer, channel->dlci);
20023deb3ec6SMatthias Ringwald                     rfcomm_channel_finalize(channel);
20033deb3ec6SMatthias Ringwald                     break;
20043deb3ec6SMatthias Ringwald                 default:
20053deb3ec6SMatthias Ringwald                     break;
20063deb3ec6SMatthias Ringwald             }
20073deb3ec6SMatthias Ringwald             break;
20083deb3ec6SMatthias Ringwald 
20093deb3ec6SMatthias Ringwald         default:
20103deb3ec6SMatthias Ringwald             break;
20113deb3ec6SMatthias Ringwald     }
20123deb3ec6SMatthias Ringwald }
20133deb3ec6SMatthias Ringwald 
20143deb3ec6SMatthias Ringwald // MARK: RFCOMM BTstack API
20153deb3ec6SMatthias Ringwald 
20163deb3ec6SMatthias Ringwald void rfcomm_init(void){
20173deb3ec6SMatthias Ringwald     rfcomm_client_cid_generator = 0;
20183deb3ec6SMatthias Ringwald     rfcomm_multiplexers = NULL;
20193deb3ec6SMatthias Ringwald     rfcomm_services     = NULL;
20203deb3ec6SMatthias Ringwald     rfcomm_channels     = NULL;
20213deb3ec6SMatthias Ringwald     rfcomm_security_level = LEVEL_2;
20223deb3ec6SMatthias Ringwald }
20233deb3ec6SMatthias Ringwald 
20243deb3ec6SMatthias Ringwald void rfcomm_set_required_security_level(gap_security_level_t security_level){
20253deb3ec6SMatthias Ringwald     rfcomm_security_level = security_level;
20263deb3ec6SMatthias Ringwald }
20273deb3ec6SMatthias Ringwald 
20283deb3ec6SMatthias Ringwald int rfcomm_can_send_packet_now(uint16_t rfcomm_cid){
20293deb3ec6SMatthias Ringwald     rfcomm_channel_t * channel = rfcomm_channel_for_rfcomm_cid(rfcomm_cid);
20303deb3ec6SMatthias Ringwald     if (!channel){
203128190c0bSMatthias Ringwald         log_error("rfcomm_send cid 0x%02x doesn't exist!", rfcomm_cid);
2032b31d33b2SMatthias Ringwald         return 0;
20333deb3ec6SMatthias Ringwald     }
20340b9d7e78SMatthias Ringwald     return rfcomm_channel_can_send(channel);
20353deb3ec6SMatthias Ringwald }
20363deb3ec6SMatthias Ringwald 
2037225a2744SMatthias Ringwald void rfcomm_request_can_send_now_event(uint16_t rfcomm_cid){
2038225a2744SMatthias Ringwald     rfcomm_channel_t * channel = rfcomm_channel_for_rfcomm_cid(rfcomm_cid);
2039225a2744SMatthias Ringwald     if (!channel){
2040225a2744SMatthias Ringwald         log_error("rfcomm_send cid 0x%02x doesn't exist!", rfcomm_cid);
2041225a2744SMatthias Ringwald         return;
2042225a2744SMatthias Ringwald     }
2043225a2744SMatthias Ringwald     channel->waiting_for_can_send_now = 1;
20444fea3822SMatthias Ringwald     l2cap_request_can_send_now_event(channel->multiplexer->l2cap_cid);
2045225a2744SMatthias Ringwald }
2046225a2744SMatthias Ringwald 
20473deb3ec6SMatthias Ringwald static int rfcomm_assert_send_valid(rfcomm_channel_t * channel , uint16_t len){
20483deb3ec6SMatthias Ringwald     if (len > channel->max_frame_size){
204928190c0bSMatthias Ringwald         log_error("rfcomm_send cid 0x%02x, rfcomm data lenght exceeds MTU!", channel->rfcomm_cid);
20503deb3ec6SMatthias Ringwald         return RFCOMM_DATA_LEN_EXCEEDS_MTU;
20513deb3ec6SMatthias Ringwald     }
20523deb3ec6SMatthias Ringwald 
20533deb3ec6SMatthias Ringwald     if (!channel->credits_outgoing){
205428190c0bSMatthias Ringwald         log_info("rfcomm_send cid 0x%02x, no rfcomm outgoing credits!", channel->rfcomm_cid);
20553deb3ec6SMatthias Ringwald         return RFCOMM_NO_OUTGOING_CREDITS;
20563deb3ec6SMatthias Ringwald     }
20573deb3ec6SMatthias Ringwald 
20583deb3ec6SMatthias Ringwald     if ((channel->multiplexer->fcon & 1) == 0){
205928190c0bSMatthias Ringwald         log_info("rfcomm_send cid 0x%02x, aggregate flow off!", channel->rfcomm_cid);
20603deb3ec6SMatthias Ringwald         return RFCOMM_AGGREGATE_FLOW_OFF;
20613deb3ec6SMatthias Ringwald     }
20623deb3ec6SMatthias Ringwald     return 0;
20633deb3ec6SMatthias Ringwald }
20643deb3ec6SMatthias Ringwald 
20653deb3ec6SMatthias Ringwald // pre: rfcomm_can_send_packet_now(rfcomm_cid) == true
20663deb3ec6SMatthias Ringwald int rfcomm_reserve_packet_buffer(void){
20673deb3ec6SMatthias Ringwald     return l2cap_reserve_packet_buffer();
20683deb3ec6SMatthias Ringwald }
20693deb3ec6SMatthias Ringwald 
20703deb3ec6SMatthias Ringwald void rfcomm_release_packet_buffer(void){
20713deb3ec6SMatthias Ringwald     l2cap_release_packet_buffer();
20723deb3ec6SMatthias Ringwald }
20733deb3ec6SMatthias Ringwald 
20743deb3ec6SMatthias Ringwald uint8_t * rfcomm_get_outgoing_buffer(void){
20753deb3ec6SMatthias Ringwald     uint8_t * rfcomm_out_buffer = l2cap_get_outgoing_buffer();
20763deb3ec6SMatthias Ringwald     // address + control + length (16) + no credit field
20773deb3ec6SMatthias Ringwald     return &rfcomm_out_buffer[4];
20783deb3ec6SMatthias Ringwald }
20793deb3ec6SMatthias Ringwald 
20803deb3ec6SMatthias Ringwald uint16_t rfcomm_get_max_frame_size(uint16_t rfcomm_cid){
20813deb3ec6SMatthias Ringwald     rfcomm_channel_t * channel = rfcomm_channel_for_rfcomm_cid(rfcomm_cid);
20823deb3ec6SMatthias Ringwald     if (!channel){
20833deb3ec6SMatthias Ringwald         log_error("rfcomm_get_max_frame_size cid 0x%02x doesn't exist!", rfcomm_cid);
20843deb3ec6SMatthias Ringwald         return 0;
20853deb3ec6SMatthias Ringwald     }
20863deb3ec6SMatthias Ringwald     return channel->max_frame_size;
20873deb3ec6SMatthias Ringwald }
20883deb3ec6SMatthias Ringwald int rfcomm_send_prepared(uint16_t rfcomm_cid, uint16_t len){
20893deb3ec6SMatthias Ringwald     rfcomm_channel_t * channel = rfcomm_channel_for_rfcomm_cid(rfcomm_cid);
20903deb3ec6SMatthias Ringwald     if (!channel){
20913deb3ec6SMatthias Ringwald         log_error("rfcomm_send_prepared cid 0x%02x doesn't exist!", rfcomm_cid);
20923deb3ec6SMatthias Ringwald         return 0;
20933deb3ec6SMatthias Ringwald     }
20943deb3ec6SMatthias Ringwald 
20953deb3ec6SMatthias Ringwald     int err = rfcomm_assert_send_valid(channel, len);
20963deb3ec6SMatthias Ringwald     if (err) return err;
209768d15bfcSMatthias Ringwald     if (!l2cap_can_send_prepared_packet_now(channel->multiplexer->l2cap_cid)){
209878707112SMatthias Ringwald         log_error("rfcomm_send_prepared: l2cap cannot send now");
209978707112SMatthias Ringwald         return BTSTACK_ACL_BUFFERS_FULL;
210078707112SMatthias Ringwald     }
21013deb3ec6SMatthias Ringwald 
21023deb3ec6SMatthias Ringwald     // send might cause l2cap to emit new credits, update counters first
21033deb3ec6SMatthias Ringwald     channel->credits_outgoing--;
21043deb3ec6SMatthias Ringwald 
21053deb3ec6SMatthias Ringwald     int result = rfcomm_send_uih_prepared(channel->multiplexer, channel->dlci, len);
21063deb3ec6SMatthias Ringwald 
21073deb3ec6SMatthias Ringwald     if (result != 0) {
21083deb3ec6SMatthias Ringwald         channel->credits_outgoing++;
210978707112SMatthias Ringwald         log_error("rfcomm_send_prepared: error %d", result);
21103deb3ec6SMatthias Ringwald         return result;
21113deb3ec6SMatthias Ringwald     }
21123deb3ec6SMatthias Ringwald 
21133deb3ec6SMatthias Ringwald     return result;
21143deb3ec6SMatthias Ringwald }
21153deb3ec6SMatthias Ringwald 
211628190c0bSMatthias Ringwald int rfcomm_send(uint16_t rfcomm_cid, uint8_t *data, uint16_t len){
21173deb3ec6SMatthias Ringwald     rfcomm_channel_t * channel = rfcomm_channel_for_rfcomm_cid(rfcomm_cid);
21183deb3ec6SMatthias Ringwald     if (!channel){
211928190c0bSMatthias Ringwald         log_error("rfcomm_send cid 0x%02x doesn't exist!", rfcomm_cid);
21203deb3ec6SMatthias Ringwald         return 1;
21213deb3ec6SMatthias Ringwald     }
21223deb3ec6SMatthias Ringwald 
21233deb3ec6SMatthias Ringwald     int err = rfcomm_assert_send_valid(channel, len);
21243deb3ec6SMatthias Ringwald     if (err) return err;
212568d15bfcSMatthias Ringwald     if (!l2cap_can_send_packet_now(channel->multiplexer->l2cap_cid)){
212678707112SMatthias Ringwald         log_error("rfcomm_send_internal: l2cap cannot send now");
212778707112SMatthias Ringwald         return BTSTACK_ACL_BUFFERS_FULL;
212878707112SMatthias Ringwald     }
21293deb3ec6SMatthias Ringwald 
21303deb3ec6SMatthias Ringwald     rfcomm_reserve_packet_buffer();
21313deb3ec6SMatthias Ringwald     uint8_t * rfcomm_payload = rfcomm_get_outgoing_buffer();
21323deb3ec6SMatthias Ringwald     memcpy(rfcomm_payload, data, len);
213378707112SMatthias Ringwald     err = rfcomm_send_prepared(rfcomm_cid, len);
213478707112SMatthias Ringwald     if (err){
213578707112SMatthias Ringwald         rfcomm_release_packet_buffer();
213678707112SMatthias Ringwald     }
213778707112SMatthias Ringwald     return err;
21383deb3ec6SMatthias Ringwald }
21393deb3ec6SMatthias Ringwald 
21403deb3ec6SMatthias Ringwald // Sends Local Lnie Status, see LINE_STATUS_..
21413deb3ec6SMatthias Ringwald int rfcomm_send_local_line_status(uint16_t rfcomm_cid, uint8_t line_status){
21423deb3ec6SMatthias Ringwald     rfcomm_channel_t * channel = rfcomm_channel_for_rfcomm_cid(rfcomm_cid);
21433deb3ec6SMatthias Ringwald     if (!channel){
21443deb3ec6SMatthias Ringwald         log_error("rfcomm_send_local_line_status cid 0x%02x doesn't exist!", rfcomm_cid);
21453deb3ec6SMatthias Ringwald         return 0;
21463deb3ec6SMatthias Ringwald     }
21473deb3ec6SMatthias Ringwald     return rfcomm_send_uih_rls_cmd(channel->multiplexer, channel->dlci, line_status);
21483deb3ec6SMatthias Ringwald }
21493deb3ec6SMatthias Ringwald 
21503deb3ec6SMatthias Ringwald // Sned local modem status. see MODEM_STAUS_..
21513deb3ec6SMatthias Ringwald int rfcomm_send_modem_status(uint16_t rfcomm_cid, uint8_t modem_status){
21523deb3ec6SMatthias Ringwald     rfcomm_channel_t * channel = rfcomm_channel_for_rfcomm_cid(rfcomm_cid);
21533deb3ec6SMatthias Ringwald     if (!channel){
21543deb3ec6SMatthias Ringwald         log_error("rfcomm_send_modem_status cid 0x%02x doesn't exist!", rfcomm_cid);
21553deb3ec6SMatthias Ringwald         return 0;
21563deb3ec6SMatthias Ringwald     }
21573deb3ec6SMatthias Ringwald     return rfcomm_send_uih_msc_cmd(channel->multiplexer, channel->dlci, modem_status);
21583deb3ec6SMatthias Ringwald }
21593deb3ec6SMatthias Ringwald 
21603deb3ec6SMatthias Ringwald // Configure remote port
21613deb3ec6SMatthias 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){
21623deb3ec6SMatthias Ringwald     rfcomm_channel_t * channel = rfcomm_channel_for_rfcomm_cid(rfcomm_cid);
21633deb3ec6SMatthias Ringwald     if (!channel){
21643deb3ec6SMatthias Ringwald         log_error("rfcomm_send_port_configuration cid 0x%02x doesn't exist!", rfcomm_cid);
21653deb3ec6SMatthias Ringwald         return 0;
21663deb3ec6SMatthias Ringwald     }
21673deb3ec6SMatthias Ringwald     rfcomm_rpn_data_t rpn_data;
21683deb3ec6SMatthias Ringwald     rpn_data.baud_rate = baud_rate;
21693deb3ec6SMatthias Ringwald     rpn_data.flags = data_bits | (stop_bits << 2) | (parity << 3);
21703deb3ec6SMatthias Ringwald     rpn_data.flow_control = flow_control;
21713deb3ec6SMatthias Ringwald     rpn_data.xon = 0;
21723deb3ec6SMatthias Ringwald     rpn_data.xoff = 0;
21733deb3ec6SMatthias Ringwald     rpn_data.parameter_mask_0 = 0x1f;   // all but xon/xoff
21743deb3ec6SMatthias Ringwald     rpn_data.parameter_mask_1 = 0x3f;   // all flow control options
21753deb3ec6SMatthias Ringwald     return rfcomm_send_uih_rpn_cmd(channel->multiplexer, channel->dlci, &rpn_data);
21763deb3ec6SMatthias Ringwald }
21773deb3ec6SMatthias Ringwald 
21783deb3ec6SMatthias Ringwald // Query remote port
21793deb3ec6SMatthias Ringwald int rfcomm_query_port_configuration(uint16_t rfcomm_cid){
21803deb3ec6SMatthias Ringwald     rfcomm_channel_t * channel = rfcomm_channel_for_rfcomm_cid(rfcomm_cid);
21813deb3ec6SMatthias Ringwald     if (!channel){
21823deb3ec6SMatthias Ringwald         log_error("rfcomm_query_port_configuration cid 0x%02x doesn't exist!", rfcomm_cid);
21833deb3ec6SMatthias Ringwald         return 0;
21843deb3ec6SMatthias Ringwald     }
21853deb3ec6SMatthias Ringwald     return rfcomm_send_uih_rpn_req(channel->multiplexer, channel->dlci);
21863deb3ec6SMatthias Ringwald }
21873deb3ec6SMatthias Ringwald 
2188aa4dd815SMatthias Ringwald 
2189ccb8ddfbSMatthias 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){
21905d1e858fSMatthias Ringwald     log_info("RFCOMM_CREATE_CHANNEL addr %s channel #%u init credits %u",  bd_addr_to_str(addr), server_channel, initial_credits);
21915d1e858fSMatthias Ringwald 
21925d1e858fSMatthias Ringwald     // create new multiplexer if necessary
21935d1e858fSMatthias Ringwald     uint8_t status = 0;
2194fc966bd3SMatthias Ringwald     uint8_t dlci = 0;
21955d1e858fSMatthias Ringwald     int new_multiplexer = 0;
21965d1e858fSMatthias Ringwald     rfcomm_channel_t * channel = NULL;
21975d1e858fSMatthias Ringwald     rfcomm_multiplexer_t * multiplexer = rfcomm_multiplexer_for_addr(addr);
21985d1e858fSMatthias Ringwald     if (!multiplexer) {
21995d1e858fSMatthias Ringwald         multiplexer = rfcomm_multiplexer_create_for_addr(addr);
22005d1e858fSMatthias Ringwald         if (!multiplexer){
22015d1e858fSMatthias Ringwald             status = BTSTACK_MEMORY_ALLOC_FAILED;
22025d1e858fSMatthias Ringwald             goto fail;
22035d1e858fSMatthias Ringwald         }
22045d1e858fSMatthias Ringwald         multiplexer->outgoing = 1;
22055d1e858fSMatthias Ringwald         multiplexer->state = RFCOMM_MULTIPLEXER_W4_CONNECT;
22065d1e858fSMatthias Ringwald         new_multiplexer = 1;
22075d1e858fSMatthias Ringwald     }
22085d1e858fSMatthias Ringwald 
22092a1147c9SMatthias Ringwald     // check if channel for this remote service already exists
2210fc966bd3SMatthias Ringwald     dlci = (server_channel << 1) | (multiplexer->outgoing ^ 1);
22112a1147c9SMatthias Ringwald     channel = rfcomm_channel_for_multiplexer_and_dlci(multiplexer, dlci);
22122a1147c9SMatthias Ringwald     if (channel){
22132a1147c9SMatthias Ringwald         status = RFCOMM_CHANNEL_ALREADY_REGISTERED;
22142a1147c9SMatthias Ringwald         goto fail;
22152a1147c9SMatthias Ringwald     }
22162a1147c9SMatthias Ringwald 
22175d1e858fSMatthias Ringwald     // prepare channel
22185d1e858fSMatthias Ringwald     channel = rfcomm_channel_create(multiplexer, NULL, server_channel);
22195d1e858fSMatthias Ringwald     if (!channel){
22205d1e858fSMatthias Ringwald         status = BTSTACK_MEMORY_ALLOC_FAILED;
22215d1e858fSMatthias Ringwald         goto fail;
22225d1e858fSMatthias Ringwald     }
2223ccb8ddfbSMatthias Ringwald 
22245d1e858fSMatthias Ringwald     // rfcomm_cid is already assigned by rfcomm_channel_create
22255d1e858fSMatthias Ringwald     channel->incoming_flow_control = incoming_flow_control;
22265d1e858fSMatthias Ringwald     channel->new_credits_incoming  = initial_credits;
2227ccb8ddfbSMatthias Ringwald     channel->packet_handler = packet_handler;
22285d1e858fSMatthias Ringwald 
22295d1e858fSMatthias Ringwald     // return rfcomm_cid
2230432fe57eSMatthias Ringwald     if (out_rfcomm_cid){
22315d1e858fSMatthias Ringwald         *out_rfcomm_cid = channel->rfcomm_cid;
2232432fe57eSMatthias Ringwald     }
22335d1e858fSMatthias Ringwald 
22345d1e858fSMatthias Ringwald     // start multiplexer setup
22355d1e858fSMatthias Ringwald     if (multiplexer->state != RFCOMM_MULTIPLEXER_OPEN) {
22365d1e858fSMatthias Ringwald         channel->state = RFCOMM_CHANNEL_W4_MULTIPLEXER;
22375d1e858fSMatthias Ringwald         uint16_t l2cap_cid = 0;
22385d1e858fSMatthias Ringwald         status = l2cap_create_channel(rfcomm_packet_handler, addr, PSM_RFCOMM, l2cap_max_mtu(), &l2cap_cid);
22395d1e858fSMatthias Ringwald         if (status) goto fail;
22405d1e858fSMatthias Ringwald         multiplexer->l2cap_cid = l2cap_cid;
22415d1e858fSMatthias Ringwald         return 0;
22425d1e858fSMatthias Ringwald     }
22435d1e858fSMatthias Ringwald 
22445d1e858fSMatthias Ringwald     channel->state = RFCOMM_CHANNEL_SEND_UIH_PN;
22455d1e858fSMatthias Ringwald 
22465d1e858fSMatthias Ringwald     // start connecting, if multiplexer is already up and running
224762b5b741SMatthias Ringwald     l2cap_request_can_send_now_event(multiplexer->l2cap_cid);
22485d1e858fSMatthias Ringwald     return 0;
22495d1e858fSMatthias Ringwald 
22505d1e858fSMatthias Ringwald fail:
22515d1e858fSMatthias Ringwald     if (new_multiplexer) btstack_memory_rfcomm_multiplexer_free(multiplexer);
22525d1e858fSMatthias Ringwald     if (channel)         btstack_memory_rfcomm_channel_free(channel);
22535d1e858fSMatthias Ringwald     return status;
22545d1e858fSMatthias Ringwald }
22555d1e858fSMatthias Ringwald 
2256ccb8ddfbSMatthias 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){
2257ccb8ddfbSMatthias Ringwald     return rfcomm_channel_create_internal(packet_handler, addr, server_channel, 1, initial_credits, out_rfcomm_cid);
22585d1e858fSMatthias Ringwald }
22595d1e858fSMatthias Ringwald 
2260ccb8ddfbSMatthias 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){
2261ccb8ddfbSMatthias Ringwald     return rfcomm_channel_create_internal(packet_handler, addr, server_channel, 0, RFCOMM_CREDITS, out_rfcomm_cid);
22625d1e858fSMatthias Ringwald }
22635d1e858fSMatthias Ringwald 
226428190c0bSMatthias Ringwald void rfcomm_disconnect(uint16_t rfcomm_cid){
22653deb3ec6SMatthias Ringwald     log_info("RFCOMM_DISCONNECT cid 0x%02x", rfcomm_cid);
22663deb3ec6SMatthias Ringwald     rfcomm_channel_t * channel = rfcomm_channel_for_rfcomm_cid(rfcomm_cid);
226770c27508SMatthias Ringwald     if (!channel) return;
22683deb3ec6SMatthias Ringwald 
226970c27508SMatthias Ringwald     channel->state = RFCOMM_CHANNEL_SEND_DISC;
227062b5b741SMatthias Ringwald     l2cap_request_can_send_now_event(channel->multiplexer->l2cap_cid);
22713deb3ec6SMatthias Ringwald }
22723deb3ec6SMatthias Ringwald 
2273ccb8ddfbSMatthias Ringwald static uint8_t rfcomm_register_service_internal(btstack_packet_handler_t packet_handler,
2274ccb8ddfbSMatthias Ringwald     uint8_t channel, uint16_t max_frame_size, uint8_t incoming_flow_control, uint8_t initial_credits){
2275ccb8ddfbSMatthias Ringwald 
2276ccb8ddfbSMatthias Ringwald     log_info("RFCOMM_REGISTER_SERVICE channel #%u mtu %u flow_control %u credits %u",
22773deb3ec6SMatthias Ringwald              channel, max_frame_size, incoming_flow_control, initial_credits);
2278457b5cb1SMatthias Ringwald 
22793deb3ec6SMatthias Ringwald     // check if already registered
22803deb3ec6SMatthias Ringwald     rfcomm_service_t * service = rfcomm_service_for_channel(channel);
22813deb3ec6SMatthias Ringwald     if (service){
2282457b5cb1SMatthias Ringwald         return RFCOMM_CHANNEL_ALREADY_REGISTERED;
22833deb3ec6SMatthias Ringwald     }
22843deb3ec6SMatthias Ringwald 
22853deb3ec6SMatthias Ringwald     // alloc structure
22863deb3ec6SMatthias Ringwald     service = btstack_memory_rfcomm_service_get();
22873deb3ec6SMatthias Ringwald     if (!service) {
2288457b5cb1SMatthias Ringwald         return BTSTACK_MEMORY_ALLOC_FAILED;
22893deb3ec6SMatthias Ringwald     }
22903deb3ec6SMatthias Ringwald 
22913deb3ec6SMatthias Ringwald     // register with l2cap if not registered before, max MTU
2292665d90f2SMatthias Ringwald     if (btstack_linked_list_empty(&rfcomm_services)){
2293be2053a6SMatthias Ringwald         l2cap_register_service(rfcomm_packet_handler, PSM_RFCOMM, 0xffff, rfcomm_security_level);
22943deb3ec6SMatthias Ringwald     }
22953deb3ec6SMatthias Ringwald 
22963deb3ec6SMatthias Ringwald     // fill in
2297ccb8ddfbSMatthias Ringwald     service->packet_handler = packet_handler;
22983deb3ec6SMatthias Ringwald     service->server_channel = channel;
22993deb3ec6SMatthias Ringwald     service->max_frame_size = max_frame_size;
23003deb3ec6SMatthias Ringwald     service->incoming_flow_control = incoming_flow_control;
23013deb3ec6SMatthias Ringwald     service->incoming_initial_credits = initial_credits;
23023deb3ec6SMatthias Ringwald 
23033deb3ec6SMatthias Ringwald     // add to services list
2304665d90f2SMatthias Ringwald     btstack_linked_list_add(&rfcomm_services, (btstack_linked_item_t *) service);
23053deb3ec6SMatthias Ringwald 
2306457b5cb1SMatthias Ringwald     return 0;
23073deb3ec6SMatthias Ringwald }
23083deb3ec6SMatthias Ringwald 
2309ccb8ddfbSMatthias Ringwald uint8_t rfcomm_register_service_with_initial_credits(btstack_packet_handler_t packet_handler,
2310ccb8ddfbSMatthias Ringwald     uint8_t channel, uint16_t max_frame_size, uint8_t initial_credits){
2311ccb8ddfbSMatthias Ringwald 
2312ccb8ddfbSMatthias Ringwald     return rfcomm_register_service_internal(packet_handler, channel, max_frame_size, 1, initial_credits);
23133deb3ec6SMatthias Ringwald }
23143deb3ec6SMatthias Ringwald 
2315ccb8ddfbSMatthias Ringwald uint8_t rfcomm_register_service(btstack_packet_handler_t packet_handler, uint8_t channel,
2316ccb8ddfbSMatthias Ringwald     uint16_t max_frame_size){
2317ccb8ddfbSMatthias Ringwald 
2318ccb8ddfbSMatthias Ringwald     return rfcomm_register_service_internal(packet_handler, channel, max_frame_size, 0,RFCOMM_CREDITS);
23193deb3ec6SMatthias Ringwald }
23203deb3ec6SMatthias Ringwald 
2321457b5cb1SMatthias Ringwald void rfcomm_unregister_service(uint8_t service_channel){
23223deb3ec6SMatthias Ringwald     log_info("RFCOMM_UNREGISTER_SERVICE #%u", service_channel);
23233deb3ec6SMatthias Ringwald     rfcomm_service_t *service = rfcomm_service_for_channel(service_channel);
23243deb3ec6SMatthias Ringwald     if (!service) return;
2325665d90f2SMatthias Ringwald     btstack_linked_list_remove(&rfcomm_services, (btstack_linked_item_t *) service);
23263deb3ec6SMatthias Ringwald     btstack_memory_rfcomm_service_free(service);
23273deb3ec6SMatthias Ringwald 
23283deb3ec6SMatthias Ringwald     // unregister if no services active
2329665d90f2SMatthias Ringwald     if (btstack_linked_list_empty(&rfcomm_services)){
23303deb3ec6SMatthias Ringwald         // bt_send_cmd(&l2cap_unregister_service, PSM_RFCOMM);
233102f83142SMatthias Ringwald         l2cap_unregister_service(PSM_RFCOMM);
23323deb3ec6SMatthias Ringwald     }
23333deb3ec6SMatthias Ringwald }
23343deb3ec6SMatthias Ringwald 
233528190c0bSMatthias Ringwald void rfcomm_accept_connection(uint16_t rfcomm_cid){
23363deb3ec6SMatthias Ringwald     log_info("RFCOMM_ACCEPT_CONNECTION cid 0x%02x", rfcomm_cid);
23373deb3ec6SMatthias Ringwald     rfcomm_channel_t * channel = rfcomm_channel_for_rfcomm_cid(rfcomm_cid);
23383deb3ec6SMatthias Ringwald     if (!channel) return;
23393deb3ec6SMatthias Ringwald     switch (channel->state) {
23403deb3ec6SMatthias Ringwald         case RFCOMM_CHANNEL_INCOMING_SETUP:
23413deb3ec6SMatthias Ringwald             rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_CLIENT_ACCEPTED);
23423deb3ec6SMatthias Ringwald             if (channel->state_var & RFCOMM_CHANNEL_STATE_VAR_RCVD_PN){
23433deb3ec6SMatthias Ringwald                 rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_PN_RSP);
234462b5b741SMatthias Ringwald                 l2cap_request_can_send_now_event(channel->multiplexer->l2cap_cid);
23453deb3ec6SMatthias Ringwald             }
23463deb3ec6SMatthias Ringwald             if (channel->state_var & RFCOMM_CHANNEL_STATE_VAR_RCVD_SABM){
23473deb3ec6SMatthias Ringwald                 rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_UA);
234862b5b741SMatthias Ringwald                 l2cap_request_can_send_now_event(channel->multiplexer->l2cap_cid);
23493deb3ec6SMatthias Ringwald             }
23503deb3ec6SMatthias Ringwald             // at least one of { PN RSP, UA } needs to be sent
23513deb3ec6SMatthias Ringwald             // state transistion incoming setup -> dlc setup happens in rfcomm_run after these have been sent
23523deb3ec6SMatthias Ringwald             break;
23533deb3ec6SMatthias Ringwald         default:
23543deb3ec6SMatthias Ringwald             break;
23553deb3ec6SMatthias Ringwald     }
23563deb3ec6SMatthias Ringwald 
23573deb3ec6SMatthias Ringwald }
23583deb3ec6SMatthias Ringwald 
235928190c0bSMatthias Ringwald void rfcomm_decline_connection(uint16_t rfcomm_cid){
23603deb3ec6SMatthias Ringwald     log_info("RFCOMM_DECLINE_CONNECTION cid 0x%02x", rfcomm_cid);
23613deb3ec6SMatthias Ringwald     rfcomm_channel_t * channel = rfcomm_channel_for_rfcomm_cid(rfcomm_cid);
23623deb3ec6SMatthias Ringwald     if (!channel) return;
23633deb3ec6SMatthias Ringwald     switch (channel->state) {
23643deb3ec6SMatthias Ringwald         case RFCOMM_CHANNEL_INCOMING_SETUP:
23653deb3ec6SMatthias Ringwald             channel->state = RFCOMM_CHANNEL_SEND_DM;
236662b5b741SMatthias Ringwald             l2cap_request_can_send_now_event(channel->multiplexer->l2cap_cid);
23673deb3ec6SMatthias Ringwald             break;
23683deb3ec6SMatthias Ringwald         default:
23693deb3ec6SMatthias Ringwald             break;
23703deb3ec6SMatthias Ringwald     }
23713deb3ec6SMatthias Ringwald }
23723deb3ec6SMatthias Ringwald 
23733deb3ec6SMatthias Ringwald void rfcomm_grant_credits(uint16_t rfcomm_cid, uint8_t credits){
23743deb3ec6SMatthias Ringwald     log_info("RFCOMM_GRANT_CREDITS cid 0x%02x credits %u", rfcomm_cid, credits);
23753deb3ec6SMatthias Ringwald     rfcomm_channel_t * channel = rfcomm_channel_for_rfcomm_cid(rfcomm_cid);
23763deb3ec6SMatthias Ringwald     if (!channel) return;
23773deb3ec6SMatthias Ringwald     if (!channel->incoming_flow_control) return;
23783deb3ec6SMatthias Ringwald     channel->new_credits_incoming += credits;
23793deb3ec6SMatthias Ringwald 
23803deb3ec6SMatthias Ringwald     // process
238162b5b741SMatthias Ringwald     l2cap_request_can_send_now_event(channel->multiplexer->l2cap_cid);
23823deb3ec6SMatthias Ringwald }
23833deb3ec6SMatthias Ringwald 
23843deb3ec6SMatthias Ringwald 
2385b1c4ef5fSMatthias Ringwald /*
2386b1c4ef5fSMatthias Ringwald  * CRC (reversed crc) lookup table as calculated by the table generator in ETSI TS 101 369 V6.3.0.
2387b1c4ef5fSMatthias Ringwald  */
2388b1c4ef5fSMatthias Ringwald static const uint8_t crc8table[256] = {    /* reversed, 8-bit, poly=0x07 */
2389b1c4ef5fSMatthias Ringwald     0x00, 0x91, 0xE3, 0x72, 0x07, 0x96, 0xE4, 0x75, 0x0E, 0x9F, 0xED, 0x7C, 0x09, 0x98, 0xEA, 0x7B,
2390b1c4ef5fSMatthias Ringwald     0x1C, 0x8D, 0xFF, 0x6E, 0x1B, 0x8A, 0xF8, 0x69, 0x12, 0x83, 0xF1, 0x60, 0x15, 0x84, 0xF6, 0x67,
2391b1c4ef5fSMatthias Ringwald     0x38, 0xA9, 0xDB, 0x4A, 0x3F, 0xAE, 0xDC, 0x4D, 0x36, 0xA7, 0xD5, 0x44, 0x31, 0xA0, 0xD2, 0x43,
2392b1c4ef5fSMatthias Ringwald     0x24, 0xB5, 0xC7, 0x56, 0x23, 0xB2, 0xC0, 0x51, 0x2A, 0xBB, 0xC9, 0x58, 0x2D, 0xBC, 0xCE, 0x5F,
2393b1c4ef5fSMatthias Ringwald     0x70, 0xE1, 0x93, 0x02, 0x77, 0xE6, 0x94, 0x05, 0x7E, 0xEF, 0x9D, 0x0C, 0x79, 0xE8, 0x9A, 0x0B,
2394b1c4ef5fSMatthias Ringwald     0x6C, 0xFD, 0x8F, 0x1E, 0x6B, 0xFA, 0x88, 0x19, 0x62, 0xF3, 0x81, 0x10, 0x65, 0xF4, 0x86, 0x17,
2395b1c4ef5fSMatthias Ringwald     0x48, 0xD9, 0xAB, 0x3A, 0x4F, 0xDE, 0xAC, 0x3D, 0x46, 0xD7, 0xA5, 0x34, 0x41, 0xD0, 0xA2, 0x33,
2396b1c4ef5fSMatthias Ringwald     0x54, 0xC5, 0xB7, 0x26, 0x53, 0xC2, 0xB0, 0x21, 0x5A, 0xCB, 0xB9, 0x28, 0x5D, 0xCC, 0xBE, 0x2F,
2397b1c4ef5fSMatthias Ringwald     0xE0, 0x71, 0x03, 0x92, 0xE7, 0x76, 0x04, 0x95, 0xEE, 0x7F, 0x0D, 0x9C, 0xE9, 0x78, 0x0A, 0x9B,
2398b1c4ef5fSMatthias Ringwald     0xFC, 0x6D, 0x1F, 0x8E, 0xFB, 0x6A, 0x18, 0x89, 0xF2, 0x63, 0x11, 0x80, 0xF5, 0x64, 0x16, 0x87,
2399b1c4ef5fSMatthias Ringwald     0xD8, 0x49, 0x3B, 0xAA, 0xDF, 0x4E, 0x3C, 0xAD, 0xD6, 0x47, 0x35, 0xA4, 0xD1, 0x40, 0x32, 0xA3,
2400b1c4ef5fSMatthias Ringwald     0xC4, 0x55, 0x27, 0xB6, 0xC3, 0x52, 0x20, 0xB1, 0xCA, 0x5B, 0x29, 0xB8, 0xCD, 0x5C, 0x2E, 0xBF,
2401b1c4ef5fSMatthias Ringwald     0x90, 0x01, 0x73, 0xE2, 0x97, 0x06, 0x74, 0xE5, 0x9E, 0x0F, 0x7D, 0xEC, 0x99, 0x08, 0x7A, 0xEB,
2402b1c4ef5fSMatthias Ringwald     0x8C, 0x1D, 0x6F, 0xFE, 0x8B, 0x1A, 0x68, 0xF9, 0x82, 0x13, 0x61, 0xF0, 0x85, 0x14, 0x66, 0xF7,
2403b1c4ef5fSMatthias Ringwald     0xA8, 0x39, 0x4B, 0xDA, 0xAF, 0x3E, 0x4C, 0xDD, 0xA6, 0x37, 0x45, 0xD4, 0xA1, 0x30, 0x42, 0xD3,
2404b1c4ef5fSMatthias Ringwald     0xB4, 0x25, 0x57, 0xC6, 0xB3, 0x22, 0x50, 0xC1, 0xBA, 0x2B, 0x59, 0xC8, 0xBD, 0x2C, 0x5E, 0xCF
2405b1c4ef5fSMatthias Ringwald };
2406b1c4ef5fSMatthias Ringwald 
2407b1c4ef5fSMatthias Ringwald #define CRC8_INIT  0xFF          // Initial FCS value
2408b1c4ef5fSMatthias Ringwald #define CRC8_OK    0xCF          // Good final FCS value
2409b1c4ef5fSMatthias Ringwald /*-----------------------------------------------------------------------------------*/
2410b1c4ef5fSMatthias Ringwald static uint8_t crc8(uint8_t *data, uint16_t len)
2411b1c4ef5fSMatthias Ringwald {
2412b1c4ef5fSMatthias Ringwald     uint16_t count;
2413b1c4ef5fSMatthias Ringwald     uint8_t crc = CRC8_INIT;
2414b1c4ef5fSMatthias Ringwald     for (count = 0; count < len; count++)
2415b1c4ef5fSMatthias Ringwald         crc = crc8table[crc ^ data[count]];
2416b1c4ef5fSMatthias Ringwald     return crc;
2417b1c4ef5fSMatthias Ringwald }
2418b1c4ef5fSMatthias Ringwald 
2419b1c4ef5fSMatthias Ringwald /*-----------------------------------------------------------------------------------*/
2420b1c4ef5fSMatthias Ringwald uint8_t crc8_check(uint8_t *data, uint16_t len, uint8_t check_sum)
2421b1c4ef5fSMatthias Ringwald {
2422b1c4ef5fSMatthias Ringwald     uint8_t crc;
2423b1c4ef5fSMatthias Ringwald 
2424b1c4ef5fSMatthias Ringwald     crc = crc8(data, len);
2425b1c4ef5fSMatthias Ringwald 
2426b1c4ef5fSMatthias Ringwald     crc = crc8table[crc ^ check_sum];
2427b1c4ef5fSMatthias Ringwald     if (crc == CRC8_OK)
2428b1c4ef5fSMatthias Ringwald         return 0;               /* Valid */
2429b1c4ef5fSMatthias Ringwald     else
2430b1c4ef5fSMatthias Ringwald         return 1;               /* Failed */
2431b1c4ef5fSMatthias Ringwald 
2432b1c4ef5fSMatthias Ringwald }
2433b1c4ef5fSMatthias Ringwald 
2434b1c4ef5fSMatthias Ringwald /*-----------------------------------------------------------------------------------*/
2435b1c4ef5fSMatthias Ringwald uint8_t crc8_calc(uint8_t *data, uint16_t len)
2436b1c4ef5fSMatthias Ringwald {
2437b1c4ef5fSMatthias Ringwald     /* Ones complement */
2438b1c4ef5fSMatthias Ringwald     return 0xFF - crc8(data, len);
2439b1c4ef5fSMatthias Ringwald }
2440b1c4ef5fSMatthias Ringwald 
2441b1c4ef5fSMatthias Ringwald 
24423deb3ec6SMatthias Ringwald 
24433deb3ec6SMatthias Ringwald 
2444