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