![](/media/cache/img/default_profile.jpg.50x50_q85.jpg)
mbed base bard check program for BlueTooth USB dongle module (3 switches, 6 leds, I2C LCD, A/D)
Fork of BTstack by
BTstack/rfcomm.c@3:7b7d1273e2d5, 2016-10-17 (annotated)
- Committer:
- tamaki
- Date:
- Mon Oct 17 00:25:18 2016 +0000
- Revision:
- 3:7b7d1273e2d5
- Parent:
- 0:1ed23ab1345f
mbed base bard check program
; for BlueTooth USB dongle module
; (3 switches, 6 leds, I2C LCD, A/D)
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
va009039 | 0:1ed23ab1345f | 1 | /* |
va009039 | 0:1ed23ab1345f | 2 | * Copyright (C) 2009-2012 by Matthias Ringwald |
va009039 | 0:1ed23ab1345f | 3 | * |
va009039 | 0:1ed23ab1345f | 4 | * Redistribution and use in source and binary forms, with or without |
va009039 | 0:1ed23ab1345f | 5 | * modification, are permitted provided that the following conditions |
va009039 | 0:1ed23ab1345f | 6 | * are met: |
va009039 | 0:1ed23ab1345f | 7 | * |
va009039 | 0:1ed23ab1345f | 8 | * 1. Redistributions of source code must retain the above copyright |
va009039 | 0:1ed23ab1345f | 9 | * notice, this list of conditions and the following disclaimer. |
va009039 | 0:1ed23ab1345f | 10 | * 2. Redistributions in binary form must reproduce the above copyright |
va009039 | 0:1ed23ab1345f | 11 | * notice, this list of conditions and the following disclaimer in the |
va009039 | 0:1ed23ab1345f | 12 | * documentation and/or other materials provided with the distribution. |
va009039 | 0:1ed23ab1345f | 13 | * 3. Neither the name of the copyright holders nor the names of |
va009039 | 0:1ed23ab1345f | 14 | * contributors may be used to endorse or promote products derived |
va009039 | 0:1ed23ab1345f | 15 | * from this software without specific prior written permission. |
va009039 | 0:1ed23ab1345f | 16 | * 4. Any redistribution, use, or modification is done solely for |
va009039 | 0:1ed23ab1345f | 17 | * personal benefit and not for any commercial purpose or for |
va009039 | 0:1ed23ab1345f | 18 | * monetary gain. |
va009039 | 0:1ed23ab1345f | 19 | * |
va009039 | 0:1ed23ab1345f | 20 | * THIS SOFTWARE IS PROVIDED BY MATTHIAS RINGWALD AND CONTRIBUTORS |
va009039 | 0:1ed23ab1345f | 21 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
va009039 | 0:1ed23ab1345f | 22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
va009039 | 0:1ed23ab1345f | 23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS |
va009039 | 0:1ed23ab1345f | 24 | * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
va009039 | 0:1ed23ab1345f | 25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
va009039 | 0:1ed23ab1345f | 26 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS |
va009039 | 0:1ed23ab1345f | 27 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
va009039 | 0:1ed23ab1345f | 28 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
va009039 | 0:1ed23ab1345f | 29 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF |
va009039 | 0:1ed23ab1345f | 30 | * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
va009039 | 0:1ed23ab1345f | 31 | * SUCH DAMAGE. |
va009039 | 0:1ed23ab1345f | 32 | * |
va009039 | 0:1ed23ab1345f | 33 | * Please inquire about commercial licensing options at btstack@ringwald.ch |
va009039 | 0:1ed23ab1345f | 34 | * |
va009039 | 0:1ed23ab1345f | 35 | */ |
va009039 | 0:1ed23ab1345f | 36 | |
va009039 | 0:1ed23ab1345f | 37 | /* |
va009039 | 0:1ed23ab1345f | 38 | * rfcomm.c |
va009039 | 0:1ed23ab1345f | 39 | */ |
va009039 | 0:1ed23ab1345f | 40 | |
va009039 | 0:1ed23ab1345f | 41 | #include <stdio.h> |
va009039 | 0:1ed23ab1345f | 42 | #include <stdlib.h> |
va009039 | 0:1ed23ab1345f | 43 | #include <string.h> // memcpy |
va009039 | 0:1ed23ab1345f | 44 | #include <stdint.h> |
va009039 | 0:1ed23ab1345f | 45 | |
va009039 | 0:1ed23ab1345f | 46 | #include <btstack/btstack.h> |
va009039 | 0:1ed23ab1345f | 47 | #include <btstack/hci_cmds.h> |
va009039 | 0:1ed23ab1345f | 48 | #include <btstack/utils.h> |
va009039 | 0:1ed23ab1345f | 49 | |
va009039 | 0:1ed23ab1345f | 50 | #include <btstack/utils.h> |
va009039 | 0:1ed23ab1345f | 51 | #include "btstack_memory.h" |
va009039 | 0:1ed23ab1345f | 52 | #include "hci.h" |
va009039 | 0:1ed23ab1345f | 53 | #include "hci_dump.h" |
va009039 | 0:1ed23ab1345f | 54 | #include "debug.h" |
va009039 | 0:1ed23ab1345f | 55 | #include "rfcomm.h" |
va009039 | 0:1ed23ab1345f | 56 | |
va009039 | 0:1ed23ab1345f | 57 | // workaround for missing PRIxPTR on mspgcc (16/20-bit MCU) |
va009039 | 0:1ed23ab1345f | 58 | #ifndef PRIxPTR |
va009039 | 0:1ed23ab1345f | 59 | #if defined(__MSP430X__) && defined(__MSP430X_LARGE__) |
va009039 | 0:1ed23ab1345f | 60 | #define PRIxPTR "lx" |
va009039 | 0:1ed23ab1345f | 61 | #else |
va009039 | 0:1ed23ab1345f | 62 | #define PRIxPTR "x" |
va009039 | 0:1ed23ab1345f | 63 | #endif |
va009039 | 0:1ed23ab1345f | 64 | #endif |
va009039 | 0:1ed23ab1345f | 65 | |
va009039 | 0:1ed23ab1345f | 66 | |
va009039 | 0:1ed23ab1345f | 67 | // Control field values bit no. 1 2 3 4 PF 6 7 8 |
va009039 | 0:1ed23ab1345f | 68 | #define BT_RFCOMM_SABM 0x3F // 1 1 1 1 1 1 0 0 |
va009039 | 0:1ed23ab1345f | 69 | #define BT_RFCOMM_UA 0x73 // 1 1 0 0 1 1 1 0 |
va009039 | 0:1ed23ab1345f | 70 | #define BT_RFCOMM_DM 0x0F // 1 1 1 1 0 0 0 0 |
va009039 | 0:1ed23ab1345f | 71 | #define BT_RFCOMM_DM_PF 0x1F // 1 1 1 1 1 0 0 0 |
va009039 | 0:1ed23ab1345f | 72 | #define BT_RFCOMM_DISC 0x53 // 1 1 0 0 1 0 1 0 |
va009039 | 0:1ed23ab1345f | 73 | #define BT_RFCOMM_UIH 0xEF // 1 1 1 1 0 1 1 1 |
va009039 | 0:1ed23ab1345f | 74 | #define BT_RFCOMM_UIH_PF 0xFF // 1 1 1 1 0 1 1 1 |
va009039 | 0:1ed23ab1345f | 75 | |
va009039 | 0:1ed23ab1345f | 76 | // Multiplexer message types |
va009039 | 0:1ed23ab1345f | 77 | #define BT_RFCOMM_CLD_CMD 0xC3 |
va009039 | 0:1ed23ab1345f | 78 | #define BT_RFCOMM_FCON_CMD 0xA3 |
va009039 | 0:1ed23ab1345f | 79 | #define BT_RFCOMM_FCON_RSP 0xA1 |
va009039 | 0:1ed23ab1345f | 80 | #define BT_RFCOMM_FCOFF_CMD 0x63 |
va009039 | 0:1ed23ab1345f | 81 | #define BT_RFCOMM_FCOFF_RSP 0x61 |
va009039 | 0:1ed23ab1345f | 82 | #define BT_RFCOMM_MSC_CMD 0xE3 |
va009039 | 0:1ed23ab1345f | 83 | #define BT_RFCOMM_MSC_RSP 0xE1 |
va009039 | 0:1ed23ab1345f | 84 | #define BT_RFCOMM_NSC_RSP 0x11 |
va009039 | 0:1ed23ab1345f | 85 | #define BT_RFCOMM_PN_CMD 0x83 |
va009039 | 0:1ed23ab1345f | 86 | #define BT_RFCOMM_PN_RSP 0x81 |
va009039 | 0:1ed23ab1345f | 87 | #define BT_RFCOMM_RLS_CMD 0x53 |
va009039 | 0:1ed23ab1345f | 88 | #define BT_RFCOMM_RLS_RSP 0x51 |
va009039 | 0:1ed23ab1345f | 89 | #define BT_RFCOMM_RPN_CMD 0x93 |
va009039 | 0:1ed23ab1345f | 90 | #define BT_RFCOMM_RPN_RSP 0x91 |
va009039 | 0:1ed23ab1345f | 91 | #define BT_RFCOMM_TEST_CMD 0x23 |
va009039 | 0:1ed23ab1345f | 92 | #define BT_RFCOMM_TEST_RSP 0x21 |
va009039 | 0:1ed23ab1345f | 93 | |
va009039 | 0:1ed23ab1345f | 94 | #define RFCOMM_MULIPLEXER_TIMEOUT_MS 60000 |
va009039 | 0:1ed23ab1345f | 95 | |
va009039 | 0:1ed23ab1345f | 96 | // FCS calc |
va009039 | 0:1ed23ab1345f | 97 | #define BT_RFCOMM_CODE_WORD 0xE0 // pol = x8+x2+x1+1 |
va009039 | 0:1ed23ab1345f | 98 | #define BT_RFCOMM_CRC_CHECK_LEN 3 |
va009039 | 0:1ed23ab1345f | 99 | #define BT_RFCOMM_UIHCRC_CHECK_LEN 2 |
va009039 | 0:1ed23ab1345f | 100 | |
va009039 | 0:1ed23ab1345f | 101 | #include "l2cap.h" |
va009039 | 0:1ed23ab1345f | 102 | |
va009039 | 0:1ed23ab1345f | 103 | // used for debugging |
va009039 | 0:1ed23ab1345f | 104 | // #define RFCOMM_LOG_CREDITS |
va009039 | 0:1ed23ab1345f | 105 | |
va009039 | 0:1ed23ab1345f | 106 | // global rfcomm data |
va009039 | 0:1ed23ab1345f | 107 | static uint16_t rfcomm_client_cid_generator; // used for client channel IDs |
va009039 | 0:1ed23ab1345f | 108 | |
va009039 | 0:1ed23ab1345f | 109 | // linked lists for all |
va009039 | 0:1ed23ab1345f | 110 | static linked_list_t rfcomm_multiplexers = NULL; |
va009039 | 0:1ed23ab1345f | 111 | static linked_list_t rfcomm_channels = NULL; |
va009039 | 0:1ed23ab1345f | 112 | static linked_list_t rfcomm_services = NULL; |
va009039 | 0:1ed23ab1345f | 113 | |
va009039 | 0:1ed23ab1345f | 114 | static void (*app_packet_handler)(void * connection, uint8_t packet_type, |
va009039 | 0:1ed23ab1345f | 115 | uint16_t channel, uint8_t *packet, uint16_t size); |
va009039 | 0:1ed23ab1345f | 116 | |
va009039 | 0:1ed23ab1345f | 117 | static void rfcomm_run(void); |
va009039 | 0:1ed23ab1345f | 118 | static void rfcomm_hand_out_credits(void); |
va009039 | 0:1ed23ab1345f | 119 | static void rfcomm_channel_state_machine(rfcomm_channel_t *channel, rfcomm_channel_event_t *event); |
va009039 | 0:1ed23ab1345f | 120 | static void rfcomm_channel_state_machine_2(rfcomm_multiplexer_t * multiplexer, uint8_t dlci, rfcomm_channel_event_t *event); |
va009039 | 0:1ed23ab1345f | 121 | static int rfcomm_channel_ready_for_open(rfcomm_channel_t *channel); |
va009039 | 0:1ed23ab1345f | 122 | static void rfcomm_multiplexer_state_machine(rfcomm_multiplexer_t * multiplexer, RFCOMM_MULTIPLEXER_EVENT event); |
va009039 | 0:1ed23ab1345f | 123 | |
va009039 | 0:1ed23ab1345f | 124 | |
va009039 | 0:1ed23ab1345f | 125 | // MARK: RFCOMM CLIENT EVENTS |
va009039 | 0:1ed23ab1345f | 126 | |
va009039 | 0:1ed23ab1345f | 127 | // data: event (8), len(8), address(48), channel (8), rfcomm_cid (16) |
va009039 | 0:1ed23ab1345f | 128 | static void rfcomm_emit_connection_request(rfcomm_channel_t *channel) { |
va009039 | 0:1ed23ab1345f | 129 | uint8_t event[11]; |
va009039 | 0:1ed23ab1345f | 130 | event[0] = RFCOMM_EVENT_INCOMING_CONNECTION; |
va009039 | 0:1ed23ab1345f | 131 | event[1] = sizeof(event) - 2; |
va009039 | 0:1ed23ab1345f | 132 | bt_flip_addr(&event[2], channel->multiplexer->remote_addr); |
va009039 | 0:1ed23ab1345f | 133 | event[8] = channel->dlci >> 1; |
va009039 | 0:1ed23ab1345f | 134 | bt_store_16(event, 9, channel->rfcomm_cid); |
va009039 | 0:1ed23ab1345f | 135 | hci_dump_packet(HCI_EVENT_PACKET, 0, event, sizeof(event)); |
va009039 | 0:1ed23ab1345f | 136 | (*app_packet_handler)(channel->connection, HCI_EVENT_PACKET, 0, (uint8_t *) event, sizeof(event)); |
va009039 | 0:1ed23ab1345f | 137 | } |
va009039 | 0:1ed23ab1345f | 138 | |
va009039 | 0:1ed23ab1345f | 139 | // API Change: BTstack-0.3.50x uses |
va009039 | 0:1ed23ab1345f | 140 | // data: event(8), len(8), status (8), address (48), server channel(8), rfcomm_cid(16), max frame size(16) |
va009039 | 0:1ed23ab1345f | 141 | // next Cydia release will use SVN version of this |
va009039 | 0:1ed23ab1345f | 142 | // data: event(8), len(8), status (8), address (48), handle (16), server channel(8), rfcomm_cid(16), max frame size(16) |
va009039 | 0:1ed23ab1345f | 143 | static void rfcomm_emit_channel_opened(rfcomm_channel_t *channel, uint8_t status) { |
va009039 | 0:1ed23ab1345f | 144 | uint8_t event[16]; |
va009039 | 0:1ed23ab1345f | 145 | uint8_t pos = 0; |
va009039 | 0:1ed23ab1345f | 146 | event[pos++] = RFCOMM_EVENT_OPEN_CHANNEL_COMPLETE; |
va009039 | 0:1ed23ab1345f | 147 | event[pos++] = sizeof(event) - 2; |
va009039 | 0:1ed23ab1345f | 148 | event[pos++] = status; |
va009039 | 0:1ed23ab1345f | 149 | bt_flip_addr(&event[pos], channel->multiplexer->remote_addr); pos += 6; |
va009039 | 0:1ed23ab1345f | 150 | bt_store_16(event, pos, channel->multiplexer->con_handle); pos += 2; |
va009039 | 0:1ed23ab1345f | 151 | event[pos++] = channel->dlci >> 1; |
va009039 | 0:1ed23ab1345f | 152 | bt_store_16(event, pos, channel->rfcomm_cid); pos += 2; // channel ID |
va009039 | 0:1ed23ab1345f | 153 | bt_store_16(event, pos, channel->max_frame_size); pos += 2; // max frame size |
va009039 | 0:1ed23ab1345f | 154 | hci_dump_packet(HCI_EVENT_PACKET, 0, event, sizeof(event)); |
va009039 | 0:1ed23ab1345f | 155 | (*app_packet_handler)(channel->connection, HCI_EVENT_PACKET, 0, (uint8_t *) event, pos); |
va009039 | 0:1ed23ab1345f | 156 | } |
va009039 | 0:1ed23ab1345f | 157 | |
va009039 | 0:1ed23ab1345f | 158 | static void rfcomm_emit_channel_open_failed_outgoing_memory(void * connection, bd_addr_t *addr, uint8_t server_channel){ |
va009039 | 0:1ed23ab1345f | 159 | uint8_t event[16]; |
va009039 | 0:1ed23ab1345f | 160 | uint8_t pos = 0; |
va009039 | 0:1ed23ab1345f | 161 | event[pos++] = RFCOMM_EVENT_OPEN_CHANNEL_COMPLETE; |
va009039 | 0:1ed23ab1345f | 162 | event[pos++] = sizeof(event) - 2; |
va009039 | 0:1ed23ab1345f | 163 | event[pos++] = BTSTACK_MEMORY_ALLOC_FAILED; |
va009039 | 0:1ed23ab1345f | 164 | bt_flip_addr(&event[pos], *addr); pos += 6; |
va009039 | 0:1ed23ab1345f | 165 | bt_store_16(event, pos, 0); pos += 2; |
va009039 | 0:1ed23ab1345f | 166 | event[pos++] = server_channel; |
va009039 | 0:1ed23ab1345f | 167 | bt_store_16(event, pos, 0); pos += 2; // channel ID |
va009039 | 0:1ed23ab1345f | 168 | bt_store_16(event, pos, 0); pos += 2; // max frame size |
va009039 | 0:1ed23ab1345f | 169 | hci_dump_packet(HCI_EVENT_PACKET, 0, event, sizeof(event)); |
va009039 | 0:1ed23ab1345f | 170 | (*app_packet_handler)(connection, HCI_EVENT_PACKET, 0, (uint8_t *) event, pos); |
va009039 | 0:1ed23ab1345f | 171 | } |
va009039 | 0:1ed23ab1345f | 172 | |
va009039 | 0:1ed23ab1345f | 173 | // data: event(8), len(8), creidts incoming(8), new credits incoming(8), credits outgoing(8) |
va009039 | 0:1ed23ab1345f | 174 | static inline void rfcomm_emit_credit_status(rfcomm_channel_t * channel) { |
va009039 | 0:1ed23ab1345f | 175 | #ifdef RFCOMM_LOG_CREDITS |
va009039 | 0:1ed23ab1345f | 176 | uint8_t event[5]; |
va009039 | 0:1ed23ab1345f | 177 | event[0] = 0x88; |
va009039 | 0:1ed23ab1345f | 178 | event[1] = sizeof(event) - 2; |
va009039 | 0:1ed23ab1345f | 179 | event[2] = channel->credits_incoming; |
va009039 | 0:1ed23ab1345f | 180 | event[3] = channel->new_credits_incoming; |
va009039 | 0:1ed23ab1345f | 181 | event[4] = channel->credits_outgoing; |
va009039 | 0:1ed23ab1345f | 182 | hci_dump_packet(HCI_EVENT_PACKET, 0, event, sizeof(event)); |
va009039 | 0:1ed23ab1345f | 183 | #endif |
va009039 | 0:1ed23ab1345f | 184 | } |
va009039 | 0:1ed23ab1345f | 185 | |
va009039 | 0:1ed23ab1345f | 186 | // data: event(8), len(8), rfcomm_cid(16) |
va009039 | 0:1ed23ab1345f | 187 | static void rfcomm_emit_channel_closed(rfcomm_channel_t * channel) { |
va009039 | 0:1ed23ab1345f | 188 | uint8_t event[4]; |
va009039 | 0:1ed23ab1345f | 189 | event[0] = RFCOMM_EVENT_CHANNEL_CLOSED; |
va009039 | 0:1ed23ab1345f | 190 | event[1] = sizeof(event) - 2; |
va009039 | 0:1ed23ab1345f | 191 | bt_store_16(event, 2, channel->rfcomm_cid); |
va009039 | 0:1ed23ab1345f | 192 | hci_dump_packet(HCI_EVENT_PACKET, 0, event, sizeof(event)); |
va009039 | 0:1ed23ab1345f | 193 | (*app_packet_handler)(channel->connection, HCI_EVENT_PACKET, 0, (uint8_t *) event, sizeof(event)); |
va009039 | 0:1ed23ab1345f | 194 | } |
va009039 | 0:1ed23ab1345f | 195 | |
va009039 | 0:1ed23ab1345f | 196 | static void rfcomm_emit_credits(rfcomm_channel_t * channel, uint8_t credits) { |
va009039 | 0:1ed23ab1345f | 197 | uint8_t event[5]; |
va009039 | 0:1ed23ab1345f | 198 | event[0] = RFCOMM_EVENT_CREDITS; |
va009039 | 0:1ed23ab1345f | 199 | event[1] = sizeof(event) - 2; |
va009039 | 0:1ed23ab1345f | 200 | bt_store_16(event, 2, channel->rfcomm_cid); |
va009039 | 0:1ed23ab1345f | 201 | event[4] = credits; |
va009039 | 0:1ed23ab1345f | 202 | hci_dump_packet(HCI_EVENT_PACKET, 0, event, sizeof(event)); |
va009039 | 0:1ed23ab1345f | 203 | (*app_packet_handler)(channel->connection, HCI_EVENT_PACKET, 0, (uint8_t *) event, sizeof(event)); |
va009039 | 0:1ed23ab1345f | 204 | } |
va009039 | 0:1ed23ab1345f | 205 | |
va009039 | 0:1ed23ab1345f | 206 | static void rfcomm_emit_service_registered(void *connection, uint8_t status, uint8_t channel){ |
va009039 | 0:1ed23ab1345f | 207 | uint8_t event[4]; |
va009039 | 0:1ed23ab1345f | 208 | event[0] = RFCOMM_EVENT_SERVICE_REGISTERED; |
va009039 | 0:1ed23ab1345f | 209 | event[1] = sizeof(event) - 2; |
va009039 | 0:1ed23ab1345f | 210 | event[2] = status; |
va009039 | 0:1ed23ab1345f | 211 | event[3] = channel; |
va009039 | 0:1ed23ab1345f | 212 | hci_dump_packet( HCI_EVENT_PACKET, 0, event, sizeof(event)); |
va009039 | 0:1ed23ab1345f | 213 | (*app_packet_handler)(connection, HCI_EVENT_PACKET, 0, (uint8_t *) event, sizeof(event)); |
va009039 | 0:1ed23ab1345f | 214 | } |
va009039 | 0:1ed23ab1345f | 215 | |
va009039 | 0:1ed23ab1345f | 216 | // MARK: RFCOMM MULTIPLEXER HELPER |
va009039 | 0:1ed23ab1345f | 217 | |
va009039 | 0:1ed23ab1345f | 218 | static uint16_t rfcomm_max_frame_size_for_l2cap_mtu(uint16_t l2cap_mtu){ |
va009039 | 0:1ed23ab1345f | 219 | |
va009039 | 0:1ed23ab1345f | 220 | // Assume RFCOMM header with credits and single byte length field |
va009039 | 0:1ed23ab1345f | 221 | uint16_t max_frame_size = l2cap_mtu - 5; |
va009039 | 0:1ed23ab1345f | 222 | |
va009039 | 0:1ed23ab1345f | 223 | // single byte can denote len up to 127 |
va009039 | 0:1ed23ab1345f | 224 | if (max_frame_size > 127) { |
va009039 | 0:1ed23ab1345f | 225 | max_frame_size--; |
va009039 | 0:1ed23ab1345f | 226 | } |
va009039 | 0:1ed23ab1345f | 227 | |
va009039 | 0:1ed23ab1345f | 228 | log_info("rfcomm_max_frame_size_for_l2cap_mtu: %u -> %u\n", l2cap_mtu, max_frame_size); |
va009039 | 0:1ed23ab1345f | 229 | return max_frame_size; |
va009039 | 0:1ed23ab1345f | 230 | } |
va009039 | 0:1ed23ab1345f | 231 | |
va009039 | 0:1ed23ab1345f | 232 | static void rfcomm_multiplexer_initialize(rfcomm_multiplexer_t *multiplexer){ |
va009039 | 0:1ed23ab1345f | 233 | |
va009039 | 0:1ed23ab1345f | 234 | memset(multiplexer, 0, sizeof(rfcomm_multiplexer_t)); |
va009039 | 0:1ed23ab1345f | 235 | |
va009039 | 0:1ed23ab1345f | 236 | multiplexer->state = RFCOMM_MULTIPLEXER_CLOSED; |
va009039 | 0:1ed23ab1345f | 237 | multiplexer->l2cap_credits = 0; |
va009039 | 0:1ed23ab1345f | 238 | multiplexer->send_dm_for_dlci = 0; |
va009039 | 0:1ed23ab1345f | 239 | multiplexer->max_frame_size = rfcomm_max_frame_size_for_l2cap_mtu(l2cap_max_mtu()); |
va009039 | 0:1ed23ab1345f | 240 | } |
va009039 | 0:1ed23ab1345f | 241 | |
va009039 | 0:1ed23ab1345f | 242 | static rfcomm_multiplexer_t * rfcomm_multiplexer_create_for_addr(bd_addr_t *addr){ |
va009039 | 0:1ed23ab1345f | 243 | |
va009039 | 0:1ed23ab1345f | 244 | // alloc structure |
va009039 | 0:1ed23ab1345f | 245 | rfcomm_multiplexer_t * multiplexer = (rfcomm_multiplexer_t*)btstack_memory_rfcomm_multiplexer_get(); |
va009039 | 0:1ed23ab1345f | 246 | if (!multiplexer) return NULL; |
va009039 | 0:1ed23ab1345f | 247 | |
va009039 | 0:1ed23ab1345f | 248 | // fill in |
va009039 | 0:1ed23ab1345f | 249 | rfcomm_multiplexer_initialize(multiplexer); |
va009039 | 0:1ed23ab1345f | 250 | BD_ADDR_COPY(&multiplexer->remote_addr, addr); |
va009039 | 0:1ed23ab1345f | 251 | |
va009039 | 0:1ed23ab1345f | 252 | // add to services list |
va009039 | 0:1ed23ab1345f | 253 | linked_list_add(&rfcomm_multiplexers, (linked_item_t *) multiplexer); |
va009039 | 0:1ed23ab1345f | 254 | |
va009039 | 0:1ed23ab1345f | 255 | return multiplexer; |
va009039 | 0:1ed23ab1345f | 256 | } |
va009039 | 0:1ed23ab1345f | 257 | |
va009039 | 0:1ed23ab1345f | 258 | static rfcomm_multiplexer_t * rfcomm_multiplexer_for_addr(bd_addr_t *addr){ |
va009039 | 0:1ed23ab1345f | 259 | linked_item_t *it; |
va009039 | 0:1ed23ab1345f | 260 | for (it = (linked_item_t *) rfcomm_multiplexers; it ; it = it->next){ |
va009039 | 0:1ed23ab1345f | 261 | rfcomm_multiplexer_t * multiplexer = ((rfcomm_multiplexer_t *) it); |
va009039 | 0:1ed23ab1345f | 262 | if (BD_ADDR_CMP(addr, multiplexer->remote_addr) == 0) { |
va009039 | 0:1ed23ab1345f | 263 | return multiplexer; |
va009039 | 0:1ed23ab1345f | 264 | }; |
va009039 | 0:1ed23ab1345f | 265 | } |
va009039 | 0:1ed23ab1345f | 266 | return NULL; |
va009039 | 0:1ed23ab1345f | 267 | } |
va009039 | 0:1ed23ab1345f | 268 | |
va009039 | 0:1ed23ab1345f | 269 | static rfcomm_multiplexer_t * rfcomm_multiplexer_for_l2cap_cid(uint16_t l2cap_cid) { |
va009039 | 0:1ed23ab1345f | 270 | linked_item_t *it; |
va009039 | 0:1ed23ab1345f | 271 | for (it = (linked_item_t *) rfcomm_multiplexers; it ; it = it->next){ |
va009039 | 0:1ed23ab1345f | 272 | rfcomm_multiplexer_t * multiplexer = ((rfcomm_multiplexer_t *) it); |
va009039 | 0:1ed23ab1345f | 273 | if (multiplexer->l2cap_cid == l2cap_cid) { |
va009039 | 0:1ed23ab1345f | 274 | return multiplexer; |
va009039 | 0:1ed23ab1345f | 275 | }; |
va009039 | 0:1ed23ab1345f | 276 | } |
va009039 | 0:1ed23ab1345f | 277 | return NULL; |
va009039 | 0:1ed23ab1345f | 278 | } |
va009039 | 0:1ed23ab1345f | 279 | |
va009039 | 0:1ed23ab1345f | 280 | static int rfcomm_multiplexer_has_channels(rfcomm_multiplexer_t * multiplexer){ |
va009039 | 0:1ed23ab1345f | 281 | linked_item_t *it; |
va009039 | 0:1ed23ab1345f | 282 | for (it = (linked_item_t *) rfcomm_channels; it ; it = it->next){ |
va009039 | 0:1ed23ab1345f | 283 | rfcomm_channel_t * channel = ((rfcomm_channel_t *) it); |
va009039 | 0:1ed23ab1345f | 284 | if (channel->multiplexer == multiplexer) { |
va009039 | 0:1ed23ab1345f | 285 | return 1; |
va009039 | 0:1ed23ab1345f | 286 | } |
va009039 | 0:1ed23ab1345f | 287 | } |
va009039 | 0:1ed23ab1345f | 288 | return 0; |
va009039 | 0:1ed23ab1345f | 289 | } |
va009039 | 0:1ed23ab1345f | 290 | |
va009039 | 0:1ed23ab1345f | 291 | // MARK: RFCOMM CHANNEL HELPER |
va009039 | 0:1ed23ab1345f | 292 | |
va009039 | 0:1ed23ab1345f | 293 | static void rfcomm_dump_channels(void){ |
va009039 | 0:1ed23ab1345f | 294 | #ifndef EMBEDDED |
va009039 | 0:1ed23ab1345f | 295 | linked_item_t * it; |
va009039 | 0:1ed23ab1345f | 296 | int channels = 0; |
va009039 | 0:1ed23ab1345f | 297 | for (it = (linked_item_t *) rfcomm_channels; it ; it = it->next){ |
va009039 | 0:1ed23ab1345f | 298 | rfcomm_channel_t * channel = (rfcomm_channel_t *) it; |
va009039 | 0:1ed23ab1345f | 299 | log_info("Channel #%u: addr %p, state %u\n", channels, channel, channel->state); |
va009039 | 0:1ed23ab1345f | 300 | channels++; |
va009039 | 0:1ed23ab1345f | 301 | } |
va009039 | 0:1ed23ab1345f | 302 | #endif |
va009039 | 0:1ed23ab1345f | 303 | } |
va009039 | 0:1ed23ab1345f | 304 | |
va009039 | 0:1ed23ab1345f | 305 | static void rfcomm_channel_initialize(rfcomm_channel_t *channel, rfcomm_multiplexer_t *multiplexer, |
va009039 | 0:1ed23ab1345f | 306 | rfcomm_service_t *service, uint8_t server_channel){ |
va009039 | 0:1ed23ab1345f | 307 | |
va009039 | 0:1ed23ab1345f | 308 | // don't use 0 as channel id |
va009039 | 0:1ed23ab1345f | 309 | if (rfcomm_client_cid_generator == 0) ++rfcomm_client_cid_generator; |
va009039 | 0:1ed23ab1345f | 310 | |
va009039 | 0:1ed23ab1345f | 311 | // setup channel |
va009039 | 0:1ed23ab1345f | 312 | memset(channel, 0, sizeof(rfcomm_channel_t)); |
va009039 | 0:1ed23ab1345f | 313 | |
va009039 | 0:1ed23ab1345f | 314 | channel->state = RFCOMM_CHANNEL_CLOSED; |
va009039 | 0:1ed23ab1345f | 315 | channel->state_var = RFCOMM_CHANNEL_STATE_VAR_NONE; |
va009039 | 0:1ed23ab1345f | 316 | |
va009039 | 0:1ed23ab1345f | 317 | channel->multiplexer = multiplexer; |
va009039 | 0:1ed23ab1345f | 318 | channel->service = service; |
va009039 | 0:1ed23ab1345f | 319 | channel->rfcomm_cid = rfcomm_client_cid_generator++; |
va009039 | 0:1ed23ab1345f | 320 | channel->max_frame_size = multiplexer->max_frame_size; |
va009039 | 0:1ed23ab1345f | 321 | |
va009039 | 0:1ed23ab1345f | 322 | channel->credits_incoming = 0; |
va009039 | 0:1ed23ab1345f | 323 | channel->credits_outgoing = 0; |
va009039 | 0:1ed23ab1345f | 324 | channel->packets_granted = 0; |
va009039 | 0:1ed23ab1345f | 325 | |
va009039 | 0:1ed23ab1345f | 326 | // incoming flow control not active |
va009039 | 0:1ed23ab1345f | 327 | channel->new_credits_incoming = 0x30; |
va009039 | 0:1ed23ab1345f | 328 | channel->incoming_flow_control = 0; |
va009039 | 0:1ed23ab1345f | 329 | |
va009039 | 0:1ed23ab1345f | 330 | if (service) { |
va009039 | 0:1ed23ab1345f | 331 | // incoming connection |
va009039 | 0:1ed23ab1345f | 332 | channel->outgoing = 0; |
va009039 | 0:1ed23ab1345f | 333 | channel->dlci = (server_channel << 1) | multiplexer->outgoing; |
va009039 | 0:1ed23ab1345f | 334 | if (channel->max_frame_size > service->max_frame_size) { |
va009039 | 0:1ed23ab1345f | 335 | channel->max_frame_size = service->max_frame_size; |
va009039 | 0:1ed23ab1345f | 336 | } |
va009039 | 0:1ed23ab1345f | 337 | channel->incoming_flow_control = service->incoming_flow_control; |
va009039 | 0:1ed23ab1345f | 338 | channel->new_credits_incoming = service->incoming_initial_credits; |
va009039 | 0:1ed23ab1345f | 339 | } else { |
va009039 | 0:1ed23ab1345f | 340 | // outgoing connection |
va009039 | 0:1ed23ab1345f | 341 | channel->outgoing = 1; |
va009039 | 0:1ed23ab1345f | 342 | channel->dlci = (server_channel << 1) | (multiplexer->outgoing ^ 1); |
va009039 | 0:1ed23ab1345f | 343 | } |
va009039 | 0:1ed23ab1345f | 344 | } |
va009039 | 0:1ed23ab1345f | 345 | |
va009039 | 0:1ed23ab1345f | 346 | // service == NULL -> outgoing channel |
va009039 | 0:1ed23ab1345f | 347 | static rfcomm_channel_t * rfcomm_channel_create(rfcomm_multiplexer_t * multiplexer, |
va009039 | 0:1ed23ab1345f | 348 | rfcomm_service_t * service, uint8_t server_channel){ |
va009039 | 0:1ed23ab1345f | 349 | |
va009039 | 0:1ed23ab1345f | 350 | log_info("rfcomm_channel_create for service %p, channel %u --- begin\n", service, server_channel); |
va009039 | 0:1ed23ab1345f | 351 | rfcomm_dump_channels(); |
va009039 | 0:1ed23ab1345f | 352 | |
va009039 | 0:1ed23ab1345f | 353 | // alloc structure |
va009039 | 0:1ed23ab1345f | 354 | rfcomm_channel_t * channel = (rfcomm_channel_t*)btstack_memory_rfcomm_channel_get(); |
va009039 | 0:1ed23ab1345f | 355 | if (!channel) return NULL; |
va009039 | 0:1ed23ab1345f | 356 | |
va009039 | 0:1ed23ab1345f | 357 | // fill in |
va009039 | 0:1ed23ab1345f | 358 | rfcomm_channel_initialize(channel, multiplexer, service, server_channel); |
va009039 | 0:1ed23ab1345f | 359 | |
va009039 | 0:1ed23ab1345f | 360 | // add to services list |
va009039 | 0:1ed23ab1345f | 361 | linked_list_add(&rfcomm_channels, (linked_item_t *) channel); |
va009039 | 0:1ed23ab1345f | 362 | |
va009039 | 0:1ed23ab1345f | 363 | return channel; |
va009039 | 0:1ed23ab1345f | 364 | } |
va009039 | 0:1ed23ab1345f | 365 | |
va009039 | 0:1ed23ab1345f | 366 | static rfcomm_channel_t * rfcomm_channel_for_rfcomm_cid(uint16_t rfcomm_cid){ |
va009039 | 0:1ed23ab1345f | 367 | linked_item_t *it; |
va009039 | 0:1ed23ab1345f | 368 | for (it = (linked_item_t *) rfcomm_channels; it ; it = it->next){ |
va009039 | 0:1ed23ab1345f | 369 | rfcomm_channel_t * channel = ((rfcomm_channel_t *) it); |
va009039 | 0:1ed23ab1345f | 370 | if (channel->rfcomm_cid == rfcomm_cid) { |
va009039 | 0:1ed23ab1345f | 371 | return channel; |
va009039 | 0:1ed23ab1345f | 372 | }; |
va009039 | 0:1ed23ab1345f | 373 | } |
va009039 | 0:1ed23ab1345f | 374 | return NULL; |
va009039 | 0:1ed23ab1345f | 375 | } |
va009039 | 0:1ed23ab1345f | 376 | |
va009039 | 0:1ed23ab1345f | 377 | static rfcomm_channel_t * rfcomm_channel_for_multiplexer_and_dlci(rfcomm_multiplexer_t * multiplexer, uint8_t dlci){ |
va009039 | 0:1ed23ab1345f | 378 | linked_item_t *it; |
va009039 | 0:1ed23ab1345f | 379 | for (it = (linked_item_t *) rfcomm_channels; it ; it = it->next){ |
va009039 | 0:1ed23ab1345f | 380 | rfcomm_channel_t * channel = ((rfcomm_channel_t *) it); |
va009039 | 0:1ed23ab1345f | 381 | if (channel->dlci == dlci && channel->multiplexer == multiplexer) { |
va009039 | 0:1ed23ab1345f | 382 | return channel; |
va009039 | 0:1ed23ab1345f | 383 | }; |
va009039 | 0:1ed23ab1345f | 384 | } |
va009039 | 0:1ed23ab1345f | 385 | return NULL; |
va009039 | 0:1ed23ab1345f | 386 | } |
va009039 | 0:1ed23ab1345f | 387 | |
va009039 | 0:1ed23ab1345f | 388 | static rfcomm_service_t * rfcomm_service_for_channel(uint8_t server_channel){ |
va009039 | 0:1ed23ab1345f | 389 | linked_item_t *it; |
va009039 | 0:1ed23ab1345f | 390 | for (it = (linked_item_t *) rfcomm_services; it ; it = it->next){ |
va009039 | 0:1ed23ab1345f | 391 | rfcomm_service_t * service = ((rfcomm_service_t *) it); |
va009039 | 0:1ed23ab1345f | 392 | if ( service->server_channel == server_channel){ |
va009039 | 0:1ed23ab1345f | 393 | return service; |
va009039 | 0:1ed23ab1345f | 394 | }; |
va009039 | 0:1ed23ab1345f | 395 | } |
va009039 | 0:1ed23ab1345f | 396 | return NULL; |
va009039 | 0:1ed23ab1345f | 397 | } |
va009039 | 0:1ed23ab1345f | 398 | |
va009039 | 0:1ed23ab1345f | 399 | // MARK: RFCOMM SEND |
va009039 | 0:1ed23ab1345f | 400 | |
va009039 | 0:1ed23ab1345f | 401 | /** |
va009039 | 0:1ed23ab1345f | 402 | * @param credits - only used for RFCOMM flow control in UIH wiht P/F = 1 |
va009039 | 0:1ed23ab1345f | 403 | */ |
va009039 | 0:1ed23ab1345f | 404 | 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){ |
va009039 | 0:1ed23ab1345f | 405 | |
va009039 | 0:1ed23ab1345f | 406 | if (!l2cap_can_send_packet_now(multiplexer->l2cap_cid)) return BTSTACK_ACL_BUFFERS_FULL; |
va009039 | 0:1ed23ab1345f | 407 | |
va009039 | 0:1ed23ab1345f | 408 | uint8_t * rfcomm_out_buffer = l2cap_get_outgoing_buffer(); |
va009039 | 0:1ed23ab1345f | 409 | |
va009039 | 0:1ed23ab1345f | 410 | uint16_t pos = 0; |
va009039 | 0:1ed23ab1345f | 411 | uint8_t crc_fields = 3; |
va009039 | 0:1ed23ab1345f | 412 | |
va009039 | 0:1ed23ab1345f | 413 | rfcomm_out_buffer[pos++] = address; |
va009039 | 0:1ed23ab1345f | 414 | rfcomm_out_buffer[pos++] = control; |
va009039 | 0:1ed23ab1345f | 415 | |
va009039 | 0:1ed23ab1345f | 416 | // length field can be 1 or 2 octets |
va009039 | 0:1ed23ab1345f | 417 | if (len < 128){ |
va009039 | 0:1ed23ab1345f | 418 | rfcomm_out_buffer[pos++] = (len << 1)| 1; // bits 0-6 |
va009039 | 0:1ed23ab1345f | 419 | } else { |
va009039 | 0:1ed23ab1345f | 420 | rfcomm_out_buffer[pos++] = (len & 0x7f) << 1; // bits 0-6 |
va009039 | 0:1ed23ab1345f | 421 | rfcomm_out_buffer[pos++] = len >> 7; // bits 7-14 |
va009039 | 0:1ed23ab1345f | 422 | crc_fields++; |
va009039 | 0:1ed23ab1345f | 423 | } |
va009039 | 0:1ed23ab1345f | 424 | |
va009039 | 0:1ed23ab1345f | 425 | // add credits for UIH frames when PF bit is set |
va009039 | 0:1ed23ab1345f | 426 | if (control == BT_RFCOMM_UIH_PF){ |
va009039 | 0:1ed23ab1345f | 427 | rfcomm_out_buffer[pos++] = credits; |
va009039 | 0:1ed23ab1345f | 428 | } |
va009039 | 0:1ed23ab1345f | 429 | |
va009039 | 0:1ed23ab1345f | 430 | // copy actual data |
va009039 | 0:1ed23ab1345f | 431 | if (len) { |
va009039 | 0:1ed23ab1345f | 432 | memcpy(&rfcomm_out_buffer[pos], data, len); |
va009039 | 0:1ed23ab1345f | 433 | pos += len; |
va009039 | 0:1ed23ab1345f | 434 | } |
va009039 | 0:1ed23ab1345f | 435 | |
va009039 | 0:1ed23ab1345f | 436 | // UIH frames only calc FCS over address + control (5.1.1) |
va009039 | 0:1ed23ab1345f | 437 | if ((control & 0xef) == BT_RFCOMM_UIH){ |
va009039 | 0:1ed23ab1345f | 438 | crc_fields = 2; |
va009039 | 0:1ed23ab1345f | 439 | } |
va009039 | 0:1ed23ab1345f | 440 | rfcomm_out_buffer[pos++] = crc8_calc(rfcomm_out_buffer, crc_fields); // calc fcs |
va009039 | 0:1ed23ab1345f | 441 | |
va009039 | 0:1ed23ab1345f | 442 | int credits_taken = 0; |
va009039 | 0:1ed23ab1345f | 443 | if (multiplexer->l2cap_credits){ |
va009039 | 0:1ed23ab1345f | 444 | credits_taken++; |
va009039 | 0:1ed23ab1345f | 445 | multiplexer->l2cap_credits--; |
va009039 | 0:1ed23ab1345f | 446 | } else { |
va009039 | 0:1ed23ab1345f | 447 | log_info( "rfcomm_send_packet addr %02x, ctrl %02x size %u without l2cap credits\n", address, control, pos); |
va009039 | 0:1ed23ab1345f | 448 | } |
va009039 | 0:1ed23ab1345f | 449 | |
va009039 | 0:1ed23ab1345f | 450 | int err = l2cap_send_prepared(multiplexer->l2cap_cid, pos); |
va009039 | 0:1ed23ab1345f | 451 | |
va009039 | 0:1ed23ab1345f | 452 | if (err) { |
va009039 | 0:1ed23ab1345f | 453 | // undo credit counting |
va009039 | 0:1ed23ab1345f | 454 | multiplexer->l2cap_credits += credits_taken; |
va009039 | 0:1ed23ab1345f | 455 | } |
va009039 | 0:1ed23ab1345f | 456 | return err; |
va009039 | 0:1ed23ab1345f | 457 | } |
va009039 | 0:1ed23ab1345f | 458 | |
va009039 | 0:1ed23ab1345f | 459 | // C/R Flag in Address |
va009039 | 0:1ed23ab1345f | 460 | // - terms: initiator = station that creates multiplexer with SABM |
va009039 | 0:1ed23ab1345f | 461 | // - terms: responder = station that responds to multiplexer setup with UA |
va009039 | 0:1ed23ab1345f | 462 | // "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" |
va009039 | 0:1ed23ab1345f | 463 | // - command initiator = 1 /response responder = 1 |
va009039 | 0:1ed23ab1345f | 464 | // - command responder = 0 /response initiator = 0 |
va009039 | 0:1ed23ab1345f | 465 | // "For UIH frames, the C/R bit is always set according to section 5.4.3.1 in GSM 07.10. |
va009039 | 0:1ed23ab1345f | 466 | // This applies independently of what is contained wthin the UIH frames, either data or control messages." |
va009039 | 0:1ed23ab1345f | 467 | // - c/r = 1 for frames by initiating station, 0 = for frames by responding station |
va009039 | 0:1ed23ab1345f | 468 | |
va009039 | 0:1ed23ab1345f | 469 | // C/R Flag in Message |
va009039 | 0:1ed23ab1345f | 470 | // "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." |
va009039 | 0:1ed23ab1345f | 471 | // - If the C/R bit is set to 1 the message is a command |
va009039 | 0:1ed23ab1345f | 472 | // - if it is set to 0 the message is a response. |
va009039 | 0:1ed23ab1345f | 473 | |
va009039 | 0:1ed23ab1345f | 474 | // temp/old messge construction |
va009039 | 0:1ed23ab1345f | 475 | |
va009039 | 0:1ed23ab1345f | 476 | // new object oriented version |
va009039 | 0:1ed23ab1345f | 477 | static int rfcomm_send_sabm(rfcomm_multiplexer_t *multiplexer, uint8_t dlci){ |
va009039 | 0:1ed23ab1345f | 478 | uint8_t address = (1 << 0) | (multiplexer->outgoing << 1) | (dlci << 2); // command |
va009039 | 0:1ed23ab1345f | 479 | return rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_SABM, 0, NULL, 0); |
va009039 | 0:1ed23ab1345f | 480 | } |
va009039 | 0:1ed23ab1345f | 481 | |
va009039 | 0:1ed23ab1345f | 482 | static int rfcomm_send_disc(rfcomm_multiplexer_t *multiplexer, uint8_t dlci){ |
va009039 | 0:1ed23ab1345f | 483 | uint8_t address = (1 << 0) | (multiplexer->outgoing << 1) | (dlci << 2); // command |
va009039 | 0:1ed23ab1345f | 484 | return rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_DISC, 0, NULL, 0); |
va009039 | 0:1ed23ab1345f | 485 | } |
va009039 | 0:1ed23ab1345f | 486 | |
va009039 | 0:1ed23ab1345f | 487 | static int rfcomm_send_ua(rfcomm_multiplexer_t *multiplexer, uint8_t dlci){ |
va009039 | 0:1ed23ab1345f | 488 | uint8_t address = (1 << 0) | ((multiplexer->outgoing ^ 1) << 1) | (dlci << 2); // response |
va009039 | 0:1ed23ab1345f | 489 | return rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_UA, 0, NULL, 0); |
va009039 | 0:1ed23ab1345f | 490 | } |
va009039 | 0:1ed23ab1345f | 491 | |
va009039 | 0:1ed23ab1345f | 492 | static int rfcomm_send_dm_pf(rfcomm_multiplexer_t *multiplexer, uint8_t dlci){ |
va009039 | 0:1ed23ab1345f | 493 | uint8_t address = (1 << 0) | ((multiplexer->outgoing ^ 1) << 1) | (dlci << 2); // response |
va009039 | 0:1ed23ab1345f | 494 | return rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_DM_PF, 0, NULL, 0); |
va009039 | 0:1ed23ab1345f | 495 | } |
va009039 | 0:1ed23ab1345f | 496 | |
va009039 | 0:1ed23ab1345f | 497 | static int rfcomm_send_uih_msc_cmd(rfcomm_multiplexer_t *multiplexer, uint8_t dlci, uint8_t signals) { |
va009039 | 0:1ed23ab1345f | 498 | uint8_t address = (1 << 0) | (multiplexer->outgoing << 1); |
va009039 | 0:1ed23ab1345f | 499 | uint8_t payload[4]; |
va009039 | 0:1ed23ab1345f | 500 | uint8_t pos = 0; |
va009039 | 0:1ed23ab1345f | 501 | payload[pos++] = BT_RFCOMM_MSC_CMD; |
va009039 | 0:1ed23ab1345f | 502 | payload[pos++] = 2 << 1 | 1; // len |
va009039 | 0:1ed23ab1345f | 503 | payload[pos++] = (1 << 0) | (1 << 1) | (dlci << 2); // CMD => C/R = 1 |
va009039 | 0:1ed23ab1345f | 504 | payload[pos++] = signals; |
va009039 | 0:1ed23ab1345f | 505 | return rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_UIH, 0, (uint8_t *) payload, pos); |
va009039 | 0:1ed23ab1345f | 506 | } |
va009039 | 0:1ed23ab1345f | 507 | |
va009039 | 0:1ed23ab1345f | 508 | static int rfcomm_send_uih_msc_rsp(rfcomm_multiplexer_t *multiplexer, uint8_t dlci, uint8_t signals) { |
va009039 | 0:1ed23ab1345f | 509 | uint8_t address = (1 << 0) | (multiplexer->outgoing<< 1); |
va009039 | 0:1ed23ab1345f | 510 | uint8_t payload[4]; |
va009039 | 0:1ed23ab1345f | 511 | uint8_t pos = 0; |
va009039 | 0:1ed23ab1345f | 512 | payload[pos++] = BT_RFCOMM_MSC_RSP; |
va009039 | 0:1ed23ab1345f | 513 | payload[pos++] = 2 << 1 | 1; // len |
va009039 | 0:1ed23ab1345f | 514 | payload[pos++] = (1 << 0) | (1 << 1) | (dlci << 2); // CMD => C/R = 1 |
va009039 | 0:1ed23ab1345f | 515 | payload[pos++] = signals; |
va009039 | 0:1ed23ab1345f | 516 | return rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_UIH, 0, (uint8_t *) payload, pos); |
va009039 | 0:1ed23ab1345f | 517 | } |
va009039 | 0:1ed23ab1345f | 518 | |
va009039 | 0:1ed23ab1345f | 519 | static int rfcomm_send_uih_pn_command(rfcomm_multiplexer_t *multiplexer, uint8_t dlci, uint16_t max_frame_size){ |
va009039 | 0:1ed23ab1345f | 520 | uint8_t payload[10]; |
va009039 | 0:1ed23ab1345f | 521 | uint8_t address = (1 << 0) | (multiplexer->outgoing << 1); |
va009039 | 0:1ed23ab1345f | 522 | uint8_t pos = 0; |
va009039 | 0:1ed23ab1345f | 523 | payload[pos++] = BT_RFCOMM_PN_CMD; |
va009039 | 0:1ed23ab1345f | 524 | payload[pos++] = 8 << 1 | 1; // len |
va009039 | 0:1ed23ab1345f | 525 | payload[pos++] = dlci; |
va009039 | 0:1ed23ab1345f | 526 | payload[pos++] = 0xf0; // pre-defined for Bluetooth, see 5.5.3 of TS 07.10 Adaption for RFCOMM |
va009039 | 0:1ed23ab1345f | 527 | payload[pos++] = 0; // priority |
va009039 | 0:1ed23ab1345f | 528 | payload[pos++] = 0; // max 60 seconds ack |
va009039 | 0:1ed23ab1345f | 529 | payload[pos++] = max_frame_size & 0xff; // max framesize low |
va009039 | 0:1ed23ab1345f | 530 | payload[pos++] = max_frame_size >> 8; // max framesize high |
va009039 | 0:1ed23ab1345f | 531 | payload[pos++] = 0x00; // number of retransmissions |
va009039 | 0:1ed23ab1345f | 532 | payload[pos++] = 0x00; // (unused error recovery window) initial number of credits |
va009039 | 0:1ed23ab1345f | 533 | return rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_UIH, 0, (uint8_t *) payload, pos); |
va009039 | 0:1ed23ab1345f | 534 | } |
va009039 | 0:1ed23ab1345f | 535 | |
va009039 | 0:1ed23ab1345f | 536 | // "The response may not change the DLCI, the priority, the convergence layer, or the timer value." RFCOMM-tutorial.pdf |
va009039 | 0:1ed23ab1345f | 537 | static int rfcomm_send_uih_pn_response(rfcomm_multiplexer_t *multiplexer, uint8_t dlci, |
va009039 | 0:1ed23ab1345f | 538 | uint8_t priority, uint16_t max_frame_size){ |
va009039 | 0:1ed23ab1345f | 539 | uint8_t payload[10]; |
va009039 | 0:1ed23ab1345f | 540 | uint8_t address = (1 << 0) | (multiplexer->outgoing << 1); |
va009039 | 0:1ed23ab1345f | 541 | uint8_t pos = 0; |
va009039 | 0:1ed23ab1345f | 542 | payload[pos++] = BT_RFCOMM_PN_RSP; |
va009039 | 0:1ed23ab1345f | 543 | payload[pos++] = 8 << 1 | 1; // len |
va009039 | 0:1ed23ab1345f | 544 | payload[pos++] = dlci; |
va009039 | 0:1ed23ab1345f | 545 | payload[pos++] = 0xe0; // pre defined for Bluetooth, see 5.5.3 of TS 07.10 Adaption for RFCOMM |
va009039 | 0:1ed23ab1345f | 546 | payload[pos++] = priority; // priority |
va009039 | 0:1ed23ab1345f | 547 | payload[pos++] = 0; // max 60 seconds ack |
va009039 | 0:1ed23ab1345f | 548 | payload[pos++] = max_frame_size & 0xff; // max framesize low |
va009039 | 0:1ed23ab1345f | 549 | payload[pos++] = max_frame_size >> 8; // max framesize high |
va009039 | 0:1ed23ab1345f | 550 | payload[pos++] = 0x00; // number of retransmissions |
va009039 | 0:1ed23ab1345f | 551 | payload[pos++] = 0x00; // (unused error recovery window) initial number of credits |
va009039 | 0:1ed23ab1345f | 552 | return rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_UIH, 0, (uint8_t *) payload, pos); |
va009039 | 0:1ed23ab1345f | 553 | } |
va009039 | 0:1ed23ab1345f | 554 | |
va009039 | 0:1ed23ab1345f | 555 | static int rfcomm_send_uih_rpn_rsp(rfcomm_multiplexer_t *multiplexer, uint8_t dlci, rfcomm_rpn_data_t *rpn_data) { |
va009039 | 0:1ed23ab1345f | 556 | uint8_t payload[10]; |
va009039 | 0:1ed23ab1345f | 557 | uint8_t address = (1 << 0) | (multiplexer->outgoing << 1); |
va009039 | 0:1ed23ab1345f | 558 | uint8_t pos = 0; |
va009039 | 0:1ed23ab1345f | 559 | payload[pos++] = BT_RFCOMM_RPN_RSP; |
va009039 | 0:1ed23ab1345f | 560 | payload[pos++] = 8 << 1 | 1; // len |
va009039 | 0:1ed23ab1345f | 561 | payload[pos++] = (1 << 0) | (1 << 1) | (dlci << 2); // CMD => C/R = 1 |
va009039 | 0:1ed23ab1345f | 562 | payload[pos++] = rpn_data->baud_rate; |
va009039 | 0:1ed23ab1345f | 563 | payload[pos++] = rpn_data->flags; |
va009039 | 0:1ed23ab1345f | 564 | payload[pos++] = rpn_data->flow_control; |
va009039 | 0:1ed23ab1345f | 565 | payload[pos++] = rpn_data->xon; |
va009039 | 0:1ed23ab1345f | 566 | payload[pos++] = rpn_data->xoff; |
va009039 | 0:1ed23ab1345f | 567 | payload[pos++] = rpn_data->parameter_mask_0; |
va009039 | 0:1ed23ab1345f | 568 | payload[pos++] = rpn_data->parameter_mask_1; |
va009039 | 0:1ed23ab1345f | 569 | return rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_UIH, 0, (uint8_t *) payload, pos); |
va009039 | 0:1ed23ab1345f | 570 | } |
va009039 | 0:1ed23ab1345f | 571 | |
va009039 | 0:1ed23ab1345f | 572 | static int rfcomm_send_uih_data(rfcomm_multiplexer_t *multiplexer, uint8_t dlci, uint8_t *data, uint16_t len){ |
va009039 | 0:1ed23ab1345f | 573 | uint8_t address = (1 << 0) | (multiplexer->outgoing << 1) | (dlci << 2); |
va009039 | 0:1ed23ab1345f | 574 | return rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_UIH, 0, data, len); |
va009039 | 0:1ed23ab1345f | 575 | } |
va009039 | 0:1ed23ab1345f | 576 | |
va009039 | 0:1ed23ab1345f | 577 | static void rfcomm_send_uih_credits(rfcomm_multiplexer_t *multiplexer, uint8_t dlci, uint8_t credits){ |
va009039 | 0:1ed23ab1345f | 578 | uint8_t address = (1 << 0) | (multiplexer->outgoing << 1) | (dlci << 2); |
va009039 | 0:1ed23ab1345f | 579 | rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_UIH_PF, credits, NULL, 0); |
va009039 | 0:1ed23ab1345f | 580 | } |
va009039 | 0:1ed23ab1345f | 581 | |
va009039 | 0:1ed23ab1345f | 582 | // MARK: RFCOMM MULTIPLEXER |
va009039 | 0:1ed23ab1345f | 583 | |
va009039 | 0:1ed23ab1345f | 584 | static void rfcomm_multiplexer_finalize(rfcomm_multiplexer_t * multiplexer){ |
va009039 | 0:1ed23ab1345f | 585 | |
va009039 | 0:1ed23ab1345f | 586 | // remove (potential) timer |
va009039 | 0:1ed23ab1345f | 587 | if (multiplexer->timer_active) { |
va009039 | 0:1ed23ab1345f | 588 | run_loop_remove_timer(&multiplexer->timer); |
va009039 | 0:1ed23ab1345f | 589 | multiplexer->timer_active = 0; |
va009039 | 0:1ed23ab1345f | 590 | } |
va009039 | 0:1ed23ab1345f | 591 | |
va009039 | 0:1ed23ab1345f | 592 | // close and remove all channels |
va009039 | 0:1ed23ab1345f | 593 | linked_item_t *it = (linked_item_t *) &rfcomm_channels; |
va009039 | 0:1ed23ab1345f | 594 | while (it->next){ |
va009039 | 0:1ed23ab1345f | 595 | rfcomm_channel_t * channel = (rfcomm_channel_t *) it->next; |
va009039 | 0:1ed23ab1345f | 596 | if (channel->multiplexer == multiplexer) { |
va009039 | 0:1ed23ab1345f | 597 | // emit appropriate events |
va009039 | 0:1ed23ab1345f | 598 | if (channel->state == RFCOMM_CHANNEL_OPEN) { |
va009039 | 0:1ed23ab1345f | 599 | rfcomm_emit_channel_closed(channel); |
va009039 | 0:1ed23ab1345f | 600 | } else { |
va009039 | 0:1ed23ab1345f | 601 | rfcomm_emit_channel_opened(channel, RFCOMM_MULTIPLEXER_STOPPED); |
va009039 | 0:1ed23ab1345f | 602 | } |
va009039 | 0:1ed23ab1345f | 603 | // remove from list |
va009039 | 0:1ed23ab1345f | 604 | it->next = it->next->next; |
va009039 | 0:1ed23ab1345f | 605 | // free channel struct |
va009039 | 0:1ed23ab1345f | 606 | btstack_memory_rfcomm_channel_free(channel); |
va009039 | 0:1ed23ab1345f | 607 | } else { |
va009039 | 0:1ed23ab1345f | 608 | it = it->next; |
va009039 | 0:1ed23ab1345f | 609 | } |
va009039 | 0:1ed23ab1345f | 610 | } |
va009039 | 0:1ed23ab1345f | 611 | |
va009039 | 0:1ed23ab1345f | 612 | // keep reference to l2cap channel |
va009039 | 0:1ed23ab1345f | 613 | uint16_t l2cap_cid = multiplexer->l2cap_cid; |
va009039 | 0:1ed23ab1345f | 614 | |
va009039 | 0:1ed23ab1345f | 615 | // remove mutliplexer |
va009039 | 0:1ed23ab1345f | 616 | linked_list_remove( &rfcomm_multiplexers, (linked_item_t *) multiplexer); |
va009039 | 0:1ed23ab1345f | 617 | btstack_memory_rfcomm_multiplexer_free(multiplexer); |
va009039 | 0:1ed23ab1345f | 618 | |
va009039 | 0:1ed23ab1345f | 619 | // close l2cap multiplexer channel, too |
va009039 | 0:1ed23ab1345f | 620 | l2cap_disconnect_internal(l2cap_cid, 0x13); |
va009039 | 0:1ed23ab1345f | 621 | } |
va009039 | 0:1ed23ab1345f | 622 | |
va009039 | 0:1ed23ab1345f | 623 | static void rfcomm_multiplexer_timer_handler(timer_source_t *timer){ |
va009039 | 0:1ed23ab1345f | 624 | rfcomm_multiplexer_t * multiplexer = (rfcomm_multiplexer_t *) linked_item_get_user( (linked_item_t *) timer); |
va009039 | 0:1ed23ab1345f | 625 | if (!rfcomm_multiplexer_has_channels(multiplexer)){ |
va009039 | 0:1ed23ab1345f | 626 | log_info( "rfcomm_multiplexer_timer_handler timeout: shutting down multiplexer!\n"); |
va009039 | 0:1ed23ab1345f | 627 | rfcomm_multiplexer_finalize(multiplexer); |
va009039 | 0:1ed23ab1345f | 628 | } |
va009039 | 0:1ed23ab1345f | 629 | } |
va009039 | 0:1ed23ab1345f | 630 | |
va009039 | 0:1ed23ab1345f | 631 | static void rfcomm_multiplexer_prepare_idle_timer(rfcomm_multiplexer_t * multiplexer){ |
va009039 | 0:1ed23ab1345f | 632 | if (multiplexer->timer_active) { |
va009039 | 0:1ed23ab1345f | 633 | run_loop_remove_timer(&multiplexer->timer); |
va009039 | 0:1ed23ab1345f | 634 | multiplexer->timer_active = 0; |
va009039 | 0:1ed23ab1345f | 635 | } |
va009039 | 0:1ed23ab1345f | 636 | if (!rfcomm_multiplexer_has_channels(multiplexer)){ |
va009039 | 0:1ed23ab1345f | 637 | // start timer for multiplexer timeout check |
va009039 | 0:1ed23ab1345f | 638 | run_loop_set_timer(&multiplexer->timer, RFCOMM_MULIPLEXER_TIMEOUT_MS); |
va009039 | 0:1ed23ab1345f | 639 | multiplexer->timer.process = rfcomm_multiplexer_timer_handler; |
va009039 | 0:1ed23ab1345f | 640 | linked_item_set_user((linked_item_t*) &multiplexer->timer, multiplexer); |
va009039 | 0:1ed23ab1345f | 641 | run_loop_add_timer(&multiplexer->timer); |
va009039 | 0:1ed23ab1345f | 642 | multiplexer->timer_active = 1; |
va009039 | 0:1ed23ab1345f | 643 | } |
va009039 | 0:1ed23ab1345f | 644 | } |
va009039 | 0:1ed23ab1345f | 645 | |
va009039 | 0:1ed23ab1345f | 646 | static void rfcomm_multiplexer_opened(rfcomm_multiplexer_t *multiplexer){ |
va009039 | 0:1ed23ab1345f | 647 | log_info("Multiplexer up and running\n"); |
va009039 | 0:1ed23ab1345f | 648 | multiplexer->state = RFCOMM_MULTIPLEXER_OPEN; |
va009039 | 0:1ed23ab1345f | 649 | |
va009039 | 0:1ed23ab1345f | 650 | rfcomm_channel_event_t event = { CH_EVT_MULTIPLEXER_READY }; |
va009039 | 0:1ed23ab1345f | 651 | |
va009039 | 0:1ed23ab1345f | 652 | // transition of channels that wait for multiplexer |
va009039 | 0:1ed23ab1345f | 653 | linked_item_t *it; |
va009039 | 0:1ed23ab1345f | 654 | for (it = (linked_item_t *) rfcomm_channels; it ; it = it->next){ |
va009039 | 0:1ed23ab1345f | 655 | rfcomm_channel_t * channel = ((rfcomm_channel_t *) it); |
va009039 | 0:1ed23ab1345f | 656 | if (channel->multiplexer != multiplexer) continue; |
va009039 | 0:1ed23ab1345f | 657 | rfcomm_channel_state_machine(channel, &event); |
va009039 | 0:1ed23ab1345f | 658 | } |
va009039 | 0:1ed23ab1345f | 659 | |
va009039 | 0:1ed23ab1345f | 660 | rfcomm_run(); |
va009039 | 0:1ed23ab1345f | 661 | rfcomm_multiplexer_prepare_idle_timer(multiplexer); |
va009039 | 0:1ed23ab1345f | 662 | } |
va009039 | 0:1ed23ab1345f | 663 | |
va009039 | 0:1ed23ab1345f | 664 | |
va009039 | 0:1ed23ab1345f | 665 | /** |
va009039 | 0:1ed23ab1345f | 666 | * @return handled packet |
va009039 | 0:1ed23ab1345f | 667 | */ |
va009039 | 0:1ed23ab1345f | 668 | static int rfcomm_multiplexer_hci_event_handler(uint8_t *packet, uint16_t size){ |
va009039 | 0:1ed23ab1345f | 669 | bd_addr_t event_addr; |
va009039 | 0:1ed23ab1345f | 670 | uint16_t psm; |
va009039 | 0:1ed23ab1345f | 671 | uint16_t l2cap_cid; |
va009039 | 0:1ed23ab1345f | 672 | hci_con_handle_t con_handle; |
va009039 | 0:1ed23ab1345f | 673 | rfcomm_multiplexer_t *multiplexer = NULL; |
va009039 | 0:1ed23ab1345f | 674 | switch (packet[0]) { |
va009039 | 0:1ed23ab1345f | 675 | |
va009039 | 0:1ed23ab1345f | 676 | // accept incoming PSM_RFCOMM connection if no multiplexer exists yet |
va009039 | 0:1ed23ab1345f | 677 | case L2CAP_EVENT_INCOMING_CONNECTION: |
va009039 | 0:1ed23ab1345f | 678 | // data: event(8), len(8), address(48), handle (16), psm (16), source cid(16) dest cid(16) |
va009039 | 0:1ed23ab1345f | 679 | bt_flip_addr(event_addr, &packet[2]); |
va009039 | 0:1ed23ab1345f | 680 | con_handle = READ_BT_16(packet, 8); |
va009039 | 0:1ed23ab1345f | 681 | psm = READ_BT_16(packet, 10); |
va009039 | 0:1ed23ab1345f | 682 | l2cap_cid = READ_BT_16(packet, 12); |
va009039 | 0:1ed23ab1345f | 683 | |
va009039 | 0:1ed23ab1345f | 684 | if (psm != PSM_RFCOMM) break; |
va009039 | 0:1ed23ab1345f | 685 | |
va009039 | 0:1ed23ab1345f | 686 | multiplexer = rfcomm_multiplexer_for_addr(&event_addr); |
va009039 | 0:1ed23ab1345f | 687 | |
va009039 | 0:1ed23ab1345f | 688 | if (multiplexer) { |
va009039 | 0:1ed23ab1345f | 689 | log_info("INCOMING_CONNECTION (l2cap_cid 0x%02x) for PSM_RFCOMM => decline - multiplexer already exists", l2cap_cid); |
va009039 | 0:1ed23ab1345f | 690 | l2cap_decline_connection_internal(l2cap_cid, 0x04); // no resources available |
va009039 | 0:1ed23ab1345f | 691 | return 1; |
va009039 | 0:1ed23ab1345f | 692 | } |
va009039 | 0:1ed23ab1345f | 693 | |
va009039 | 0:1ed23ab1345f | 694 | // create and inititialize new multiplexer instance (incoming) |
va009039 | 0:1ed23ab1345f | 695 | multiplexer = rfcomm_multiplexer_create_for_addr(&event_addr); |
va009039 | 0:1ed23ab1345f | 696 | if (!multiplexer){ |
va009039 | 0:1ed23ab1345f | 697 | log_info("INCOMING_CONNECTION (l2cap_cid 0x%02x) for PSM_RFCOMM => decline - no memory left", l2cap_cid); |
va009039 | 0:1ed23ab1345f | 698 | l2cap_decline_connection_internal(l2cap_cid, 0x04); // no resources available |
va009039 | 0:1ed23ab1345f | 699 | return 1; |
va009039 | 0:1ed23ab1345f | 700 | } |
va009039 | 0:1ed23ab1345f | 701 | |
va009039 | 0:1ed23ab1345f | 702 | multiplexer->con_handle = con_handle; |
va009039 | 0:1ed23ab1345f | 703 | multiplexer->l2cap_cid = l2cap_cid; |
va009039 | 0:1ed23ab1345f | 704 | multiplexer->state = RFCOMM_MULTIPLEXER_W4_SABM_0; |
va009039 | 0:1ed23ab1345f | 705 | |
va009039 | 0:1ed23ab1345f | 706 | log_info("L2CAP_EVENT_INCOMING_CONNECTION (l2cap_cid 0x%02x) for PSM_RFCOMM => accept", l2cap_cid); |
va009039 | 0:1ed23ab1345f | 707 | l2cap_accept_connection_internal(l2cap_cid); |
va009039 | 0:1ed23ab1345f | 708 | return 1; |
va009039 | 0:1ed23ab1345f | 709 | |
va009039 | 0:1ed23ab1345f | 710 | // l2cap connection opened -> store l2cap_cid, remote_addr |
va009039 | 0:1ed23ab1345f | 711 | case L2CAP_EVENT_CHANNEL_OPENED: |
va009039 | 0:1ed23ab1345f | 712 | if (READ_BT_16(packet, 11) != PSM_RFCOMM) break; |
va009039 | 0:1ed23ab1345f | 713 | log_info("L2CAP_EVENT_CHANNEL_OPENED for PSM_RFCOMM\n"); |
va009039 | 0:1ed23ab1345f | 714 | // get multiplexer for remote addr |
va009039 | 0:1ed23ab1345f | 715 | con_handle = READ_BT_16(packet, 9); |
va009039 | 0:1ed23ab1345f | 716 | l2cap_cid = READ_BT_16(packet, 13); |
va009039 | 0:1ed23ab1345f | 717 | bt_flip_addr(event_addr, &packet[3]); |
va009039 | 0:1ed23ab1345f | 718 | multiplexer = rfcomm_multiplexer_for_addr(&event_addr); |
va009039 | 0:1ed23ab1345f | 719 | if (!multiplexer) { |
va009039 | 0:1ed23ab1345f | 720 | log_error("L2CAP_EVENT_CHANNEL_OPENED but no multiplexer prepared\n"); |
va009039 | 0:1ed23ab1345f | 721 | return 1; |
va009039 | 0:1ed23ab1345f | 722 | } |
va009039 | 0:1ed23ab1345f | 723 | if (multiplexer->state == RFCOMM_MULTIPLEXER_W4_CONNECT) { |
va009039 | 0:1ed23ab1345f | 724 | log_info("L2CAP_EVENT_CHANNEL_OPENED: outgoing connection\n"); |
va009039 | 0:1ed23ab1345f | 725 | // wrong remote addr |
va009039 | 0:1ed23ab1345f | 726 | if (BD_ADDR_CMP(event_addr, multiplexer->remote_addr)) break; |
va009039 | 0:1ed23ab1345f | 727 | multiplexer->l2cap_cid = l2cap_cid; |
va009039 | 0:1ed23ab1345f | 728 | multiplexer->con_handle = con_handle; |
va009039 | 0:1ed23ab1345f | 729 | // send SABM #0 |
va009039 | 0:1ed23ab1345f | 730 | multiplexer->state = RFCOMM_MULTIPLEXER_SEND_SABM_0; |
va009039 | 0:1ed23ab1345f | 731 | } else { // multiplexer->state == RFCOMM_MULTIPLEXER_W4_SABM_0 |
va009039 | 0:1ed23ab1345f | 732 | |
va009039 | 0:1ed23ab1345f | 733 | // set max frame size based on l2cap MTU |
va009039 | 0:1ed23ab1345f | 734 | multiplexer->max_frame_size = rfcomm_max_frame_size_for_l2cap_mtu(READ_BT_16(packet, 17)); |
va009039 | 0:1ed23ab1345f | 735 | } |
va009039 | 0:1ed23ab1345f | 736 | return 1; |
va009039 | 0:1ed23ab1345f | 737 | |
va009039 | 0:1ed23ab1345f | 738 | // l2cap disconnect -> state = RFCOMM_MULTIPLEXER_CLOSED; |
va009039 | 0:1ed23ab1345f | 739 | |
va009039 | 0:1ed23ab1345f | 740 | case L2CAP_EVENT_CREDITS: |
va009039 | 0:1ed23ab1345f | 741 | // data: event(8), len(8), local_cid(16), credits(8) |
va009039 | 0:1ed23ab1345f | 742 | l2cap_cid = READ_BT_16(packet, 2); |
va009039 | 0:1ed23ab1345f | 743 | multiplexer = rfcomm_multiplexer_for_l2cap_cid(l2cap_cid); |
va009039 | 0:1ed23ab1345f | 744 | if (!multiplexer) break; |
va009039 | 0:1ed23ab1345f | 745 | multiplexer->l2cap_credits += packet[4]; |
va009039 | 0:1ed23ab1345f | 746 | |
va009039 | 0:1ed23ab1345f | 747 | // log_info("L2CAP_EVENT_CREDITS: %u (now %u)\n", packet[4], multiplexer->l2cap_credits); |
va009039 | 0:1ed23ab1345f | 748 | |
va009039 | 0:1ed23ab1345f | 749 | // new credits, continue with signaling |
va009039 | 0:1ed23ab1345f | 750 | rfcomm_run(); |
va009039 | 0:1ed23ab1345f | 751 | |
va009039 | 0:1ed23ab1345f | 752 | if (multiplexer->state != RFCOMM_MULTIPLEXER_OPEN) break; |
va009039 | 0:1ed23ab1345f | 753 | rfcomm_hand_out_credits(); |
va009039 | 0:1ed23ab1345f | 754 | return 1; |
va009039 | 0:1ed23ab1345f | 755 | |
va009039 | 0:1ed23ab1345f | 756 | case DAEMON_EVENT_HCI_PACKET_SENT: |
va009039 | 0:1ed23ab1345f | 757 | // testing DMA done code |
va009039 | 0:1ed23ab1345f | 758 | rfcomm_run(); |
va009039 | 0:1ed23ab1345f | 759 | break; |
va009039 | 0:1ed23ab1345f | 760 | |
va009039 | 0:1ed23ab1345f | 761 | case L2CAP_EVENT_CHANNEL_CLOSED: |
va009039 | 0:1ed23ab1345f | 762 | // data: event (8), len(8), channel (16) |
va009039 | 0:1ed23ab1345f | 763 | l2cap_cid = READ_BT_16(packet, 2); |
va009039 | 0:1ed23ab1345f | 764 | multiplexer = rfcomm_multiplexer_for_l2cap_cid(l2cap_cid); |
va009039 | 0:1ed23ab1345f | 765 | if (!multiplexer) break; |
va009039 | 0:1ed23ab1345f | 766 | switch (multiplexer->state) { |
va009039 | 0:1ed23ab1345f | 767 | case RFCOMM_MULTIPLEXER_W4_SABM_0: |
va009039 | 0:1ed23ab1345f | 768 | case RFCOMM_MULTIPLEXER_W4_UA_0: |
va009039 | 0:1ed23ab1345f | 769 | case RFCOMM_MULTIPLEXER_OPEN: |
va009039 | 0:1ed23ab1345f | 770 | rfcomm_multiplexer_finalize(multiplexer); |
va009039 | 0:1ed23ab1345f | 771 | return 1; |
va009039 | 0:1ed23ab1345f | 772 | default: |
va009039 | 0:1ed23ab1345f | 773 | break; |
va009039 | 0:1ed23ab1345f | 774 | } |
va009039 | 0:1ed23ab1345f | 775 | break; |
va009039 | 0:1ed23ab1345f | 776 | default: |
va009039 | 0:1ed23ab1345f | 777 | break; |
va009039 | 0:1ed23ab1345f | 778 | } |
va009039 | 0:1ed23ab1345f | 779 | return 0; |
va009039 | 0:1ed23ab1345f | 780 | } |
va009039 | 0:1ed23ab1345f | 781 | |
va009039 | 0:1ed23ab1345f | 782 | static int rfcomm_multiplexer_l2cap_packet_handler(uint16_t channel, uint8_t *packet, uint16_t size){ |
va009039 | 0:1ed23ab1345f | 783 | |
va009039 | 0:1ed23ab1345f | 784 | // get or create a multiplexer for a certain device |
va009039 | 0:1ed23ab1345f | 785 | rfcomm_multiplexer_t *multiplexer = rfcomm_multiplexer_for_l2cap_cid(channel); |
va009039 | 0:1ed23ab1345f | 786 | if (!multiplexer) return 0; |
va009039 | 0:1ed23ab1345f | 787 | |
va009039 | 0:1ed23ab1345f | 788 | // but only care for multiplexer control channel |
va009039 | 0:1ed23ab1345f | 789 | uint8_t frame_dlci = packet[0] >> 2; |
va009039 | 0:1ed23ab1345f | 790 | if (frame_dlci) return 0; |
va009039 | 0:1ed23ab1345f | 791 | const uint8_t length_offset = (packet[2] & 1) ^ 1; // to be used for pos >= 3 |
va009039 | 0:1ed23ab1345f | 792 | const uint8_t credit_offset = ((packet[1] & BT_RFCOMM_UIH_PF) == BT_RFCOMM_UIH_PF) ? 1 : 0; // credits for uih_pf frames |
va009039 | 0:1ed23ab1345f | 793 | const uint8_t payload_offset = 3 + length_offset + credit_offset; |
va009039 | 0:1ed23ab1345f | 794 | switch (packet[1]){ |
va009039 | 0:1ed23ab1345f | 795 | |
va009039 | 0:1ed23ab1345f | 796 | case BT_RFCOMM_SABM: |
va009039 | 0:1ed23ab1345f | 797 | if (multiplexer->state == RFCOMM_MULTIPLEXER_W4_SABM_0){ |
va009039 | 0:1ed23ab1345f | 798 | log_info("Received SABM #0\n"); |
va009039 | 0:1ed23ab1345f | 799 | multiplexer->outgoing = 0; |
va009039 | 0:1ed23ab1345f | 800 | multiplexer->state = RFCOMM_MULTIPLEXER_SEND_UA_0; |
va009039 | 0:1ed23ab1345f | 801 | return 1; |
va009039 | 0:1ed23ab1345f | 802 | } |
va009039 | 0:1ed23ab1345f | 803 | break; |
va009039 | 0:1ed23ab1345f | 804 | |
va009039 | 0:1ed23ab1345f | 805 | case BT_RFCOMM_UA: |
va009039 | 0:1ed23ab1345f | 806 | if (multiplexer->state == RFCOMM_MULTIPLEXER_W4_UA_0) { |
va009039 | 0:1ed23ab1345f | 807 | // UA #0 -> send UA #0, state = RFCOMM_MULTIPLEXER_OPEN |
va009039 | 0:1ed23ab1345f | 808 | log_info("Received UA #0 \n"); |
va009039 | 0:1ed23ab1345f | 809 | rfcomm_multiplexer_opened(multiplexer); |
va009039 | 0:1ed23ab1345f | 810 | return 1; |
va009039 | 0:1ed23ab1345f | 811 | } |
va009039 | 0:1ed23ab1345f | 812 | break; |
va009039 | 0:1ed23ab1345f | 813 | |
va009039 | 0:1ed23ab1345f | 814 | case BT_RFCOMM_DISC: |
va009039 | 0:1ed23ab1345f | 815 | // DISC #0 -> send UA #0, close multiplexer |
va009039 | 0:1ed23ab1345f | 816 | log_info("Received DISC #0, (ougoing = %u)\n", multiplexer->outgoing); |
va009039 | 0:1ed23ab1345f | 817 | multiplexer->state = RFCOMM_MULTIPLEXER_SEND_UA_0_AND_DISC; |
va009039 | 0:1ed23ab1345f | 818 | return 1; |
va009039 | 0:1ed23ab1345f | 819 | |
va009039 | 0:1ed23ab1345f | 820 | case BT_RFCOMM_DM: |
va009039 | 0:1ed23ab1345f | 821 | // DM #0 - we shouldn't get this, just give up |
va009039 | 0:1ed23ab1345f | 822 | log_info("Received DM #0\n"); |
va009039 | 0:1ed23ab1345f | 823 | log_info("-> Closing down multiplexer\n"); |
va009039 | 0:1ed23ab1345f | 824 | rfcomm_multiplexer_finalize(multiplexer); |
va009039 | 0:1ed23ab1345f | 825 | return 1; |
va009039 | 0:1ed23ab1345f | 826 | |
va009039 | 0:1ed23ab1345f | 827 | case BT_RFCOMM_UIH: |
va009039 | 0:1ed23ab1345f | 828 | if (packet[payload_offset] == BT_RFCOMM_CLD_CMD){ |
va009039 | 0:1ed23ab1345f | 829 | // Multiplexer close down (CLD) -> close mutliplexer |
va009039 | 0:1ed23ab1345f | 830 | log_info("Received Multiplexer close down command\n"); |
va009039 | 0:1ed23ab1345f | 831 | log_info("-> Closing down multiplexer\n"); |
va009039 | 0:1ed23ab1345f | 832 | rfcomm_multiplexer_finalize(multiplexer); |
va009039 | 0:1ed23ab1345f | 833 | return 1; |
va009039 | 0:1ed23ab1345f | 834 | } |
va009039 | 0:1ed23ab1345f | 835 | break; |
va009039 | 0:1ed23ab1345f | 836 | |
va009039 | 0:1ed23ab1345f | 837 | default: |
va009039 | 0:1ed23ab1345f | 838 | break; |
va009039 | 0:1ed23ab1345f | 839 | |
va009039 | 0:1ed23ab1345f | 840 | } |
va009039 | 0:1ed23ab1345f | 841 | return 0; |
va009039 | 0:1ed23ab1345f | 842 | } |
va009039 | 0:1ed23ab1345f | 843 | |
va009039 | 0:1ed23ab1345f | 844 | static void rfcomm_multiplexer_state_machine(rfcomm_multiplexer_t * multiplexer, RFCOMM_MULTIPLEXER_EVENT event){ |
va009039 | 0:1ed23ab1345f | 845 | |
va009039 | 0:1ed23ab1345f | 846 | // process stored DM responses |
va009039 | 0:1ed23ab1345f | 847 | if (multiplexer->send_dm_for_dlci){ |
va009039 | 0:1ed23ab1345f | 848 | rfcomm_send_dm_pf(multiplexer, multiplexer->send_dm_for_dlci); |
va009039 | 0:1ed23ab1345f | 849 | multiplexer->send_dm_for_dlci = 0; |
va009039 | 0:1ed23ab1345f | 850 | } |
va009039 | 0:1ed23ab1345f | 851 | |
va009039 | 0:1ed23ab1345f | 852 | switch (multiplexer->state) { |
va009039 | 0:1ed23ab1345f | 853 | case RFCOMM_MULTIPLEXER_SEND_SABM_0: |
va009039 | 0:1ed23ab1345f | 854 | switch (event) { |
va009039 | 0:1ed23ab1345f | 855 | case MULT_EV_READY_TO_SEND: |
va009039 | 0:1ed23ab1345f | 856 | log_info("Sending SABM #0 - (multi 0x%p)\n", multiplexer); |
va009039 | 0:1ed23ab1345f | 857 | multiplexer->state = RFCOMM_MULTIPLEXER_W4_UA_0; |
va009039 | 0:1ed23ab1345f | 858 | rfcomm_send_sabm(multiplexer, 0); |
va009039 | 0:1ed23ab1345f | 859 | break; |
va009039 | 0:1ed23ab1345f | 860 | default: |
va009039 | 0:1ed23ab1345f | 861 | break; |
va009039 | 0:1ed23ab1345f | 862 | } |
va009039 | 0:1ed23ab1345f | 863 | break; |
va009039 | 0:1ed23ab1345f | 864 | case RFCOMM_MULTIPLEXER_SEND_UA_0: |
va009039 | 0:1ed23ab1345f | 865 | switch (event) { |
va009039 | 0:1ed23ab1345f | 866 | case MULT_EV_READY_TO_SEND: |
va009039 | 0:1ed23ab1345f | 867 | log_info("Sending UA #0\n"); |
va009039 | 0:1ed23ab1345f | 868 | multiplexer->state = RFCOMM_MULTIPLEXER_OPEN; |
va009039 | 0:1ed23ab1345f | 869 | rfcomm_send_ua(multiplexer, 0); |
va009039 | 0:1ed23ab1345f | 870 | rfcomm_multiplexer_opened(multiplexer); |
va009039 | 0:1ed23ab1345f | 871 | break; |
va009039 | 0:1ed23ab1345f | 872 | default: |
va009039 | 0:1ed23ab1345f | 873 | break; |
va009039 | 0:1ed23ab1345f | 874 | } |
va009039 | 0:1ed23ab1345f | 875 | break; |
va009039 | 0:1ed23ab1345f | 876 | case RFCOMM_MULTIPLEXER_SEND_UA_0_AND_DISC: |
va009039 | 0:1ed23ab1345f | 877 | switch (event) { |
va009039 | 0:1ed23ab1345f | 878 | case MULT_EV_READY_TO_SEND: |
va009039 | 0:1ed23ab1345f | 879 | log_info("Sending UA #0\n"); |
va009039 | 0:1ed23ab1345f | 880 | log_info("Closing down multiplexer\n"); |
va009039 | 0:1ed23ab1345f | 881 | multiplexer->state = RFCOMM_MULTIPLEXER_CLOSED; |
va009039 | 0:1ed23ab1345f | 882 | rfcomm_send_ua(multiplexer, 0); |
va009039 | 0:1ed23ab1345f | 883 | rfcomm_multiplexer_finalize(multiplexer); |
va009039 | 0:1ed23ab1345f | 884 | // try to detect authentication errors: drop link key if multiplexer closed before first channel got opened |
va009039 | 0:1ed23ab1345f | 885 | if (!multiplexer->at_least_one_connection){ |
va009039 | 0:1ed23ab1345f | 886 | log_info("TODO: no connections established - delete link key prophylactically\n"); |
va009039 | 0:1ed23ab1345f | 887 | // hci_send_cmd(&hci_delete_stored_link_key, multiplexer->remote_addr); |
va009039 | 0:1ed23ab1345f | 888 | } |
va009039 | 0:1ed23ab1345f | 889 | default: |
va009039 | 0:1ed23ab1345f | 890 | break; |
va009039 | 0:1ed23ab1345f | 891 | } |
va009039 | 0:1ed23ab1345f | 892 | break; |
va009039 | 0:1ed23ab1345f | 893 | default: |
va009039 | 0:1ed23ab1345f | 894 | break; |
va009039 | 0:1ed23ab1345f | 895 | } |
va009039 | 0:1ed23ab1345f | 896 | } |
va009039 | 0:1ed23ab1345f | 897 | |
va009039 | 0:1ed23ab1345f | 898 | // MARK: RFCOMM CHANNEL |
va009039 | 0:1ed23ab1345f | 899 | |
va009039 | 0:1ed23ab1345f | 900 | static void rfcomm_hand_out_credits(void){ |
va009039 | 0:1ed23ab1345f | 901 | linked_item_t * it; |
va009039 | 0:1ed23ab1345f | 902 | for (it = (linked_item_t *) rfcomm_channels; it ; it = it->next){ |
va009039 | 0:1ed23ab1345f | 903 | rfcomm_channel_t * channel = (rfcomm_channel_t *) it; |
va009039 | 0:1ed23ab1345f | 904 | if (channel->state != RFCOMM_CHANNEL_OPEN) { |
va009039 | 0:1ed23ab1345f | 905 | // log_info("RFCOMM_EVENT_CREDITS: multiplexer not open\n"); |
va009039 | 0:1ed23ab1345f | 906 | continue; |
va009039 | 0:1ed23ab1345f | 907 | } |
va009039 | 0:1ed23ab1345f | 908 | if (channel->packets_granted) { |
va009039 | 0:1ed23ab1345f | 909 | // log_info("RFCOMM_EVENT_CREDITS: already packets granted\n"); |
va009039 | 0:1ed23ab1345f | 910 | continue; |
va009039 | 0:1ed23ab1345f | 911 | } |
va009039 | 0:1ed23ab1345f | 912 | if (!channel->credits_outgoing) { |
va009039 | 0:1ed23ab1345f | 913 | // log_info("RFCOMM_EVENT_CREDITS: no outgoing credits\n"); |
va009039 | 0:1ed23ab1345f | 914 | continue; |
va009039 | 0:1ed23ab1345f | 915 | } |
va009039 | 0:1ed23ab1345f | 916 | if (!channel->multiplexer->l2cap_credits){ |
va009039 | 0:1ed23ab1345f | 917 | // log_info("RFCOMM_EVENT_CREDITS: no l2cap credits\n"); |
va009039 | 0:1ed23ab1345f | 918 | continue; |
va009039 | 0:1ed23ab1345f | 919 | } |
va009039 | 0:1ed23ab1345f | 920 | // channel open, multiplexer has l2cap credits and we didn't hand out credit before -> go! |
va009039 | 0:1ed23ab1345f | 921 | // log_info("RFCOMM_EVENT_CREDITS: 1\n"); |
va009039 | 0:1ed23ab1345f | 922 | channel->packets_granted += 1; |
va009039 | 0:1ed23ab1345f | 923 | rfcomm_emit_credits(channel, 1); |
va009039 | 0:1ed23ab1345f | 924 | } |
va009039 | 0:1ed23ab1345f | 925 | } |
va009039 | 0:1ed23ab1345f | 926 | |
va009039 | 0:1ed23ab1345f | 927 | static void rfcomm_channel_send_credits(rfcomm_channel_t *channel, uint8_t credits){ |
va009039 | 0:1ed23ab1345f | 928 | rfcomm_send_uih_credits(channel->multiplexer, channel->dlci, credits); |
va009039 | 0:1ed23ab1345f | 929 | channel->credits_incoming += credits; |
va009039 | 0:1ed23ab1345f | 930 | |
va009039 | 0:1ed23ab1345f | 931 | rfcomm_emit_credit_status(channel); |
va009039 | 0:1ed23ab1345f | 932 | } |
va009039 | 0:1ed23ab1345f | 933 | |
va009039 | 0:1ed23ab1345f | 934 | static void rfcomm_channel_opened(rfcomm_channel_t *rfChannel){ |
va009039 | 0:1ed23ab1345f | 935 | |
va009039 | 0:1ed23ab1345f | 936 | log_info("rfcomm_channel_opened!\n"); |
va009039 | 0:1ed23ab1345f | 937 | |
va009039 | 0:1ed23ab1345f | 938 | rfChannel->state = RFCOMM_CHANNEL_OPEN; |
va009039 | 0:1ed23ab1345f | 939 | rfcomm_emit_channel_opened(rfChannel, 0); |
va009039 | 0:1ed23ab1345f | 940 | rfcomm_hand_out_credits(); |
va009039 | 0:1ed23ab1345f | 941 | |
va009039 | 0:1ed23ab1345f | 942 | // remove (potential) timer |
va009039 | 0:1ed23ab1345f | 943 | rfcomm_multiplexer_t *multiplexer = rfChannel->multiplexer; |
va009039 | 0:1ed23ab1345f | 944 | if (multiplexer->timer_active) { |
va009039 | 0:1ed23ab1345f | 945 | run_loop_remove_timer(&multiplexer->timer); |
va009039 | 0:1ed23ab1345f | 946 | multiplexer->timer_active = 0; |
va009039 | 0:1ed23ab1345f | 947 | } |
va009039 | 0:1ed23ab1345f | 948 | // hack for problem detecting authentication failure |
va009039 | 0:1ed23ab1345f | 949 | multiplexer->at_least_one_connection = 1; |
va009039 | 0:1ed23ab1345f | 950 | |
va009039 | 0:1ed23ab1345f | 951 | // start next connection request if pending |
va009039 | 0:1ed23ab1345f | 952 | rfcomm_run(); |
va009039 | 0:1ed23ab1345f | 953 | } |
va009039 | 0:1ed23ab1345f | 954 | |
va009039 | 0:1ed23ab1345f | 955 | static void rfcomm_channel_packet_handler_uih(rfcomm_multiplexer_t *multiplexer, uint8_t * packet, uint16_t size){ |
va009039 | 0:1ed23ab1345f | 956 | const uint8_t frame_dlci = packet[0] >> 2; |
va009039 | 0:1ed23ab1345f | 957 | const uint8_t length_offset = (packet[2] & 1) ^ 1; // to be used for pos >= 3 |
va009039 | 0:1ed23ab1345f | 958 | const uint8_t credit_offset = ((packet[1] & BT_RFCOMM_UIH_PF) == BT_RFCOMM_UIH_PF) ? 1 : 0; // credits for uih_pf frames |
va009039 | 0:1ed23ab1345f | 959 | const uint8_t payload_offset = 3 + length_offset + credit_offset; |
va009039 | 0:1ed23ab1345f | 960 | |
va009039 | 0:1ed23ab1345f | 961 | rfcomm_channel_t * channel = rfcomm_channel_for_multiplexer_and_dlci(multiplexer, frame_dlci); |
va009039 | 0:1ed23ab1345f | 962 | if (!channel) return; |
va009039 | 0:1ed23ab1345f | 963 | |
va009039 | 0:1ed23ab1345f | 964 | // handle new outgoing credits |
va009039 | 0:1ed23ab1345f | 965 | if (packet[1] == BT_RFCOMM_UIH_PF) { |
va009039 | 0:1ed23ab1345f | 966 | |
va009039 | 0:1ed23ab1345f | 967 | // add them |
va009039 | 0:1ed23ab1345f | 968 | uint16_t new_credits = packet[3+length_offset]; |
va009039 | 0:1ed23ab1345f | 969 | channel->credits_outgoing += new_credits; |
va009039 | 0:1ed23ab1345f | 970 | log_info( "RFCOMM data UIH_PF, new credits: %u, now %u\n", new_credits, channel->credits_outgoing); |
va009039 | 0:1ed23ab1345f | 971 | |
va009039 | 0:1ed23ab1345f | 972 | // notify channel statemachine |
va009039 | 0:1ed23ab1345f | 973 | rfcomm_channel_event_t channel_event = { CH_EVT_RCVD_CREDITS }; |
va009039 | 0:1ed23ab1345f | 974 | rfcomm_channel_state_machine(channel, &channel_event); |
va009039 | 0:1ed23ab1345f | 975 | } |
va009039 | 0:1ed23ab1345f | 976 | |
va009039 | 0:1ed23ab1345f | 977 | // contains payload? |
va009039 | 0:1ed23ab1345f | 978 | if (size - 1 > payload_offset){ |
va009039 | 0:1ed23ab1345f | 979 | |
va009039 | 0:1ed23ab1345f | 980 | // log_info( "RFCOMM data UIH_PF, size %u, channel %p\n", size-payload_offset-1, rfChannel->connection); |
va009039 | 0:1ed23ab1345f | 981 | |
va009039 | 0:1ed23ab1345f | 982 | // decrease incoming credit counter |
va009039 | 0:1ed23ab1345f | 983 | if (channel->credits_incoming > 0){ |
va009039 | 0:1ed23ab1345f | 984 | channel->credits_incoming--; |
va009039 | 0:1ed23ab1345f | 985 | } |
va009039 | 0:1ed23ab1345f | 986 | |
va009039 | 0:1ed23ab1345f | 987 | // deliver payload |
va009039 | 0:1ed23ab1345f | 988 | (*app_packet_handler)(channel->connection, RFCOMM_DATA_PACKET, channel->rfcomm_cid, |
va009039 | 0:1ed23ab1345f | 989 | &packet[payload_offset], size-payload_offset-1); |
va009039 | 0:1ed23ab1345f | 990 | } |
va009039 | 0:1ed23ab1345f | 991 | |
va009039 | 0:1ed23ab1345f | 992 | // automatically provide new credits to remote device, if no incoming flow control |
va009039 | 0:1ed23ab1345f | 993 | if (!channel->incoming_flow_control && channel->credits_incoming < 5){ |
va009039 | 0:1ed23ab1345f | 994 | channel->new_credits_incoming = 0x30; |
va009039 | 0:1ed23ab1345f | 995 | } |
va009039 | 0:1ed23ab1345f | 996 | |
va009039 | 0:1ed23ab1345f | 997 | rfcomm_emit_credit_status(channel); |
va009039 | 0:1ed23ab1345f | 998 | |
va009039 | 0:1ed23ab1345f | 999 | // we received new RFCOMM credits, hand them out if possible |
va009039 | 0:1ed23ab1345f | 1000 | rfcomm_hand_out_credits(); |
va009039 | 0:1ed23ab1345f | 1001 | } |
va009039 | 0:1ed23ab1345f | 1002 | |
va009039 | 0:1ed23ab1345f | 1003 | static void rfcomm_channel_accept_pn(rfcomm_channel_t *channel, rfcomm_channel_event_pn_t *event){ |
va009039 | 0:1ed23ab1345f | 1004 | // priority of client request |
va009039 | 0:1ed23ab1345f | 1005 | channel->pn_priority = event->priority; |
va009039 | 0:1ed23ab1345f | 1006 | |
va009039 | 0:1ed23ab1345f | 1007 | // new credits |
va009039 | 0:1ed23ab1345f | 1008 | channel->credits_outgoing = event->credits_outgoing; |
va009039 | 0:1ed23ab1345f | 1009 | |
va009039 | 0:1ed23ab1345f | 1010 | // negotiate max frame size |
va009039 | 0:1ed23ab1345f | 1011 | if (channel->max_frame_size > channel->multiplexer->max_frame_size) { |
va009039 | 0:1ed23ab1345f | 1012 | channel->max_frame_size = channel->multiplexer->max_frame_size; |
va009039 | 0:1ed23ab1345f | 1013 | } |
va009039 | 0:1ed23ab1345f | 1014 | if (channel->max_frame_size > event->max_frame_size) { |
va009039 | 0:1ed23ab1345f | 1015 | channel->max_frame_size = event->max_frame_size; |
va009039 | 0:1ed23ab1345f | 1016 | } |
va009039 | 0:1ed23ab1345f | 1017 | |
va009039 | 0:1ed23ab1345f | 1018 | } |
va009039 | 0:1ed23ab1345f | 1019 | |
va009039 | 0:1ed23ab1345f | 1020 | static void rfcomm_channel_finalize(rfcomm_channel_t *channel){ |
va009039 | 0:1ed23ab1345f | 1021 | |
va009039 | 0:1ed23ab1345f | 1022 | rfcomm_multiplexer_t *multiplexer = channel->multiplexer; |
va009039 | 0:1ed23ab1345f | 1023 | |
va009039 | 0:1ed23ab1345f | 1024 | // remove from list |
va009039 | 0:1ed23ab1345f | 1025 | linked_list_remove( &rfcomm_channels, (linked_item_t *) channel); |
va009039 | 0:1ed23ab1345f | 1026 | |
va009039 | 0:1ed23ab1345f | 1027 | // free channel |
va009039 | 0:1ed23ab1345f | 1028 | btstack_memory_rfcomm_channel_free(channel); |
va009039 | 0:1ed23ab1345f | 1029 | |
va009039 | 0:1ed23ab1345f | 1030 | // update multiplexer timeout after channel was removed from list |
va009039 | 0:1ed23ab1345f | 1031 | rfcomm_multiplexer_prepare_idle_timer(multiplexer); |
va009039 | 0:1ed23ab1345f | 1032 | } |
va009039 | 0:1ed23ab1345f | 1033 | |
va009039 | 0:1ed23ab1345f | 1034 | static void rfcomm_channel_state_machine_2(rfcomm_multiplexer_t * multiplexer, uint8_t dlci, rfcomm_channel_event_t *event){ |
va009039 | 0:1ed23ab1345f | 1035 | |
va009039 | 0:1ed23ab1345f | 1036 | // TODO: if client max frame size is smaller than RFCOMM_DEFAULT_SIZE, send PN |
va009039 | 0:1ed23ab1345f | 1037 | |
va009039 | 0:1ed23ab1345f | 1038 | |
va009039 | 0:1ed23ab1345f | 1039 | // lookup existing channel |
va009039 | 0:1ed23ab1345f | 1040 | rfcomm_channel_t * channel = rfcomm_channel_for_multiplexer_and_dlci(multiplexer, dlci); |
va009039 | 0:1ed23ab1345f | 1041 | |
va009039 | 0:1ed23ab1345f | 1042 | // log_info("rfcomm_channel_state_machine_2 lookup dlci #%u = 0x%08x - event %u\n", dlci, (int) channel, event->type); |
va009039 | 0:1ed23ab1345f | 1043 | |
va009039 | 0:1ed23ab1345f | 1044 | if (channel) { |
va009039 | 0:1ed23ab1345f | 1045 | rfcomm_channel_state_machine(channel, event); |
va009039 | 0:1ed23ab1345f | 1046 | return; |
va009039 | 0:1ed23ab1345f | 1047 | } |
va009039 | 0:1ed23ab1345f | 1048 | |
va009039 | 0:1ed23ab1345f | 1049 | // service registered? |
va009039 | 0:1ed23ab1345f | 1050 | rfcomm_service_t * service = rfcomm_service_for_channel(dlci >> 1); |
va009039 | 0:1ed23ab1345f | 1051 | // log_info("rfcomm_channel_state_machine_2 service dlci #%u = 0x%08x\n", dlci, (int) service); |
va009039 | 0:1ed23ab1345f | 1052 | if (!service) { |
va009039 | 0:1ed23ab1345f | 1053 | // discard request by sending disconnected mode |
va009039 | 0:1ed23ab1345f | 1054 | multiplexer->send_dm_for_dlci = dlci; |
va009039 | 0:1ed23ab1345f | 1055 | return; |
va009039 | 0:1ed23ab1345f | 1056 | } |
va009039 | 0:1ed23ab1345f | 1057 | |
va009039 | 0:1ed23ab1345f | 1058 | // create channel for some events |
va009039 | 0:1ed23ab1345f | 1059 | switch (event->type) { |
va009039 | 0:1ed23ab1345f | 1060 | case CH_EVT_RCVD_SABM: |
va009039 | 0:1ed23ab1345f | 1061 | case CH_EVT_RCVD_PN: |
va009039 | 0:1ed23ab1345f | 1062 | case CH_EVT_RCVD_RPN_REQ: |
va009039 | 0:1ed23ab1345f | 1063 | case CH_EVT_RCVD_RPN_CMD: |
va009039 | 0:1ed23ab1345f | 1064 | // setup incoming channel |
va009039 | 0:1ed23ab1345f | 1065 | channel = rfcomm_channel_create(multiplexer, service, dlci >> 1); |
va009039 | 0:1ed23ab1345f | 1066 | if (!channel){ |
va009039 | 0:1ed23ab1345f | 1067 | // discard request by sending disconnected mode |
va009039 | 0:1ed23ab1345f | 1068 | multiplexer->send_dm_for_dlci = dlci; |
va009039 | 0:1ed23ab1345f | 1069 | } |
va009039 | 0:1ed23ab1345f | 1070 | break; |
va009039 | 0:1ed23ab1345f | 1071 | default: |
va009039 | 0:1ed23ab1345f | 1072 | break; |
va009039 | 0:1ed23ab1345f | 1073 | } |
va009039 | 0:1ed23ab1345f | 1074 | |
va009039 | 0:1ed23ab1345f | 1075 | if (!channel) { |
va009039 | 0:1ed23ab1345f | 1076 | // discard request by sending disconnected mode |
va009039 | 0:1ed23ab1345f | 1077 | multiplexer->send_dm_for_dlci = dlci; |
va009039 | 0:1ed23ab1345f | 1078 | return; |
va009039 | 0:1ed23ab1345f | 1079 | } |
va009039 | 0:1ed23ab1345f | 1080 | channel->connection = service->connection; |
va009039 | 0:1ed23ab1345f | 1081 | rfcomm_channel_state_machine(channel, event); |
va009039 | 0:1ed23ab1345f | 1082 | } |
va009039 | 0:1ed23ab1345f | 1083 | |
va009039 | 0:1ed23ab1345f | 1084 | void rfcomm_channel_packet_handler(rfcomm_multiplexer_t * multiplexer, uint8_t *packet, uint16_t size){ |
va009039 | 0:1ed23ab1345f | 1085 | |
va009039 | 0:1ed23ab1345f | 1086 | // rfcomm: (0) addr [76543 server channel] [2 direction: initiator uses 1] [1 C/R: CMD by initiator = 1] [0 EA=1] |
va009039 | 0:1ed23ab1345f | 1087 | const uint8_t frame_dlci = packet[0] >> 2; |
va009039 | 0:1ed23ab1345f | 1088 | uint8_t message_dlci; // used by commands in UIH(_PF) packets |
va009039 | 0:1ed23ab1345f | 1089 | uint8_t message_len; // " |
va009039 | 0:1ed23ab1345f | 1090 | |
va009039 | 0:1ed23ab1345f | 1091 | // rfcomm: (1) command/control |
va009039 | 0:1ed23ab1345f | 1092 | // -- credits_offset = 1 if command == BT_RFCOMM_UIH_PF |
va009039 | 0:1ed23ab1345f | 1093 | const uint8_t credit_offset = ((packet[1] & BT_RFCOMM_UIH_PF) == BT_RFCOMM_UIH_PF) ? 1 : 0; // credits for uih_pf frames |
va009039 | 0:1ed23ab1345f | 1094 | // rfcomm: (2) length. if bit 0 is cleared, 2 byte length is used. (little endian) |
va009039 | 0:1ed23ab1345f | 1095 | const uint8_t length_offset = (packet[2] & 1) ^ 1; // to be used for pos >= 3 |
va009039 | 0:1ed23ab1345f | 1096 | // rfcomm: (3+length_offset) credits if credits_offset == 1 |
va009039 | 0:1ed23ab1345f | 1097 | // rfcomm: (3+length_offest+credits_offset) |
va009039 | 0:1ed23ab1345f | 1098 | const uint8_t payload_offset = 3 + length_offset + credit_offset; |
va009039 | 0:1ed23ab1345f | 1099 | |
va009039 | 0:1ed23ab1345f | 1100 | rfcomm_channel_event_t event; |
va009039 | 0:1ed23ab1345f | 1101 | rfcomm_channel_event_pn_t event_pn; |
va009039 | 0:1ed23ab1345f | 1102 | rfcomm_channel_event_rpn_t event_rpn; |
va009039 | 0:1ed23ab1345f | 1103 | |
va009039 | 0:1ed23ab1345f | 1104 | // switch by rfcomm message type |
va009039 | 0:1ed23ab1345f | 1105 | switch(packet[1]) { |
va009039 | 0:1ed23ab1345f | 1106 | |
va009039 | 0:1ed23ab1345f | 1107 | case BT_RFCOMM_SABM: |
va009039 | 0:1ed23ab1345f | 1108 | event.type = CH_EVT_RCVD_SABM; |
va009039 | 0:1ed23ab1345f | 1109 | log_info("Received SABM #%u\n", frame_dlci); |
va009039 | 0:1ed23ab1345f | 1110 | rfcomm_channel_state_machine_2(multiplexer, frame_dlci, &event); |
va009039 | 0:1ed23ab1345f | 1111 | break; |
va009039 | 0:1ed23ab1345f | 1112 | |
va009039 | 0:1ed23ab1345f | 1113 | case BT_RFCOMM_UA: |
va009039 | 0:1ed23ab1345f | 1114 | event.type = CH_EVT_RCVD_UA; |
va009039 | 0:1ed23ab1345f | 1115 | log_info("Received UA #%u - channel opened\n",frame_dlci); |
va009039 | 0:1ed23ab1345f | 1116 | rfcomm_channel_state_machine_2(multiplexer, frame_dlci, &event); |
va009039 | 0:1ed23ab1345f | 1117 | break; |
va009039 | 0:1ed23ab1345f | 1118 | |
va009039 | 0:1ed23ab1345f | 1119 | case BT_RFCOMM_DISC: |
va009039 | 0:1ed23ab1345f | 1120 | event.type = CH_EVT_RCVD_DISC; |
va009039 | 0:1ed23ab1345f | 1121 | rfcomm_channel_state_machine_2(multiplexer, frame_dlci, &event); |
va009039 | 0:1ed23ab1345f | 1122 | break; |
va009039 | 0:1ed23ab1345f | 1123 | |
va009039 | 0:1ed23ab1345f | 1124 | case BT_RFCOMM_DM: |
va009039 | 0:1ed23ab1345f | 1125 | case BT_RFCOMM_DM_PF: |
va009039 | 0:1ed23ab1345f | 1126 | event.type = CH_EVT_RCVD_DM; |
va009039 | 0:1ed23ab1345f | 1127 | rfcomm_channel_state_machine_2(multiplexer, frame_dlci, &event); |
va009039 | 0:1ed23ab1345f | 1128 | break; |
va009039 | 0:1ed23ab1345f | 1129 | |
va009039 | 0:1ed23ab1345f | 1130 | case BT_RFCOMM_UIH_PF: |
va009039 | 0:1ed23ab1345f | 1131 | case BT_RFCOMM_UIH: |
va009039 | 0:1ed23ab1345f | 1132 | |
va009039 | 0:1ed23ab1345f | 1133 | message_len = packet[payload_offset+1] >> 1; |
va009039 | 0:1ed23ab1345f | 1134 | |
va009039 | 0:1ed23ab1345f | 1135 | switch (packet[payload_offset]) { |
va009039 | 0:1ed23ab1345f | 1136 | case BT_RFCOMM_PN_CMD: |
va009039 | 0:1ed23ab1345f | 1137 | message_dlci = packet[payload_offset+2]; |
va009039 | 0:1ed23ab1345f | 1138 | event_pn.super.type = CH_EVT_RCVD_PN; |
va009039 | 0:1ed23ab1345f | 1139 | event_pn.priority = packet[payload_offset+4]; |
va009039 | 0:1ed23ab1345f | 1140 | event_pn.max_frame_size = READ_BT_16(packet, payload_offset+6); |
va009039 | 0:1ed23ab1345f | 1141 | event_pn.credits_outgoing = packet[payload_offset+9]; |
va009039 | 0:1ed23ab1345f | 1142 | log_info("Received UIH Parameter Negotiation Command for #%u\n", message_dlci); |
va009039 | 0:1ed23ab1345f | 1143 | rfcomm_channel_state_machine_2(multiplexer, message_dlci, (rfcomm_channel_event_t*) &event_pn); |
va009039 | 0:1ed23ab1345f | 1144 | break; |
va009039 | 0:1ed23ab1345f | 1145 | |
va009039 | 0:1ed23ab1345f | 1146 | case BT_RFCOMM_PN_RSP: |
va009039 | 0:1ed23ab1345f | 1147 | message_dlci = packet[payload_offset+2]; |
va009039 | 0:1ed23ab1345f | 1148 | event_pn.super.type = CH_EVT_RCVD_PN_RSP; |
va009039 | 0:1ed23ab1345f | 1149 | event_pn.priority = packet[payload_offset+4]; |
va009039 | 0:1ed23ab1345f | 1150 | event_pn.max_frame_size = READ_BT_16(packet, payload_offset+6); |
va009039 | 0:1ed23ab1345f | 1151 | event_pn.credits_outgoing = packet[payload_offset+9]; |
va009039 | 0:1ed23ab1345f | 1152 | log_info("UIH Parameter Negotiation Response max frame %u, credits %u\n", |
va009039 | 0:1ed23ab1345f | 1153 | event_pn.max_frame_size, event_pn.credits_outgoing); |
va009039 | 0:1ed23ab1345f | 1154 | rfcomm_channel_state_machine_2(multiplexer, message_dlci, (rfcomm_channel_event_t*) &event_pn); |
va009039 | 0:1ed23ab1345f | 1155 | break; |
va009039 | 0:1ed23ab1345f | 1156 | |
va009039 | 0:1ed23ab1345f | 1157 | case BT_RFCOMM_MSC_CMD: |
va009039 | 0:1ed23ab1345f | 1158 | message_dlci = packet[payload_offset+2] >> 2; |
va009039 | 0:1ed23ab1345f | 1159 | event.type = CH_EVT_RCVD_MSC_CMD; |
va009039 | 0:1ed23ab1345f | 1160 | log_info("Received MSC CMD for #%u, \n", message_dlci); |
va009039 | 0:1ed23ab1345f | 1161 | rfcomm_channel_state_machine_2(multiplexer, message_dlci, &event); |
va009039 | 0:1ed23ab1345f | 1162 | break; |
va009039 | 0:1ed23ab1345f | 1163 | |
va009039 | 0:1ed23ab1345f | 1164 | case BT_RFCOMM_MSC_RSP: |
va009039 | 0:1ed23ab1345f | 1165 | message_dlci = packet[payload_offset+2] >> 2; |
va009039 | 0:1ed23ab1345f | 1166 | event.type = CH_EVT_RCVD_MSC_RSP; |
va009039 | 0:1ed23ab1345f | 1167 | log_info("Received MSC RSP for #%u\n", message_dlci); |
va009039 | 0:1ed23ab1345f | 1168 | rfcomm_channel_state_machine_2(multiplexer, message_dlci, &event); |
va009039 | 0:1ed23ab1345f | 1169 | break; |
va009039 | 0:1ed23ab1345f | 1170 | |
va009039 | 0:1ed23ab1345f | 1171 | case BT_RFCOMM_RPN_CMD: |
va009039 | 0:1ed23ab1345f | 1172 | message_dlci = packet[payload_offset+2] >> 2; |
va009039 | 0:1ed23ab1345f | 1173 | switch (message_len){ |
va009039 | 0:1ed23ab1345f | 1174 | case 1: |
va009039 | 0:1ed23ab1345f | 1175 | log_info("Received Remote Port Negotiation for #%u\n", message_dlci); |
va009039 | 0:1ed23ab1345f | 1176 | event.type = CH_EVT_RCVD_RPN_REQ; |
va009039 | 0:1ed23ab1345f | 1177 | rfcomm_channel_state_machine_2(multiplexer, message_dlci, &event); |
va009039 | 0:1ed23ab1345f | 1178 | break; |
va009039 | 0:1ed23ab1345f | 1179 | case 8: |
va009039 | 0:1ed23ab1345f | 1180 | log_info("Received Remote Port Negotiation (Info) for #%u\n", message_dlci); |
va009039 | 0:1ed23ab1345f | 1181 | event_rpn.super.type = CH_EVT_RCVD_RPN_CMD; |
va009039 | 0:1ed23ab1345f | 1182 | event_rpn.data.baud_rate = packet[payload_offset+3]; |
va009039 | 0:1ed23ab1345f | 1183 | event_rpn.data.flags = packet[payload_offset+4]; |
va009039 | 0:1ed23ab1345f | 1184 | event_rpn.data.flow_control = packet[payload_offset+5]; |
va009039 | 0:1ed23ab1345f | 1185 | event_rpn.data.xon = packet[payload_offset+6]; |
va009039 | 0:1ed23ab1345f | 1186 | event_rpn.data.xoff = packet[payload_offset+7]; |
va009039 | 0:1ed23ab1345f | 1187 | event_rpn.data.parameter_mask_0 = packet[payload_offset+8]; |
va009039 | 0:1ed23ab1345f | 1188 | event_rpn.data.parameter_mask_1 = packet[payload_offset+9]; |
va009039 | 0:1ed23ab1345f | 1189 | rfcomm_channel_state_machine_2(multiplexer, message_dlci, (rfcomm_channel_event_t*) &event_rpn); |
va009039 | 0:1ed23ab1345f | 1190 | break; |
va009039 | 0:1ed23ab1345f | 1191 | default: |
va009039 | 0:1ed23ab1345f | 1192 | break; |
va009039 | 0:1ed23ab1345f | 1193 | } |
va009039 | 0:1ed23ab1345f | 1194 | break; |
va009039 | 0:1ed23ab1345f | 1195 | |
va009039 | 0:1ed23ab1345f | 1196 | default: |
va009039 | 0:1ed23ab1345f | 1197 | log_error("Received unknown UIH packet - 0x%02x\n", packet[payload_offset]); |
va009039 | 0:1ed23ab1345f | 1198 | break; |
va009039 | 0:1ed23ab1345f | 1199 | } |
va009039 | 0:1ed23ab1345f | 1200 | break; |
va009039 | 0:1ed23ab1345f | 1201 | |
va009039 | 0:1ed23ab1345f | 1202 | default: |
va009039 | 0:1ed23ab1345f | 1203 | log_error("Received unknown RFCOMM message type %x\n", packet[1]); |
va009039 | 0:1ed23ab1345f | 1204 | break; |
va009039 | 0:1ed23ab1345f | 1205 | } |
va009039 | 0:1ed23ab1345f | 1206 | |
va009039 | 0:1ed23ab1345f | 1207 | // trigger next action - example W4_PN_RSP: transition to SEND_SABM which only depends on "can send" |
va009039 | 0:1ed23ab1345f | 1208 | rfcomm_run(); |
va009039 | 0:1ed23ab1345f | 1209 | } |
va009039 | 0:1ed23ab1345f | 1210 | |
va009039 | 0:1ed23ab1345f | 1211 | void rfcomm_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ |
va009039 | 0:1ed23ab1345f | 1212 | |
va009039 | 0:1ed23ab1345f | 1213 | // multiplexer handler |
va009039 | 0:1ed23ab1345f | 1214 | int handled = 0; |
va009039 | 0:1ed23ab1345f | 1215 | switch (packet_type) { |
va009039 | 0:1ed23ab1345f | 1216 | case HCI_EVENT_PACKET: |
va009039 | 0:1ed23ab1345f | 1217 | handled = rfcomm_multiplexer_hci_event_handler(packet, size); |
va009039 | 0:1ed23ab1345f | 1218 | break; |
va009039 | 0:1ed23ab1345f | 1219 | case L2CAP_DATA_PACKET: |
va009039 | 0:1ed23ab1345f | 1220 | handled = rfcomm_multiplexer_l2cap_packet_handler(channel, packet, size); |
va009039 | 0:1ed23ab1345f | 1221 | break; |
va009039 | 0:1ed23ab1345f | 1222 | default: |
va009039 | 0:1ed23ab1345f | 1223 | break; |
va009039 | 0:1ed23ab1345f | 1224 | } |
va009039 | 0:1ed23ab1345f | 1225 | |
va009039 | 0:1ed23ab1345f | 1226 | if (handled) { |
va009039 | 0:1ed23ab1345f | 1227 | rfcomm_run(); |
va009039 | 0:1ed23ab1345f | 1228 | return; |
va009039 | 0:1ed23ab1345f | 1229 | } |
va009039 | 0:1ed23ab1345f | 1230 | |
va009039 | 0:1ed23ab1345f | 1231 | // we only handle l2cap packet over open multiplexer channel now |
va009039 | 0:1ed23ab1345f | 1232 | if (packet_type != L2CAP_DATA_PACKET) { |
va009039 | 0:1ed23ab1345f | 1233 | (*app_packet_handler)(NULL, packet_type, channel, packet, size); |
va009039 | 0:1ed23ab1345f | 1234 | return; |
va009039 | 0:1ed23ab1345f | 1235 | } |
va009039 | 0:1ed23ab1345f | 1236 | rfcomm_multiplexer_t * multiplexer = rfcomm_multiplexer_for_l2cap_cid(channel); |
va009039 | 0:1ed23ab1345f | 1237 | if (!multiplexer || multiplexer->state != RFCOMM_MULTIPLEXER_OPEN) { |
va009039 | 0:1ed23ab1345f | 1238 | (*app_packet_handler)(NULL, packet_type, channel, packet, size); |
va009039 | 0:1ed23ab1345f | 1239 | return; |
va009039 | 0:1ed23ab1345f | 1240 | } |
va009039 | 0:1ed23ab1345f | 1241 | |
va009039 | 0:1ed23ab1345f | 1242 | // channel data ? |
va009039 | 0:1ed23ab1345f | 1243 | // rfcomm: (0) addr [76543 server channel] [2 direction: initiator uses 1] [1 C/R: CMD by initiator = 1] [0 EA=1] |
va009039 | 0:1ed23ab1345f | 1244 | const uint8_t frame_dlci = packet[0] >> 2; |
va009039 | 0:1ed23ab1345f | 1245 | |
va009039 | 0:1ed23ab1345f | 1246 | if (frame_dlci && (packet[1] == BT_RFCOMM_UIH || packet[1] == BT_RFCOMM_UIH_PF)) { |
va009039 | 0:1ed23ab1345f | 1247 | rfcomm_channel_packet_handler_uih(multiplexer, packet, size); |
va009039 | 0:1ed23ab1345f | 1248 | rfcomm_run(); |
va009039 | 0:1ed23ab1345f | 1249 | return; |
va009039 | 0:1ed23ab1345f | 1250 | } |
va009039 | 0:1ed23ab1345f | 1251 | |
va009039 | 0:1ed23ab1345f | 1252 | rfcomm_channel_packet_handler(multiplexer, packet, size); |
va009039 | 0:1ed23ab1345f | 1253 | } |
va009039 | 0:1ed23ab1345f | 1254 | |
va009039 | 0:1ed23ab1345f | 1255 | static int rfcomm_channel_ready_for_open(rfcomm_channel_t *channel){ |
va009039 | 0:1ed23ab1345f | 1256 | // log_info("rfcomm_channel_ready_for_open state %u, flags needed %04x, current %04x, rf credits %u, l2cap credits %u \n", 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); |
va009039 | 0:1ed23ab1345f | 1257 | if ((channel->state_var & RFCOMM_CHANNEL_STATE_VAR_RCVD_MSC_RSP) == 0) return 0; |
va009039 | 0:1ed23ab1345f | 1258 | if ((channel->state_var & RFCOMM_CHANNEL_STATE_VAR_SENT_MSC_RSP) == 0) return 0; |
va009039 | 0:1ed23ab1345f | 1259 | if ((channel->state_var & RFCOMM_CHANNEL_STATE_VAR_SENT_CREDITS) == 0) return 0; |
va009039 | 0:1ed23ab1345f | 1260 | if (channel->credits_outgoing == 0) return 0; |
va009039 | 0:1ed23ab1345f | 1261 | |
va009039 | 0:1ed23ab1345f | 1262 | return 1; |
va009039 | 0:1ed23ab1345f | 1263 | } |
va009039 | 0:1ed23ab1345f | 1264 | |
va009039 | 0:1ed23ab1345f | 1265 | static void rfcomm_channel_state_machine(rfcomm_channel_t *channel, rfcomm_channel_event_t *event){ |
va009039 | 0:1ed23ab1345f | 1266 | |
va009039 | 0:1ed23ab1345f | 1267 | // log_info("rfcomm_channel_state_machine: state %u, state_var %04x, event %u\n", channel->state, channel->state_var ,event->type); |
va009039 | 0:1ed23ab1345f | 1268 | |
va009039 | 0:1ed23ab1345f | 1269 | rfcomm_multiplexer_t *multiplexer = channel->multiplexer; |
va009039 | 0:1ed23ab1345f | 1270 | |
va009039 | 0:1ed23ab1345f | 1271 | // TODO: integrate in common switch |
va009039 | 0:1ed23ab1345f | 1272 | if (event->type == CH_EVT_RCVD_DISC){ |
va009039 | 0:1ed23ab1345f | 1273 | rfcomm_emit_channel_closed(channel); |
va009039 | 0:1ed23ab1345f | 1274 | channel->state = RFCOMM_CHANNEL_SEND_UA_AFTER_DISC; |
va009039 | 0:1ed23ab1345f | 1275 | return; |
va009039 | 0:1ed23ab1345f | 1276 | } |
va009039 | 0:1ed23ab1345f | 1277 | |
va009039 | 0:1ed23ab1345f | 1278 | // TODO: integrate in common switch |
va009039 | 0:1ed23ab1345f | 1279 | if (event->type == CH_EVT_RCVD_DM){ |
va009039 | 0:1ed23ab1345f | 1280 | log_info("Received DM message for #%u\n", channel->dlci); |
va009039 | 0:1ed23ab1345f | 1281 | log_info("-> Closing channel locally for #%u\n", channel->dlci); |
va009039 | 0:1ed23ab1345f | 1282 | rfcomm_emit_channel_closed(channel); |
va009039 | 0:1ed23ab1345f | 1283 | rfcomm_channel_finalize(channel); |
va009039 | 0:1ed23ab1345f | 1284 | return; |
va009039 | 0:1ed23ab1345f | 1285 | } |
va009039 | 0:1ed23ab1345f | 1286 | |
va009039 | 0:1ed23ab1345f | 1287 | // remote port negotiation command - just accept everything for now |
va009039 | 0:1ed23ab1345f | 1288 | // |
va009039 | 0:1ed23ab1345f | 1289 | // "The RPN command can be used before a new DLC is opened and should be used whenever the port settings change." |
va009039 | 0:1ed23ab1345f | 1290 | // "The RPN command is specified as optional in TS 07.10, but it is mandatory to recognize and respond to it in RFCOMM. |
va009039 | 0:1ed23ab1345f | 1291 | // (Although the handling of individual settings are implementation-dependent.)" |
va009039 | 0:1ed23ab1345f | 1292 | // |
va009039 | 0:1ed23ab1345f | 1293 | |
va009039 | 0:1ed23ab1345f | 1294 | // TODO: integrate in common switch |
va009039 | 0:1ed23ab1345f | 1295 | if (event->type == CH_EVT_RCVD_RPN_CMD){ |
va009039 | 0:1ed23ab1345f | 1296 | // control port parameters |
va009039 | 0:1ed23ab1345f | 1297 | rfcomm_channel_event_rpn_t *event_rpn = (rfcomm_channel_event_rpn_t*) event; |
va009039 | 0:1ed23ab1345f | 1298 | memcpy(&channel->rpn_data, &event_rpn->data, sizeof(rfcomm_rpn_data_t)); |
va009039 | 0:1ed23ab1345f | 1299 | channel->state_var |= RFCOMM_CHANNEL_STATE_VAR_SEND_RPN_RSP; |
va009039 | 0:1ed23ab1345f | 1300 | return; |
va009039 | 0:1ed23ab1345f | 1301 | } |
va009039 | 0:1ed23ab1345f | 1302 | |
va009039 | 0:1ed23ab1345f | 1303 | // TODO: integrate in common switch |
va009039 | 0:1ed23ab1345f | 1304 | if (event->type == CH_EVT_RCVD_RPN_REQ){ |
va009039 | 0:1ed23ab1345f | 1305 | // default rpn rsp |
va009039 | 0:1ed23ab1345f | 1306 | rfcomm_rpn_data_t rpn_data; |
va009039 | 0:1ed23ab1345f | 1307 | rpn_data.baud_rate = 0xa0; /* 9600 bps */ |
va009039 | 0:1ed23ab1345f | 1308 | rpn_data.flags = 0x03; /* 8-n-1 */ |
va009039 | 0:1ed23ab1345f | 1309 | rpn_data.flow_control = 0; /* no flow control */ |
va009039 | 0:1ed23ab1345f | 1310 | rpn_data.xon = 0xd1; /* XON */ |
va009039 | 0:1ed23ab1345f | 1311 | rpn_data.xoff = 0xd3; /* XOFF */ |
va009039 | 0:1ed23ab1345f | 1312 | rpn_data.parameter_mask_0 = 0x7f; /* parameter mask, all values set */ |
va009039 | 0:1ed23ab1345f | 1313 | rpn_data.parameter_mask_1 = 0x3f; /* parameter mask, all values set */ |
va009039 | 0:1ed23ab1345f | 1314 | memcpy(&channel->rpn_data, &rpn_data, sizeof(rfcomm_rpn_data_t)); |
va009039 | 0:1ed23ab1345f | 1315 | channel->state_var |= RFCOMM_CHANNEL_STATE_VAR_SEND_RPN_RSP; |
va009039 | 0:1ed23ab1345f | 1316 | return; |
va009039 | 0:1ed23ab1345f | 1317 | } |
va009039 | 0:1ed23ab1345f | 1318 | |
va009039 | 0:1ed23ab1345f | 1319 | // TODO: integrate in common swich |
va009039 | 0:1ed23ab1345f | 1320 | if (event->type == CH_EVT_READY_TO_SEND){ |
va009039 | 0:1ed23ab1345f | 1321 | if (channel->state_var & RFCOMM_CHANNEL_STATE_VAR_SEND_RPN_RSP){ |
va009039 | 0:1ed23ab1345f | 1322 | log_info("Sending Remote Port Negotiation RSP for #%u\n", channel->dlci); |
va009039 | 0:1ed23ab1345f | 1323 | channel->state_var &= ~RFCOMM_CHANNEL_STATE_VAR_SEND_RPN_RSP; |
va009039 | 0:1ed23ab1345f | 1324 | rfcomm_send_uih_rpn_rsp(multiplexer, channel->dlci, &channel->rpn_data); |
va009039 | 0:1ed23ab1345f | 1325 | return; |
va009039 | 0:1ed23ab1345f | 1326 | } |
va009039 | 0:1ed23ab1345f | 1327 | } |
va009039 | 0:1ed23ab1345f | 1328 | |
va009039 | 0:1ed23ab1345f | 1329 | rfcomm_channel_event_pn_t * event_pn = (rfcomm_channel_event_pn_t*) event; |
va009039 | 0:1ed23ab1345f | 1330 | |
va009039 | 0:1ed23ab1345f | 1331 | switch (channel->state) { |
va009039 | 0:1ed23ab1345f | 1332 | case RFCOMM_CHANNEL_CLOSED: |
va009039 | 0:1ed23ab1345f | 1333 | switch (event->type){ |
va009039 | 0:1ed23ab1345f | 1334 | case CH_EVT_RCVD_SABM: |
va009039 | 0:1ed23ab1345f | 1335 | log_info("-> Inform app\n"); |
va009039 | 0:1ed23ab1345f | 1336 | channel->state_var |= RFCOMM_CHANNEL_STATE_VAR_RCVD_SABM; |
va009039 | 0:1ed23ab1345f | 1337 | channel->state = RFCOMM_CHANNEL_INCOMING_SETUP; |
va009039 | 0:1ed23ab1345f | 1338 | rfcomm_emit_connection_request(channel); |
va009039 | 0:1ed23ab1345f | 1339 | break; |
va009039 | 0:1ed23ab1345f | 1340 | case CH_EVT_RCVD_PN: |
va009039 | 0:1ed23ab1345f | 1341 | rfcomm_channel_accept_pn(channel, event_pn); |
va009039 | 0:1ed23ab1345f | 1342 | log_info("-> Inform app\n"); |
va009039 | 0:1ed23ab1345f | 1343 | channel->state_var |= RFCOMM_CHANNEL_STATE_VAR_RCVD_PN; |
va009039 | 0:1ed23ab1345f | 1344 | channel->state = RFCOMM_CHANNEL_INCOMING_SETUP; |
va009039 | 0:1ed23ab1345f | 1345 | rfcomm_emit_connection_request(channel); |
va009039 | 0:1ed23ab1345f | 1346 | break; |
va009039 | 0:1ed23ab1345f | 1347 | default: |
va009039 | 0:1ed23ab1345f | 1348 | break; |
va009039 | 0:1ed23ab1345f | 1349 | } |
va009039 | 0:1ed23ab1345f | 1350 | break; |
va009039 | 0:1ed23ab1345f | 1351 | |
va009039 | 0:1ed23ab1345f | 1352 | case RFCOMM_CHANNEL_INCOMING_SETUP: |
va009039 | 0:1ed23ab1345f | 1353 | switch (event->type){ |
va009039 | 0:1ed23ab1345f | 1354 | case CH_EVT_RCVD_SABM: |
va009039 | 0:1ed23ab1345f | 1355 | channel->state_var |= RFCOMM_CHANNEL_STATE_VAR_RCVD_SABM; |
va009039 | 0:1ed23ab1345f | 1356 | if (channel->state_var & RFCOMM_CHANNEL_STATE_VAR_CLIENT_ACCEPTED) { |
va009039 | 0:1ed23ab1345f | 1357 | channel->state_var |= RFCOMM_CHANNEL_STATE_VAR_SEND_UA; |
va009039 | 0:1ed23ab1345f | 1358 | } |
va009039 | 0:1ed23ab1345f | 1359 | break; |
va009039 | 0:1ed23ab1345f | 1360 | case CH_EVT_RCVD_PN: |
va009039 | 0:1ed23ab1345f | 1361 | rfcomm_channel_accept_pn(channel, event_pn); |
va009039 | 0:1ed23ab1345f | 1362 | channel->state_var |= RFCOMM_CHANNEL_STATE_VAR_RCVD_PN; |
va009039 | 0:1ed23ab1345f | 1363 | if (channel->state_var & RFCOMM_CHANNEL_STATE_VAR_CLIENT_ACCEPTED) { |
va009039 | 0:1ed23ab1345f | 1364 | channel->state_var |= RFCOMM_CHANNEL_STATE_VAR_SEND_PN_RSP; |
va009039 | 0:1ed23ab1345f | 1365 | } |
va009039 | 0:1ed23ab1345f | 1366 | break; |
va009039 | 0:1ed23ab1345f | 1367 | case CH_EVT_READY_TO_SEND: |
va009039 | 0:1ed23ab1345f | 1368 | if (channel->state_var & RFCOMM_CHANNEL_STATE_VAR_SEND_PN_RSP){ |
va009039 | 0:1ed23ab1345f | 1369 | log_info("Sending UIH Parameter Negotiation Respond for #%u\n", channel->dlci); |
va009039 | 0:1ed23ab1345f | 1370 | channel->state_var &= ~RFCOMM_CHANNEL_STATE_VAR_SEND_PN_RSP; |
va009039 | 0:1ed23ab1345f | 1371 | rfcomm_send_uih_pn_response(multiplexer, channel->dlci, channel->pn_priority, channel->max_frame_size); |
va009039 | 0:1ed23ab1345f | 1372 | } |
va009039 | 0:1ed23ab1345f | 1373 | else if (channel->state_var & RFCOMM_CHANNEL_STATE_VAR_SEND_UA){ |
va009039 | 0:1ed23ab1345f | 1374 | log_info("Sending UA #%u\n", channel->dlci); |
va009039 | 0:1ed23ab1345f | 1375 | channel->state_var &= ~RFCOMM_CHANNEL_STATE_VAR_SEND_UA; |
va009039 | 0:1ed23ab1345f | 1376 | rfcomm_send_ua(multiplexer, channel->dlci); |
va009039 | 0:1ed23ab1345f | 1377 | } |
va009039 | 0:1ed23ab1345f | 1378 | if ((channel->state_var & RFCOMM_CHANNEL_STATE_VAR_CLIENT_ACCEPTED) && (channel->state_var & RFCOMM_CHANNEL_STATE_VAR_RCVD_SABM)) { |
va009039 | 0:1ed23ab1345f | 1379 | channel->state_var |= RFCOMM_CHANNEL_STATE_VAR_SEND_MSC_CMD; |
va009039 | 0:1ed23ab1345f | 1380 | channel->state_var |= RFCOMM_CHANNEL_STATE_VAR_SEND_CREDITS; |
va009039 | 0:1ed23ab1345f | 1381 | channel->state = RFCOMM_CHANNEL_DLC_SETUP; |
va009039 | 0:1ed23ab1345f | 1382 | } |
va009039 | 0:1ed23ab1345f | 1383 | break; |
va009039 | 0:1ed23ab1345f | 1384 | |
va009039 | 0:1ed23ab1345f | 1385 | default: |
va009039 | 0:1ed23ab1345f | 1386 | break; |
va009039 | 0:1ed23ab1345f | 1387 | } |
va009039 | 0:1ed23ab1345f | 1388 | break; |
va009039 | 0:1ed23ab1345f | 1389 | |
va009039 | 0:1ed23ab1345f | 1390 | case RFCOMM_CHANNEL_W4_MULTIPLEXER: |
va009039 | 0:1ed23ab1345f | 1391 | switch (event->type) { |
va009039 | 0:1ed23ab1345f | 1392 | case CH_EVT_MULTIPLEXER_READY: |
va009039 | 0:1ed23ab1345f | 1393 | log_info("Muliplexer opened, sending UIH PN next\n"); |
va009039 | 0:1ed23ab1345f | 1394 | channel->state = RFCOMM_CHANNEL_SEND_UIH_PN; |
va009039 | 0:1ed23ab1345f | 1395 | break; |
va009039 | 0:1ed23ab1345f | 1396 | default: |
va009039 | 0:1ed23ab1345f | 1397 | break; |
va009039 | 0:1ed23ab1345f | 1398 | } |
va009039 | 0:1ed23ab1345f | 1399 | break; |
va009039 | 0:1ed23ab1345f | 1400 | |
va009039 | 0:1ed23ab1345f | 1401 | case RFCOMM_CHANNEL_SEND_UIH_PN: |
va009039 | 0:1ed23ab1345f | 1402 | switch (event->type) { |
va009039 | 0:1ed23ab1345f | 1403 | case CH_EVT_READY_TO_SEND: |
va009039 | 0:1ed23ab1345f | 1404 | log_info("Sending UIH Parameter Negotiation Command for #%u (channel 0x%p)\n", channel->dlci, channel ); |
va009039 | 0:1ed23ab1345f | 1405 | channel->state = RFCOMM_CHANNEL_W4_PN_RSP; |
va009039 | 0:1ed23ab1345f | 1406 | rfcomm_send_uih_pn_command(multiplexer, channel->dlci, channel->max_frame_size); |
va009039 | 0:1ed23ab1345f | 1407 | break; |
va009039 | 0:1ed23ab1345f | 1408 | default: |
va009039 | 0:1ed23ab1345f | 1409 | break; |
va009039 | 0:1ed23ab1345f | 1410 | } |
va009039 | 0:1ed23ab1345f | 1411 | break; |
va009039 | 0:1ed23ab1345f | 1412 | |
va009039 | 0:1ed23ab1345f | 1413 | case RFCOMM_CHANNEL_W4_PN_RSP: |
va009039 | 0:1ed23ab1345f | 1414 | switch (event->type){ |
va009039 | 0:1ed23ab1345f | 1415 | case CH_EVT_RCVD_PN_RSP: |
va009039 | 0:1ed23ab1345f | 1416 | // update max frame size |
va009039 | 0:1ed23ab1345f | 1417 | if (channel->max_frame_size > event_pn->max_frame_size) { |
va009039 | 0:1ed23ab1345f | 1418 | channel->max_frame_size = event_pn->max_frame_size; |
va009039 | 0:1ed23ab1345f | 1419 | } |
va009039 | 0:1ed23ab1345f | 1420 | // new credits |
va009039 | 0:1ed23ab1345f | 1421 | channel->credits_outgoing = event_pn->credits_outgoing; |
va009039 | 0:1ed23ab1345f | 1422 | channel->state = RFCOMM_CHANNEL_SEND_SABM_W4_UA; |
va009039 | 0:1ed23ab1345f | 1423 | break; |
va009039 | 0:1ed23ab1345f | 1424 | default: |
va009039 | 0:1ed23ab1345f | 1425 | break; |
va009039 | 0:1ed23ab1345f | 1426 | } |
va009039 | 0:1ed23ab1345f | 1427 | break; |
va009039 | 0:1ed23ab1345f | 1428 | |
va009039 | 0:1ed23ab1345f | 1429 | case RFCOMM_CHANNEL_SEND_SABM_W4_UA: |
va009039 | 0:1ed23ab1345f | 1430 | switch (event->type) { |
va009039 | 0:1ed23ab1345f | 1431 | case CH_EVT_READY_TO_SEND: |
va009039 | 0:1ed23ab1345f | 1432 | log_info("Sending SABM #%u\n", channel->dlci); |
va009039 | 0:1ed23ab1345f | 1433 | channel->state = RFCOMM_CHANNEL_W4_UA; |
va009039 | 0:1ed23ab1345f | 1434 | rfcomm_send_sabm(multiplexer, channel->dlci); |
va009039 | 0:1ed23ab1345f | 1435 | break; |
va009039 | 0:1ed23ab1345f | 1436 | default: |
va009039 | 0:1ed23ab1345f | 1437 | break; |
va009039 | 0:1ed23ab1345f | 1438 | } |
va009039 | 0:1ed23ab1345f | 1439 | break; |
va009039 | 0:1ed23ab1345f | 1440 | |
va009039 | 0:1ed23ab1345f | 1441 | case RFCOMM_CHANNEL_W4_UA: |
va009039 | 0:1ed23ab1345f | 1442 | switch (event->type){ |
va009039 | 0:1ed23ab1345f | 1443 | case CH_EVT_RCVD_UA: |
va009039 | 0:1ed23ab1345f | 1444 | channel->state = RFCOMM_CHANNEL_DLC_SETUP; |
va009039 | 0:1ed23ab1345f | 1445 | channel->state_var |= RFCOMM_CHANNEL_STATE_VAR_SEND_MSC_CMD; |
va009039 | 0:1ed23ab1345f | 1446 | channel->state_var |= RFCOMM_CHANNEL_STATE_VAR_SEND_CREDITS; |
va009039 | 0:1ed23ab1345f | 1447 | break; |
va009039 | 0:1ed23ab1345f | 1448 | default: |
va009039 | 0:1ed23ab1345f | 1449 | break; |
va009039 | 0:1ed23ab1345f | 1450 | } |
va009039 | 0:1ed23ab1345f | 1451 | break; |
va009039 | 0:1ed23ab1345f | 1452 | |
va009039 | 0:1ed23ab1345f | 1453 | case RFCOMM_CHANNEL_DLC_SETUP: |
va009039 | 0:1ed23ab1345f | 1454 | switch (event->type){ |
va009039 | 0:1ed23ab1345f | 1455 | case CH_EVT_RCVD_MSC_CMD: |
va009039 | 0:1ed23ab1345f | 1456 | channel->state_var |= RFCOMM_CHANNEL_STATE_VAR_RCVD_MSC_CMD; |
va009039 | 0:1ed23ab1345f | 1457 | channel->state_var |= RFCOMM_CHANNEL_STATE_VAR_SEND_MSC_RSP; |
va009039 | 0:1ed23ab1345f | 1458 | break; |
va009039 | 0:1ed23ab1345f | 1459 | case CH_EVT_RCVD_MSC_RSP: |
va009039 | 0:1ed23ab1345f | 1460 | channel->state_var |= RFCOMM_CHANNEL_STATE_VAR_RCVD_MSC_RSP; |
va009039 | 0:1ed23ab1345f | 1461 | break; |
va009039 | 0:1ed23ab1345f | 1462 | |
va009039 | 0:1ed23ab1345f | 1463 | case CH_EVT_READY_TO_SEND: |
va009039 | 0:1ed23ab1345f | 1464 | if (channel->state_var & RFCOMM_CHANNEL_STATE_VAR_SEND_MSC_CMD){ |
va009039 | 0:1ed23ab1345f | 1465 | log_info("Sending MSC CMD for #%u\n", channel->dlci); |
va009039 | 0:1ed23ab1345f | 1466 | channel->state_var &= ~RFCOMM_CHANNEL_STATE_VAR_SEND_MSC_CMD; |
va009039 | 0:1ed23ab1345f | 1467 | channel->state_var |= RFCOMM_CHANNEL_STATE_VAR_SENT_MSC_CMD; |
va009039 | 0:1ed23ab1345f | 1468 | rfcomm_send_uih_msc_cmd(multiplexer, channel->dlci , 0x8d); // ea=1,fc=0,rtc=1,rtr=1,ic=0,dv=1 |
va009039 | 0:1ed23ab1345f | 1469 | break; |
va009039 | 0:1ed23ab1345f | 1470 | } |
va009039 | 0:1ed23ab1345f | 1471 | if (channel->state_var & RFCOMM_CHANNEL_STATE_VAR_SEND_MSC_RSP){ |
va009039 | 0:1ed23ab1345f | 1472 | log_info("Sending MSC RSP for #%u\n", channel->dlci); |
va009039 | 0:1ed23ab1345f | 1473 | channel->state_var &= ~RFCOMM_CHANNEL_STATE_VAR_SEND_MSC_RSP; |
va009039 | 0:1ed23ab1345f | 1474 | channel->state_var |= RFCOMM_CHANNEL_STATE_VAR_SENT_MSC_RSP; |
va009039 | 0:1ed23ab1345f | 1475 | rfcomm_send_uih_msc_rsp(multiplexer, channel->dlci, 0x8d); // ea=1,fc=0,rtc=1,rtr=1,ic=0,dv=1 |
va009039 | 0:1ed23ab1345f | 1476 | break; |
va009039 | 0:1ed23ab1345f | 1477 | } |
va009039 | 0:1ed23ab1345f | 1478 | if (channel->state_var & RFCOMM_CHANNEL_STATE_VAR_SEND_CREDITS){ |
va009039 | 0:1ed23ab1345f | 1479 | log_info("Providing credits for #%u\n", channel->dlci); |
va009039 | 0:1ed23ab1345f | 1480 | channel->state_var &= ~RFCOMM_CHANNEL_STATE_VAR_SEND_CREDITS; |
va009039 | 0:1ed23ab1345f | 1481 | channel->state_var |= RFCOMM_CHANNEL_STATE_VAR_SENT_CREDITS; |
va009039 | 0:1ed23ab1345f | 1482 | if (channel->new_credits_incoming) { |
va009039 | 0:1ed23ab1345f | 1483 | uint8_t new_credits = channel->new_credits_incoming; |
va009039 | 0:1ed23ab1345f | 1484 | channel->new_credits_incoming = 0; |
va009039 | 0:1ed23ab1345f | 1485 | rfcomm_channel_send_credits(channel, new_credits); |
va009039 | 0:1ed23ab1345f | 1486 | } |
va009039 | 0:1ed23ab1345f | 1487 | break; |
va009039 | 0:1ed23ab1345f | 1488 | |
va009039 | 0:1ed23ab1345f | 1489 | } |
va009039 | 0:1ed23ab1345f | 1490 | break; |
va009039 | 0:1ed23ab1345f | 1491 | default: |
va009039 | 0:1ed23ab1345f | 1492 | break; |
va009039 | 0:1ed23ab1345f | 1493 | } |
va009039 | 0:1ed23ab1345f | 1494 | // finally done? |
va009039 | 0:1ed23ab1345f | 1495 | if (rfcomm_channel_ready_for_open(channel)){ |
va009039 | 0:1ed23ab1345f | 1496 | channel->state = RFCOMM_CHANNEL_OPEN; |
va009039 | 0:1ed23ab1345f | 1497 | rfcomm_channel_opened(channel); |
va009039 | 0:1ed23ab1345f | 1498 | } |
va009039 | 0:1ed23ab1345f | 1499 | break; |
va009039 | 0:1ed23ab1345f | 1500 | |
va009039 | 0:1ed23ab1345f | 1501 | case RFCOMM_CHANNEL_OPEN: |
va009039 | 0:1ed23ab1345f | 1502 | switch (event->type){ |
va009039 | 0:1ed23ab1345f | 1503 | case CH_EVT_RCVD_MSC_CMD: |
va009039 | 0:1ed23ab1345f | 1504 | channel->state_var |= RFCOMM_CHANNEL_STATE_VAR_SEND_MSC_RSP; |
va009039 | 0:1ed23ab1345f | 1505 | break; |
va009039 | 0:1ed23ab1345f | 1506 | case CH_EVT_READY_TO_SEND: |
va009039 | 0:1ed23ab1345f | 1507 | if (channel->state_var & RFCOMM_CHANNEL_STATE_VAR_SEND_MSC_RSP){ |
va009039 | 0:1ed23ab1345f | 1508 | log_info("Sending MSC RSP for #%u\n", channel->dlci); |
va009039 | 0:1ed23ab1345f | 1509 | channel->state_var &= ~RFCOMM_CHANNEL_STATE_VAR_SEND_MSC_RSP; |
va009039 | 0:1ed23ab1345f | 1510 | rfcomm_send_uih_msc_rsp(multiplexer, channel->dlci, 0x8d); // ea=1,fc=0,rtc=1,rtr=1,ic=0,dv=1 |
va009039 | 0:1ed23ab1345f | 1511 | break; |
va009039 | 0:1ed23ab1345f | 1512 | } |
va009039 | 0:1ed23ab1345f | 1513 | if (channel->new_credits_incoming) { |
va009039 | 0:1ed23ab1345f | 1514 | uint8_t new_credits = channel->new_credits_incoming; |
va009039 | 0:1ed23ab1345f | 1515 | channel->new_credits_incoming = 0; |
va009039 | 0:1ed23ab1345f | 1516 | rfcomm_channel_send_credits(channel, new_credits); |
va009039 | 0:1ed23ab1345f | 1517 | break; |
va009039 | 0:1ed23ab1345f | 1518 | } |
va009039 | 0:1ed23ab1345f | 1519 | break; |
va009039 | 0:1ed23ab1345f | 1520 | case CH_EVT_RCVD_CREDITS: { |
va009039 | 0:1ed23ab1345f | 1521 | // notify daemon -> might trigger re-try of parked connections |
va009039 | 0:1ed23ab1345f | 1522 | uint8_t event[1] = { DAEMON_EVENT_NEW_RFCOMM_CREDITS }; |
va009039 | 0:1ed23ab1345f | 1523 | (*app_packet_handler)(channel->connection, DAEMON_EVENT_PACKET, channel->rfcomm_cid, event, sizeof(event)); |
va009039 | 0:1ed23ab1345f | 1524 | break; |
va009039 | 0:1ed23ab1345f | 1525 | } |
va009039 | 0:1ed23ab1345f | 1526 | default: |
va009039 | 0:1ed23ab1345f | 1527 | break; |
va009039 | 0:1ed23ab1345f | 1528 | } |
va009039 | 0:1ed23ab1345f | 1529 | break; |
va009039 | 0:1ed23ab1345f | 1530 | |
va009039 | 0:1ed23ab1345f | 1531 | case RFCOMM_CHANNEL_SEND_DM: |
va009039 | 0:1ed23ab1345f | 1532 | switch (event->type) { |
va009039 | 0:1ed23ab1345f | 1533 | case CH_EVT_READY_TO_SEND: |
va009039 | 0:1ed23ab1345f | 1534 | log_info("Sending DM_PF for #%u\n", channel->dlci); |
va009039 | 0:1ed23ab1345f | 1535 | // don't emit channel closed - channel was never open |
va009039 | 0:1ed23ab1345f | 1536 | channel->state = RFCOMM_CHANNEL_CLOSED; |
va009039 | 0:1ed23ab1345f | 1537 | rfcomm_send_dm_pf(multiplexer, channel->dlci); |
va009039 | 0:1ed23ab1345f | 1538 | rfcomm_channel_finalize(channel); |
va009039 | 0:1ed23ab1345f | 1539 | break; |
va009039 | 0:1ed23ab1345f | 1540 | default: |
va009039 | 0:1ed23ab1345f | 1541 | break; |
va009039 | 0:1ed23ab1345f | 1542 | } |
va009039 | 0:1ed23ab1345f | 1543 | break; |
va009039 | 0:1ed23ab1345f | 1544 | |
va009039 | 0:1ed23ab1345f | 1545 | case RFCOMM_CHANNEL_SEND_DISC: |
va009039 | 0:1ed23ab1345f | 1546 | switch (event->type) { |
va009039 | 0:1ed23ab1345f | 1547 | case CH_EVT_READY_TO_SEND: |
va009039 | 0:1ed23ab1345f | 1548 | channel->state = RFCOMM_CHANNEL_CLOSED; |
va009039 | 0:1ed23ab1345f | 1549 | rfcomm_send_disc(multiplexer, channel->dlci); |
va009039 | 0:1ed23ab1345f | 1550 | rfcomm_emit_channel_closed(channel); |
va009039 | 0:1ed23ab1345f | 1551 | rfcomm_channel_finalize(channel); |
va009039 | 0:1ed23ab1345f | 1552 | break; |
va009039 | 0:1ed23ab1345f | 1553 | default: |
va009039 | 0:1ed23ab1345f | 1554 | break; |
va009039 | 0:1ed23ab1345f | 1555 | } |
va009039 | 0:1ed23ab1345f | 1556 | break; |
va009039 | 0:1ed23ab1345f | 1557 | |
va009039 | 0:1ed23ab1345f | 1558 | case RFCOMM_CHANNEL_SEND_UA_AFTER_DISC: |
va009039 | 0:1ed23ab1345f | 1559 | switch (event->type) { |
va009039 | 0:1ed23ab1345f | 1560 | case CH_EVT_READY_TO_SEND: |
va009039 | 0:1ed23ab1345f | 1561 | log_info("Sending UA after DISC for #%u\n", channel->dlci); |
va009039 | 0:1ed23ab1345f | 1562 | channel->state = RFCOMM_CHANNEL_CLOSED; |
va009039 | 0:1ed23ab1345f | 1563 | rfcomm_send_ua(multiplexer, channel->dlci); |
va009039 | 0:1ed23ab1345f | 1564 | rfcomm_channel_finalize(channel); |
va009039 | 0:1ed23ab1345f | 1565 | break; |
va009039 | 0:1ed23ab1345f | 1566 | default: |
va009039 | 0:1ed23ab1345f | 1567 | break; |
va009039 | 0:1ed23ab1345f | 1568 | } |
va009039 | 0:1ed23ab1345f | 1569 | break; |
va009039 | 0:1ed23ab1345f | 1570 | |
va009039 | 0:1ed23ab1345f | 1571 | default: |
va009039 | 0:1ed23ab1345f | 1572 | break; |
va009039 | 0:1ed23ab1345f | 1573 | } |
va009039 | 0:1ed23ab1345f | 1574 | } |
va009039 | 0:1ed23ab1345f | 1575 | |
va009039 | 0:1ed23ab1345f | 1576 | |
va009039 | 0:1ed23ab1345f | 1577 | // MARK: RFCOMM RUN |
va009039 | 0:1ed23ab1345f | 1578 | // process outstanding signaling tasks |
va009039 | 0:1ed23ab1345f | 1579 | static void rfcomm_run(void){ |
va009039 | 0:1ed23ab1345f | 1580 | |
va009039 | 0:1ed23ab1345f | 1581 | linked_item_t *it; |
va009039 | 0:1ed23ab1345f | 1582 | linked_item_t *next; |
va009039 | 0:1ed23ab1345f | 1583 | |
va009039 | 0:1ed23ab1345f | 1584 | for (it = (linked_item_t *) rfcomm_multiplexers; it ; it = next){ |
va009039 | 0:1ed23ab1345f | 1585 | |
va009039 | 0:1ed23ab1345f | 1586 | next = it->next; // be prepared for removal of channel in state machine |
va009039 | 0:1ed23ab1345f | 1587 | |
va009039 | 0:1ed23ab1345f | 1588 | rfcomm_multiplexer_t * multiplexer = ((rfcomm_multiplexer_t *) it); |
va009039 | 0:1ed23ab1345f | 1589 | |
va009039 | 0:1ed23ab1345f | 1590 | if (!l2cap_can_send_packet_now(multiplexer->l2cap_cid)) { |
va009039 | 0:1ed23ab1345f | 1591 | // log_info("rfcomm_run cannot send l2cap packet for #%u, credits %u\n", multiplexer->l2cap_cid, multiplexer->l2cap_credits); |
va009039 | 0:1ed23ab1345f | 1592 | continue; |
va009039 | 0:1ed23ab1345f | 1593 | } |
va009039 | 0:1ed23ab1345f | 1594 | // log_info("rfcomm_run: multi 0x%08x, state %u\n", (int) multiplexer, multiplexer->state); |
va009039 | 0:1ed23ab1345f | 1595 | |
va009039 | 0:1ed23ab1345f | 1596 | rfcomm_multiplexer_state_machine(multiplexer, MULT_EV_READY_TO_SEND); |
va009039 | 0:1ed23ab1345f | 1597 | } |
va009039 | 0:1ed23ab1345f | 1598 | |
va009039 | 0:1ed23ab1345f | 1599 | for (it = (linked_item_t *) rfcomm_channels; it ; it = next){ |
va009039 | 0:1ed23ab1345f | 1600 | |
va009039 | 0:1ed23ab1345f | 1601 | next = it->next; // be prepared for removal of channel in state machine |
va009039 | 0:1ed23ab1345f | 1602 | |
va009039 | 0:1ed23ab1345f | 1603 | rfcomm_channel_t * channel = ((rfcomm_channel_t *) it); |
va009039 | 0:1ed23ab1345f | 1604 | rfcomm_multiplexer_t * multiplexer = channel->multiplexer; |
va009039 | 0:1ed23ab1345f | 1605 | |
va009039 | 0:1ed23ab1345f | 1606 | if (!l2cap_can_send_packet_now(multiplexer->l2cap_cid)) continue; |
va009039 | 0:1ed23ab1345f | 1607 | |
va009039 | 0:1ed23ab1345f | 1608 | rfcomm_channel_event_t event = { CH_EVT_READY_TO_SEND }; |
va009039 | 0:1ed23ab1345f | 1609 | rfcomm_channel_state_machine(channel, &event); |
va009039 | 0:1ed23ab1345f | 1610 | } |
va009039 | 0:1ed23ab1345f | 1611 | } |
va009039 | 0:1ed23ab1345f | 1612 | |
va009039 | 0:1ed23ab1345f | 1613 | // MARK: RFCOMM BTstack API |
va009039 | 0:1ed23ab1345f | 1614 | |
va009039 | 0:1ed23ab1345f | 1615 | void rfcomm_init(void){ |
va009039 | 0:1ed23ab1345f | 1616 | rfcomm_client_cid_generator = 0; |
va009039 | 0:1ed23ab1345f | 1617 | rfcomm_multiplexers = NULL; |
va009039 | 0:1ed23ab1345f | 1618 | rfcomm_services = NULL; |
va009039 | 0:1ed23ab1345f | 1619 | rfcomm_channels = NULL; |
va009039 | 0:1ed23ab1345f | 1620 | } |
va009039 | 0:1ed23ab1345f | 1621 | |
va009039 | 0:1ed23ab1345f | 1622 | // register packet handler |
va009039 | 0:1ed23ab1345f | 1623 | void rfcomm_register_packet_handler(void (*handler)(void * connection, uint8_t packet_type, |
va009039 | 0:1ed23ab1345f | 1624 | uint16_t channel, uint8_t *packet, uint16_t size)){ |
va009039 | 0:1ed23ab1345f | 1625 | app_packet_handler = handler; |
va009039 | 0:1ed23ab1345f | 1626 | } |
va009039 | 0:1ed23ab1345f | 1627 | |
va009039 | 0:1ed23ab1345f | 1628 | // send packet over specific channel |
va009039 | 0:1ed23ab1345f | 1629 | int rfcomm_send_internal(uint16_t rfcomm_cid, uint8_t *data, uint16_t len){ |
va009039 | 0:1ed23ab1345f | 1630 | |
va009039 | 0:1ed23ab1345f | 1631 | rfcomm_channel_t * channel = rfcomm_channel_for_rfcomm_cid(rfcomm_cid); |
va009039 | 0:1ed23ab1345f | 1632 | if (!channel){ |
va009039 | 0:1ed23ab1345f | 1633 | log_error("rfcomm_send_internal cid %u doesn't exist!\n", rfcomm_cid); |
va009039 | 0:1ed23ab1345f | 1634 | return 0; |
va009039 | 0:1ed23ab1345f | 1635 | } |
va009039 | 0:1ed23ab1345f | 1636 | |
va009039 | 0:1ed23ab1345f | 1637 | if (!channel->credits_outgoing){ |
va009039 | 0:1ed23ab1345f | 1638 | log_info("rfcomm_send_internal cid %u, no rfcomm outgoing credits!\n", rfcomm_cid); |
va009039 | 0:1ed23ab1345f | 1639 | return RFCOMM_NO_OUTGOING_CREDITS; |
va009039 | 0:1ed23ab1345f | 1640 | } |
va009039 | 0:1ed23ab1345f | 1641 | |
va009039 | 0:1ed23ab1345f | 1642 | if (!channel->packets_granted){ |
va009039 | 0:1ed23ab1345f | 1643 | log_info("rfcomm_send_internal cid %u, no rfcomm credits granted!\n", rfcomm_cid); |
va009039 | 0:1ed23ab1345f | 1644 | return RFCOMM_NO_OUTGOING_CREDITS; |
va009039 | 0:1ed23ab1345f | 1645 | } |
va009039 | 0:1ed23ab1345f | 1646 | |
va009039 | 0:1ed23ab1345f | 1647 | // log_info("rfcomm_send_internal: len %u... outgoing credits %u, l2cap credit %us, granted %u\n", |
va009039 | 0:1ed23ab1345f | 1648 | // len, channel->credits_outgoing, channel->multiplexer->l2cap_credits, channel->packets_granted); |
va009039 | 0:1ed23ab1345f | 1649 | |
va009039 | 0:1ed23ab1345f | 1650 | |
va009039 | 0:1ed23ab1345f | 1651 | // send might cause l2cap to emit new credits, update counters first |
va009039 | 0:1ed23ab1345f | 1652 | channel->credits_outgoing--; |
va009039 | 0:1ed23ab1345f | 1653 | int packets_granted_decreased = 0; |
va009039 | 0:1ed23ab1345f | 1654 | if (channel->packets_granted) { |
va009039 | 0:1ed23ab1345f | 1655 | channel->packets_granted--; |
va009039 | 0:1ed23ab1345f | 1656 | packets_granted_decreased++; |
va009039 | 0:1ed23ab1345f | 1657 | } |
va009039 | 0:1ed23ab1345f | 1658 | |
va009039 | 0:1ed23ab1345f | 1659 | int result = rfcomm_send_uih_data(channel->multiplexer, channel->dlci, data, len); |
va009039 | 0:1ed23ab1345f | 1660 | |
va009039 | 0:1ed23ab1345f | 1661 | if (result != 0) { |
va009039 | 0:1ed23ab1345f | 1662 | channel->credits_outgoing++; |
va009039 | 0:1ed23ab1345f | 1663 | channel->packets_granted += packets_granted_decreased; |
va009039 | 0:1ed23ab1345f | 1664 | log_info("rfcomm_send_internal: error %d\n", result); |
va009039 | 0:1ed23ab1345f | 1665 | return result; |
va009039 | 0:1ed23ab1345f | 1666 | } |
va009039 | 0:1ed23ab1345f | 1667 | |
va009039 | 0:1ed23ab1345f | 1668 | // log_info("rfcomm_send_internal: now outgoing credits %u, l2cap credit %us, granted %u\n", |
va009039 | 0:1ed23ab1345f | 1669 | // channel->credits_outgoing, channel->multiplexer->l2cap_credits, channel->packets_granted); |
va009039 | 0:1ed23ab1345f | 1670 | |
va009039 | 0:1ed23ab1345f | 1671 | rfcomm_hand_out_credits(); |
va009039 | 0:1ed23ab1345f | 1672 | |
va009039 | 0:1ed23ab1345f | 1673 | return result; |
va009039 | 0:1ed23ab1345f | 1674 | } |
va009039 | 0:1ed23ab1345f | 1675 | |
va009039 | 0:1ed23ab1345f | 1676 | void rfcomm_create_channel2(void * connection, bd_addr_t *addr, uint8_t server_channel, uint8_t incoming_flow_control, uint8_t initial_credits){ |
va009039 | 0:1ed23ab1345f | 1677 | log_info("rfcomm_create_channel_internal to %s, at channel #%02x, flow control %u, init credits %u\n", bd_addr_to_str(*addr), server_channel, |
va009039 | 0:1ed23ab1345f | 1678 | incoming_flow_control, initial_credits); |
va009039 | 0:1ed23ab1345f | 1679 | |
va009039 | 0:1ed23ab1345f | 1680 | // create new multiplexer if necessary |
va009039 | 0:1ed23ab1345f | 1681 | rfcomm_multiplexer_t * multiplexer = rfcomm_multiplexer_for_addr(addr); |
va009039 | 0:1ed23ab1345f | 1682 | if (!multiplexer) { |
va009039 | 0:1ed23ab1345f | 1683 | multiplexer = rfcomm_multiplexer_create_for_addr(addr); |
va009039 | 0:1ed23ab1345f | 1684 | if (!multiplexer){ |
va009039 | 0:1ed23ab1345f | 1685 | rfcomm_emit_channel_open_failed_outgoing_memory(connection, addr, server_channel); |
va009039 | 0:1ed23ab1345f | 1686 | return; |
va009039 | 0:1ed23ab1345f | 1687 | } |
va009039 | 0:1ed23ab1345f | 1688 | multiplexer->outgoing = 1; |
va009039 | 0:1ed23ab1345f | 1689 | multiplexer->state = RFCOMM_MULTIPLEXER_W4_CONNECT; |
va009039 | 0:1ed23ab1345f | 1690 | } |
va009039 | 0:1ed23ab1345f | 1691 | |
va009039 | 0:1ed23ab1345f | 1692 | // prepare channel |
va009039 | 0:1ed23ab1345f | 1693 | rfcomm_channel_t * channel = rfcomm_channel_create(multiplexer, NULL, server_channel); |
va009039 | 0:1ed23ab1345f | 1694 | if (!channel){ |
va009039 | 0:1ed23ab1345f | 1695 | rfcomm_emit_channel_open_failed_outgoing_memory(connection, addr, server_channel); |
va009039 | 0:1ed23ab1345f | 1696 | return; |
va009039 | 0:1ed23ab1345f | 1697 | } |
va009039 | 0:1ed23ab1345f | 1698 | channel->connection = connection; |
va009039 | 0:1ed23ab1345f | 1699 | channel->incoming_flow_control = incoming_flow_control; |
va009039 | 0:1ed23ab1345f | 1700 | channel->new_credits_incoming = initial_credits; |
va009039 | 0:1ed23ab1345f | 1701 | |
va009039 | 0:1ed23ab1345f | 1702 | // start multiplexer setup |
va009039 | 0:1ed23ab1345f | 1703 | if (multiplexer->state != RFCOMM_MULTIPLEXER_OPEN) { |
va009039 | 0:1ed23ab1345f | 1704 | |
va009039 | 0:1ed23ab1345f | 1705 | channel->state = RFCOMM_CHANNEL_W4_MULTIPLEXER; |
va009039 | 0:1ed23ab1345f | 1706 | |
va009039 | 0:1ed23ab1345f | 1707 | l2cap_create_channel_internal(connection, rfcomm_packet_handler, *addr, PSM_RFCOMM, l2cap_max_mtu()); |
va009039 | 0:1ed23ab1345f | 1708 | |
va009039 | 0:1ed23ab1345f | 1709 | return; |
va009039 | 0:1ed23ab1345f | 1710 | } |
va009039 | 0:1ed23ab1345f | 1711 | |
va009039 | 0:1ed23ab1345f | 1712 | channel->state = RFCOMM_CHANNEL_SEND_UIH_PN; |
va009039 | 0:1ed23ab1345f | 1713 | |
va009039 | 0:1ed23ab1345f | 1714 | // start connecting, if multiplexer is already up and running |
va009039 | 0:1ed23ab1345f | 1715 | rfcomm_run(); |
va009039 | 0:1ed23ab1345f | 1716 | } |
va009039 | 0:1ed23ab1345f | 1717 | |
va009039 | 0:1ed23ab1345f | 1718 | void rfcomm_create_channel_with_initial_credits_internal(void * connection, bd_addr_t *addr, uint8_t server_channel, uint8_t initial_credits){ |
va009039 | 0:1ed23ab1345f | 1719 | rfcomm_create_channel2(connection, addr, server_channel, 1, initial_credits); |
va009039 | 0:1ed23ab1345f | 1720 | } |
va009039 | 0:1ed23ab1345f | 1721 | |
va009039 | 0:1ed23ab1345f | 1722 | void rfcomm_create_channel_internal(void * connection, bd_addr_t *addr, uint8_t server_channel){ |
va009039 | 0:1ed23ab1345f | 1723 | rfcomm_create_channel2(connection, addr, server_channel, 0, 0x30); |
va009039 | 0:1ed23ab1345f | 1724 | } |
va009039 | 0:1ed23ab1345f | 1725 | |
va009039 | 0:1ed23ab1345f | 1726 | void rfcomm_disconnect_internal(uint16_t rfcomm_cid){ |
va009039 | 0:1ed23ab1345f | 1727 | rfcomm_channel_t * channel = rfcomm_channel_for_rfcomm_cid(rfcomm_cid); |
va009039 | 0:1ed23ab1345f | 1728 | if (channel) { |
va009039 | 0:1ed23ab1345f | 1729 | channel->state = RFCOMM_CHANNEL_SEND_DISC; |
va009039 | 0:1ed23ab1345f | 1730 | } |
va009039 | 0:1ed23ab1345f | 1731 | |
va009039 | 0:1ed23ab1345f | 1732 | // process |
va009039 | 0:1ed23ab1345f | 1733 | rfcomm_run(); |
va009039 | 0:1ed23ab1345f | 1734 | } |
va009039 | 0:1ed23ab1345f | 1735 | |
va009039 | 0:1ed23ab1345f | 1736 | |
va009039 | 0:1ed23ab1345f | 1737 | void rfcomm_register_service2(void * connection, uint8_t channel, uint16_t max_frame_size, uint8_t incoming_flow_control, uint8_t initial_credits){ |
va009039 | 0:1ed23ab1345f | 1738 | // check if already registered |
va009039 | 0:1ed23ab1345f | 1739 | rfcomm_service_t * service = rfcomm_service_for_channel(channel); |
va009039 | 0:1ed23ab1345f | 1740 | if (service){ |
va009039 | 0:1ed23ab1345f | 1741 | rfcomm_emit_service_registered(connection, RFCOMM_CHANNEL_ALREADY_REGISTERED, channel); |
va009039 | 0:1ed23ab1345f | 1742 | return; |
va009039 | 0:1ed23ab1345f | 1743 | } |
va009039 | 0:1ed23ab1345f | 1744 | |
va009039 | 0:1ed23ab1345f | 1745 | // alloc structure |
va009039 | 0:1ed23ab1345f | 1746 | service = (rfcomm_service_t*)btstack_memory_rfcomm_service_get(); |
va009039 | 0:1ed23ab1345f | 1747 | if (!service) { |
va009039 | 0:1ed23ab1345f | 1748 | rfcomm_emit_service_registered(connection, BTSTACK_MEMORY_ALLOC_FAILED, channel); |
va009039 | 0:1ed23ab1345f | 1749 | return; |
va009039 | 0:1ed23ab1345f | 1750 | } |
va009039 | 0:1ed23ab1345f | 1751 | |
va009039 | 0:1ed23ab1345f | 1752 | // register with l2cap if not registered before, max MTU |
va009039 | 0:1ed23ab1345f | 1753 | if (linked_list_empty(&rfcomm_services)){ |
va009039 | 0:1ed23ab1345f | 1754 | l2cap_register_service_internal(NULL, rfcomm_packet_handler, PSM_RFCOMM, 0xffff); |
va009039 | 0:1ed23ab1345f | 1755 | } |
va009039 | 0:1ed23ab1345f | 1756 | |
va009039 | 0:1ed23ab1345f | 1757 | // fill in |
va009039 | 0:1ed23ab1345f | 1758 | service->connection = connection; |
va009039 | 0:1ed23ab1345f | 1759 | service->server_channel = channel; |
va009039 | 0:1ed23ab1345f | 1760 | service->max_frame_size = max_frame_size; |
va009039 | 0:1ed23ab1345f | 1761 | service->incoming_flow_control = incoming_flow_control; |
va009039 | 0:1ed23ab1345f | 1762 | service->incoming_initial_credits = initial_credits; |
va009039 | 0:1ed23ab1345f | 1763 | |
va009039 | 0:1ed23ab1345f | 1764 | // add to services list |
va009039 | 0:1ed23ab1345f | 1765 | linked_list_add(&rfcomm_services, (linked_item_t *) service); |
va009039 | 0:1ed23ab1345f | 1766 | |
va009039 | 0:1ed23ab1345f | 1767 | // done |
va009039 | 0:1ed23ab1345f | 1768 | rfcomm_emit_service_registered(connection, 0, channel); |
va009039 | 0:1ed23ab1345f | 1769 | } |
va009039 | 0:1ed23ab1345f | 1770 | |
va009039 | 0:1ed23ab1345f | 1771 | void rfcomm_register_service_with_initial_credits_internal(void * connection, uint8_t channel, uint16_t max_frame_size, uint8_t initial_credits){ |
va009039 | 0:1ed23ab1345f | 1772 | rfcomm_register_service2(connection, channel, max_frame_size, 1, initial_credits); |
va009039 | 0:1ed23ab1345f | 1773 | } |
va009039 | 0:1ed23ab1345f | 1774 | |
va009039 | 0:1ed23ab1345f | 1775 | void rfcomm_register_service_internal(void * connection, uint8_t channel, uint16_t max_frame_size){ |
va009039 | 0:1ed23ab1345f | 1776 | rfcomm_register_service2(connection, channel, max_frame_size, 0, 0x30); |
va009039 | 0:1ed23ab1345f | 1777 | } |
va009039 | 0:1ed23ab1345f | 1778 | |
va009039 | 0:1ed23ab1345f | 1779 | void rfcomm_unregister_service_internal(uint8_t service_channel){ |
va009039 | 0:1ed23ab1345f | 1780 | rfcomm_service_t *service = rfcomm_service_for_channel(service_channel); |
va009039 | 0:1ed23ab1345f | 1781 | if (!service) return; |
va009039 | 0:1ed23ab1345f | 1782 | linked_list_remove(&rfcomm_services, (linked_item_t *) service); |
va009039 | 0:1ed23ab1345f | 1783 | btstack_memory_rfcomm_service_free(service); |
va009039 | 0:1ed23ab1345f | 1784 | |
va009039 | 0:1ed23ab1345f | 1785 | // unregister if no services active |
va009039 | 0:1ed23ab1345f | 1786 | if (linked_list_empty(&rfcomm_services)){ |
va009039 | 0:1ed23ab1345f | 1787 | // bt_send_cmd(&l2cap_unregister_service, PSM_RFCOMM); |
va009039 | 0:1ed23ab1345f | 1788 | l2cap_unregister_service_internal(NULL, PSM_RFCOMM); |
va009039 | 0:1ed23ab1345f | 1789 | } |
va009039 | 0:1ed23ab1345f | 1790 | } |
va009039 | 0:1ed23ab1345f | 1791 | |
va009039 | 0:1ed23ab1345f | 1792 | void rfcomm_accept_connection_internal(uint16_t rfcomm_cid){ |
va009039 | 0:1ed23ab1345f | 1793 | log_info("Received Accept Connction\n"); |
va009039 | 0:1ed23ab1345f | 1794 | rfcomm_channel_t * channel = rfcomm_channel_for_rfcomm_cid(rfcomm_cid); |
va009039 | 0:1ed23ab1345f | 1795 | if (!channel) return; |
va009039 | 0:1ed23ab1345f | 1796 | switch (channel->state) { |
va009039 | 0:1ed23ab1345f | 1797 | case RFCOMM_CHANNEL_INCOMING_SETUP: |
va009039 | 0:1ed23ab1345f | 1798 | channel->state_var |= RFCOMM_CHANNEL_STATE_VAR_CLIENT_ACCEPTED; |
va009039 | 0:1ed23ab1345f | 1799 | if (channel->state_var & RFCOMM_CHANNEL_STATE_VAR_RCVD_PN){ |
va009039 | 0:1ed23ab1345f | 1800 | channel->state_var |= RFCOMM_CHANNEL_STATE_VAR_SEND_PN_RSP; |
va009039 | 0:1ed23ab1345f | 1801 | } |
va009039 | 0:1ed23ab1345f | 1802 | if (channel->state_var & RFCOMM_CHANNEL_STATE_VAR_RCVD_SABM){ |
va009039 | 0:1ed23ab1345f | 1803 | channel->state_var |= RFCOMM_CHANNEL_STATE_VAR_SEND_UA; |
va009039 | 0:1ed23ab1345f | 1804 | } |
va009039 | 0:1ed23ab1345f | 1805 | break; |
va009039 | 0:1ed23ab1345f | 1806 | default: |
va009039 | 0:1ed23ab1345f | 1807 | break; |
va009039 | 0:1ed23ab1345f | 1808 | } |
va009039 | 0:1ed23ab1345f | 1809 | |
va009039 | 0:1ed23ab1345f | 1810 | // process |
va009039 | 0:1ed23ab1345f | 1811 | rfcomm_run(); |
va009039 | 0:1ed23ab1345f | 1812 | } |
va009039 | 0:1ed23ab1345f | 1813 | |
va009039 | 0:1ed23ab1345f | 1814 | void rfcomm_decline_connection_internal(uint16_t rfcomm_cid){ |
va009039 | 0:1ed23ab1345f | 1815 | log_info("Received Decline Connction\n"); |
va009039 | 0:1ed23ab1345f | 1816 | rfcomm_channel_t * channel = rfcomm_channel_for_rfcomm_cid(rfcomm_cid); |
va009039 | 0:1ed23ab1345f | 1817 | if (!channel) return; |
va009039 | 0:1ed23ab1345f | 1818 | switch (channel->state) { |
va009039 | 0:1ed23ab1345f | 1819 | case RFCOMM_CHANNEL_INCOMING_SETUP: |
va009039 | 0:1ed23ab1345f | 1820 | channel->state = RFCOMM_CHANNEL_SEND_DM; |
va009039 | 0:1ed23ab1345f | 1821 | break; |
va009039 | 0:1ed23ab1345f | 1822 | default: |
va009039 | 0:1ed23ab1345f | 1823 | break; |
va009039 | 0:1ed23ab1345f | 1824 | } |
va009039 | 0:1ed23ab1345f | 1825 | |
va009039 | 0:1ed23ab1345f | 1826 | // process |
va009039 | 0:1ed23ab1345f | 1827 | rfcomm_run(); |
va009039 | 0:1ed23ab1345f | 1828 | } |
va009039 | 0:1ed23ab1345f | 1829 | |
va009039 | 0:1ed23ab1345f | 1830 | void rfcomm_grant_credits(uint16_t rfcomm_cid, uint8_t credits){ |
va009039 | 0:1ed23ab1345f | 1831 | rfcomm_channel_t * channel = rfcomm_channel_for_rfcomm_cid(rfcomm_cid); |
va009039 | 0:1ed23ab1345f | 1832 | if (!channel) return; |
va009039 | 0:1ed23ab1345f | 1833 | if (!channel->incoming_flow_control) return; |
va009039 | 0:1ed23ab1345f | 1834 | channel->new_credits_incoming += credits; |
va009039 | 0:1ed23ab1345f | 1835 | |
va009039 | 0:1ed23ab1345f | 1836 | // process |
va009039 | 0:1ed23ab1345f | 1837 | rfcomm_run(); |
va009039 | 0:1ed23ab1345f | 1838 | } |
va009039 | 0:1ed23ab1345f | 1839 | |
va009039 | 0:1ed23ab1345f | 1840 | // |
va009039 | 0:1ed23ab1345f | 1841 | void rfcomm_close_connection(void *connection){ |
va009039 | 0:1ed23ab1345f | 1842 | linked_item_t *it; |
va009039 | 0:1ed23ab1345f | 1843 | |
va009039 | 0:1ed23ab1345f | 1844 | // close open channels |
va009039 | 0:1ed23ab1345f | 1845 | for (it = (linked_item_t *) rfcomm_channels; it ; it = it->next){ |
va009039 | 0:1ed23ab1345f | 1846 | rfcomm_channel_t * channel = (rfcomm_channel_t *)it; |
va009039 | 0:1ed23ab1345f | 1847 | if (channel->connection != connection) continue; |
va009039 | 0:1ed23ab1345f | 1848 | channel->state = RFCOMM_CHANNEL_SEND_DISC; |
va009039 | 0:1ed23ab1345f | 1849 | } |
va009039 | 0:1ed23ab1345f | 1850 | |
va009039 | 0:1ed23ab1345f | 1851 | // unregister services |
va009039 | 0:1ed23ab1345f | 1852 | it = (linked_item_t *) &rfcomm_services; |
va009039 | 0:1ed23ab1345f | 1853 | while (it->next) { |
va009039 | 0:1ed23ab1345f | 1854 | rfcomm_service_t * service = (rfcomm_service_t *) it->next; |
va009039 | 0:1ed23ab1345f | 1855 | if (service->connection == connection){ |
va009039 | 0:1ed23ab1345f | 1856 | it->next = it->next->next; |
va009039 | 0:1ed23ab1345f | 1857 | btstack_memory_rfcomm_service_free(service); |
va009039 | 0:1ed23ab1345f | 1858 | } else { |
va009039 | 0:1ed23ab1345f | 1859 | it = it->next; |
va009039 | 0:1ed23ab1345f | 1860 | } |
va009039 | 0:1ed23ab1345f | 1861 | } |
va009039 | 0:1ed23ab1345f | 1862 | |
va009039 | 0:1ed23ab1345f | 1863 | // process |
va009039 | 0:1ed23ab1345f | 1864 | rfcomm_run(); |
va009039 | 0:1ed23ab1345f | 1865 | } |
va009039 | 0:1ed23ab1345f | 1866 | |
va009039 | 0:1ed23ab1345f | 1867 | |
va009039 | 0:1ed23ab1345f | 1868 | |
va009039 | 0:1ed23ab1345f | 1869 |