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