[337] | 1 | /*
|
---|
| 2 | * Copyright (C) 2009-2012 by Matthias Ringwald
|
---|
| 3 | *
|
---|
| 4 | * Redistribution and use in source and binary forms, with or without
|
---|
| 5 | * modification, are permitted provided that the following conditions
|
---|
| 6 | * are met:
|
---|
| 7 | *
|
---|
| 8 | * 1. Redistributions of source code must retain the above copyright
|
---|
| 9 | * notice, this list of conditions and the following disclaimer.
|
---|
| 10 | * 2. Redistributions in binary form must reproduce the above copyright
|
---|
| 11 | * notice, this list of conditions and the following disclaimer in the
|
---|
| 12 | * documentation and/or other materials provided with the distribution.
|
---|
| 13 | * 3. Neither the name of the copyright holders nor the names of
|
---|
| 14 | * contributors may be used to endorse or promote products derived
|
---|
| 15 | * from this software without specific prior written permission.
|
---|
| 16 | * 4. Any redistribution, use, or modification is done solely for
|
---|
| 17 | * personal benefit and not for any commercial purpose or for
|
---|
| 18 | * monetary gain.
|
---|
| 19 | *
|
---|
| 20 | * THIS SOFTWARE IS PROVIDED BY MATTHIAS RINGWALD AND CONTRIBUTORS
|
---|
| 21 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
---|
| 22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
---|
| 23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
|
---|
| 24 | * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
---|
| 25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
---|
| 26 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
---|
| 27 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
---|
| 28 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
---|
| 29 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
---|
| 30 | * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
---|
| 31 | * SUCH DAMAGE.
|
---|
| 32 | *
|
---|
| 33 | * Please inquire about commercial licensing options at btstack@ringwald.ch
|
---|
| 34 | *
|
---|
| 35 | */
|
---|
| 36 |
|
---|
| 37 | /*
|
---|
| 38 | * rfcomm.c
|
---|
| 39 | */
|
---|
| 40 |
|
---|
| 41 | #include <stdio.h>
|
---|
| 42 | #include <stdlib.h>
|
---|
| 43 | #include <string.h> // memcpy
|
---|
| 44 | #include <stdint.h>
|
---|
| 45 |
|
---|
| 46 | #include <btstack/btstack.h>
|
---|
| 47 | #include <btstack/hci_cmds.h>
|
---|
| 48 | #include <btstack/utils.h>
|
---|
| 49 |
|
---|
| 50 | #include <btstack/utils.h>
|
---|
| 51 | #include "btstack_memory.h"
|
---|
| 52 | #include "hci.h"
|
---|
| 53 | #include "hci_dump.h"
|
---|
| 54 | #include "debug.h"
|
---|
| 55 | #include "rfcomm.h"
|
---|
| 56 |
|
---|
| 57 | // workaround for missing PRIxPTR on mspgcc (16/20-bit MCU)
|
---|
| 58 | #ifndef PRIxPTR
|
---|
| 59 | #if defined(__MSP430X__) && defined(__MSP430X_LARGE__)
|
---|
| 60 | #define PRIxPTR "lx"
|
---|
| 61 | #else
|
---|
| 62 | #define PRIxPTR "x"
|
---|
| 63 | #endif
|
---|
| 64 | #endif
|
---|
| 65 |
|
---|
| 66 |
|
---|
| 67 | // Control field values bit no. 1 2 3 4 PF 6 7 8
|
---|
| 68 | #define BT_RFCOMM_SABM 0x3F // 1 1 1 1 1 1 0 0
|
---|
| 69 | #define BT_RFCOMM_UA 0x73 // 1 1 0 0 1 1 1 0
|
---|
| 70 | #define BT_RFCOMM_DM 0x0F // 1 1 1 1 0 0 0 0
|
---|
| 71 | #define BT_RFCOMM_DM_PF 0x1F // 1 1 1 1 1 0 0 0
|
---|
| 72 | #define BT_RFCOMM_DISC 0x53 // 1 1 0 0 1 0 1 0
|
---|
| 73 | #define BT_RFCOMM_UIH 0xEF // 1 1 1 1 0 1 1 1
|
---|
| 74 | #define BT_RFCOMM_UIH_PF 0xFF // 1 1 1 1 0 1 1 1
|
---|
| 75 |
|
---|
| 76 | // Multiplexer message types
|
---|
| 77 | #define BT_RFCOMM_CLD_CMD 0xC3
|
---|
| 78 | #define BT_RFCOMM_FCON_CMD 0xA3
|
---|
| 79 | #define BT_RFCOMM_FCON_RSP 0xA1
|
---|
| 80 | #define BT_RFCOMM_FCOFF_CMD 0x63
|
---|
| 81 | #define BT_RFCOMM_FCOFF_RSP 0x61
|
---|
| 82 | #define BT_RFCOMM_MSC_CMD 0xE3
|
---|
| 83 | #define BT_RFCOMM_MSC_RSP 0xE1
|
---|
| 84 | #define BT_RFCOMM_NSC_RSP 0x11
|
---|
| 85 | #define BT_RFCOMM_PN_CMD 0x83
|
---|
| 86 | #define BT_RFCOMM_PN_RSP 0x81
|
---|
| 87 | #define BT_RFCOMM_RLS_CMD 0x53
|
---|
| 88 | #define BT_RFCOMM_RLS_RSP 0x51
|
---|
| 89 | #define BT_RFCOMM_RPN_CMD 0x93
|
---|
| 90 | #define BT_RFCOMM_RPN_RSP 0x91
|
---|
| 91 | #define BT_RFCOMM_TEST_CMD 0x23
|
---|
| 92 | #define BT_RFCOMM_TEST_RSP 0x21
|
---|
| 93 |
|
---|
| 94 | #define RFCOMM_MULIPLEXER_TIMEOUT_MS 60000
|
---|
| 95 |
|
---|
| 96 | #define RFCOMM_CREDITS 10
|
---|
| 97 |
|
---|
| 98 | // FCS calc
|
---|
| 99 | #define BT_RFCOMM_CODE_WORD 0xE0 // pol = x8+x2+x1+1
|
---|
| 100 | #define BT_RFCOMM_CRC_CHECK_LEN 3
|
---|
| 101 | #define BT_RFCOMM_UIHCRC_CHECK_LEN 2
|
---|
| 102 |
|
---|
| 103 | #include "l2cap.h"
|
---|
| 104 |
|
---|
| 105 | // used for debugging
|
---|
| 106 | // #define RFCOMM_LOG_CREDITS
|
---|
| 107 |
|
---|
| 108 | // global rfcomm data
|
---|
| 109 | static uint16_t rfcomm_client_cid_generator; // used for client channel IDs
|
---|
| 110 |
|
---|
| 111 | // linked lists for all
|
---|
| 112 | static linked_list_t rfcomm_multiplexers = NULL;
|
---|
| 113 | static linked_list_t rfcomm_channels = NULL;
|
---|
| 114 | static linked_list_t rfcomm_services = NULL;
|
---|
| 115 |
|
---|
| 116 | static gap_security_level_t rfcomm_security_level;
|
---|
| 117 |
|
---|
| 118 | static void (*app_packet_handler)(void * connection, uint8_t packet_type,
|
---|
| 119 | uint16_t channel, uint8_t *packet, uint16_t size);
|
---|
| 120 |
|
---|
| 121 | static void rfcomm_run(void);
|
---|
| 122 | static void rfcomm_hand_out_credits(void);
|
---|
| 123 | static void rfcomm_channel_state_machine(rfcomm_channel_t *channel, rfcomm_channel_event_t *event);
|
---|
| 124 | static void rfcomm_channel_state_machine_2(rfcomm_multiplexer_t * multiplexer, uint8_t dlci, rfcomm_channel_event_t *event);
|
---|
| 125 | static int rfcomm_channel_ready_for_open(rfcomm_channel_t *channel);
|
---|
| 126 | static void rfcomm_multiplexer_state_machine(rfcomm_multiplexer_t * multiplexer, RFCOMM_MULTIPLEXER_EVENT event);
|
---|
| 127 |
|
---|
| 128 |
|
---|
| 129 | // MARK: RFCOMM CLIENT EVENTS
|
---|
| 130 |
|
---|
| 131 | // data: event (8), len(8), address(48), channel (8), rfcomm_cid (16)
|
---|
| 132 | static void rfcomm_emit_connection_request(rfcomm_channel_t *channel) {
|
---|
| 133 | uint8_t event[11];
|
---|
| 134 | log_info("RFCOMM_EVENT_INCOMING_CONNECTION addr %s channel #%u cid 0x%02x",
|
---|
| 135 | bd_addr_to_str(channel->multiplexer->remote_addr), channel->dlci>>1, channel->rfcomm_cid);
|
---|
| 136 | event[0] = RFCOMM_EVENT_INCOMING_CONNECTION;
|
---|
| 137 | event[1] = sizeof(event) - 2;
|
---|
[374] | 138 | reverse_bd_addr(channel->multiplexer->remote_addr, &event[2]);
|
---|
[337] | 139 | event[8] = channel->dlci >> 1;
|
---|
[374] | 140 | little_endian_store_16(event, 9, channel->rfcomm_cid);
|
---|
[337] | 141 | hci_dump_packet(HCI_EVENT_PACKET, 0, event, sizeof(event));
|
---|
| 142 | (*app_packet_handler)(channel->connection, HCI_EVENT_PACKET, 0, (uint8_t *) event, sizeof(event));
|
---|
| 143 | }
|
---|
| 144 |
|
---|
| 145 | // API Change: BTstack-0.3.50x uses
|
---|
| 146 | // data: event(8), len(8), status (8), address (48), server channel(8), rfcomm_cid(16), max frame size(16)
|
---|
| 147 | // next Cydia release will use SVN version of this
|
---|
| 148 | // data: event(8), len(8), status (8), address (48), handle (16), server channel(8), rfcomm_cid(16), max frame size(16)
|
---|
| 149 | static void rfcomm_emit_channel_opened(rfcomm_channel_t *channel, uint8_t status) {
|
---|
| 150 | uint8_t event[16];
|
---|
| 151 | uint8_t pos;
|
---|
| 152 | log_info("RFCOMM_EVENT_OPEN_CHANNEL_COMPLETE status 0x%x addr %s handle 0x%x channel #%u cid 0x%02x mtu %u",
|
---|
| 153 | status, bd_addr_to_str(channel->multiplexer->remote_addr), channel->multiplexer->con_handle,
|
---|
| 154 | channel->dlci>>1, channel->rfcomm_cid, channel->max_frame_size);
|
---|
| 155 | pos = 0;
|
---|
| 156 | event[pos++] = RFCOMM_EVENT_OPEN_CHANNEL_COMPLETE;
|
---|
| 157 | event[pos++] = sizeof(event) - 2;
|
---|
| 158 | event[pos++] = status;
|
---|
[374] | 159 | reverse_bd_addr(channel->multiplexer->remote_addr, &event[pos]); pos += 6;
|
---|
| 160 | little_endian_store_16(event, pos, channel->multiplexer->con_handle); pos += 2;
|
---|
[337] | 161 | event[pos++] = channel->dlci >> 1;
|
---|
[374] | 162 | little_endian_store_16(event, pos, channel->rfcomm_cid); pos += 2; // channel ID
|
---|
| 163 | little_endian_store_16(event, pos, channel->max_frame_size); pos += 2; // max frame size
|
---|
[337] | 164 | hci_dump_packet(HCI_EVENT_PACKET, 0, event, sizeof(event));
|
---|
| 165 | (*app_packet_handler)(channel->connection, HCI_EVENT_PACKET, 0, (uint8_t *) event, pos);
|
---|
| 166 | }
|
---|
| 167 |
|
---|
| 168 | static void rfcomm_emit_channel_open_failed_outgoing_memory(void * connection, bd_addr_t *addr, uint8_t server_channel){
|
---|
| 169 | uint8_t event[16];
|
---|
| 170 | uint8_t pos;
|
---|
| 171 | log_info("RFCOMM_EVENT_OPEN_CHANNEL_COMPLETE BTSTACK_MEMORY_ALLOC_FAILED addr %s",
|
---|
| 172 | bd_addr_to_str(*addr));
|
---|
| 173 | pos = 0;
|
---|
| 174 | event[pos++] = RFCOMM_EVENT_OPEN_CHANNEL_COMPLETE;
|
---|
| 175 | event[pos++] = sizeof(event) - 2;
|
---|
| 176 | event[pos++] = BTSTACK_MEMORY_ALLOC_FAILED;
|
---|
[374] | 177 | reverse_bd_addr(*addr, &event[pos]); pos += 6;
|
---|
| 178 | little_endian_store_16(event, pos, 0); pos += 2;
|
---|
[337] | 179 | event[pos++] = server_channel;
|
---|
[374] | 180 | little_endian_store_16(event, pos, 0); pos += 2; // channel ID
|
---|
| 181 | little_endian_store_16(event, pos, 0); pos += 2; // max frame size
|
---|
[337] | 182 | hci_dump_packet(HCI_EVENT_PACKET, 0, event, sizeof(event));
|
---|
| 183 | (*app_packet_handler)(connection, HCI_EVENT_PACKET, 0, (uint8_t *) event, pos);
|
---|
| 184 | }
|
---|
| 185 |
|
---|
| 186 | // data: event(8), len(8), creidts incoming(8), new credits incoming(8), credits outgoing(8)
|
---|
| 187 | static /*inline*/ void rfcomm_emit_credit_status(rfcomm_channel_t * channel) {
|
---|
| 188 | #ifdef RFCOMM_LOG_CREDITS
|
---|
| 189 | log_info("RFCOMM_LOG_CREDITS incoming %u new_incoming %u outgoing %u", channel->credits_incoming, channel->new_credits_incoming, channel->credits_outgoing);
|
---|
| 190 | uint8_t event[5];
|
---|
| 191 | event[0] = 0x88;
|
---|
| 192 | event[1] = sizeof(event) - 2;
|
---|
| 193 | event[2] = channel->credits_incoming;
|
---|
| 194 | event[3] = channel->new_credits_incoming;
|
---|
| 195 | event[4] = channel->credits_outgoing;
|
---|
| 196 | hci_dump_packet(HCI_EVENT_PACKET, 0, event, sizeof(event));
|
---|
| 197 | #endif
|
---|
| 198 | }
|
---|
| 199 |
|
---|
| 200 | // data: event(8), len(8), rfcomm_cid(16)
|
---|
| 201 | static void rfcomm_emit_channel_closed(rfcomm_channel_t * channel) {
|
---|
| 202 | uint8_t event[4];
|
---|
| 203 | log_info("RFCOMM_EVENT_CHANNEL_CLOSED cid 0x%02x", channel->rfcomm_cid);
|
---|
| 204 | event[0] = RFCOMM_EVENT_CHANNEL_CLOSED;
|
---|
| 205 | event[1] = sizeof(event) - 2;
|
---|
[374] | 206 | little_endian_store_16(event, 2, channel->rfcomm_cid);
|
---|
[337] | 207 | hci_dump_packet(HCI_EVENT_PACKET, 0, event, sizeof(event));
|
---|
| 208 | (*app_packet_handler)(channel->connection, HCI_EVENT_PACKET, 0, (uint8_t *) event, sizeof(event));
|
---|
| 209 | }
|
---|
| 210 |
|
---|
| 211 | static void rfcomm_emit_credits(rfcomm_channel_t * channel, uint8_t credits) {
|
---|
| 212 | uint8_t event[5];
|
---|
| 213 | log_info("RFCOMM_EVENT_CREDITS cid 0x%02x credits %u", channel->rfcomm_cid, credits);
|
---|
| 214 | event[0] = RFCOMM_EVENT_CREDITS;
|
---|
| 215 | event[1] = sizeof(event) - 2;
|
---|
[374] | 216 | little_endian_store_16(event, 2, channel->rfcomm_cid);
|
---|
[337] | 217 | event[4] = credits;
|
---|
| 218 | hci_dump_packet(HCI_EVENT_PACKET, 0, event, sizeof(event));
|
---|
| 219 | (*app_packet_handler)(channel->connection, HCI_EVENT_PACKET, 0, (uint8_t *) event, sizeof(event));
|
---|
| 220 | }
|
---|
| 221 |
|
---|
| 222 | static void rfcomm_emit_service_registered(void *connection, uint8_t status, uint8_t channel){
|
---|
| 223 | uint8_t event[4];
|
---|
| 224 | log_info("RFCOMM_EVENT_SERVICE_REGISTERED status 0x%x channel #%u", status, channel);
|
---|
| 225 | event[0] = RFCOMM_EVENT_SERVICE_REGISTERED;
|
---|
| 226 | event[1] = sizeof(event) - 2;
|
---|
| 227 | event[2] = status;
|
---|
| 228 | event[3] = channel;
|
---|
| 229 | hci_dump_packet( HCI_EVENT_PACKET, 0, event, sizeof(event));
|
---|
| 230 | (*app_packet_handler)(connection, HCI_EVENT_PACKET, 0, (uint8_t *) event, sizeof(event));
|
---|
| 231 | }
|
---|
| 232 |
|
---|
| 233 | // static
|
---|
| 234 | void rfcomm_emit_remote_line_status(rfcomm_channel_t *channel, uint8_t line_status){
|
---|
| 235 | uint8_t event[5];
|
---|
| 236 | log_info("RFCOMM_EVENT_REMOTE_LINE_STATUS cid 0x%02x c, line status 0x%x", channel->rfcomm_cid, line_status);
|
---|
| 237 | event[0] = RFCOMM_EVENT_REMOTE_LINE_STATUS;
|
---|
| 238 | event[1] = sizeof(event) - 2;
|
---|
[374] | 239 | little_endian_store_16(event, 2, channel->rfcomm_cid);
|
---|
[337] | 240 | event[4] = line_status;
|
---|
| 241 | hci_dump_packet( HCI_EVENT_PACKET, 0, event, sizeof(event));
|
---|
| 242 | (*app_packet_handler)(channel->connection, HCI_EVENT_PACKET, 0, (uint8_t *) event, sizeof(event));
|
---|
| 243 | }
|
---|
| 244 |
|
---|
| 245 | void rfcomm_emit_port_configuration(rfcomm_channel_t *channel){
|
---|
| 246 | // notify client about new settings
|
---|
| 247 | uint8_t event[2+sizeof(rfcomm_rpn_data_t)];
|
---|
| 248 | event[0] = RFCOMM_EVENT_PORT_CONFIGURATION;
|
---|
| 249 | event[1] = sizeof(rfcomm_rpn_data_t);
|
---|
| 250 | memcpy(&event[2], (uint8_t*) &channel->rpn_data, sizeof(rfcomm_rpn_data_t));
|
---|
| 251 | hci_dump_packet( HCI_EVENT_PACKET, 0, event, sizeof(event));
|
---|
| 252 | (*app_packet_handler)(channel->connection, HCI_EVENT_PACKET, channel->rfcomm_cid, (uint8_t*)&event, sizeof(event));
|
---|
| 253 | }
|
---|
| 254 |
|
---|
| 255 | // MARK RFCOMM RPN DATA HELPER
|
---|
| 256 | static void rfcomm_rpn_data_set_defaults(rfcomm_rpn_data_t * rpn_data){
|
---|
| 257 | rpn_data->baud_rate = RPN_BAUD_9600; /* 9600 bps */
|
---|
| 258 | rpn_data->flags = 0x03; /* 8-n-1 */
|
---|
| 259 | rpn_data->flow_control = 0; /* no flow control */
|
---|
| 260 | rpn_data->xon = 0xd1; /* XON */
|
---|
| 261 | rpn_data->xoff = 0xd3; /* XOFF */
|
---|
| 262 | rpn_data->parameter_mask_0 = 0x7f; /* parameter mask, all values set */
|
---|
| 263 | rpn_data->parameter_mask_1 = 0x3f; /* parameter mask, all values set */
|
---|
| 264 | }
|
---|
| 265 |
|
---|
| 266 | static void rfcomm_rpn_data_update(rfcomm_rpn_data_t * dest, rfcomm_rpn_data_t * src){
|
---|
| 267 | int i;
|
---|
| 268 | if (src->parameter_mask_0 & RPN_PARAM_MASK_0_BAUD){
|
---|
| 269 | dest->baud_rate = src->baud_rate;
|
---|
| 270 | }
|
---|
| 271 | if (src->parameter_mask_0 & RPN_PARAM_MASK_0_DATA_BITS){
|
---|
| 272 | dest->flags = (dest->flags & 0xfc) | (src->flags & 0x03);
|
---|
| 273 | }
|
---|
| 274 | if (src->parameter_mask_0 & RPN_PARAM_MASK_0_STOP_BITS){
|
---|
| 275 | dest->flags = (dest->flags & 0xfb) | (src->flags & 0x04);
|
---|
| 276 | }
|
---|
| 277 | if (src->parameter_mask_0 & RPN_PARAM_MASK_0_PARITY){
|
---|
| 278 | dest->flags = (dest->flags & 0xf7) | (src->flags & 0x08);
|
---|
| 279 | }
|
---|
| 280 | if (src->parameter_mask_0 & RPN_PARAM_MASK_0_PARITY_TYPE){
|
---|
| 281 | dest->flags = (dest->flags & 0xfc) | (src->flags & 0x30);
|
---|
| 282 | }
|
---|
| 283 | if (src->parameter_mask_0 & RPN_PARAM_MASK_0_XON_CHAR){
|
---|
| 284 | dest->xon = src->xon;
|
---|
| 285 | }
|
---|
| 286 | if (src->parameter_mask_0 & RPN_PARAM_MASK_0_XOFF_CHAR){
|
---|
| 287 | dest->xoff = src->xoff;
|
---|
| 288 | }
|
---|
| 289 | for (i=0; i < 6 ; i++){
|
---|
| 290 | uint8_t mask = 1 << i;
|
---|
| 291 | if (src->parameter_mask_1 & mask){
|
---|
| 292 | dest->flags = (dest->flags & ~mask) | (src->flags & mask);
|
---|
| 293 | }
|
---|
| 294 | }
|
---|
| 295 | // always copy parameter mask, too. informative for client, needed for response
|
---|
| 296 | dest->parameter_mask_0 = src->parameter_mask_0;
|
---|
| 297 | dest->parameter_mask_1 = src->parameter_mask_1;
|
---|
| 298 | }
|
---|
| 299 | // MARK: RFCOMM MULTIPLEXER HELPER
|
---|
| 300 |
|
---|
| 301 | static uint16_t rfcomm_max_frame_size_for_l2cap_mtu(uint16_t l2cap_mtu){
|
---|
| 302 | // Assume RFCOMM header without credits and 2 byte (14 bit) length field
|
---|
| 303 | uint16_t max_frame_size = l2cap_mtu - 5;
|
---|
| 304 | log_info("rfcomm_max_frame_size_for_l2cap_mtu: %u -> %u", l2cap_mtu, max_frame_size);
|
---|
| 305 | return max_frame_size;
|
---|
| 306 | }
|
---|
| 307 |
|
---|
| 308 | static void rfcomm_multiplexer_initialize(rfcomm_multiplexer_t *multiplexer){
|
---|
| 309 |
|
---|
| 310 | memset(multiplexer, 0, sizeof(rfcomm_multiplexer_t));
|
---|
| 311 |
|
---|
| 312 | multiplexer->state = RFCOMM_MULTIPLEXER_CLOSED;
|
---|
| 313 | multiplexer->l2cap_credits = 0;
|
---|
| 314 | multiplexer->fcon = 1;
|
---|
| 315 | multiplexer->send_dm_for_dlci = 0;
|
---|
| 316 | multiplexer->max_frame_size = rfcomm_max_frame_size_for_l2cap_mtu(l2cap_max_mtu());
|
---|
| 317 | multiplexer->test_data_len = 0;
|
---|
| 318 | multiplexer->nsc_command = 0;
|
---|
| 319 | }
|
---|
| 320 |
|
---|
| 321 | static rfcomm_multiplexer_t * rfcomm_multiplexer_create_for_addr(bd_addr_t *addr){
|
---|
| 322 |
|
---|
| 323 | // alloc structure
|
---|
| 324 | rfcomm_multiplexer_t * multiplexer = btstack_memory_rfcomm_multiplexer_get();
|
---|
| 325 | if (!multiplexer) return NULL;
|
---|
| 326 |
|
---|
| 327 | // fill in
|
---|
| 328 | rfcomm_multiplexer_initialize(multiplexer);
|
---|
| 329 | BD_ADDR_COPY(&multiplexer->remote_addr, addr);
|
---|
| 330 |
|
---|
| 331 | // add to services list
|
---|
| 332 | linked_list_add(&rfcomm_multiplexers, (linked_item_t *) multiplexer);
|
---|
| 333 |
|
---|
| 334 | return multiplexer;
|
---|
| 335 | }
|
---|
| 336 |
|
---|
| 337 | static rfcomm_multiplexer_t * rfcomm_multiplexer_for_addr(bd_addr_t *addr){
|
---|
| 338 | linked_item_t *it;
|
---|
| 339 | for (it = (linked_item_t *) rfcomm_multiplexers; it ; it = it->next){
|
---|
| 340 | rfcomm_multiplexer_t * multiplexer = ((rfcomm_multiplexer_t *) it);
|
---|
| 341 | if (BD_ADDR_CMP(addr, multiplexer->remote_addr) == 0) {
|
---|
| 342 | return multiplexer;
|
---|
| 343 | };
|
---|
| 344 | }
|
---|
| 345 | return NULL;
|
---|
| 346 | }
|
---|
| 347 |
|
---|
| 348 | static rfcomm_multiplexer_t * rfcomm_multiplexer_for_l2cap_cid(uint16_t l2cap_cid) {
|
---|
| 349 | linked_item_t *it;
|
---|
| 350 | for (it = (linked_item_t *) rfcomm_multiplexers; it ; it = it->next){
|
---|
| 351 | rfcomm_multiplexer_t * multiplexer = ((rfcomm_multiplexer_t *) it);
|
---|
| 352 | if (multiplexer->l2cap_cid == l2cap_cid) {
|
---|
| 353 | return multiplexer;
|
---|
| 354 | };
|
---|
| 355 | }
|
---|
| 356 | return NULL;
|
---|
| 357 | }
|
---|
| 358 |
|
---|
| 359 | static int rfcomm_multiplexer_has_channels(rfcomm_multiplexer_t * multiplexer){
|
---|
| 360 | linked_item_t *it;
|
---|
| 361 | for (it = (linked_item_t *) rfcomm_channels; it ; it = it->next){
|
---|
| 362 | rfcomm_channel_t * channel = ((rfcomm_channel_t *) it);
|
---|
| 363 | if (channel->multiplexer == multiplexer) {
|
---|
| 364 | return 1;
|
---|
| 365 | }
|
---|
| 366 | }
|
---|
| 367 | return 0;
|
---|
| 368 | }
|
---|
| 369 |
|
---|
| 370 | // MARK: RFCOMM CHANNEL HELPER
|
---|
| 371 |
|
---|
| 372 | static void rfcomm_dump_channels(void){
|
---|
| 373 | #ifndef EMBEDDED
|
---|
| 374 | linked_item_t * it;
|
---|
| 375 | int channels = 0;
|
---|
| 376 | for (it = (linked_item_t *) rfcomm_channels; it ; it = it->next){
|
---|
| 377 | rfcomm_channel_t * channel = (rfcomm_channel_t *) it;
|
---|
| 378 | log_info("Channel #%u: addr %p, state %u", channels, channel, channel->state);
|
---|
| 379 | channels++;
|
---|
| 380 | }
|
---|
| 381 | #endif
|
---|
| 382 | }
|
---|
| 383 |
|
---|
| 384 | static void rfcomm_channel_initialize(rfcomm_channel_t *channel, rfcomm_multiplexer_t *multiplexer,
|
---|
| 385 | rfcomm_service_t *service, uint8_t server_channel){
|
---|
| 386 |
|
---|
| 387 | // don't use 0 as channel id
|
---|
| 388 | if (rfcomm_client_cid_generator == 0) ++rfcomm_client_cid_generator;
|
---|
| 389 |
|
---|
| 390 | // setup channel
|
---|
| 391 | memset(channel, 0, sizeof(rfcomm_channel_t));
|
---|
| 392 |
|
---|
| 393 | channel->state = RFCOMM_CHANNEL_CLOSED;
|
---|
| 394 | channel->state_var = RFCOMM_CHANNEL_STATE_VAR_NONE;
|
---|
| 395 |
|
---|
| 396 | channel->multiplexer = multiplexer;
|
---|
| 397 | channel->service = service;
|
---|
| 398 | channel->rfcomm_cid = rfcomm_client_cid_generator++;
|
---|
| 399 | channel->max_frame_size = multiplexer->max_frame_size;
|
---|
| 400 |
|
---|
| 401 | channel->credits_incoming = 0;
|
---|
| 402 | channel->credits_outgoing = 0;
|
---|
| 403 | channel->packets_granted = 0;
|
---|
| 404 |
|
---|
| 405 | // set defaults for port configuration (even for services)
|
---|
| 406 | rfcomm_rpn_data_set_defaults(&channel->rpn_data);
|
---|
| 407 |
|
---|
| 408 | // incoming flow control not active
|
---|
| 409 | channel->new_credits_incoming =RFCOMM_CREDITS;
|
---|
| 410 | channel->incoming_flow_control = 0;
|
---|
| 411 |
|
---|
| 412 | channel->rls_line_status = RFCOMM_RLS_STATUS_INVALID;
|
---|
| 413 |
|
---|
| 414 | if (service) {
|
---|
| 415 | // incoming connection
|
---|
| 416 | channel->outgoing = 0;
|
---|
| 417 | channel->dlci = (server_channel << 1) | multiplexer->outgoing;
|
---|
| 418 | if (channel->max_frame_size > service->max_frame_size) {
|
---|
| 419 | channel->max_frame_size = service->max_frame_size;
|
---|
| 420 | }
|
---|
| 421 | channel->incoming_flow_control = service->incoming_flow_control;
|
---|
| 422 | channel->new_credits_incoming = service->incoming_initial_credits;
|
---|
| 423 | } else {
|
---|
| 424 | // outgoing connection
|
---|
| 425 | channel->outgoing = 1;
|
---|
| 426 | channel->dlci = (server_channel << 1) | (multiplexer->outgoing ^ 1);
|
---|
| 427 |
|
---|
| 428 | }
|
---|
| 429 | }
|
---|
| 430 |
|
---|
| 431 | // service == NULL -> outgoing channel
|
---|
| 432 | static rfcomm_channel_t * rfcomm_channel_create(rfcomm_multiplexer_t * multiplexer,
|
---|
| 433 | rfcomm_service_t * service, uint8_t server_channel){
|
---|
| 434 | rfcomm_channel_t * channel;
|
---|
| 435 | log_info("rfcomm_channel_create for service %p, channel %u --- list of channels:", service, server_channel);
|
---|
| 436 | rfcomm_dump_channels();
|
---|
| 437 |
|
---|
| 438 | // alloc structure
|
---|
| 439 | channel = btstack_memory_rfcomm_channel_get();
|
---|
| 440 | if (!channel) return NULL;
|
---|
| 441 |
|
---|
| 442 | // fill in
|
---|
| 443 | rfcomm_channel_initialize(channel, multiplexer, service, server_channel);
|
---|
| 444 |
|
---|
| 445 | // add to services list
|
---|
| 446 | linked_list_add(&rfcomm_channels, (linked_item_t *) channel);
|
---|
| 447 |
|
---|
| 448 | return channel;
|
---|
| 449 | }
|
---|
| 450 |
|
---|
| 451 | static rfcomm_channel_t * rfcomm_channel_for_rfcomm_cid(uint16_t rfcomm_cid){
|
---|
| 452 | linked_item_t *it;
|
---|
| 453 | for (it = (linked_item_t *) rfcomm_channels; it ; it = it->next){
|
---|
| 454 | rfcomm_channel_t * channel = ((rfcomm_channel_t *) it);
|
---|
| 455 | if (channel->rfcomm_cid == rfcomm_cid) {
|
---|
| 456 | return channel;
|
---|
| 457 | };
|
---|
| 458 | }
|
---|
| 459 | return NULL;
|
---|
| 460 | }
|
---|
| 461 |
|
---|
| 462 | static rfcomm_channel_t * rfcomm_channel_for_multiplexer_and_dlci(rfcomm_multiplexer_t * multiplexer, uint8_t dlci){
|
---|
| 463 | linked_item_t *it;
|
---|
| 464 | for (it = (linked_item_t *) rfcomm_channels; it ; it = it->next){
|
---|
| 465 | rfcomm_channel_t * channel = ((rfcomm_channel_t *) it);
|
---|
| 466 | if (channel->dlci == dlci && channel->multiplexer == multiplexer) {
|
---|
| 467 | return channel;
|
---|
| 468 | };
|
---|
| 469 | }
|
---|
| 470 | return NULL;
|
---|
| 471 | }
|
---|
| 472 |
|
---|
| 473 | static rfcomm_service_t * rfcomm_service_for_channel(uint8_t server_channel){
|
---|
| 474 | linked_item_t *it;
|
---|
| 475 | for (it = (linked_item_t *) rfcomm_services; it ; it = it->next){
|
---|
| 476 | rfcomm_service_t * service = ((rfcomm_service_t *) it);
|
---|
| 477 | if ( service->server_channel == server_channel){
|
---|
| 478 | return service;
|
---|
| 479 | };
|
---|
| 480 | }
|
---|
| 481 | return NULL;
|
---|
| 482 | }
|
---|
| 483 |
|
---|
| 484 | // MARK: RFCOMM SEND
|
---|
| 485 |
|
---|
| 486 | /**
|
---|
| 487 | * @param credits - only used for RFCOMM flow control in UIH wiht P/F = 1
|
---|
| 488 | */
|
---|
| 489 | 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){
|
---|
| 490 | uint8_t * rfcomm_out_buffer;
|
---|
| 491 | uint16_t pos;
|
---|
| 492 | uint8_t crc_fields;
|
---|
| 493 | int credits_taken;
|
---|
| 494 | int err;
|
---|
| 495 |
|
---|
| 496 | if (!l2cap_can_send_packet_now(multiplexer->l2cap_cid)) return BTSTACK_ACL_BUFFERS_FULL;
|
---|
| 497 |
|
---|
| 498 | l2cap_reserve_packet_buffer();
|
---|
| 499 | rfcomm_out_buffer = l2cap_get_outgoing_buffer();
|
---|
| 500 |
|
---|
| 501 | pos = 0;
|
---|
| 502 | crc_fields = 3;
|
---|
| 503 |
|
---|
| 504 | rfcomm_out_buffer[pos++] = address;
|
---|
| 505 | rfcomm_out_buffer[pos++] = control;
|
---|
| 506 |
|
---|
| 507 | // length field can be 1 or 2 octets
|
---|
| 508 | if (len < 128){
|
---|
| 509 | rfcomm_out_buffer[pos++] = (len << 1)| 1; // bits 0-6
|
---|
| 510 | } else {
|
---|
| 511 | rfcomm_out_buffer[pos++] = (len & 0x7f) << 1; // bits 0-6
|
---|
| 512 | rfcomm_out_buffer[pos++] = len >> 7; // bits 7-14
|
---|
| 513 | crc_fields++;
|
---|
| 514 | }
|
---|
| 515 |
|
---|
| 516 | // add credits for UIH frames when PF bit is set
|
---|
| 517 | if (control == BT_RFCOMM_UIH_PF){
|
---|
| 518 | rfcomm_out_buffer[pos++] = credits;
|
---|
| 519 | }
|
---|
| 520 |
|
---|
| 521 | // copy actual data
|
---|
| 522 | if (len) {
|
---|
| 523 | memcpy(&rfcomm_out_buffer[pos], data, len);
|
---|
| 524 | pos += len;
|
---|
| 525 | }
|
---|
| 526 |
|
---|
| 527 | // UIH frames only calc FCS over address + control (5.1.1)
|
---|
| 528 | if ((control & 0xef) == BT_RFCOMM_UIH){
|
---|
| 529 | crc_fields = 2;
|
---|
| 530 | }
|
---|
| 531 | rfcomm_out_buffer[pos++] = crc8_calc(rfcomm_out_buffer, crc_fields); // calc fcs
|
---|
| 532 |
|
---|
| 533 | credits_taken = 0;
|
---|
| 534 | if (multiplexer->l2cap_credits){
|
---|
| 535 | credits_taken++;
|
---|
| 536 | multiplexer->l2cap_credits--;
|
---|
| 537 | } else {
|
---|
| 538 | log_info( "rfcomm_send_packet addr %02x, ctrl %02x size %u without l2cap credits", address, control, pos);
|
---|
| 539 | }
|
---|
| 540 |
|
---|
| 541 | err = l2cap_send_prepared(multiplexer->l2cap_cid, pos);
|
---|
| 542 |
|
---|
| 543 | if (err) {
|
---|
| 544 | // undo credit counting
|
---|
| 545 | multiplexer->l2cap_credits += credits_taken;
|
---|
| 546 | }
|
---|
| 547 | return err;
|
---|
| 548 | }
|
---|
| 549 |
|
---|
| 550 | // simplified version of rfcomm_send_packet_for_multiplexer for prepared rfcomm packet (UIH, 2 byte len, no credits)
|
---|
| 551 | static int rfcomm_send_uih_prepared(rfcomm_multiplexer_t *multiplexer, uint8_t dlci, uint16_t len){
|
---|
| 552 |
|
---|
| 553 | uint8_t address = (1 << 0) | (multiplexer->outgoing << 1) | (dlci << 2);
|
---|
| 554 | uint8_t control = BT_RFCOMM_UIH;
|
---|
| 555 |
|
---|
| 556 | uint8_t * rfcomm_out_buffer = l2cap_get_outgoing_buffer();
|
---|
| 557 |
|
---|
| 558 | uint16_t pos = 0;
|
---|
| 559 | int credits_taken;
|
---|
| 560 | int err;
|
---|
| 561 |
|
---|
| 562 | rfcomm_out_buffer[pos++] = address;
|
---|
| 563 | rfcomm_out_buffer[pos++] = BT_RFCOMM_UIH;
|
---|
| 564 | rfcomm_out_buffer[pos++] = (len & 0x7f) << 1; // bits 0-6
|
---|
| 565 | rfcomm_out_buffer[pos++] = len >> 7; // bits 7-14
|
---|
| 566 |
|
---|
| 567 | // actual data is already in place
|
---|
| 568 | pos += len;
|
---|
| 569 |
|
---|
| 570 | // UIH frames only calc FCS over address + control (5.1.1)
|
---|
| 571 | rfcomm_out_buffer[pos++] = crc8_calc(rfcomm_out_buffer, 2); // calc fcs
|
---|
| 572 |
|
---|
| 573 | credits_taken = 0;
|
---|
| 574 | if (multiplexer->l2cap_credits){
|
---|
| 575 | credits_taken++;
|
---|
| 576 | multiplexer->l2cap_credits--;
|
---|
| 577 | } else {
|
---|
| 578 | log_info( "rfcomm_send_uih_prepared addr %02x, ctrl %02x size %u without l2cap credits", address, control, pos);
|
---|
| 579 | }
|
---|
| 580 |
|
---|
| 581 | err = l2cap_send_prepared(multiplexer->l2cap_cid, pos);
|
---|
| 582 |
|
---|
| 583 | if (err) {
|
---|
| 584 | // undo credit counting
|
---|
| 585 | multiplexer->l2cap_credits += credits_taken;
|
---|
| 586 | }
|
---|
| 587 | return err;
|
---|
| 588 | }
|
---|
| 589 |
|
---|
| 590 | // C/R Flag in Address
|
---|
| 591 | // - terms: initiator = station that creates multiplexer with SABM
|
---|
| 592 | // - terms: responder = station that responds to multiplexer setup with UA
|
---|
| 593 | // "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"
|
---|
| 594 | // - command initiator = 1 /response responder = 1
|
---|
| 595 | // - command responder = 0 /response initiator = 0
|
---|
| 596 | // "For UIH frames, the C/R bit is always set according to section 5.4.3.1 in GSM 07.10.
|
---|
| 597 | // This applies independently of what is contained wthin the UIH frames, either data or control messages."
|
---|
| 598 | // - c/r = 1 for frames by initiating station, 0 = for frames by responding station
|
---|
| 599 |
|
---|
| 600 | // C/R Flag in Message
|
---|
| 601 | // "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."
|
---|
| 602 | // - If the C/R bit is set to 1 the message is a command
|
---|
| 603 | // - if it is set to 0 the message is a response.
|
---|
| 604 |
|
---|
| 605 | // temp/old messge construction
|
---|
| 606 |
|
---|
| 607 | // new object oriented version
|
---|
| 608 | static int rfcomm_send_sabm(rfcomm_multiplexer_t *multiplexer, uint8_t dlci){
|
---|
| 609 | uint8_t address = (1 << 0) | (multiplexer->outgoing << 1) | (dlci << 2); // command
|
---|
| 610 | return rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_SABM, 0, NULL, 0);
|
---|
| 611 | }
|
---|
| 612 |
|
---|
| 613 | static int rfcomm_send_disc(rfcomm_multiplexer_t *multiplexer, uint8_t dlci){
|
---|
| 614 | uint8_t address = (1 << 0) | (multiplexer->outgoing << 1) | (dlci << 2); // command
|
---|
| 615 | return rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_DISC, 0, NULL, 0);
|
---|
| 616 | }
|
---|
| 617 |
|
---|
| 618 | static int rfcomm_send_ua(rfcomm_multiplexer_t *multiplexer, uint8_t dlci){
|
---|
| 619 | uint8_t address = (1 << 0) | ((multiplexer->outgoing ^ 1) << 1) | (dlci << 2); // response
|
---|
| 620 | return rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_UA, 0, NULL, 0);
|
---|
| 621 | }
|
---|
| 622 |
|
---|
| 623 | static int rfcomm_send_dm_pf(rfcomm_multiplexer_t *multiplexer, uint8_t dlci){
|
---|
| 624 | uint8_t address = (1 << 0) | ((multiplexer->outgoing ^ 1) << 1) | (dlci << 2); // response
|
---|
| 625 | return rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_DM_PF, 0, NULL, 0);
|
---|
| 626 | }
|
---|
| 627 |
|
---|
| 628 | static int rfcomm_send_uih_fc_rsp(rfcomm_multiplexer_t *multiplexer, uint8_t fcon) {
|
---|
| 629 | uint8_t address = (1 << 0) | (multiplexer->outgoing<< 1);
|
---|
| 630 | uint8_t payload[2];
|
---|
| 631 | uint8_t pos = 0;
|
---|
| 632 | payload[pos++] = fcon ? BT_RFCOMM_FCON_RSP : BT_RFCOMM_FCOFF_RSP;
|
---|
| 633 | payload[pos++] = (0 << 1) | 1; // len
|
---|
| 634 | return rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_UIH, 0, (uint8_t *) payload, pos);
|
---|
| 635 | }
|
---|
| 636 |
|
---|
| 637 | // static int rfcomm_send_uih_test_cmd(rfcomm_multiplexer_t *multiplexer, uint8_t * data, uint16_t len) {
|
---|
| 638 | // uint8_t address = (1 << 0) | (multiplexer->outgoing << 1);
|
---|
| 639 | // uint8_t payload[2+len];
|
---|
| 640 | // uint8_t pos = 0;
|
---|
| 641 | // payload[pos++] = BT_RFCOMM_TEST_CMD;
|
---|
| 642 | // payload[pos++] = (len + 1) << 1 | 1; // len
|
---|
| 643 | // memcpy(&payload[pos], data, len);
|
---|
| 644 | // pos += len;
|
---|
| 645 | // return rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_UIH, 0, (uint8_t *) payload, pos);
|
---|
| 646 | // }
|
---|
| 647 |
|
---|
| 648 | static int rfcomm_send_uih_test_rsp(rfcomm_multiplexer_t *multiplexer, uint8_t * data, uint16_t len) {
|
---|
| 649 | uint8_t address = (1 << 0) | (multiplexer->outgoing << 1);
|
---|
| 650 | uint8_t payload[2+RFCOMM_TEST_DATA_MAX_LEN];
|
---|
| 651 | uint8_t pos = 0;
|
---|
| 652 | payload[pos++] = BT_RFCOMM_TEST_RSP;
|
---|
| 653 | if (len > RFCOMM_TEST_DATA_MAX_LEN) {
|
---|
| 654 | len = RFCOMM_TEST_DATA_MAX_LEN;
|
---|
| 655 | }
|
---|
| 656 | payload[pos++] = (len << 1) | 1; // len
|
---|
| 657 | memcpy(&payload[pos], data, len);
|
---|
| 658 | pos += len;
|
---|
| 659 | return rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_UIH, 0, (uint8_t *) payload, pos);
|
---|
| 660 | }
|
---|
| 661 |
|
---|
| 662 | static int rfcomm_send_uih_msc_cmd(rfcomm_multiplexer_t *multiplexer, uint8_t dlci, uint8_t signals) {
|
---|
| 663 | uint8_t address = (1 << 0) | (multiplexer->outgoing << 1);
|
---|
| 664 | uint8_t payload[4];
|
---|
| 665 | uint8_t pos = 0;
|
---|
| 666 | payload[pos++] = BT_RFCOMM_MSC_CMD;
|
---|
| 667 | payload[pos++] = (2 << 1) | 1; // len
|
---|
| 668 | payload[pos++] = (1 << 0) | (1 << 1) | (dlci << 2); // CMD => C/R = 1
|
---|
| 669 | payload[pos++] = signals;
|
---|
| 670 | return rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_UIH, 0, (uint8_t *) payload, pos);
|
---|
| 671 | }
|
---|
| 672 |
|
---|
| 673 | static int rfcomm_send_uih_msc_rsp(rfcomm_multiplexer_t *multiplexer, uint8_t dlci, uint8_t signals) {
|
---|
| 674 | uint8_t address = (1 << 0) | (multiplexer->outgoing<< 1);
|
---|
| 675 | uint8_t payload[4];
|
---|
| 676 | uint8_t pos = 0;
|
---|
| 677 | payload[pos++] = BT_RFCOMM_MSC_RSP;
|
---|
| 678 | payload[pos++] = (2 << 1) | 1; // len
|
---|
| 679 | payload[pos++] = (1 << 0) | (1 << 1) | (dlci << 2); // CMD => C/R = 1
|
---|
| 680 | payload[pos++] = signals;
|
---|
| 681 | return rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_UIH, 0, (uint8_t *) payload, pos);
|
---|
| 682 | }
|
---|
| 683 |
|
---|
| 684 | static int rfcomm_send_uih_nsc_rsp(rfcomm_multiplexer_t *multiplexer, uint8_t command) {
|
---|
| 685 | uint8_t address = (1 << 0) | (multiplexer->outgoing<< 1);
|
---|
| 686 | uint8_t payload[3];
|
---|
| 687 | uint8_t pos = 0;
|
---|
| 688 | payload[pos++] = BT_RFCOMM_NSC_RSP;
|
---|
| 689 | payload[pos++] = (1 << 1) | 1; // len
|
---|
| 690 | payload[pos++] = command;
|
---|
| 691 | return rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_UIH, 0, (uint8_t *) payload, pos);
|
---|
| 692 | }
|
---|
| 693 |
|
---|
| 694 | static int rfcomm_send_uih_pn_command(rfcomm_multiplexer_t *multiplexer, uint8_t dlci, uint16_t max_frame_size){
|
---|
| 695 | uint8_t payload[10];
|
---|
| 696 | uint8_t address = (1 << 0) | (multiplexer->outgoing << 1);
|
---|
| 697 | uint8_t pos = 0;
|
---|
| 698 | payload[pos++] = BT_RFCOMM_PN_CMD;
|
---|
| 699 | payload[pos++] = (8 << 1) | 1; // len
|
---|
| 700 | payload[pos++] = dlci;
|
---|
| 701 | payload[pos++] = 0xf0; // pre-defined for Bluetooth, see 5.5.3 of TS 07.10 Adaption for RFCOMM
|
---|
| 702 | payload[pos++] = 0; // priority
|
---|
| 703 | payload[pos++] = 0; // max 60 seconds ack
|
---|
| 704 | payload[pos++] = max_frame_size & 0xff; // max framesize low
|
---|
| 705 | payload[pos++] = max_frame_size >> 8; // max framesize high
|
---|
| 706 | payload[pos++] = 0x00; // number of retransmissions
|
---|
| 707 | payload[pos++] = 0x00; // (unused error recovery window) initial number of credits
|
---|
| 708 | return rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_UIH, 0, (uint8_t *) payload, pos);
|
---|
| 709 | }
|
---|
| 710 |
|
---|
| 711 | // "The response may not change the DLCI, the priority, the convergence layer, or the timer value." RFCOMM-tutorial.pdf
|
---|
| 712 | static int rfcomm_send_uih_pn_response(rfcomm_multiplexer_t *multiplexer, uint8_t dlci,
|
---|
| 713 | uint8_t priority, uint16_t max_frame_size){
|
---|
| 714 | uint8_t payload[10];
|
---|
| 715 | uint8_t address = (1 << 0) | (multiplexer->outgoing << 1);
|
---|
| 716 | uint8_t pos = 0;
|
---|
| 717 | payload[pos++] = BT_RFCOMM_PN_RSP;
|
---|
| 718 | payload[pos++] = (8 << 1) | 1; // len
|
---|
| 719 | payload[pos++] = dlci;
|
---|
| 720 | payload[pos++] = 0xe0; // pre defined for Bluetooth, see 5.5.3 of TS 07.10 Adaption for RFCOMM
|
---|
| 721 | payload[pos++] = priority; // priority
|
---|
| 722 | payload[pos++] = 0; // max 60 seconds ack
|
---|
| 723 | payload[pos++] = max_frame_size & 0xff; // max framesize low
|
---|
| 724 | payload[pos++] = max_frame_size >> 8; // max framesize high
|
---|
| 725 | payload[pos++] = 0x00; // number of retransmissions
|
---|
| 726 | payload[pos++] = 0x00; // (unused error recovery window) initial number of credits
|
---|
| 727 | return rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_UIH, 0, (uint8_t *) payload, pos);
|
---|
| 728 | }
|
---|
| 729 |
|
---|
| 730 | static int rfcomm_send_uih_rls_cmd(rfcomm_multiplexer_t *multiplexer, uint8_t dlci, uint8_t line_status) {
|
---|
| 731 | uint8_t address = (1 << 0) | (multiplexer->outgoing << 1);
|
---|
| 732 | uint8_t payload[4];
|
---|
| 733 | uint8_t pos = 0;
|
---|
| 734 | payload[pos++] = BT_RFCOMM_RLS_CMD;
|
---|
| 735 | payload[pos++] = (2 << 1) | 1; // len
|
---|
| 736 | payload[pos++] = (1 << 0) | (1 << 1) | (dlci << 2); // CMD => C/R = 1
|
---|
| 737 | payload[pos++] = line_status;
|
---|
| 738 | return rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_UIH, 0, (uint8_t *) payload, pos);
|
---|
| 739 | }
|
---|
| 740 |
|
---|
| 741 | static int rfcomm_send_uih_rls_rsp(rfcomm_multiplexer_t *multiplexer, uint8_t dlci, uint8_t line_status) {
|
---|
| 742 | uint8_t address = (1 << 0) | (multiplexer->outgoing << 1);
|
---|
| 743 | uint8_t payload[4];
|
---|
| 744 | uint8_t pos = 0;
|
---|
| 745 | payload[pos++] = BT_RFCOMM_RLS_RSP;
|
---|
| 746 | payload[pos++] = (2 << 1) | 1; // len
|
---|
| 747 | payload[pos++] = (1 << 0) | (1 << 1) | (dlci << 2); // CMD => C/R = 1
|
---|
| 748 | payload[pos++] = line_status;
|
---|
| 749 | return rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_UIH, 0, (uint8_t *) payload, pos);
|
---|
| 750 | }
|
---|
| 751 |
|
---|
| 752 | static int rfcomm_send_uih_rpn_cmd(rfcomm_multiplexer_t *multiplexer, uint8_t dlci, rfcomm_rpn_data_t *rpn_data) {
|
---|
| 753 | uint8_t payload[10];
|
---|
| 754 | uint8_t address = (1 << 0) | (multiplexer->outgoing << 1);
|
---|
| 755 | uint8_t pos = 0;
|
---|
| 756 | payload[pos++] = BT_RFCOMM_RPN_CMD;
|
---|
| 757 | payload[pos++] = (8 << 1) | 1; // len
|
---|
| 758 | payload[pos++] = (1 << 0) | (1 << 1) | (dlci << 2); // CMD => C/R = 1
|
---|
| 759 | payload[pos++] = rpn_data->baud_rate;
|
---|
| 760 | payload[pos++] = rpn_data->flags;
|
---|
| 761 | payload[pos++] = rpn_data->flow_control;
|
---|
| 762 | payload[pos++] = rpn_data->xon;
|
---|
| 763 | payload[pos++] = rpn_data->xoff;
|
---|
| 764 | payload[pos++] = rpn_data->parameter_mask_0;
|
---|
| 765 | payload[pos++] = rpn_data->parameter_mask_1;
|
---|
| 766 | return rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_UIH, 0, (uint8_t *) payload, pos);
|
---|
| 767 | }
|
---|
| 768 |
|
---|
| 769 | static int rfcomm_send_uih_rpn_req(rfcomm_multiplexer_t *multiplexer, uint8_t dlci) {
|
---|
| 770 | uint8_t payload[3];
|
---|
| 771 | uint8_t address = (1 << 0) | (multiplexer->outgoing << 1);
|
---|
| 772 | uint8_t pos = 0;
|
---|
| 773 | payload[pos++] = BT_RFCOMM_RPN_CMD;
|
---|
| 774 | payload[pos++] = (1 << 1) | 1; // len
|
---|
| 775 | payload[pos++] = (1 << 0) | (1 << 1) | (dlci << 2); // CMD => C/R = 1
|
---|
| 776 | return rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_UIH, 0, (uint8_t *) payload, pos);
|
---|
| 777 | }
|
---|
| 778 |
|
---|
| 779 | static int rfcomm_send_uih_rpn_rsp(rfcomm_multiplexer_t *multiplexer, uint8_t dlci, rfcomm_rpn_data_t *rpn_data) {
|
---|
| 780 | uint8_t payload[10];
|
---|
| 781 | uint8_t address = (1 << 0) | (multiplexer->outgoing << 1);
|
---|
| 782 | uint8_t pos = 0;
|
---|
| 783 | payload[pos++] = BT_RFCOMM_RPN_RSP;
|
---|
| 784 | payload[pos++] = (8 << 1) | 1; // len
|
---|
| 785 | payload[pos++] = (1 << 0) | (1 << 1) | (dlci << 2); // CMD => C/R = 1
|
---|
| 786 | payload[pos++] = rpn_data->baud_rate;
|
---|
| 787 | payload[pos++] = rpn_data->flags;
|
---|
| 788 | payload[pos++] = rpn_data->flow_control;
|
---|
| 789 | payload[pos++] = rpn_data->xon;
|
---|
| 790 | payload[pos++] = rpn_data->xoff;
|
---|
| 791 | payload[pos++] = rpn_data->parameter_mask_0;
|
---|
| 792 | payload[pos++] = rpn_data->parameter_mask_1;
|
---|
| 793 | return rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_UIH, 0, (uint8_t *) payload, pos);
|
---|
| 794 | }
|
---|
| 795 |
|
---|
| 796 | static void rfcomm_send_uih_credits(rfcomm_multiplexer_t *multiplexer, uint8_t dlci, uint8_t credits){
|
---|
| 797 | uint8_t address = (1 << 0) | (multiplexer->outgoing << 1) | (dlci << 2);
|
---|
| 798 | rfcomm_send_packet_for_multiplexer(multiplexer, address, BT_RFCOMM_UIH_PF, credits, NULL, 0);
|
---|
| 799 | }
|
---|
| 800 |
|
---|
| 801 | // MARK: RFCOMM MULTIPLEXER
|
---|
| 802 | static void rfcomm_multiplexer_stop_timer(rfcomm_multiplexer_t * multiplexer){
|
---|
| 803 | if (multiplexer->timer_active) {
|
---|
| 804 | run_loop_remove_timer(&multiplexer->timer);
|
---|
| 805 | multiplexer->timer_active = 0;
|
---|
| 806 | }
|
---|
| 807 | }
|
---|
| 808 | static void rfcomm_multiplexer_free(rfcomm_multiplexer_t * multiplexer){
|
---|
| 809 | linked_list_remove( &rfcomm_multiplexers, (linked_item_t *) multiplexer);
|
---|
| 810 | btstack_memory_rfcomm_multiplexer_free(multiplexer);
|
---|
| 811 | }
|
---|
| 812 |
|
---|
| 813 | static void rfcomm_multiplexer_finalize(rfcomm_multiplexer_t * multiplexer){
|
---|
| 814 | linked_item_t *it;
|
---|
| 815 | uint16_t l2cap_cid;
|
---|
| 816 |
|
---|
| 817 | // remove (potential) timer
|
---|
| 818 | rfcomm_multiplexer_stop_timer(multiplexer);
|
---|
| 819 |
|
---|
| 820 | // close and remove all channels
|
---|
| 821 | it = (linked_item_t *) &rfcomm_channels;
|
---|
| 822 | while (it->next){
|
---|
| 823 | rfcomm_channel_t * channel = (rfcomm_channel_t *) it->next;
|
---|
| 824 | if (channel->multiplexer == multiplexer) {
|
---|
| 825 | // emit appropriate events
|
---|
| 826 | if (channel->state == RFCOMM_CHANNEL_OPEN) {
|
---|
| 827 | rfcomm_emit_channel_closed(channel);
|
---|
| 828 | } else {
|
---|
| 829 | rfcomm_emit_channel_opened(channel, RFCOMM_MULTIPLEXER_STOPPED);
|
---|
| 830 | }
|
---|
| 831 | // remove from list
|
---|
| 832 | it->next = it->next->next;
|
---|
| 833 | // free channel struct
|
---|
| 834 | btstack_memory_rfcomm_channel_free(channel);
|
---|
| 835 | } else {
|
---|
| 836 | it = it->next;
|
---|
| 837 | }
|
---|
| 838 | }
|
---|
| 839 |
|
---|
| 840 | // keep reference to l2cap channel
|
---|
| 841 | l2cap_cid = multiplexer->l2cap_cid;
|
---|
| 842 |
|
---|
| 843 | // remove mutliplexer
|
---|
| 844 | rfcomm_multiplexer_free(multiplexer);
|
---|
| 845 |
|
---|
| 846 | // close l2cap multiplexer channel, too
|
---|
| 847 | l2cap_disconnect_internal(l2cap_cid, 0x13);
|
---|
| 848 | }
|
---|
| 849 |
|
---|
| 850 | static void rfcomm_multiplexer_timer_handler(timer_source_t *timer){
|
---|
| 851 | rfcomm_multiplexer_t * multiplexer = (rfcomm_multiplexer_t *) linked_item_get_user( (linked_item_t *) timer);
|
---|
| 852 | if (!rfcomm_multiplexer_has_channels(multiplexer)){
|
---|
| 853 | log_info( "rfcomm_multiplexer_timer_handler timeout: shutting down multiplexer!");
|
---|
| 854 | rfcomm_multiplexer_finalize(multiplexer);
|
---|
| 855 | }
|
---|
| 856 | }
|
---|
| 857 |
|
---|
| 858 | static void rfcomm_multiplexer_prepare_idle_timer(rfcomm_multiplexer_t * multiplexer){
|
---|
| 859 | if (multiplexer->timer_active) {
|
---|
| 860 | run_loop_remove_timer(&multiplexer->timer);
|
---|
| 861 | multiplexer->timer_active = 0;
|
---|
| 862 | }
|
---|
| 863 | if (!rfcomm_multiplexer_has_channels(multiplexer)){
|
---|
| 864 | // start timer for multiplexer timeout check
|
---|
| 865 | run_loop_set_timer(&multiplexer->timer, RFCOMM_MULIPLEXER_TIMEOUT_MS);
|
---|
| 866 | multiplexer->timer.process = rfcomm_multiplexer_timer_handler;
|
---|
| 867 | linked_item_set_user((linked_item_t*) &multiplexer->timer, multiplexer);
|
---|
| 868 | run_loop_add_timer(&multiplexer->timer);
|
---|
| 869 | multiplexer->timer_active = 1;
|
---|
| 870 | }
|
---|
| 871 | }
|
---|
| 872 |
|
---|
| 873 | static void rfcomm_multiplexer_opened(rfcomm_multiplexer_t *multiplexer){
|
---|
| 874 | rfcomm_channel_event_t event = { CH_EVT_MULTIPLEXER_READY };
|
---|
| 875 | linked_item_t *it;
|
---|
| 876 | log_info("Multiplexer up and running");
|
---|
| 877 | multiplexer->state = RFCOMM_MULTIPLEXER_OPEN;
|
---|
| 878 |
|
---|
| 879 | // transition of channels that wait for multiplexer
|
---|
| 880 | for (it = (linked_item_t *) rfcomm_channels; it ; it = it->next){
|
---|
| 881 | rfcomm_channel_t * channel = ((rfcomm_channel_t *) it);
|
---|
| 882 | if (channel->multiplexer != multiplexer) continue;
|
---|
| 883 | rfcomm_channel_state_machine(channel, &event);
|
---|
| 884 | }
|
---|
| 885 |
|
---|
| 886 | rfcomm_run();
|
---|
| 887 | rfcomm_multiplexer_prepare_idle_timer(multiplexer);
|
---|
| 888 | }
|
---|
| 889 |
|
---|
| 890 |
|
---|
| 891 | /**
|
---|
| 892 | * @return handled packet
|
---|
| 893 | */
|
---|
| 894 | static int rfcomm_multiplexer_hci_event_handler(uint8_t *packet, uint16_t size){
|
---|
| 895 | bd_addr_t event_addr;
|
---|
| 896 | uint16_t psm;
|
---|
| 897 | uint16_t l2cap_cid;
|
---|
| 898 | hci_con_handle_t con_handle;
|
---|
| 899 | rfcomm_multiplexer_t *multiplexer = NULL;
|
---|
| 900 | uint8_t status;
|
---|
| 901 |
|
---|
| 902 | switch (packet[0]) {
|
---|
| 903 |
|
---|
| 904 | // accept incoming PSM_RFCOMM connection if no multiplexer exists yet
|
---|
| 905 | case L2CAP_EVENT_INCOMING_CONNECTION:
|
---|
| 906 | // data: event(8), len(8), address(48), handle (16), psm (16), source cid(16) dest cid(16)
|
---|
[374] | 907 | reverse_bd_addr(&packet[2], event_addr);
|
---|
| 908 | con_handle = little_endian_read_16(packet, 8);
|
---|
| 909 | psm = little_endian_read_16(packet, 10);
|
---|
| 910 | l2cap_cid = little_endian_read_16(packet, 12);
|
---|
[337] | 911 |
|
---|
| 912 | if (psm != PSM_RFCOMM) break;
|
---|
| 913 |
|
---|
| 914 | multiplexer = rfcomm_multiplexer_for_addr(&event_addr);
|
---|
| 915 |
|
---|
| 916 | if (multiplexer) {
|
---|
| 917 | log_info("INCOMING_CONNECTION (l2cap_cid 0x%02x) for PSM_RFCOMM => decline - multiplexer already exists", l2cap_cid);
|
---|
| 918 | l2cap_decline_connection_internal(l2cap_cid, 0x04); // no resources available
|
---|
| 919 | return 1;
|
---|
| 920 | }
|
---|
| 921 |
|
---|
| 922 | // create and inititialize new multiplexer instance (incoming)
|
---|
| 923 | multiplexer = rfcomm_multiplexer_create_for_addr(&event_addr);
|
---|
| 924 | if (!multiplexer){
|
---|
| 925 | log_info("INCOMING_CONNECTION (l2cap_cid 0x%02x) for PSM_RFCOMM => decline - no memory left", l2cap_cid);
|
---|
| 926 | l2cap_decline_connection_internal(l2cap_cid, 0x04); // no resources available
|
---|
| 927 | return 1;
|
---|
| 928 | }
|
---|
| 929 |
|
---|
| 930 | multiplexer->con_handle = con_handle;
|
---|
| 931 | multiplexer->l2cap_cid = l2cap_cid;
|
---|
| 932 | multiplexer->state = RFCOMM_MULTIPLEXER_W4_SABM_0;
|
---|
| 933 |
|
---|
| 934 | log_info("L2CAP_EVENT_INCOMING_CONNECTION (l2cap_cid 0x%02x) for PSM_RFCOMM => accept", l2cap_cid);
|
---|
| 935 | l2cap_accept_connection_internal(l2cap_cid);
|
---|
| 936 | return 1;
|
---|
| 937 |
|
---|
| 938 | // l2cap connection opened -> store l2cap_cid, remote_addr
|
---|
| 939 | case L2CAP_EVENT_CHANNEL_OPENED:
|
---|
| 940 |
|
---|
[374] | 941 | if (little_endian_read_16(packet, 11) != PSM_RFCOMM) break;
|
---|
[337] | 942 |
|
---|
| 943 | status = packet[2];
|
---|
| 944 | log_info("L2CAP_EVENT_CHANNEL_OPENED for PSM_RFCOMM, status %u", status);
|
---|
| 945 |
|
---|
| 946 | // get multiplexer for remote addr
|
---|
[374] | 947 | con_handle = little_endian_read_16(packet, 9);
|
---|
| 948 | l2cap_cid = little_endian_read_16(packet, 13);
|
---|
| 949 | reverse_bd_addr(&packet[3], event_addr);
|
---|
[337] | 950 | multiplexer = rfcomm_multiplexer_for_addr(&event_addr);
|
---|
| 951 | if (!multiplexer) {
|
---|
| 952 | log_error("L2CAP_EVENT_CHANNEL_OPENED but no multiplexer prepared");
|
---|
| 953 | return 1;
|
---|
| 954 | }
|
---|
| 955 |
|
---|
| 956 | // on l2cap open error discard everything
|
---|
| 957 | if (status){
|
---|
| 958 | linked_item_t * it;
|
---|
| 959 |
|
---|
| 960 | // remove (potential) timer
|
---|
| 961 | rfcomm_multiplexer_stop_timer(multiplexer);
|
---|
| 962 |
|
---|
| 963 | // emit rfcomm_channel_opened with status and free channel
|
---|
| 964 | it = (linked_item_t *) &rfcomm_channels;
|
---|
| 965 | while (it->next) {
|
---|
| 966 | rfcomm_channel_t * channel = (rfcomm_channel_t *) it->next;
|
---|
| 967 | if (channel->multiplexer == multiplexer){
|
---|
| 968 | rfcomm_emit_channel_opened(channel, status);
|
---|
| 969 | it->next = it->next->next;
|
---|
| 970 | btstack_memory_rfcomm_channel_free(channel);
|
---|
| 971 | } else {
|
---|
| 972 | it = it->next;
|
---|
| 973 | }
|
---|
| 974 | }
|
---|
| 975 |
|
---|
| 976 | // free multiplexer
|
---|
| 977 | rfcomm_multiplexer_free(multiplexer);
|
---|
| 978 | return 1;
|
---|
| 979 | }
|
---|
| 980 |
|
---|
| 981 | if (multiplexer->state == RFCOMM_MULTIPLEXER_W4_CONNECT) {
|
---|
| 982 | log_info("L2CAP_EVENT_CHANNEL_OPENED: outgoing connection");
|
---|
| 983 | // wrong remote addr
|
---|
| 984 | if (BD_ADDR_CMP(event_addr, multiplexer->remote_addr)) break;
|
---|
| 985 | multiplexer->l2cap_cid = l2cap_cid;
|
---|
| 986 | multiplexer->con_handle = con_handle;
|
---|
| 987 | // send SABM #0
|
---|
| 988 | multiplexer->state = RFCOMM_MULTIPLEXER_SEND_SABM_0;
|
---|
| 989 | } else { // multiplexer->state == RFCOMM_MULTIPLEXER_W4_SABM_0
|
---|
| 990 |
|
---|
| 991 | // set max frame size based on l2cap MTU
|
---|
[374] | 992 | multiplexer->max_frame_size = rfcomm_max_frame_size_for_l2cap_mtu(little_endian_read_16(packet, 17));
|
---|
[337] | 993 | }
|
---|
| 994 | return 1;
|
---|
| 995 |
|
---|
| 996 | // l2cap disconnect -> state = RFCOMM_MULTIPLEXER_CLOSED;
|
---|
| 997 |
|
---|
| 998 | case L2CAP_EVENT_CREDITS:
|
---|
| 999 | // data: event(8), len(8), local_cid(16), credits(8)
|
---|
[374] | 1000 | l2cap_cid = little_endian_read_16(packet, 2);
|
---|
[337] | 1001 | multiplexer = rfcomm_multiplexer_for_l2cap_cid(l2cap_cid);
|
---|
| 1002 | if (!multiplexer) break;
|
---|
| 1003 | multiplexer->l2cap_credits += packet[4];
|
---|
| 1004 |
|
---|
| 1005 | // log_info("L2CAP_EVENT_CREDITS: %u (now %u)", packet[4], multiplexer->l2cap_credits);
|
---|
| 1006 |
|
---|
| 1007 | // new credits, continue with signaling
|
---|
| 1008 | rfcomm_run();
|
---|
| 1009 |
|
---|
| 1010 | if (multiplexer->state != RFCOMM_MULTIPLEXER_OPEN) break;
|
---|
| 1011 | rfcomm_hand_out_credits();
|
---|
| 1012 | return 1;
|
---|
| 1013 |
|
---|
| 1014 | case DAEMON_EVENT_HCI_PACKET_SENT:
|
---|
| 1015 | // testing DMA done code
|
---|
| 1016 | rfcomm_run();
|
---|
| 1017 | break;
|
---|
| 1018 |
|
---|
| 1019 | case L2CAP_EVENT_CHANNEL_CLOSED:
|
---|
| 1020 | // data: event (8), len(8), channel (16)
|
---|
[374] | 1021 | l2cap_cid = little_endian_read_16(packet, 2);
|
---|
[337] | 1022 | multiplexer = rfcomm_multiplexer_for_l2cap_cid(l2cap_cid);
|
---|
| 1023 | log_info("L2CAP_EVENT_CHANNEL_CLOSED cid 0x%0x, mult %p", l2cap_cid, multiplexer);
|
---|
| 1024 | if (!multiplexer) break;
|
---|
| 1025 | log_info("L2CAP_EVENT_CHANNEL_CLOSED state %u", multiplexer->state);
|
---|
| 1026 | switch (multiplexer->state) {
|
---|
| 1027 | case RFCOMM_MULTIPLEXER_W4_CONNECT:
|
---|
| 1028 | case RFCOMM_MULTIPLEXER_SEND_SABM_0:
|
---|
| 1029 | case RFCOMM_MULTIPLEXER_W4_SABM_0:
|
---|
| 1030 | case RFCOMM_MULTIPLEXER_SEND_UA_0:
|
---|
| 1031 | case RFCOMM_MULTIPLEXER_W4_UA_0:
|
---|
| 1032 | case RFCOMM_MULTIPLEXER_OPEN:
|
---|
| 1033 | rfcomm_multiplexer_finalize(multiplexer);
|
---|
| 1034 | return 1;
|
---|
| 1035 | default:
|
---|
| 1036 | break;
|
---|
| 1037 | }
|
---|
| 1038 | break;
|
---|
| 1039 | default:
|
---|
| 1040 | break;
|
---|
| 1041 | }
|
---|
| 1042 | return 0;
|
---|
| 1043 | }
|
---|
| 1044 |
|
---|
| 1045 | static int rfcomm_multiplexer_l2cap_packet_handler(uint16_t channel, uint8_t *packet, uint16_t size){
|
---|
| 1046 |
|
---|
| 1047 | // get or create a multiplexer for a certain device
|
---|
| 1048 | rfcomm_multiplexer_t *multiplexer = rfcomm_multiplexer_for_l2cap_cid(channel);
|
---|
| 1049 | uint8_t frame_dlci;
|
---|
| 1050 | uint8_t length_offset;
|
---|
| 1051 | uint8_t credit_offset;
|
---|
| 1052 | uint8_t payload_offset;
|
---|
| 1053 |
|
---|
| 1054 | if (!multiplexer) return 0;
|
---|
| 1055 |
|
---|
| 1056 | // but only care for multiplexer control channel
|
---|
| 1057 | frame_dlci = packet[0] >> 2;
|
---|
| 1058 | if (frame_dlci) return 0;
|
---|
| 1059 | length_offset = (packet[2] & 1) ^ 1; // to be used for pos >= 3
|
---|
| 1060 | credit_offset = ((packet[1] & BT_RFCOMM_UIH_PF) == BT_RFCOMM_UIH_PF) ? 1 : 0; // credits for uih_pf frames
|
---|
| 1061 | payload_offset = 3 + length_offset + credit_offset;
|
---|
| 1062 | switch (packet[1]){
|
---|
| 1063 |
|
---|
| 1064 | case BT_RFCOMM_SABM:
|
---|
| 1065 | if (multiplexer->state == RFCOMM_MULTIPLEXER_W4_SABM_0){
|
---|
| 1066 | log_info("Received SABM #0");
|
---|
| 1067 | multiplexer->outgoing = 0;
|
---|
| 1068 | multiplexer->state = RFCOMM_MULTIPLEXER_SEND_UA_0;
|
---|
| 1069 | return 1;
|
---|
| 1070 | }
|
---|
| 1071 | break;
|
---|
| 1072 |
|
---|
| 1073 | case BT_RFCOMM_UA:
|
---|
| 1074 | if (multiplexer->state == RFCOMM_MULTIPLEXER_W4_UA_0) {
|
---|
| 1075 | // UA #0 -> send UA #0, state = RFCOMM_MULTIPLEXER_OPEN
|
---|
| 1076 | log_info("Received UA #0 ");
|
---|
| 1077 | rfcomm_multiplexer_opened(multiplexer);
|
---|
| 1078 | return 1;
|
---|
| 1079 | }
|
---|
| 1080 | break;
|
---|
| 1081 |
|
---|
| 1082 | case BT_RFCOMM_DISC:
|
---|
| 1083 | // DISC #0 -> send UA #0, close multiplexer
|
---|
| 1084 | log_info("Received DISC #0, (ougoing = %u)", multiplexer->outgoing);
|
---|
| 1085 | multiplexer->state = RFCOMM_MULTIPLEXER_SEND_UA_0_AND_DISC;
|
---|
| 1086 | return 1;
|
---|
| 1087 |
|
---|
| 1088 | case BT_RFCOMM_DM:
|
---|
| 1089 | // DM #0 - we shouldn't get this, just give up
|
---|
| 1090 | log_info("Received DM #0");
|
---|
| 1091 | log_info("-> Closing down multiplexer");
|
---|
| 1092 | rfcomm_multiplexer_finalize(multiplexer);
|
---|
| 1093 | return 1;
|
---|
| 1094 |
|
---|
| 1095 | case BT_RFCOMM_UIH:
|
---|
| 1096 | if (packet[payload_offset] == BT_RFCOMM_CLD_CMD){
|
---|
| 1097 | // Multiplexer close down (CLD) -> close mutliplexer
|
---|
| 1098 | log_info("Received Multiplexer close down command");
|
---|
| 1099 | log_info("-> Closing down multiplexer");
|
---|
| 1100 | rfcomm_multiplexer_finalize(multiplexer);
|
---|
| 1101 | return 1;
|
---|
| 1102 | }
|
---|
| 1103 | switch (packet[payload_offset]){
|
---|
| 1104 | case BT_RFCOMM_CLD_CMD:
|
---|
| 1105 | // Multiplexer close down (CLD) -> close mutliplexer
|
---|
| 1106 | log_info("Received Multiplexer close down command");
|
---|
| 1107 | log_info("-> Closing down multiplexer");
|
---|
| 1108 | rfcomm_multiplexer_finalize(multiplexer);
|
---|
| 1109 | return 1;
|
---|
| 1110 |
|
---|
| 1111 | case BT_RFCOMM_FCON_CMD:
|
---|
| 1112 | multiplexer->fcon = 0x81;
|
---|
| 1113 | break;
|
---|
| 1114 |
|
---|
| 1115 | case BT_RFCOMM_FCOFF_CMD:
|
---|
| 1116 | multiplexer->fcon = 0x80;
|
---|
| 1117 | break;
|
---|
| 1118 |
|
---|
| 1119 | case BT_RFCOMM_TEST_CMD: {
|
---|
| 1120 | int len;
|
---|
| 1121 | log_info("Received test command");
|
---|
| 1122 | len = packet[payload_offset+1] >> 1; // length < 125
|
---|
| 1123 | if (len > RFCOMM_TEST_DATA_MAX_LEN){
|
---|
| 1124 | len = RFCOMM_TEST_DATA_MAX_LEN;
|
---|
| 1125 | }
|
---|
| 1126 | multiplexer->test_data_len = len;
|
---|
| 1127 | memcpy(multiplexer->test_data, &packet[payload_offset + 2], len);
|
---|
| 1128 | return 1;
|
---|
| 1129 | }
|
---|
| 1130 | default:
|
---|
| 1131 | break;
|
---|
| 1132 | }
|
---|
| 1133 | break;
|
---|
| 1134 |
|
---|
| 1135 | default:
|
---|
| 1136 | break;
|
---|
| 1137 |
|
---|
| 1138 | }
|
---|
| 1139 | return 0;
|
---|
| 1140 | }
|
---|
| 1141 |
|
---|
| 1142 | static void rfcomm_multiplexer_state_machine(rfcomm_multiplexer_t * multiplexer, RFCOMM_MULTIPLEXER_EVENT event){
|
---|
| 1143 |
|
---|
| 1144 | // process stored DM responses
|
---|
| 1145 | if (multiplexer->send_dm_for_dlci){
|
---|
| 1146 | uint8_t dlci = multiplexer->send_dm_for_dlci;
|
---|
| 1147 | multiplexer->send_dm_for_dlci = 0;
|
---|
| 1148 | rfcomm_send_dm_pf(multiplexer, dlci);
|
---|
| 1149 | return;
|
---|
| 1150 | }
|
---|
| 1151 |
|
---|
| 1152 | if (multiplexer->nsc_command){
|
---|
| 1153 | uint8_t command = multiplexer->nsc_command;
|
---|
| 1154 | multiplexer->nsc_command = 0;
|
---|
| 1155 | rfcomm_send_uih_nsc_rsp(multiplexer, command);
|
---|
| 1156 | return;
|
---|
| 1157 | }
|
---|
| 1158 |
|
---|
| 1159 | if (multiplexer->fcon & 0x80){
|
---|
| 1160 | uint8_t event[] = { DAEMON_EVENT_HCI_PACKET_SENT, 0};
|
---|
| 1161 | linked_item_t *it;
|
---|
| 1162 | multiplexer->fcon &= 0x01;
|
---|
| 1163 | rfcomm_send_uih_fc_rsp(multiplexer, multiplexer->fcon);
|
---|
| 1164 | if (multiplexer->fcon == 0) return;
|
---|
| 1165 | // trigger client to send again after sending FCon Response
|
---|
| 1166 | for (it = (linked_item_t *) rfcomm_channels; it ; it = it->next){
|
---|
| 1167 | rfcomm_channel_t * channel = ((rfcomm_channel_t *) it);
|
---|
| 1168 | if (channel->multiplexer != multiplexer) continue;
|
---|
| 1169 | (*app_packet_handler)(channel->connection, HCI_EVENT_PACKET, 0, (uint8_t *) event, sizeof(event));
|
---|
| 1170 | }
|
---|
| 1171 | return;
|
---|
| 1172 | }
|
---|
| 1173 |
|
---|
| 1174 | switch (multiplexer->state) {
|
---|
| 1175 | case RFCOMM_MULTIPLEXER_SEND_SABM_0:
|
---|
| 1176 | switch (event) {
|
---|
| 1177 | case MULT_EV_READY_TO_SEND:
|
---|
| 1178 | log_info("Sending SABM #0 - (multi 0x%p)", multiplexer);
|
---|
| 1179 | multiplexer->state = RFCOMM_MULTIPLEXER_W4_UA_0;
|
---|
| 1180 | rfcomm_send_sabm(multiplexer, 0);
|
---|
| 1181 | break;
|
---|
| 1182 | default:
|
---|
| 1183 | break;
|
---|
| 1184 | }
|
---|
| 1185 | break;
|
---|
| 1186 | case RFCOMM_MULTIPLEXER_SEND_UA_0:
|
---|
| 1187 | switch (event) {
|
---|
| 1188 | case MULT_EV_READY_TO_SEND:
|
---|
| 1189 | log_info("Sending UA #0");
|
---|
| 1190 | multiplexer->state = RFCOMM_MULTIPLEXER_OPEN;
|
---|
| 1191 | rfcomm_send_ua(multiplexer, 0);
|
---|
| 1192 | rfcomm_multiplexer_opened(multiplexer);
|
---|
| 1193 | break;
|
---|
| 1194 | default:
|
---|
| 1195 | break;
|
---|
| 1196 | }
|
---|
| 1197 | break;
|
---|
| 1198 | case RFCOMM_MULTIPLEXER_SEND_UA_0_AND_DISC:
|
---|
| 1199 | switch (event) {
|
---|
| 1200 | case MULT_EV_READY_TO_SEND:
|
---|
| 1201 | // try to detect authentication errors: drop link key if multiplexer closed before first channel got opened
|
---|
| 1202 | if (!multiplexer->at_least_one_connection){
|
---|
| 1203 | log_info("TODO: no connections established - delete link key prophylactically");
|
---|
| 1204 | // hci_send_cmd(&hci_delete_stored_link_key, multiplexer->remote_addr);
|
---|
| 1205 | }
|
---|
| 1206 | log_info("Sending UA #0");
|
---|
| 1207 | log_info("Closing down multiplexer");
|
---|
| 1208 | multiplexer->state = RFCOMM_MULTIPLEXER_CLOSED;
|
---|
| 1209 | rfcomm_send_ua(multiplexer, 0);
|
---|
| 1210 | rfcomm_multiplexer_finalize(multiplexer);
|
---|
| 1211 | default:
|
---|
| 1212 | break;
|
---|
| 1213 | }
|
---|
| 1214 | break;
|
---|
| 1215 | case RFCOMM_MULTIPLEXER_OPEN:
|
---|
| 1216 | switch (event) {
|
---|
| 1217 | case MULT_EV_READY_TO_SEND:
|
---|
| 1218 | // respond to test command
|
---|
| 1219 | if (multiplexer->test_data_len){
|
---|
| 1220 | int len = multiplexer->test_data_len;
|
---|
| 1221 | log_info("Sending TEST Response with %u bytes", len);
|
---|
| 1222 | multiplexer->test_data_len = 0;
|
---|
| 1223 | rfcomm_send_uih_test_rsp(multiplexer, multiplexer->test_data, len);
|
---|
| 1224 | return;
|
---|
| 1225 | }
|
---|
| 1226 | break;
|
---|
| 1227 | default:
|
---|
| 1228 | break;
|
---|
| 1229 | }
|
---|
| 1230 | break;
|
---|
| 1231 | default:
|
---|
| 1232 | break;
|
---|
| 1233 | }
|
---|
| 1234 | }
|
---|
| 1235 |
|
---|
| 1236 | // MARK: RFCOMM CHANNEL
|
---|
| 1237 |
|
---|
| 1238 | static void rfcomm_hand_out_credits(void){
|
---|
| 1239 | linked_item_t * it;
|
---|
| 1240 | for (it = (linked_item_t *) rfcomm_channels; it ; it = it->next){
|
---|
| 1241 | rfcomm_channel_t * channel = (rfcomm_channel_t *) it;
|
---|
| 1242 | if (channel->state != RFCOMM_CHANNEL_OPEN) {
|
---|
| 1243 | // log_info("RFCOMM_EVENT_CREDITS: multiplexer not open");
|
---|
| 1244 | continue;
|
---|
| 1245 | }
|
---|
| 1246 | if (channel->packets_granted) {
|
---|
| 1247 | // log_info("RFCOMM_EVENT_CREDITS: already packets granted");
|
---|
| 1248 | continue;
|
---|
| 1249 | }
|
---|
| 1250 | if (!channel->credits_outgoing) {
|
---|
| 1251 | // log_info("RFCOMM_EVENT_CREDITS: no outgoing credits");
|
---|
| 1252 | continue;
|
---|
| 1253 | }
|
---|
| 1254 | if (!channel->multiplexer->l2cap_credits){
|
---|
| 1255 | // log_info("RFCOMM_EVENT_CREDITS: no l2cap credits");
|
---|
| 1256 | continue;
|
---|
| 1257 | }
|
---|
| 1258 | // channel open, multiplexer has l2cap credits and we didn't hand out credit before -> go!
|
---|
| 1259 | // log_info("RFCOMM_EVENT_CREDITS: 1");
|
---|
| 1260 | channel->packets_granted += 1;
|
---|
| 1261 | rfcomm_emit_credits(channel, 1);
|
---|
| 1262 | }
|
---|
| 1263 | }
|
---|
| 1264 |
|
---|
| 1265 | static void rfcomm_channel_send_credits(rfcomm_channel_t *channel, uint8_t credits){
|
---|
| 1266 | rfcomm_send_uih_credits(channel->multiplexer, channel->dlci, credits);
|
---|
| 1267 | channel->credits_incoming += credits;
|
---|
| 1268 |
|
---|
| 1269 | rfcomm_emit_credit_status(channel);
|
---|
| 1270 | }
|
---|
| 1271 |
|
---|
| 1272 | static void rfcomm_channel_opened(rfcomm_channel_t *rfChannel){
|
---|
| 1273 | rfcomm_multiplexer_t *multiplexer;
|
---|
| 1274 | log_info("rfcomm_channel_opened!");
|
---|
| 1275 |
|
---|
| 1276 | rfChannel->state = RFCOMM_CHANNEL_OPEN;
|
---|
| 1277 | rfcomm_emit_channel_opened(rfChannel, 0);
|
---|
| 1278 | rfcomm_emit_port_configuration(rfChannel);
|
---|
| 1279 | rfcomm_hand_out_credits();
|
---|
| 1280 |
|
---|
| 1281 | // remove (potential) timer
|
---|
| 1282 | multiplexer = rfChannel->multiplexer;
|
---|
| 1283 | if (multiplexer->timer_active) {
|
---|
| 1284 | run_loop_remove_timer(&multiplexer->timer);
|
---|
| 1285 | multiplexer->timer_active = 0;
|
---|
| 1286 | }
|
---|
| 1287 | // hack for problem detecting authentication failure
|
---|
| 1288 | multiplexer->at_least_one_connection = 1;
|
---|
| 1289 |
|
---|
| 1290 | // start next connection request if pending
|
---|
| 1291 | rfcomm_run();
|
---|
| 1292 | }
|
---|
| 1293 |
|
---|
| 1294 | static void rfcomm_channel_packet_handler_uih(rfcomm_multiplexer_t *multiplexer, uint8_t * packet, uint16_t size){
|
---|
| 1295 | const uint8_t frame_dlci = packet[0] >> 2;
|
---|
| 1296 | const uint8_t length_offset = (packet[2] & 1) ^ 1; // to be used for pos >= 3
|
---|
| 1297 | const uint8_t credit_offset = ((packet[1] & BT_RFCOMM_UIH_PF) == BT_RFCOMM_UIH_PF) ? 1 : 0; // credits for uih_pf frames
|
---|
| 1298 | const uint8_t payload_offset = 3 + length_offset + credit_offset;
|
---|
| 1299 |
|
---|
| 1300 | rfcomm_channel_t * channel = rfcomm_channel_for_multiplexer_and_dlci(multiplexer, frame_dlci);
|
---|
| 1301 | if (!channel) return;
|
---|
| 1302 |
|
---|
| 1303 | // handle new outgoing credits
|
---|
| 1304 | if (packet[1] == BT_RFCOMM_UIH_PF) {
|
---|
| 1305 | rfcomm_channel_event_t channel_event = { CH_EVT_RCVD_CREDITS };
|
---|
| 1306 | // add them
|
---|
| 1307 | uint16_t new_credits = packet[3+length_offset];
|
---|
| 1308 | channel->credits_outgoing += new_credits;
|
---|
| 1309 | log_info( "RFCOMM data UIH_PF, new credits: %u, now %u", new_credits, channel->credits_outgoing);
|
---|
| 1310 |
|
---|
| 1311 | // notify channel statemachine
|
---|
| 1312 | rfcomm_channel_state_machine(channel, &channel_event);
|
---|
| 1313 | }
|
---|
| 1314 |
|
---|
| 1315 | // contains payload?
|
---|
| 1316 | if (size - 1 > payload_offset){
|
---|
| 1317 |
|
---|
| 1318 | // log_info( "RFCOMM data UIH_PF, size %u, channel %p", size-payload_offset-1, rfChannel->connection);
|
---|
| 1319 |
|
---|
| 1320 | // decrease incoming credit counter
|
---|
| 1321 | if (channel->credits_incoming > 0){
|
---|
| 1322 | channel->credits_incoming--;
|
---|
| 1323 | }
|
---|
| 1324 |
|
---|
| 1325 | // deliver payload
|
---|
| 1326 | (*app_packet_handler)(channel->connection, RFCOMM_DATA_PACKET, channel->rfcomm_cid,
|
---|
| 1327 | &packet[payload_offset], size-payload_offset-1);
|
---|
| 1328 | }
|
---|
| 1329 |
|
---|
| 1330 | // automatically provide new credits to remote device, if no incoming flow control
|
---|
| 1331 | if (!channel->incoming_flow_control && channel->credits_incoming < 5){
|
---|
| 1332 | channel->new_credits_incoming =RFCOMM_CREDITS;
|
---|
| 1333 | }
|
---|
| 1334 |
|
---|
| 1335 | rfcomm_emit_credit_status(channel);
|
---|
| 1336 |
|
---|
| 1337 | // we received new RFCOMM credits, hand them out if possible
|
---|
| 1338 | rfcomm_hand_out_credits();
|
---|
| 1339 | }
|
---|
| 1340 |
|
---|
| 1341 | static void rfcomm_channel_accept_pn(rfcomm_channel_t *channel, rfcomm_channel_event_pn_t *event){
|
---|
| 1342 | // priority of client request
|
---|
| 1343 | channel->pn_priority = event->priority;
|
---|
| 1344 |
|
---|
| 1345 | // new credits
|
---|
| 1346 | channel->credits_outgoing = event->credits_outgoing;
|
---|
| 1347 |
|
---|
| 1348 | // negotiate max frame size
|
---|
| 1349 | if (channel->max_frame_size > channel->multiplexer->max_frame_size) {
|
---|
| 1350 | channel->max_frame_size = channel->multiplexer->max_frame_size;
|
---|
| 1351 | }
|
---|
| 1352 | if (channel->max_frame_size > event->max_frame_size) {
|
---|
| 1353 | channel->max_frame_size = event->max_frame_size;
|
---|
| 1354 | }
|
---|
| 1355 |
|
---|
| 1356 | }
|
---|
| 1357 |
|
---|
| 1358 | static void rfcomm_channel_finalize(rfcomm_channel_t *channel){
|
---|
| 1359 |
|
---|
| 1360 | rfcomm_multiplexer_t *multiplexer = channel->multiplexer;
|
---|
| 1361 |
|
---|
| 1362 | // remove from list
|
---|
| 1363 | linked_list_remove( &rfcomm_channels, (linked_item_t *) channel);
|
---|
| 1364 |
|
---|
| 1365 | // free channel
|
---|
| 1366 | btstack_memory_rfcomm_channel_free(channel);
|
---|
| 1367 |
|
---|
| 1368 | // update multiplexer timeout after channel was removed from list
|
---|
| 1369 | rfcomm_multiplexer_prepare_idle_timer(multiplexer);
|
---|
| 1370 | }
|
---|
| 1371 |
|
---|
| 1372 | static void rfcomm_channel_state_machine_2(rfcomm_multiplexer_t * multiplexer, uint8_t dlci, rfcomm_channel_event_t *event){
|
---|
| 1373 |
|
---|
| 1374 | // TODO: if client max frame size is smaller than RFCOMM_DEFAULT_SIZE, send PN
|
---|
| 1375 |
|
---|
| 1376 |
|
---|
| 1377 | // lookup existing channel
|
---|
| 1378 | rfcomm_channel_t * channel = rfcomm_channel_for_multiplexer_and_dlci(multiplexer, dlci);
|
---|
| 1379 | rfcomm_service_t * service;
|
---|
| 1380 |
|
---|
| 1381 | // log_info("rfcomm_channel_state_machine_2 lookup dlci #%u = 0x%08x - event %u", dlci, (int) channel, event->type);
|
---|
| 1382 |
|
---|
| 1383 | if (channel) {
|
---|
| 1384 | rfcomm_channel_state_machine(channel, event);
|
---|
| 1385 | return;
|
---|
| 1386 | }
|
---|
| 1387 |
|
---|
| 1388 | // service registered?
|
---|
| 1389 | service = rfcomm_service_for_channel(dlci >> 1);
|
---|
| 1390 | // log_info("rfcomm_channel_state_machine_2 service dlci #%u = 0x%08x", dlci, (int) service);
|
---|
| 1391 | if (!service) {
|
---|
| 1392 | // discard request by sending disconnected mode
|
---|
| 1393 | multiplexer->send_dm_for_dlci = dlci;
|
---|
| 1394 | return;
|
---|
| 1395 | }
|
---|
| 1396 |
|
---|
| 1397 | // create channel for some events
|
---|
| 1398 | switch (event->type) {
|
---|
| 1399 | case CH_EVT_RCVD_SABM:
|
---|
| 1400 | case CH_EVT_RCVD_PN:
|
---|
| 1401 | case CH_EVT_RCVD_RPN_REQ:
|
---|
| 1402 | case CH_EVT_RCVD_RPN_CMD:
|
---|
| 1403 | // setup incoming channel
|
---|
| 1404 | channel = rfcomm_channel_create(multiplexer, service, dlci >> 1);
|
---|
| 1405 | if (!channel){
|
---|
| 1406 | // discard request by sending disconnected mode
|
---|
| 1407 | multiplexer->send_dm_for_dlci = dlci;
|
---|
| 1408 | }
|
---|
| 1409 | break;
|
---|
| 1410 | default:
|
---|
| 1411 | break;
|
---|
| 1412 | }
|
---|
| 1413 |
|
---|
| 1414 | if (!channel) {
|
---|
| 1415 | // discard request by sending disconnected mode
|
---|
| 1416 | multiplexer->send_dm_for_dlci = dlci;
|
---|
| 1417 | return;
|
---|
| 1418 | }
|
---|
| 1419 | channel->connection = service->connection;
|
---|
| 1420 | rfcomm_channel_state_machine(channel, event);
|
---|
| 1421 | }
|
---|
| 1422 |
|
---|
| 1423 | void rfcomm_channel_packet_handler(rfcomm_multiplexer_t * multiplexer, uint8_t *packet, uint16_t size){
|
---|
| 1424 |
|
---|
| 1425 | // rfcomm: (0) addr [76543 server channel] [2 direction: initiator uses 1] [1 C/R: CMD by initiator = 1] [0 EA=1]
|
---|
| 1426 | const uint8_t frame_dlci = packet[0] >> 2;
|
---|
| 1427 | uint8_t message_dlci; // used by commands in UIH(_PF) packets
|
---|
| 1428 | uint8_t message_len; // "
|
---|
| 1429 |
|
---|
| 1430 | // rfcomm: (1) command/control
|
---|
| 1431 | // -- credits_offset = 1 if command == BT_RFCOMM_UIH_PF
|
---|
| 1432 | const uint8_t credit_offset = ((packet[1] & BT_RFCOMM_UIH_PF) == BT_RFCOMM_UIH_PF) ? 1 : 0; // credits for uih_pf frames
|
---|
| 1433 | // rfcomm: (2) length. if bit 0 is cleared, 2 byte length is used. (little endian)
|
---|
| 1434 | const uint8_t length_offset = (packet[2] & 1) ^ 1; // to be used for pos >= 3
|
---|
| 1435 | // rfcomm: (3+length_offset) credits if credits_offset == 1
|
---|
| 1436 | // rfcomm: (3+length_offest+credits_offset)
|
---|
| 1437 | const uint8_t payload_offset = 3 + length_offset + credit_offset;
|
---|
| 1438 |
|
---|
| 1439 | rfcomm_channel_event_t event;
|
---|
| 1440 | rfcomm_channel_event_pn_t event_pn;
|
---|
| 1441 | rfcomm_channel_event_rpn_t event_rpn;
|
---|
| 1442 | rfcomm_channel_event_msc_t event_msc;
|
---|
| 1443 |
|
---|
| 1444 | // switch by rfcomm message type
|
---|
| 1445 | switch(packet[1]) {
|
---|
| 1446 |
|
---|
| 1447 | case BT_RFCOMM_SABM:
|
---|
| 1448 | event.type = CH_EVT_RCVD_SABM;
|
---|
| 1449 | log_info("Received SABM #%u", frame_dlci);
|
---|
| 1450 | rfcomm_channel_state_machine_2(multiplexer, frame_dlci, &event);
|
---|
| 1451 | break;
|
---|
| 1452 |
|
---|
| 1453 | case BT_RFCOMM_UA:
|
---|
| 1454 | event.type = CH_EVT_RCVD_UA;
|
---|
| 1455 | log_info("Received UA #%u",frame_dlci);
|
---|
| 1456 | rfcomm_channel_state_machine_2(multiplexer, frame_dlci, &event);
|
---|
| 1457 | break;
|
---|
| 1458 |
|
---|
| 1459 | case BT_RFCOMM_DISC:
|
---|
| 1460 | event.type = CH_EVT_RCVD_DISC;
|
---|
| 1461 | rfcomm_channel_state_machine_2(multiplexer, frame_dlci, &event);
|
---|
| 1462 | break;
|
---|
| 1463 |
|
---|
| 1464 | case BT_RFCOMM_DM:
|
---|
| 1465 | case BT_RFCOMM_DM_PF:
|
---|
| 1466 | event.type = CH_EVT_RCVD_DM;
|
---|
| 1467 | rfcomm_channel_state_machine_2(multiplexer, frame_dlci, &event);
|
---|
| 1468 | break;
|
---|
| 1469 |
|
---|
| 1470 | case BT_RFCOMM_UIH_PF:
|
---|
| 1471 | case BT_RFCOMM_UIH:
|
---|
| 1472 |
|
---|
| 1473 | message_len = packet[payload_offset+1] >> 1;
|
---|
| 1474 |
|
---|
| 1475 | switch (packet[payload_offset]) {
|
---|
| 1476 | case BT_RFCOMM_PN_CMD:
|
---|
| 1477 | message_dlci = packet[payload_offset+2];
|
---|
| 1478 | event_pn.super.type = CH_EVT_RCVD_PN;
|
---|
| 1479 | event_pn.priority = packet[payload_offset+4];
|
---|
[374] | 1480 | event_pn.max_frame_size = little_endian_read_16(packet, payload_offset+6);
|
---|
[337] | 1481 | event_pn.credits_outgoing = packet[payload_offset+9];
|
---|
| 1482 | log_info("Received UIH Parameter Negotiation Command for #%u, credits %u",
|
---|
| 1483 | message_dlci, event_pn.credits_outgoing);
|
---|
| 1484 | rfcomm_channel_state_machine_2(multiplexer, message_dlci, (rfcomm_channel_event_t*) &event_pn);
|
---|
| 1485 | break;
|
---|
| 1486 |
|
---|
| 1487 | case BT_RFCOMM_PN_RSP:
|
---|
| 1488 | message_dlci = packet[payload_offset+2];
|
---|
| 1489 | event_pn.super.type = CH_EVT_RCVD_PN_RSP;
|
---|
| 1490 | event_pn.priority = packet[payload_offset+4];
|
---|
[374] | 1491 | event_pn.max_frame_size = little_endian_read_16(packet, payload_offset+6);
|
---|
[337] | 1492 | event_pn.credits_outgoing = packet[payload_offset+9];
|
---|
| 1493 | log_info("Received UIH Parameter Negotiation Response max frame %u, credits %u",
|
---|
| 1494 | event_pn.max_frame_size, event_pn.credits_outgoing);
|
---|
| 1495 | rfcomm_channel_state_machine_2(multiplexer, message_dlci, (rfcomm_channel_event_t*) &event_pn);
|
---|
| 1496 | break;
|
---|
| 1497 |
|
---|
| 1498 | case BT_RFCOMM_MSC_CMD:
|
---|
| 1499 | message_dlci = packet[payload_offset+2] >> 2;
|
---|
| 1500 | event_msc.super.type = CH_EVT_RCVD_MSC_CMD;
|
---|
| 1501 | event_msc.modem_status = packet[payload_offset+3];
|
---|
| 1502 | log_info("Received MSC CMD for #%u, ", message_dlci);
|
---|
| 1503 | rfcomm_channel_state_machine_2(multiplexer, message_dlci, (rfcomm_channel_event_t*) &event_msc);
|
---|
| 1504 | break;
|
---|
| 1505 |
|
---|
| 1506 | case BT_RFCOMM_MSC_RSP:
|
---|
| 1507 | message_dlci = packet[payload_offset+2] >> 2;
|
---|
| 1508 | event.type = CH_EVT_RCVD_MSC_RSP;
|
---|
| 1509 | log_info("Received MSC RSP for #%u", message_dlci);
|
---|
| 1510 | rfcomm_channel_state_machine_2(multiplexer, message_dlci, &event);
|
---|
| 1511 | break;
|
---|
| 1512 |
|
---|
| 1513 | case BT_RFCOMM_RPN_CMD:
|
---|
| 1514 | message_dlci = packet[payload_offset+2] >> 2;
|
---|
| 1515 | switch (message_len){
|
---|
| 1516 | case 1:
|
---|
| 1517 | log_info("Received Remote Port Negotiation Request for #%u", message_dlci);
|
---|
| 1518 | event.type = CH_EVT_RCVD_RPN_REQ;
|
---|
| 1519 | rfcomm_channel_state_machine_2(multiplexer, message_dlci, &event);
|
---|
| 1520 | break;
|
---|
| 1521 | case 8:
|
---|
| 1522 | log_info("Received Remote Port Negotiation Update for #%u", message_dlci);
|
---|
| 1523 | event_rpn.super.type = CH_EVT_RCVD_RPN_CMD;
|
---|
| 1524 | event_rpn.data = *(rfcomm_rpn_data_t*) &packet[payload_offset+3];
|
---|
| 1525 | rfcomm_channel_state_machine_2(multiplexer, message_dlci, (rfcomm_channel_event_t*) &event_rpn);
|
---|
| 1526 | break;
|
---|
| 1527 | default:
|
---|
| 1528 | break;
|
---|
| 1529 | }
|
---|
| 1530 | break;
|
---|
| 1531 |
|
---|
| 1532 | case BT_RFCOMM_RPN_RSP:
|
---|
| 1533 | log_info("Received RPN response");
|
---|
| 1534 | break;
|
---|
| 1535 |
|
---|
| 1536 | case BT_RFCOMM_RLS_CMD: {
|
---|
| 1537 | rfcomm_channel_event_rls_t event_rls;
|
---|
| 1538 | log_info("Received RLS command");
|
---|
| 1539 | message_dlci = packet[payload_offset+2] >> 2;
|
---|
| 1540 | event_rls.super.type = CH_EVT_RCVD_RLS_CMD;
|
---|
| 1541 | event_rls.line_status = packet[payload_offset+3];
|
---|
| 1542 | rfcomm_channel_state_machine_2(multiplexer, message_dlci, (rfcomm_channel_event_t*) &event_rls);
|
---|
| 1543 | break;
|
---|
| 1544 | }
|
---|
| 1545 |
|
---|
| 1546 | case BT_RFCOMM_RLS_RSP:
|
---|
| 1547 | log_info("Received RLS response");
|
---|
| 1548 | break;
|
---|
| 1549 |
|
---|
| 1550 | // Following commands are handled by rfcomm_multiplexer_l2cap_packet_handler
|
---|
| 1551 | // case BT_RFCOMM_TEST_CMD:
|
---|
| 1552 | // case BT_RFCOMM_FCOFF_CMD:
|
---|
| 1553 | // case BT_RFCOMM_FCON_CMD:
|
---|
| 1554 | // everything else is an not supported command
|
---|
| 1555 | default: {
|
---|
| 1556 | log_error("Received unknown UIH command packet - 0x%02x", packet[payload_offset]);
|
---|
| 1557 | multiplexer->nsc_command = packet[payload_offset];
|
---|
| 1558 | break;
|
---|
| 1559 | }
|
---|
| 1560 | }
|
---|
| 1561 | break;
|
---|
| 1562 |
|
---|
| 1563 | default:
|
---|
| 1564 | log_error("Received unknown RFCOMM message type %x", packet[1]);
|
---|
| 1565 | break;
|
---|
| 1566 | }
|
---|
| 1567 |
|
---|
| 1568 | // trigger next action - example W4_PN_RSP: transition to SEND_SABM which only depends on "can send"
|
---|
| 1569 | rfcomm_run();
|
---|
| 1570 | }
|
---|
| 1571 |
|
---|
| 1572 | void rfcomm_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
---|
| 1573 | rfcomm_multiplexer_t * multiplexer;
|
---|
| 1574 | uint8_t frame_dlci;
|
---|
| 1575 |
|
---|
| 1576 | // multiplexer handler
|
---|
| 1577 | int handled = 0;
|
---|
| 1578 | switch (packet_type) {
|
---|
| 1579 | case HCI_EVENT_PACKET:
|
---|
| 1580 | handled = rfcomm_multiplexer_hci_event_handler(packet, size);
|
---|
| 1581 | break;
|
---|
| 1582 | case L2CAP_DATA_PACKET:
|
---|
| 1583 | handled = rfcomm_multiplexer_l2cap_packet_handler(channel, packet, size);
|
---|
| 1584 | break;
|
---|
| 1585 | default:
|
---|
| 1586 | break;
|
---|
| 1587 | }
|
---|
| 1588 |
|
---|
| 1589 | if (handled) {
|
---|
| 1590 | rfcomm_run();
|
---|
| 1591 | return;
|
---|
| 1592 | }
|
---|
| 1593 |
|
---|
| 1594 | // we only handle l2cap packet over open multiplexer channel now
|
---|
| 1595 | if (packet_type != L2CAP_DATA_PACKET) {
|
---|
| 1596 | (*app_packet_handler)(NULL, packet_type, channel, packet, size);
|
---|
| 1597 | return;
|
---|
| 1598 | }
|
---|
| 1599 | multiplexer = rfcomm_multiplexer_for_l2cap_cid(channel);
|
---|
| 1600 | if (!multiplexer || multiplexer->state != RFCOMM_MULTIPLEXER_OPEN) {
|
---|
| 1601 | (*app_packet_handler)(NULL, packet_type, channel, packet, size);
|
---|
| 1602 | return;
|
---|
| 1603 | }
|
---|
| 1604 |
|
---|
| 1605 | // channel data ?
|
---|
| 1606 | // rfcomm: (0) addr [76543 server channel] [2 direction: initiator uses 1] [1 C/R: CMD by initiator = 1] [0 EA=1]
|
---|
| 1607 | frame_dlci = packet[0] >> 2;
|
---|
| 1608 |
|
---|
| 1609 | if (frame_dlci && (packet[1] == BT_RFCOMM_UIH || packet[1] == BT_RFCOMM_UIH_PF)) {
|
---|
| 1610 | rfcomm_channel_packet_handler_uih(multiplexer, packet, size);
|
---|
| 1611 | rfcomm_run();
|
---|
| 1612 | return;
|
---|
| 1613 | }
|
---|
| 1614 |
|
---|
| 1615 | rfcomm_channel_packet_handler(multiplexer, packet, size);
|
---|
| 1616 | }
|
---|
| 1617 |
|
---|
| 1618 | static int rfcomm_channel_ready_for_open(rfcomm_channel_t *channel){
|
---|
| 1619 | // note: exchanging MSC isn't neccessary to consider channel open
|
---|
| 1620 | // note: having outgoing credits is also not necessary to consider channel open
|
---|
| 1621 | // log_info("rfcomm_channel_ready_for_open state %u, flags needed %04x, current %04x, rf credits %u, l2cap credits %u ", channel->state, RFCOMM_CHANNEL_STATE_VAR_RCVD_MSC_RSP|RFCOMM_CHANNEL_STATE_VAR_SENT_MSC_RSP|RFCOMM_CHANNEL_STATE_VAR_SENT_CREDITS, channel->state_var, channel->credits_outgoing, channel->multiplexer->l2cap_credits);
|
---|
| 1622 | // if ((channel->state_var & RFCOMM_CHANNEL_STATE_VAR_SENT_MSC_RSP) == 0) return 0;
|
---|
| 1623 | // if (channel->credits_outgoing == 0) return 0;
|
---|
| 1624 | log_info("rfcomm_channel_ready_for_open state %u, flags needed %04x, current %04x, rf credits %u, l2cap credits %u ", channel->state, RFCOMM_CHANNEL_STATE_VAR_RCVD_MSC_RSP, channel->state_var, channel->credits_outgoing, channel->multiplexer->l2cap_credits);
|
---|
| 1625 | if ((channel->state_var & RFCOMM_CHANNEL_STATE_VAR_RCVD_MSC_RSP) == 0) return 0;
|
---|
| 1626 | if ((channel->state_var & RFCOMM_CHANNEL_STATE_VAR_SENT_CREDITS) == 0) return 0;
|
---|
| 1627 |
|
---|
| 1628 | return 1;
|
---|
| 1629 | }
|
---|
| 1630 |
|
---|
| 1631 | static int rfcomm_channel_ready_for_incoming_dlc_setup(rfcomm_channel_t * channel){
|
---|
| 1632 | log_info("rfcomm_channel_ready_for_incoming_dlc_setup state var %04x", channel->state_var);
|
---|
| 1633 | // Client accept and SABM/UA is required, PN RSP is needed if PN was received
|
---|
| 1634 | if ((channel->state_var & RFCOMM_CHANNEL_STATE_VAR_CLIENT_ACCEPTED) == 0) return 0;
|
---|
| 1635 | if ((channel->state_var & RFCOMM_CHANNEL_STATE_VAR_RCVD_SABM ) == 0) return 0;
|
---|
| 1636 | if ((channel->state_var & RFCOMM_CHANNEL_STATE_VAR_SEND_UA ) != 0) return 0;
|
---|
| 1637 | if ((channel->state_var & RFCOMM_CHANNEL_STATE_VAR_SEND_PN_RSP ) != 0) return 0;
|
---|
| 1638 | return 1;
|
---|
| 1639 | }
|
---|
| 1640 |
|
---|
| 1641 | /*inline*/ static void rfcomm_channel_state_add(rfcomm_channel_t *channel, RFCOMM_CHANNEL_STATE_VAR event){
|
---|
| 1642 | channel->state_var = (RFCOMM_CHANNEL_STATE_VAR) (channel->state_var | event);
|
---|
| 1643 | }
|
---|
| 1644 | /*inline*/ static void rfcomm_channel_state_remove(rfcomm_channel_t *channel, RFCOMM_CHANNEL_STATE_VAR event){
|
---|
| 1645 | channel->state_var = (RFCOMM_CHANNEL_STATE_VAR) (channel->state_var & ~event);
|
---|
| 1646 | }
|
---|
| 1647 |
|
---|
| 1648 | static void rfcomm_channel_state_machine(rfcomm_channel_t *channel, rfcomm_channel_event_t *event){
|
---|
| 1649 |
|
---|
| 1650 | // log_info("rfcomm_channel_state_machine: state %u, state_var %04x, event %u", channel->state, channel->state_var ,event->type);
|
---|
| 1651 |
|
---|
| 1652 | rfcomm_multiplexer_t *multiplexer = channel->multiplexer;
|
---|
| 1653 | rfcomm_channel_event_pn_t * event_pn;
|
---|
| 1654 |
|
---|
| 1655 | // TODO: integrate in common switch
|
---|
| 1656 | if (event->type == CH_EVT_RCVD_DISC){
|
---|
| 1657 | rfcomm_emit_channel_closed(channel);
|
---|
| 1658 | channel->state = RFCOMM_CHANNEL_SEND_UA_AFTER_DISC;
|
---|
| 1659 | return;
|
---|
| 1660 | }
|
---|
| 1661 |
|
---|
| 1662 | // TODO: integrate in common switch
|
---|
| 1663 | if (event->type == CH_EVT_RCVD_DM){
|
---|
| 1664 | log_info("Received DM message for #%u", channel->dlci);
|
---|
| 1665 | log_info("-> Closing channel locally for #%u", channel->dlci);
|
---|
| 1666 | rfcomm_emit_channel_closed(channel);
|
---|
| 1667 | rfcomm_channel_finalize(channel);
|
---|
| 1668 | return;
|
---|
| 1669 | }
|
---|
| 1670 |
|
---|
| 1671 | // remote port negotiation command - just accept everything for now
|
---|
| 1672 | //
|
---|
| 1673 | // "The RPN command can be used before a new DLC is opened and should be used whenever the port settings change."
|
---|
| 1674 | // "The RPN command is specified as optional in TS 07.10, but it is mandatory to recognize and respond to it in RFCOMM.
|
---|
| 1675 | // (Although the handling of individual settings are implementation-dependent.)"
|
---|
| 1676 | //
|
---|
| 1677 |
|
---|
| 1678 | // TODO: integrate in common switch
|
---|
| 1679 | if (event->type == CH_EVT_RCVD_RPN_CMD){
|
---|
| 1680 | // control port parameters
|
---|
| 1681 | rfcomm_channel_event_rpn_t *event_rpn = (rfcomm_channel_event_rpn_t*) event;
|
---|
| 1682 | rfcomm_rpn_data_update(&channel->rpn_data, &event_rpn->data);
|
---|
| 1683 | rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_RPN_RSP);
|
---|
| 1684 | // notify client about new settings
|
---|
| 1685 | rfcomm_emit_port_configuration(channel);
|
---|
| 1686 | return;
|
---|
| 1687 | }
|
---|
| 1688 |
|
---|
| 1689 | // TODO: integrate in common switch
|
---|
| 1690 | if (event->type == CH_EVT_RCVD_RPN_REQ){
|
---|
| 1691 | // no values got accepted (no values have beens sent)
|
---|
| 1692 | channel->rpn_data.parameter_mask_0 = 0x00;
|
---|
| 1693 | channel->rpn_data.parameter_mask_1 = 0x00;
|
---|
| 1694 | rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_RPN_RSP);
|
---|
| 1695 | return;
|
---|
| 1696 | }
|
---|
| 1697 |
|
---|
| 1698 | if (event->type == CH_EVT_RCVD_RLS_CMD){
|
---|
| 1699 | rfcomm_channel_event_rls_t * event_rls = (rfcomm_channel_event_rls_t*) event;
|
---|
| 1700 | channel->rls_line_status = event_rls->line_status & 0x0f;
|
---|
| 1701 | log_info("CH_EVT_RCVD_RLS_CMD setting line status to 0x%0x", channel->rls_line_status);
|
---|
| 1702 | rfcomm_emit_remote_line_status(channel, event_rls->line_status);
|
---|
| 1703 | return;
|
---|
| 1704 | }
|
---|
| 1705 |
|
---|
| 1706 | // TODO: integrate in common swich
|
---|
| 1707 | if (event->type == CH_EVT_READY_TO_SEND){
|
---|
| 1708 | if (channel->state_var & RFCOMM_CHANNEL_STATE_VAR_SEND_RPN_RSP){
|
---|
| 1709 | log_info("Sending Remote Port Negotiation RSP for #%u", channel->dlci);
|
---|
| 1710 | rfcomm_channel_state_remove(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_RPN_RSP);
|
---|
| 1711 | rfcomm_send_uih_rpn_rsp(multiplexer, channel->dlci, &channel->rpn_data);
|
---|
| 1712 | return;
|
---|
| 1713 | }
|
---|
| 1714 | if (channel->state_var & RFCOMM_CHANNEL_STATE_VAR_SEND_MSC_RSP){
|
---|
| 1715 | log_info("Sending MSC RSP for #%u", channel->dlci);
|
---|
| 1716 | rfcomm_channel_state_remove(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_MSC_RSP);
|
---|
| 1717 | rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_SENT_MSC_RSP);
|
---|
| 1718 | rfcomm_send_uih_msc_rsp(multiplexer, channel->dlci, 0x8d); // ea=1,fc=0,rtc=1,rtr=1,ic=0,dv=1
|
---|
| 1719 | return;
|
---|
| 1720 | }
|
---|
| 1721 | if (channel->rls_line_status != RFCOMM_RLS_STATUS_INVALID){
|
---|
| 1722 | uint8_t line_status;
|
---|
| 1723 | log_info("Sending RLS RSP 0x%0x", channel->rls_line_status);
|
---|
| 1724 | line_status = channel->rls_line_status;
|
---|
| 1725 | channel->rls_line_status = RFCOMM_RLS_STATUS_INVALID;
|
---|
| 1726 | rfcomm_send_uih_rls_rsp(multiplexer, channel->dlci, line_status);
|
---|
| 1727 | return;
|
---|
| 1728 | }
|
---|
| 1729 | }
|
---|
| 1730 |
|
---|
| 1731 | // emit MSC status to app
|
---|
| 1732 | if (event->type == CH_EVT_RCVD_MSC_CMD){
|
---|
| 1733 | // notify client about new settings
|
---|
| 1734 | rfcomm_channel_event_msc_t *event_msc = (rfcomm_channel_event_msc_t*) event;
|
---|
| 1735 | uint8_t event[2+1];
|
---|
| 1736 | event[0] = RFCOMM_EVENT_REMOTE_MODEM_STATUS;
|
---|
| 1737 | event[1] = 1;
|
---|
| 1738 | event[2] = event_msc->modem_status;
|
---|
| 1739 | (*app_packet_handler)(channel->connection, HCI_EVENT_PACKET, channel->rfcomm_cid, (uint8_t*)&event, sizeof(event));
|
---|
| 1740 | // no return, MSC_CMD will be handled by state machine below
|
---|
| 1741 | }
|
---|
| 1742 |
|
---|
| 1743 | event_pn = (rfcomm_channel_event_pn_t*) event;
|
---|
| 1744 |
|
---|
| 1745 | switch (channel->state) {
|
---|
| 1746 | case RFCOMM_CHANNEL_CLOSED:
|
---|
| 1747 | switch (event->type){
|
---|
| 1748 | case CH_EVT_RCVD_SABM:
|
---|
| 1749 | log_info("-> Inform app");
|
---|
| 1750 | rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_RCVD_SABM);
|
---|
| 1751 | channel->state = RFCOMM_CHANNEL_INCOMING_SETUP;
|
---|
| 1752 | rfcomm_emit_connection_request(channel);
|
---|
| 1753 | break;
|
---|
| 1754 | case CH_EVT_RCVD_PN:
|
---|
| 1755 | rfcomm_channel_accept_pn(channel, event_pn);
|
---|
| 1756 | log_info("-> Inform app");
|
---|
| 1757 | rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_RCVD_PN);
|
---|
| 1758 | channel->state = RFCOMM_CHANNEL_INCOMING_SETUP;
|
---|
| 1759 | rfcomm_emit_connection_request(channel);
|
---|
| 1760 | break;
|
---|
| 1761 | default:
|
---|
| 1762 | break;
|
---|
| 1763 | }
|
---|
| 1764 | break;
|
---|
| 1765 |
|
---|
| 1766 | case RFCOMM_CHANNEL_INCOMING_SETUP:
|
---|
| 1767 | switch (event->type){
|
---|
| 1768 | case CH_EVT_RCVD_SABM:
|
---|
| 1769 | rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_RCVD_SABM);
|
---|
| 1770 | if (channel->state_var & RFCOMM_CHANNEL_STATE_VAR_CLIENT_ACCEPTED) {
|
---|
| 1771 | rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_UA);
|
---|
| 1772 | }
|
---|
| 1773 | break;
|
---|
| 1774 | case CH_EVT_RCVD_PN:
|
---|
| 1775 | rfcomm_channel_accept_pn(channel, event_pn);
|
---|
| 1776 | rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_RCVD_PN);
|
---|
| 1777 | if (channel->state_var & RFCOMM_CHANNEL_STATE_VAR_CLIENT_ACCEPTED) {
|
---|
| 1778 | rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_PN_RSP);
|
---|
| 1779 | }
|
---|
| 1780 | break;
|
---|
| 1781 | case CH_EVT_READY_TO_SEND:
|
---|
| 1782 | // if / else if is used to check for state transition after sending
|
---|
| 1783 | if (channel->state_var & RFCOMM_CHANNEL_STATE_VAR_SEND_PN_RSP){
|
---|
| 1784 | log_info("Sending UIH Parameter Negotiation Respond for #%u", channel->dlci);
|
---|
| 1785 | rfcomm_channel_state_remove(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_PN_RSP);
|
---|
| 1786 | rfcomm_send_uih_pn_response(multiplexer, channel->dlci, channel->pn_priority, channel->max_frame_size);
|
---|
| 1787 | } else if (channel->state_var & RFCOMM_CHANNEL_STATE_VAR_SEND_UA){
|
---|
| 1788 | log_info("Sending UA #%u", channel->dlci);
|
---|
| 1789 | rfcomm_channel_state_remove(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_UA);
|
---|
| 1790 | rfcomm_send_ua(multiplexer, channel->dlci);
|
---|
| 1791 | }
|
---|
| 1792 | if (rfcomm_channel_ready_for_incoming_dlc_setup(channel)){
|
---|
| 1793 | log_info("Incomping setup done, requesting send MSC CMD and send Credits");
|
---|
| 1794 | rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_MSC_CMD);
|
---|
| 1795 | rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_CREDITS);
|
---|
| 1796 | channel->state = RFCOMM_CHANNEL_DLC_SETUP;
|
---|
| 1797 | }
|
---|
| 1798 | break;
|
---|
| 1799 | default:
|
---|
| 1800 | break;
|
---|
| 1801 | }
|
---|
| 1802 | break;
|
---|
| 1803 |
|
---|
| 1804 | case RFCOMM_CHANNEL_W4_MULTIPLEXER:
|
---|
| 1805 | switch (event->type) {
|
---|
| 1806 | case CH_EVT_MULTIPLEXER_READY:
|
---|
| 1807 | log_info("Muliplexer opened, sending UIH PN next");
|
---|
| 1808 | channel->state = RFCOMM_CHANNEL_SEND_UIH_PN;
|
---|
| 1809 | break;
|
---|
| 1810 | default:
|
---|
| 1811 | break;
|
---|
| 1812 | }
|
---|
| 1813 | break;
|
---|
| 1814 |
|
---|
| 1815 | case RFCOMM_CHANNEL_SEND_UIH_PN:
|
---|
| 1816 | switch (event->type) {
|
---|
| 1817 | case CH_EVT_READY_TO_SEND:
|
---|
| 1818 | log_info("Sending UIH Parameter Negotiation Command for #%u (channel 0x%p)", channel->dlci, channel );
|
---|
| 1819 | channel->state = RFCOMM_CHANNEL_W4_PN_RSP;
|
---|
| 1820 | rfcomm_send_uih_pn_command(multiplexer, channel->dlci, channel->max_frame_size);
|
---|
| 1821 | break;
|
---|
| 1822 | default:
|
---|
| 1823 | break;
|
---|
| 1824 | }
|
---|
| 1825 | break;
|
---|
| 1826 |
|
---|
| 1827 | case RFCOMM_CHANNEL_W4_PN_RSP:
|
---|
| 1828 | switch (event->type){
|
---|
| 1829 | case CH_EVT_RCVD_PN_RSP:
|
---|
| 1830 | // update max frame size
|
---|
| 1831 | if (channel->max_frame_size > event_pn->max_frame_size) {
|
---|
| 1832 | channel->max_frame_size = event_pn->max_frame_size;
|
---|
| 1833 | }
|
---|
| 1834 | // new credits
|
---|
| 1835 | channel->credits_outgoing = event_pn->credits_outgoing;
|
---|
| 1836 | channel->state = RFCOMM_CHANNEL_SEND_SABM_W4_UA;
|
---|
| 1837 | break;
|
---|
| 1838 | default:
|
---|
| 1839 | break;
|
---|
| 1840 | }
|
---|
| 1841 | break;
|
---|
| 1842 |
|
---|
| 1843 | case RFCOMM_CHANNEL_SEND_SABM_W4_UA:
|
---|
| 1844 | switch (event->type) {
|
---|
| 1845 | case CH_EVT_READY_TO_SEND:
|
---|
| 1846 | log_info("Sending SABM #%u", channel->dlci);
|
---|
| 1847 | channel->state = RFCOMM_CHANNEL_W4_UA;
|
---|
| 1848 | rfcomm_send_sabm(multiplexer, channel->dlci);
|
---|
| 1849 | break;
|
---|
| 1850 | default:
|
---|
| 1851 | break;
|
---|
| 1852 | }
|
---|
| 1853 | break;
|
---|
| 1854 |
|
---|
| 1855 | case RFCOMM_CHANNEL_W4_UA:
|
---|
| 1856 | switch (event->type){
|
---|
| 1857 | case CH_EVT_RCVD_UA:
|
---|
| 1858 | channel->state = RFCOMM_CHANNEL_DLC_SETUP;
|
---|
| 1859 | rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_MSC_CMD);
|
---|
| 1860 | rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_CREDITS);
|
---|
| 1861 | break;
|
---|
| 1862 | default:
|
---|
| 1863 | break;
|
---|
| 1864 | }
|
---|
| 1865 | break;
|
---|
| 1866 |
|
---|
| 1867 | case RFCOMM_CHANNEL_DLC_SETUP:
|
---|
| 1868 | switch (event->type){
|
---|
| 1869 | case CH_EVT_RCVD_MSC_CMD:
|
---|
| 1870 | rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_RCVD_MSC_CMD);
|
---|
| 1871 | rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_MSC_RSP);
|
---|
| 1872 | break;
|
---|
| 1873 | case CH_EVT_RCVD_MSC_RSP:
|
---|
| 1874 | rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_RCVD_MSC_RSP);
|
---|
| 1875 | break;
|
---|
| 1876 |
|
---|
| 1877 | case CH_EVT_READY_TO_SEND:
|
---|
| 1878 | if (channel->state_var & RFCOMM_CHANNEL_STATE_VAR_SEND_MSC_CMD){
|
---|
| 1879 | log_info("Sending MSC CMD for #%u", channel->dlci);
|
---|
| 1880 | rfcomm_channel_state_remove(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_MSC_CMD);
|
---|
| 1881 | rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_SENT_MSC_CMD);
|
---|
| 1882 | rfcomm_send_uih_msc_cmd(multiplexer, channel->dlci , 0x8d); // ea=1,fc=0,rtc=1,rtr=1,ic=0,dv=1
|
---|
| 1883 | break;
|
---|
| 1884 | }
|
---|
| 1885 | if (channel->state_var & RFCOMM_CHANNEL_STATE_VAR_SEND_CREDITS){
|
---|
| 1886 | log_info("Providing credits for #%u", channel->dlci);
|
---|
| 1887 | rfcomm_channel_state_remove(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_CREDITS);
|
---|
| 1888 | rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_SENT_CREDITS);
|
---|
| 1889 |
|
---|
| 1890 | if (channel->new_credits_incoming) {
|
---|
| 1891 | uint8_t new_credits = channel->new_credits_incoming;
|
---|
| 1892 | channel->new_credits_incoming = 0;
|
---|
| 1893 | rfcomm_channel_send_credits(channel, new_credits);
|
---|
| 1894 | }
|
---|
| 1895 | break;
|
---|
| 1896 |
|
---|
| 1897 | }
|
---|
| 1898 | break;
|
---|
| 1899 | default:
|
---|
| 1900 | break;
|
---|
| 1901 | }
|
---|
| 1902 | // finally done?
|
---|
| 1903 | if (rfcomm_channel_ready_for_open(channel)){
|
---|
| 1904 | channel->state = RFCOMM_CHANNEL_OPEN;
|
---|
| 1905 | rfcomm_channel_opened(channel);
|
---|
| 1906 | }
|
---|
| 1907 | break;
|
---|
| 1908 |
|
---|
| 1909 | case RFCOMM_CHANNEL_OPEN:
|
---|
| 1910 | switch (event->type){
|
---|
| 1911 | case CH_EVT_RCVD_MSC_CMD:
|
---|
| 1912 | rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_MSC_RSP);
|
---|
| 1913 | break;
|
---|
| 1914 | case CH_EVT_READY_TO_SEND:
|
---|
| 1915 | if (channel->new_credits_incoming) {
|
---|
| 1916 | uint8_t new_credits = channel->new_credits_incoming;
|
---|
| 1917 | channel->new_credits_incoming = 0;
|
---|
| 1918 | rfcomm_channel_send_credits(channel, new_credits);
|
---|
| 1919 | break;
|
---|
| 1920 | }
|
---|
| 1921 | break;
|
---|
| 1922 | case CH_EVT_RCVD_CREDITS: {
|
---|
| 1923 | // notify daemon -> might trigger re-try of parked connections
|
---|
| 1924 | uint8_t event[2] = { DAEMON_EVENT_NEW_RFCOMM_CREDITS, 0 };
|
---|
| 1925 | (*app_packet_handler)(channel->connection, DAEMON_EVENT_PACKET, channel->rfcomm_cid, event, sizeof(event));
|
---|
| 1926 | break;
|
---|
| 1927 | }
|
---|
| 1928 | default:
|
---|
| 1929 | break;
|
---|
| 1930 | }
|
---|
| 1931 | break;
|
---|
| 1932 |
|
---|
| 1933 | case RFCOMM_CHANNEL_SEND_DM:
|
---|
| 1934 | switch (event->type) {
|
---|
| 1935 | case CH_EVT_READY_TO_SEND:
|
---|
| 1936 | log_info("Sending DM_PF for #%u", channel->dlci);
|
---|
| 1937 | // don't emit channel closed - channel was never open
|
---|
| 1938 | channel->state = RFCOMM_CHANNEL_CLOSED;
|
---|
| 1939 | rfcomm_send_dm_pf(multiplexer, channel->dlci);
|
---|
| 1940 | rfcomm_channel_finalize(channel);
|
---|
| 1941 | break;
|
---|
| 1942 | default:
|
---|
| 1943 | break;
|
---|
| 1944 | }
|
---|
| 1945 | break;
|
---|
| 1946 |
|
---|
| 1947 | case RFCOMM_CHANNEL_SEND_DISC:
|
---|
| 1948 | switch (event->type) {
|
---|
| 1949 | case CH_EVT_READY_TO_SEND:
|
---|
| 1950 | channel->state = RFCOMM_CHANNEL_W4_UA_AFTER_UA;
|
---|
| 1951 | rfcomm_send_disc(multiplexer, channel->dlci);
|
---|
| 1952 | break;
|
---|
| 1953 | default:
|
---|
| 1954 | break;
|
---|
| 1955 | }
|
---|
| 1956 | break;
|
---|
| 1957 |
|
---|
| 1958 | case RFCOMM_CHANNEL_W4_UA_AFTER_UA:
|
---|
| 1959 | switch (event->type){
|
---|
| 1960 | case CH_EVT_RCVD_UA:
|
---|
| 1961 | channel->state = RFCOMM_CHANNEL_CLOSED;
|
---|
| 1962 | rfcomm_emit_channel_closed(channel);
|
---|
| 1963 | rfcomm_channel_finalize(channel);
|
---|
| 1964 | break;
|
---|
| 1965 | default:
|
---|
| 1966 | break;
|
---|
| 1967 | }
|
---|
| 1968 | break;
|
---|
| 1969 |
|
---|
| 1970 | case RFCOMM_CHANNEL_SEND_UA_AFTER_DISC:
|
---|
| 1971 | switch (event->type) {
|
---|
| 1972 | case CH_EVT_READY_TO_SEND:
|
---|
| 1973 | log_info("Sending UA after DISC for #%u", channel->dlci);
|
---|
| 1974 | channel->state = RFCOMM_CHANNEL_CLOSED;
|
---|
| 1975 | rfcomm_send_ua(multiplexer, channel->dlci);
|
---|
| 1976 | rfcomm_channel_finalize(channel);
|
---|
| 1977 | break;
|
---|
| 1978 | default:
|
---|
| 1979 | break;
|
---|
| 1980 | }
|
---|
| 1981 | break;
|
---|
| 1982 |
|
---|
| 1983 | default:
|
---|
| 1984 | break;
|
---|
| 1985 | }
|
---|
| 1986 | }
|
---|
| 1987 |
|
---|
| 1988 |
|
---|
| 1989 | // MARK: RFCOMM RUN
|
---|
| 1990 | // process outstanding signaling tasks
|
---|
| 1991 | static void rfcomm_run(void){
|
---|
| 1992 |
|
---|
| 1993 | linked_item_t *it;
|
---|
| 1994 | linked_item_t *next;
|
---|
| 1995 |
|
---|
| 1996 | for (it = (linked_item_t *) rfcomm_multiplexers; it ; it = next){
|
---|
| 1997 | rfcomm_multiplexer_t * multiplexer;
|
---|
| 1998 |
|
---|
| 1999 | next = it->next; // be prepared for removal of channel in state machine
|
---|
| 2000 |
|
---|
| 2001 | multiplexer = ((rfcomm_multiplexer_t *) it);
|
---|
| 2002 |
|
---|
| 2003 | if (!l2cap_can_send_packet_now(multiplexer->l2cap_cid)) {
|
---|
| 2004 | // log_info("rfcomm_run A cannot send l2cap packet for #%u, credits %u", multiplexer->l2cap_cid, multiplexer->l2cap_credits);
|
---|
| 2005 | continue;
|
---|
| 2006 | }
|
---|
| 2007 | // log_info("rfcomm_run: multi 0x%08x, state %u", (int) multiplexer, multiplexer->state);
|
---|
| 2008 |
|
---|
| 2009 | rfcomm_multiplexer_state_machine(multiplexer, MULT_EV_READY_TO_SEND);
|
---|
| 2010 | }
|
---|
| 2011 |
|
---|
| 2012 | for (it = (linked_item_t *) rfcomm_channels; it ; it = next){
|
---|
| 2013 | rfcomm_channel_t * channel;
|
---|
| 2014 | rfcomm_multiplexer_t * multiplexer;
|
---|
| 2015 | rfcomm_channel_event_t event = { CH_EVT_READY_TO_SEND };
|
---|
| 2016 |
|
---|
| 2017 | next = it->next; // be prepared for removal of channel in state machine
|
---|
| 2018 |
|
---|
| 2019 | channel = ((rfcomm_channel_t *) it);
|
---|
| 2020 | multiplexer = channel->multiplexer;
|
---|
| 2021 |
|
---|
| 2022 | if (!l2cap_can_send_packet_now(multiplexer->l2cap_cid)) {
|
---|
| 2023 | // log_info("rfcomm_run B cannot send l2cap packet for #%u, credits %u", multiplexer->l2cap_cid, multiplexer->l2cap_credits);
|
---|
| 2024 | continue;
|
---|
| 2025 | }
|
---|
| 2026 |
|
---|
| 2027 | rfcomm_channel_state_machine(channel, &event);
|
---|
| 2028 | }
|
---|
| 2029 | }
|
---|
| 2030 |
|
---|
| 2031 | // MARK: RFCOMM BTstack API
|
---|
| 2032 |
|
---|
| 2033 | void rfcomm_init(void){
|
---|
| 2034 | rfcomm_client_cid_generator = 0;
|
---|
| 2035 | rfcomm_multiplexers = NULL;
|
---|
| 2036 | rfcomm_services = NULL;
|
---|
| 2037 | rfcomm_channels = NULL;
|
---|
| 2038 | rfcomm_security_level = LEVEL_0;
|
---|
| 2039 | }
|
---|
| 2040 |
|
---|
| 2041 | void rfcomm_set_required_security_level(gap_security_level_t security_level){
|
---|
| 2042 | rfcomm_security_level = security_level;
|
---|
| 2043 | }
|
---|
| 2044 |
|
---|
| 2045 | // register packet handler
|
---|
| 2046 | void rfcomm_register_packet_handler(void (*handler)(void * connection, uint8_t packet_type,
|
---|
| 2047 | uint16_t channel, uint8_t *packet, uint16_t size)){
|
---|
| 2048 | app_packet_handler = handler;
|
---|
| 2049 | }
|
---|
| 2050 |
|
---|
| 2051 | int rfcomm_can_send_packet_now(uint16_t rfcomm_cid){
|
---|
| 2052 | rfcomm_channel_t * channel = rfcomm_channel_for_rfcomm_cid(rfcomm_cid);
|
---|
| 2053 | if (!channel){
|
---|
| 2054 | log_error("rfcomm_send_internal cid 0x%02x doesn't exist!", rfcomm_cid);
|
---|
| 2055 | return 0;
|
---|
| 2056 | }
|
---|
| 2057 | if (!channel->credits_outgoing) return 0;
|
---|
| 2058 | if (!channel->packets_granted) return 0;
|
---|
| 2059 | if ((channel->multiplexer->fcon & 1) == 0) return 0;
|
---|
| 2060 |
|
---|
| 2061 | return l2cap_can_send_packet_now(channel->multiplexer->l2cap_cid);
|
---|
| 2062 | }
|
---|
| 2063 |
|
---|
| 2064 | static int rfcomm_assert_send_valid(rfcomm_channel_t * channel , uint16_t len){
|
---|
| 2065 | if (len > channel->max_frame_size){
|
---|
| 2066 | log_error("rfcomm_send_internal cid 0x%02x, rfcomm data lenght exceeds MTU!", channel->rfcomm_cid);
|
---|
| 2067 | return RFCOMM_DATA_LEN_EXCEEDS_MTU;
|
---|
| 2068 | }
|
---|
| 2069 |
|
---|
| 2070 | if (!channel->credits_outgoing){
|
---|
| 2071 | log_info("rfcomm_send_internal cid 0x%02x, no rfcomm outgoing credits!", channel->rfcomm_cid);
|
---|
| 2072 | return RFCOMM_NO_OUTGOING_CREDITS;
|
---|
| 2073 | }
|
---|
| 2074 |
|
---|
| 2075 | if (!channel->packets_granted){
|
---|
| 2076 | log_info("rfcomm_send_internal cid 0x%02x, no rfcomm credits granted!", channel->rfcomm_cid);
|
---|
| 2077 | return RFCOMM_NO_OUTGOING_CREDITS;
|
---|
| 2078 | }
|
---|
| 2079 |
|
---|
| 2080 | if ((channel->multiplexer->fcon & 1) == 0){
|
---|
| 2081 | log_info("rfcomm_send_internal cid 0x%02x, aggregate flow off!", channel->rfcomm_cid);
|
---|
| 2082 | return RFCOMM_AGGREGATE_FLOW_OFF;
|
---|
| 2083 | }
|
---|
| 2084 | return 0;
|
---|
| 2085 | }
|
---|
| 2086 |
|
---|
| 2087 | // pre: rfcomm_can_send_packet_now(rfcomm_cid) == true
|
---|
| 2088 | int rfcomm_reserve_packet_buffer(void){
|
---|
| 2089 | return l2cap_reserve_packet_buffer();
|
---|
| 2090 | }
|
---|
| 2091 |
|
---|
| 2092 | void rfcomm_release_packet_buffer(void){
|
---|
| 2093 | l2cap_release_packet_buffer();
|
---|
| 2094 | }
|
---|
| 2095 |
|
---|
| 2096 | uint8_t * rfcomm_get_outgoing_buffer(void){
|
---|
| 2097 | uint8_t * rfcomm_out_buffer = l2cap_get_outgoing_buffer();
|
---|
| 2098 | // address + control + length (16) + no credit field
|
---|
| 2099 | return &rfcomm_out_buffer[4];
|
---|
| 2100 | }
|
---|
| 2101 |
|
---|
| 2102 | uint16_t rfcomm_get_max_frame_size(uint16_t rfcomm_cid){
|
---|
| 2103 | rfcomm_channel_t * channel = rfcomm_channel_for_rfcomm_cid(rfcomm_cid);
|
---|
| 2104 | if (!channel){
|
---|
| 2105 | log_error("rfcomm_get_max_frame_size cid 0x%02x doesn't exist!", rfcomm_cid);
|
---|
| 2106 | return 0;
|
---|
| 2107 | }
|
---|
| 2108 | return channel->max_frame_size;
|
---|
| 2109 | }
|
---|
| 2110 | int rfcomm_send_prepared(uint16_t rfcomm_cid, uint16_t len){
|
---|
| 2111 | rfcomm_channel_t * channel = rfcomm_channel_for_rfcomm_cid(rfcomm_cid);
|
---|
| 2112 | int packets_granted_decreased;
|
---|
| 2113 | int result;
|
---|
| 2114 | int err;
|
---|
| 2115 |
|
---|
| 2116 | if (!channel){
|
---|
| 2117 | log_error("rfcomm_send_prepared cid 0x%02x doesn't exist!", rfcomm_cid);
|
---|
| 2118 | return 0;
|
---|
| 2119 | }
|
---|
| 2120 |
|
---|
| 2121 | err = rfcomm_assert_send_valid(channel, len);
|
---|
| 2122 | if (err) return err;
|
---|
| 2123 |
|
---|
| 2124 | // send might cause l2cap to emit new credits, update counters first
|
---|
| 2125 | channel->credits_outgoing--;
|
---|
| 2126 | packets_granted_decreased = 0;
|
---|
| 2127 | if (channel->packets_granted) {
|
---|
| 2128 | channel->packets_granted--;
|
---|
| 2129 | packets_granted_decreased++;
|
---|
| 2130 | }
|
---|
| 2131 |
|
---|
| 2132 | result = result = rfcomm_send_uih_prepared(channel->multiplexer, channel->dlci, len);
|
---|
| 2133 |
|
---|
| 2134 | if (result != 0) {
|
---|
| 2135 | channel->credits_outgoing++;
|
---|
| 2136 | channel->packets_granted += packets_granted_decreased;
|
---|
| 2137 | log_info("rfcomm_send_internal: error %d", result);
|
---|
| 2138 | return result;
|
---|
| 2139 | }
|
---|
| 2140 |
|
---|
| 2141 | rfcomm_hand_out_credits();
|
---|
| 2142 |
|
---|
| 2143 | return result;
|
---|
| 2144 | }
|
---|
| 2145 |
|
---|
| 2146 | int rfcomm_send_internal(uint16_t rfcomm_cid, uint8_t *data, uint16_t len){
|
---|
| 2147 | rfcomm_channel_t * channel = rfcomm_channel_for_rfcomm_cid(rfcomm_cid);
|
---|
| 2148 | int err;
|
---|
| 2149 | uint8_t * rfcomm_payload;
|
---|
| 2150 |
|
---|
| 2151 | if (!channel){
|
---|
| 2152 | log_error("rfcomm_send_internal cid 0x%02x doesn't exist!", rfcomm_cid);
|
---|
| 2153 | return 1;
|
---|
| 2154 | }
|
---|
| 2155 |
|
---|
| 2156 | err = rfcomm_assert_send_valid(channel, len);
|
---|
| 2157 | if (err) return err;
|
---|
| 2158 |
|
---|
| 2159 | rfcomm_reserve_packet_buffer();
|
---|
| 2160 | rfcomm_payload = rfcomm_get_outgoing_buffer();
|
---|
| 2161 | memcpy(rfcomm_payload, data, len);
|
---|
| 2162 | return rfcomm_send_prepared(rfcomm_cid, len);
|
---|
| 2163 | }
|
---|
| 2164 |
|
---|
| 2165 | // Sends Local Lnie Status, see LINE_STATUS_..
|
---|
| 2166 | int rfcomm_send_local_line_status(uint16_t rfcomm_cid, uint8_t line_status){
|
---|
| 2167 | rfcomm_channel_t * channel = rfcomm_channel_for_rfcomm_cid(rfcomm_cid);
|
---|
| 2168 | if (!channel){
|
---|
| 2169 | log_error("rfcomm_send_local_line_status cid 0x%02x doesn't exist!", rfcomm_cid);
|
---|
| 2170 | return 0;
|
---|
| 2171 | }
|
---|
| 2172 | return rfcomm_send_uih_rls_cmd(channel->multiplexer, channel->dlci, line_status);
|
---|
| 2173 | }
|
---|
| 2174 |
|
---|
| 2175 | // Sned local modem status. see MODEM_STAUS_..
|
---|
| 2176 | int rfcomm_send_modem_status(uint16_t rfcomm_cid, uint8_t modem_status){
|
---|
| 2177 | rfcomm_channel_t * channel = rfcomm_channel_for_rfcomm_cid(rfcomm_cid);
|
---|
| 2178 | if (!channel){
|
---|
| 2179 | log_error("rfcomm_send_modem_status cid 0x%02x doesn't exist!", rfcomm_cid);
|
---|
| 2180 | return 0;
|
---|
| 2181 | }
|
---|
| 2182 | return rfcomm_send_uih_msc_cmd(channel->multiplexer, channel->dlci, modem_status);
|
---|
| 2183 | }
|
---|
| 2184 |
|
---|
| 2185 | // Configure remote port
|
---|
| 2186 | int rfcomm_send_port_configuration(uint16_t rfcomm_cid, rpn_baud_t baud_rate, rpn_data_bits_t data_bits, rpn_stop_bits_t stop_bits, rpn_parity_t parity, rpn_flow_control_t flow_control){
|
---|
| 2187 | rfcomm_channel_t * channel = rfcomm_channel_for_rfcomm_cid(rfcomm_cid);
|
---|
| 2188 | rfcomm_rpn_data_t rpn_data;
|
---|
| 2189 | if (!channel){
|
---|
| 2190 | log_error("rfcomm_send_port_configuration cid 0x%02x doesn't exist!", rfcomm_cid);
|
---|
| 2191 | return 0;
|
---|
| 2192 | }
|
---|
| 2193 | rpn_data.baud_rate = baud_rate;
|
---|
| 2194 | rpn_data.flags = data_bits | (stop_bits << 2) | (parity << 3);
|
---|
| 2195 | rpn_data.flow_control = flow_control;
|
---|
| 2196 | rpn_data.xon = 0;
|
---|
| 2197 | rpn_data.xoff = 0;
|
---|
| 2198 | rpn_data.parameter_mask_0 = 0x1f; // all but xon/xoff
|
---|
| 2199 | rpn_data.parameter_mask_1 = 0x3f; // all flow control options
|
---|
| 2200 | return rfcomm_send_uih_rpn_cmd(channel->multiplexer, channel->dlci, &rpn_data);
|
---|
| 2201 | }
|
---|
| 2202 |
|
---|
| 2203 | // Query remote port
|
---|
| 2204 | int rfcomm_query_port_configuration(uint16_t rfcomm_cid){
|
---|
| 2205 | rfcomm_channel_t * channel = rfcomm_channel_for_rfcomm_cid(rfcomm_cid);
|
---|
| 2206 | if (!channel){
|
---|
| 2207 | log_error("rfcomm_query_port_configuration cid 0x%02x doesn't exist!", rfcomm_cid);
|
---|
| 2208 | return 0;
|
---|
| 2209 | }
|
---|
| 2210 | return rfcomm_send_uih_rpn_req(channel->multiplexer, channel->dlci);
|
---|
| 2211 | }
|
---|
| 2212 |
|
---|
| 2213 |
|
---|
| 2214 | void rfcomm_create_channel2(void * connection, bd_addr_t *addr, uint8_t server_channel, uint8_t incoming_flow_control, uint8_t initial_credits){
|
---|
| 2215 | rfcomm_multiplexer_t * multiplexer;
|
---|
| 2216 | rfcomm_channel_t * channel;
|
---|
| 2217 | log_info("RFCOMM_CREATE_CHANNEL addr %s channel #%u flow control %u init credits %u", bd_addr_to_str(*addr), server_channel,
|
---|
| 2218 | incoming_flow_control, initial_credits);
|
---|
| 2219 |
|
---|
| 2220 | // create new multiplexer if necessary
|
---|
| 2221 | multiplexer = rfcomm_multiplexer_for_addr(addr);
|
---|
| 2222 | if (!multiplexer) {
|
---|
| 2223 | multiplexer = rfcomm_multiplexer_create_for_addr(addr);
|
---|
| 2224 | if (!multiplexer){
|
---|
| 2225 | rfcomm_emit_channel_open_failed_outgoing_memory(connection, addr, server_channel);
|
---|
| 2226 | return;
|
---|
| 2227 | }
|
---|
| 2228 | multiplexer->outgoing = 1;
|
---|
| 2229 | multiplexer->state = RFCOMM_MULTIPLEXER_W4_CONNECT;
|
---|
| 2230 | }
|
---|
| 2231 |
|
---|
| 2232 | // prepare channel
|
---|
| 2233 | channel = rfcomm_channel_create(multiplexer, NULL, server_channel);
|
---|
| 2234 | if (!channel){
|
---|
| 2235 | rfcomm_emit_channel_open_failed_outgoing_memory(connection, addr, server_channel);
|
---|
| 2236 | return;
|
---|
| 2237 | }
|
---|
| 2238 | channel->connection = connection;
|
---|
| 2239 | channel->incoming_flow_control = incoming_flow_control;
|
---|
| 2240 | channel->new_credits_incoming = initial_credits;
|
---|
| 2241 |
|
---|
| 2242 | // start multiplexer setup
|
---|
| 2243 | if (multiplexer->state != RFCOMM_MULTIPLEXER_OPEN) {
|
---|
| 2244 |
|
---|
| 2245 | channel->state = RFCOMM_CHANNEL_W4_MULTIPLEXER;
|
---|
| 2246 |
|
---|
| 2247 | l2cap_create_channel_internal(connection, rfcomm_packet_handler, *addr, PSM_RFCOMM, l2cap_max_mtu());
|
---|
| 2248 |
|
---|
| 2249 | return;
|
---|
| 2250 | }
|
---|
| 2251 |
|
---|
| 2252 | channel->state = RFCOMM_CHANNEL_SEND_UIH_PN;
|
---|
| 2253 |
|
---|
| 2254 | // start connecting, if multiplexer is already up and running
|
---|
| 2255 | rfcomm_run();
|
---|
| 2256 | }
|
---|
| 2257 |
|
---|
| 2258 | void rfcomm_create_channel_with_initial_credits_internal(void * connection, bd_addr_t *addr, uint8_t server_channel, uint8_t initial_credits){
|
---|
| 2259 | rfcomm_create_channel2(connection, addr, server_channel, 1, initial_credits);
|
---|
| 2260 | }
|
---|
| 2261 |
|
---|
| 2262 | void rfcomm_create_channel_internal(void * connection, bd_addr_t *addr, uint8_t server_channel){
|
---|
| 2263 | rfcomm_create_channel2(connection, addr, server_channel, 0,RFCOMM_CREDITS);
|
---|
| 2264 | }
|
---|
| 2265 |
|
---|
| 2266 | void rfcomm_disconnect_internal(uint16_t rfcomm_cid){
|
---|
| 2267 | rfcomm_channel_t * channel;
|
---|
| 2268 | log_info("RFCOMM_DISCONNECT cid 0x%02x", rfcomm_cid);
|
---|
| 2269 | channel = rfcomm_channel_for_rfcomm_cid(rfcomm_cid);
|
---|
| 2270 | if (channel) {
|
---|
| 2271 | channel->state = RFCOMM_CHANNEL_SEND_DISC;
|
---|
| 2272 | }
|
---|
| 2273 |
|
---|
| 2274 | // process
|
---|
| 2275 | rfcomm_run();
|
---|
| 2276 | }
|
---|
| 2277 |
|
---|
| 2278 |
|
---|
| 2279 | void rfcomm_register_service2(void * connection, uint8_t channel, uint16_t max_frame_size, uint8_t incoming_flow_control, uint8_t initial_credits){
|
---|
| 2280 | rfcomm_service_t * service;
|
---|
| 2281 | log_info("RFCOMM_REGISTER_SERVICE channel #%u mtu %u flow_control %u credits %u",
|
---|
| 2282 | channel, max_frame_size, incoming_flow_control, initial_credits);
|
---|
| 2283 | // check if already registered
|
---|
| 2284 | service = rfcomm_service_for_channel(channel);
|
---|
| 2285 | if (service){
|
---|
| 2286 | rfcomm_emit_service_registered(connection, RFCOMM_CHANNEL_ALREADY_REGISTERED, channel);
|
---|
| 2287 | return;
|
---|
| 2288 | }
|
---|
| 2289 |
|
---|
| 2290 | // alloc structure
|
---|
| 2291 | service = btstack_memory_rfcomm_service_get();
|
---|
| 2292 | if (!service) {
|
---|
| 2293 | rfcomm_emit_service_registered(connection, BTSTACK_MEMORY_ALLOC_FAILED, channel);
|
---|
| 2294 | return;
|
---|
| 2295 | }
|
---|
| 2296 |
|
---|
| 2297 | // register with l2cap if not registered before, max MTU
|
---|
| 2298 | if (linked_list_empty(&rfcomm_services)){
|
---|
| 2299 | l2cap_register_service_internal(NULL, rfcomm_packet_handler, PSM_RFCOMM, 0xffff, rfcomm_security_level);
|
---|
| 2300 | }
|
---|
| 2301 |
|
---|
| 2302 | // fill in
|
---|
| 2303 | service->connection = connection;
|
---|
| 2304 | service->server_channel = channel;
|
---|
| 2305 | service->max_frame_size = max_frame_size;
|
---|
| 2306 | service->incoming_flow_control = incoming_flow_control;
|
---|
| 2307 | service->incoming_initial_credits = initial_credits;
|
---|
| 2308 |
|
---|
| 2309 | // add to services list
|
---|
| 2310 | linked_list_add(&rfcomm_services, (linked_item_t *) service);
|
---|
| 2311 |
|
---|
| 2312 | // done
|
---|
| 2313 | rfcomm_emit_service_registered(connection, 0, channel);
|
---|
| 2314 | }
|
---|
| 2315 |
|
---|
| 2316 | void rfcomm_register_service_with_initial_credits_internal(void * connection, uint8_t channel, uint16_t max_frame_size, uint8_t initial_credits){
|
---|
| 2317 | rfcomm_register_service2(connection, channel, max_frame_size, 1, initial_credits);
|
---|
| 2318 | }
|
---|
| 2319 |
|
---|
| 2320 | void rfcomm_register_service_internal(void * connection, uint8_t channel, uint16_t max_frame_size){
|
---|
| 2321 | rfcomm_register_service2(connection, channel, max_frame_size, 0,RFCOMM_CREDITS);
|
---|
| 2322 | }
|
---|
| 2323 |
|
---|
| 2324 | void rfcomm_unregister_service_internal(uint8_t service_channel){
|
---|
| 2325 | rfcomm_service_t *service;
|
---|
| 2326 | log_info("RFCOMM_UNREGISTER_SERVICE #%u", service_channel);
|
---|
| 2327 | service = rfcomm_service_for_channel(service_channel);
|
---|
| 2328 | if (!service) return;
|
---|
| 2329 | linked_list_remove(&rfcomm_services, (linked_item_t *) service);
|
---|
| 2330 | btstack_memory_rfcomm_service_free(service);
|
---|
| 2331 |
|
---|
| 2332 | // unregister if no services active
|
---|
| 2333 | if (linked_list_empty(&rfcomm_services)){
|
---|
| 2334 | // bt_send_cmd(&l2cap_unregister_service, PSM_RFCOMM);
|
---|
| 2335 | l2cap_unregister_service_internal(NULL, PSM_RFCOMM);
|
---|
| 2336 | }
|
---|
| 2337 | }
|
---|
| 2338 |
|
---|
| 2339 | void rfcomm_accept_connection_internal(uint16_t rfcomm_cid){
|
---|
| 2340 | rfcomm_channel_t * channel;
|
---|
| 2341 | log_info("RFCOMM_ACCEPT_CONNECTION cid 0x%02x", rfcomm_cid);
|
---|
| 2342 | channel = rfcomm_channel_for_rfcomm_cid(rfcomm_cid);
|
---|
| 2343 | if (!channel) return;
|
---|
| 2344 | switch (channel->state) {
|
---|
| 2345 | case RFCOMM_CHANNEL_INCOMING_SETUP:
|
---|
| 2346 | rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_CLIENT_ACCEPTED);
|
---|
| 2347 | if (channel->state_var & RFCOMM_CHANNEL_STATE_VAR_RCVD_PN){
|
---|
| 2348 | rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_PN_RSP);
|
---|
| 2349 | }
|
---|
| 2350 | if (channel->state_var & RFCOMM_CHANNEL_STATE_VAR_RCVD_SABM){
|
---|
| 2351 | rfcomm_channel_state_add(channel, RFCOMM_CHANNEL_STATE_VAR_SEND_UA);
|
---|
| 2352 | }
|
---|
| 2353 | // at least one of { PN RSP, UA } needs to be sent
|
---|
| 2354 | // state transistion incoming setup -> dlc setup happens in rfcomm_run after these have been sent
|
---|
| 2355 | break;
|
---|
| 2356 | default:
|
---|
| 2357 | break;
|
---|
| 2358 | }
|
---|
| 2359 |
|
---|
| 2360 | // process
|
---|
| 2361 | rfcomm_run();
|
---|
| 2362 | }
|
---|
| 2363 |
|
---|
| 2364 | void rfcomm_decline_connection_internal(uint16_t rfcomm_cid){
|
---|
| 2365 | rfcomm_channel_t * channel;
|
---|
| 2366 | log_info("RFCOMM_DECLINE_CONNECTION cid 0x%02x", rfcomm_cid);
|
---|
| 2367 | channel = rfcomm_channel_for_rfcomm_cid(rfcomm_cid);
|
---|
| 2368 | if (!channel) return;
|
---|
| 2369 | switch (channel->state) {
|
---|
| 2370 | case RFCOMM_CHANNEL_INCOMING_SETUP:
|
---|
| 2371 | channel->state = RFCOMM_CHANNEL_SEND_DM;
|
---|
| 2372 | break;
|
---|
| 2373 | default:
|
---|
| 2374 | break;
|
---|
| 2375 | }
|
---|
| 2376 |
|
---|
| 2377 | // process
|
---|
| 2378 | rfcomm_run();
|
---|
| 2379 | }
|
---|
| 2380 |
|
---|
| 2381 | void rfcomm_grant_credits(uint16_t rfcomm_cid, uint8_t credits){
|
---|
| 2382 | rfcomm_channel_t * channel;
|
---|
| 2383 | log_info("RFCOMM_GRANT_CREDITS cid 0x%02x credits %u", rfcomm_cid, credits);
|
---|
| 2384 | channel = rfcomm_channel_for_rfcomm_cid(rfcomm_cid);
|
---|
| 2385 | if (!channel) return;
|
---|
| 2386 | if (!channel->incoming_flow_control) return;
|
---|
| 2387 | channel->new_credits_incoming += credits;
|
---|
| 2388 |
|
---|
| 2389 | // process
|
---|
| 2390 | rfcomm_run();
|
---|
| 2391 | }
|
---|
| 2392 |
|
---|
| 2393 |
|
---|
| 2394 |
|
---|
| 2395 |
|
---|