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;
|
---|
138 | reverse_bd_addr(channel->multiplexer->remote_addr, &event[2]);
|
---|
139 | event[8] = channel->dlci >> 1;
|
---|
140 | little_endian_store_16(event, 9, channel->rfcomm_cid);
|
---|
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;
|
---|
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;
|
---|
161 | event[pos++] = channel->dlci >> 1;
|
---|
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
|
---|
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;
|
---|
177 | reverse_bd_addr(*addr, &event[pos]); pos += 6;
|
---|
178 | little_endian_store_16(event, pos, 0); pos += 2;
|
---|
179 | event[pos++] = server_channel;
|
---|
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
|
---|
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;
|
---|
206 | little_endian_store_16(event, 2, channel->rfcomm_cid);
|
---|
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;
|
---|
216 | little_endian_store_16(event, 2, channel->rfcomm_cid);
|
---|
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;
|
---|
239 | little_endian_store_16(event, 2, channel->rfcomm_cid);
|
---|
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)
|
---|
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);
|
---|
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 |
|
---|
941 | if (little_endian_read_16(packet, 11) != PSM_RFCOMM) break;
|
---|
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
|
---|
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);
|
---|
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
|
---|
992 | multiplexer->max_frame_size = rfcomm_max_frame_size_for_l2cap_mtu(little_endian_read_16(packet, 17));
|
---|
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)
|
---|
1000 | l2cap_cid = little_endian_read_16(packet, 2);
|
---|
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)
|
---|
1021 | l2cap_cid = little_endian_read_16(packet, 2);
|
---|
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];
|
---|
1480 | event_pn.max_frame_size = little_endian_read_16(packet, payload_offset+6);
|
---|
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];
|
---|
1491 | event_pn.max_frame_size = little_endian_read_16(packet, payload_offset+6);
|
---|
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 |
|
---|