1 /*
2 * Copyright (C) 2014 BlueKitchen GmbH
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 BLUEKITCHEN GMBH 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 BLUEKITCHEN
24 * GMBH 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
34 * [email protected]
35 *
36 */
37
38 /**
39 * @title RFCOMM
40 *
41 */
42
43 #ifndef RFCOMM_H
44 #define RFCOMM_H
45
46 #include "btstack_util.h"
47
48 #include <stdint.h>
49 #include "btstack_run_loop.h"
50 #include "gap.h"
51 #include "l2cap.h"
52
53 #if defined __cplusplus
54 extern "C" {
55 #endif
56
57 #define UNLIMITED_INCOMING_CREDITS 0xff
58
59 #define RFCOMM_TEST_DATA_MAX_LEN 4
60
61 #define RFCOMM_RLS_STATUS_INVALID 0xff
62
63
64 // private structs
65 typedef enum {
66 RFCOMM_MULTIPLEXER_CLOSED = 1,
67 RFCOMM_MULTIPLEXER_W4_CONNECT, // outgoing
68 RFCOMM_MULTIPLEXER_SEND_SABM_0, // "
69 RFCOMM_MULTIPLEXER_W4_UA_0, // "
70 RFCOMM_MULTIPLEXER_W4_SABM_0, // incoming
71 RFCOMM_MULTIPLEXER_SEND_UA_0,
72 RFCOMM_MULTIPLEXER_OPEN,
73 RFCOMM_MULTIPLEXER_SEND_UA_0_AND_DISC,
74 RFCOMM_MULTIPLEXER_SHUTTING_DOWN,
75 } RFCOMM_MULTIPLEXER_STATE;
76
77 typedef enum {
78 MULT_EV_READY_TO_SEND = 1,
79 } RFCOMM_MULTIPLEXER_EVENT;
80
81 typedef enum {
82 RFCOMM_CHANNEL_CLOSED = 1,
83 RFCOMM_CHANNEL_W4_MULTIPLEXER,
84 RFCOMM_CHANNEL_SEND_UIH_PN,
85 RFCOMM_CHANNEL_W4_PN_RSP,
86 RFCOMM_CHANNEL_SEND_SABM_W4_UA,
87 RFCOMM_CHANNEL_W4_UA,
88 RFCOMM_CHANNEL_INCOMING_SETUP,
89 RFCOMM_CHANNEL_DLC_SETUP,
90 RFCOMM_CHANNEL_OPEN,
91 RFCOMM_CHANNEL_SEND_UA_AFTER_DISC,
92 RFCOMM_CHANNEL_SEND_DISC,
93 RFCOMM_CHANNEL_W4_UA_AFTER_DISC,
94 RFCOMM_CHANNEL_SEND_DM,
95 } RFCOMM_CHANNEL_STATE;
96
97
98 #define RFCOMM_CHANNEL_STATE_VAR_NONE 0
99 #define RFCOMM_CHANNEL_STATE_VAR_CLIENT_ACCEPTED 1 << 0
100 #define RFCOMM_CHANNEL_STATE_VAR_RCVD_PN 1 << 1
101 #define RFCOMM_CHANNEL_STATE_VAR_RCVD_SABM 1 << 2
102 #define RFCOMM_CHANNEL_STATE_VAR_RCVD_MSC_CMD 1 << 3
103 #define RFCOMM_CHANNEL_STATE_VAR_RCVD_MSC_RSP 1 << 4
104 #define RFCOMM_CHANNEL_STATE_VAR_SEND_PN_RSP 1 << 5
105 #define RFCOMM_CHANNEL_STATE_VAR_SEND_RPN_QUERY 1 << 6
106 #define RFCOMM_CHANNEL_STATE_VAR_SEND_RPN_CONFIG 1 << 7
107 #define RFCOMM_CHANNEL_STATE_VAR_SEND_RPN_RESPONSE 1 << 8
108 #define RFCOMM_CHANNEL_STATE_VAR_EMIT_RPN_RESPONSE 1 << 9
109 #define RFCOMM_CHANNEL_STATE_VAR_SEND_UA 1 << 10
110 #define RFCOMM_CHANNEL_STATE_VAR_SEND_MSC_CMD 1 << 11
111 #define RFCOMM_CHANNEL_STATE_VAR_SEND_MSC_RSP 1 << 12
112 #define RFCOMM_CHANNEL_STATE_VAR_SEND_CREDITS 1 << 13
113 #define RFCOMM_CHANNEL_STATE_VAR_SENT_MSC_CMD 1 << 14
114 #define RFCOMM_CHANNEL_STATE_VAR_SENT_MSC_RSP 1 << 15
115 #define RFCOMM_CHANNEL_STATE_VAR_SENT_CREDITS 1 << 16
116
117 typedef struct rfcomm_rpn_data {
118 uint8_t baud_rate;
119 uint8_t flags;
120 uint8_t flow_control;
121 uint8_t xon;
122 uint8_t xoff;
123 uint8_t parameter_mask_0; // first byte
124 uint8_t parameter_mask_1; // second byte
125 } rfcomm_rpn_data_t;
126
127 // info regarding potential connections
128 typedef struct {
129 // linked list - assert: first field
130 btstack_linked_item_t item;
131
132 // packet handler
133 btstack_packet_handler_t packet_handler;
134
135 // server channel
136 uint8_t server_channel;
137
138 // incoming max frame size
139 uint16_t max_frame_size;
140
141 // use incoming flow control
142 uint8_t incoming_flow_control;
143
144 // initial incoming credits
145 uint8_t incoming_initial_credits;
146
147
148 } rfcomm_service_t;
149
150 // info regarding multiplexer
151 // note: spec mandates single multiplexer per device combination
152 typedef struct {
153 // linked list - assert: first field
154 btstack_linked_item_t item;
155
156 RFCOMM_MULTIPLEXER_STATE state;
157
158 uint16_t l2cap_cid;
159
160 uint8_t fcon; // only send if fcon & 1, send rsp if fcon & 0x80
161
162 bd_addr_t remote_addr;
163 hci_con_handle_t con_handle;
164
165 uint8_t outgoing;
166
167 // hack to deal with authentication failure only observed by remote side
168 uint8_t at_least_one_connection;
169
170 uint16_t max_frame_size;
171
172 // send DM for DLCI != 0
173 uint8_t send_dm_for_dlci;
174
175 // non supported command, 0 if not set
176 uint8_t nsc_command;
177
178 // ertm id
179 uint16_t ertm_id;
180
181 // test data - limited to RFCOMM_TEST_DATA_MAX_LEN
182 uint8_t test_data_len;
183 uint8_t test_data[RFCOMM_TEST_DATA_MAX_LEN];
184
185 } rfcomm_multiplexer_t;
186
187 // info regarding an actual connection
188 typedef struct {
189
190 // linked list - assert: first field
191 btstack_linked_item_t item;
192
193 // packet handler
194 btstack_packet_handler_t packet_handler;
195
196 // server channel (see rfcomm_service_t) - NULL => outgoing channel
197 rfcomm_service_t * service;
198
199 // muliplexer for this channel
200 rfcomm_multiplexer_t *multiplexer;
201
202 // RFCOMM Channel ID
203 uint16_t rfcomm_cid;
204
205 //
206 uint8_t dlci;
207
208 // credits for outgoing traffic
209 uint8_t credits_outgoing;
210
211 // number of packets remote will be granted
212 uint8_t new_credits_incoming;
213
214 // credits for incoming traffic
215 uint8_t credits_incoming;
216
217 // use incoming flow control
218 uint8_t incoming_flow_control;
219
220 // channel state
221 RFCOMM_CHANNEL_STATE state;
222
223 // state variables/flags
224 uint32_t state_var;
225
226 // priority set by incoming side in PN
227 uint8_t pn_priority;
228
229 // negotiated frame size
230 uint16_t max_frame_size;
231
232 // local rpn data
233 rfcomm_rpn_data_t local_rpn_data;
234
235 // remote rpn data
236 rfcomm_rpn_data_t remote_rpn_data;
237
238 // local line status. RFCOMM_RLS_STATUS_INVALID if not set
239 // buffers local status for RLS CMD
240 uint8_t local_line_status;
241
242 // remote line status. RFCOMM_RLS_STATUS_INVALID if not set
243 // send RLS RSP with status from the RLS CMD
244 uint8_t remote_line_status;
245
246 // local modem status.
247 uint8_t local_modem_status;
248
249 // remote modem status.
250 uint8_t remote_modem_status;
251
252 //
253 uint8_t waiting_for_can_send_now;
254
255 } rfcomm_channel_t;
256
257 // struct used in ERTM callback
258 typedef struct {
259 // remote address
260 bd_addr_t addr;
261
262 // ERTM ID - returned in RFCOMM_EVENT_ERTM_BUFFER_RELEASED.
263 uint16_t ertm_id;
264
265 // ERTM Configuration - needs to stay valid indefinitely
266 l2cap_ertm_config_t * ertm_config;
267
268 // ERTM buffer
269 uint8_t * ertm_buffer;
270 uint32_t ertm_buffer_size;
271 } rfcomm_ertm_request_t;
272
273 /* API_START */
274
275 /**
276 * @brief Set up RFCOMM.
277 */
278 void rfcomm_init(void);
279
280 /**
281 * @brief Set security level required for incoming connections, need to be called before registering services.
282 * @deprecated use gap_set_security_level instead
283 */
284 void rfcomm_set_required_security_level(gap_security_level_t security_level);
285
286 /*
287 * @brief Create RFCOMM connection to a given server channel on a remote deivce.
288 * This channel will automatically provide enough credits to the remote side.
289 * @param addr
290 * @param server_channel
291 * @param out_cid
292 * @result status
293 */
294 uint8_t rfcomm_create_channel(btstack_packet_handler_t packet_handler, bd_addr_t addr, uint8_t server_channel, uint16_t * out_cid);
295
296 /*
297 * @brief Create RFCOMM connection to a given server channel on a remote deivce.
298 * This channel will use explicit credit management. During channel establishment, an initial amount of credits is provided.
299 * @param addr
300 * @param server_channel
301 * @param initial_credits
302 * @param out_cid
303 * @result status
304 */
305 uint8_t rfcomm_create_channel_with_initial_credits(btstack_packet_handler_t packet_handler, bd_addr_t addr, uint8_t server_channel, uint8_t initial_credits, uint16_t * out_cid);
306
307 /**
308 * @brief Disconnects RFCOMM channel with given identifier.
309 * @return status
310 */
311 uint8_t rfcomm_disconnect(uint16_t rfcomm_cid);
312
313 /**
314 * @brief Registers RFCOMM service for a server channel and a maximum frame size, and assigns a packet handler.
315 * This channel provides credits automatically to the remote side -> no flow control
316 * @param packet handler for all channels of this service
317 * @param channel
318 * @param max_frame_size
319 * @return status ERROR_CODE_SUCCESS if successful, otherwise L2CAP_SERVICE_ALREADY_REGISTERED or BTSTACK_MEMORY_ALLOC_FAILED
320 */
321 uint8_t rfcomm_register_service(btstack_packet_handler_t packet_handler, uint8_t channel, uint16_t max_frame_size);
322
323 /**
324 * @brief Registers RFCOMM service for a server channel and a maximum frame size, and assigns a packet handler.
325 * This channel will use explicit credit management. During channel establishment, an initial amount of credits is provided.
326 * @param packet handler for all channels of this service
327 * @param channel
328 * @param max_frame_size
329 * @param initial_credits
330 * @return status ERROR_CODE_SUCCESS if successful, otherwise L2CAP_SERVICE_ALREADY_REGISTERED or BTSTACK_MEMORY_ALLOC_FAILED
331 */
332 uint8_t rfcomm_register_service_with_initial_credits(btstack_packet_handler_t packet_handler, uint8_t channel, uint16_t max_frame_size, uint8_t initial_credits);
333
334 /**
335 * @brief Unregister RFCOMM service.
336 */
337 void rfcomm_unregister_service(uint8_t service_channel);
338
339 /**
340 * @brief Accepts incoming RFCOMM connection.
341 * @return status
342 */
343 uint8_t rfcomm_accept_connection(uint16_t rfcomm_cid);
344
345 /**
346 * @brief Deny incoming RFCOMM connection.
347 * @return status
348 */
349 uint8_t rfcomm_decline_connection(uint16_t rfcomm_cid);
350
351 /**
352 * @brief Grant more incoming credits to the remote side for the given RFCOMM channel identifier.
353 * @return status
354 */
355 uint8_t rfcomm_grant_credits(uint16_t rfcomm_cid, uint8_t credits);
356
357 /**
358 * @brief Checks if RFCOMM can send packet.
359 * @param rfcomm_cid
360 * @result true if can send now
361 */
362 bool rfcomm_can_send_packet_now(uint16_t rfcomm_cid);
363
364 /**
365 * @brief Request emission of RFCOMM_EVENT_CAN_SEND_NOW as soon as possible
366 * @note RFCOMM_EVENT_CAN_SEND_NOW might be emitted during call to this function
367 * so packet handler should be ready to handle it
368 * @param rfcomm_cid
369 * @prarm status
370 */
371 uint8_t rfcomm_request_can_send_now_event(uint16_t rfcomm_cid);
372
373 /**
374 * @brief Sends RFCOMM data packet to the RFCOMM channel with given identifier.
375 * @param rfcomm_cid
376 * @return status
377 */
378 uint8_t rfcomm_send(uint16_t rfcomm_cid, uint8_t *data, uint16_t len);
379
380 /**
381 * @brief Sends Local Line Status, see LINE_STATUS_..
382 * @param rfcomm_cid
383 * @param line_status
384 * @return status
385 */
386 uint8_t rfcomm_send_local_line_status(uint16_t rfcomm_cid, uint8_t line_status);
387
388 /**
389 * @brief Send local modem status. see MODEM_STAUS_..
390 * @param rfcomm_cid
391 * @param modem_status
392 * @return status
393 */
394 uint8_t rfcomm_send_modem_status(uint16_t rfcomm_cid, uint8_t modem_status);
395
396 /**
397 * @brief Configure remote port
398 * @param rfcomm_cid
399 * @param baud_rate
400 * @param data_bits
401 * @param stop_bits
402 * @param parity
403 * @param flow_control
404 * @return status
405 */
406 uint8_t 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, uint8_t flow_control);
407
408 /**
409 * @brief Query remote port
410 * @param rfcomm_cid
411 * @return status
412 */
413 uint8_t rfcomm_query_port_configuration(uint16_t rfcomm_cid);
414
415 /**
416 * @brief Query max frame size
417 * @param rfcomm_cid
418 * @return max frame size
419 */
420 uint16_t rfcomm_get_max_frame_size(uint16_t rfcomm_cid);
421
422 /**
423 * @brief Reserve packet buffer to allow to create RFCOMM packet in place
424 * @note Must only be called after a 'can send now' check or event
425 * @note Asserts if packet buffer is already reserved
426 *
427 * if (rfcomm_can_send_packet_now(cid)){
428 * rfcomm_reserve_packet_buffer();
429 * uint8_t * buffer = rfcomm_get_outgoing_buffer();
430 * uint16_t buffer_size = rfcomm_get_max_frame_size(cid);
431 * .. setup data in buffer with len ..
432 * rfcomm_send_prepared(cid, len)
433 * }
434 */
435 void rfcomm_reserve_packet_buffer(void);
436
437 /**
438 * @brief Get outgoing buffer
439 * @return pointer to outgoing rfcomm buffer
440 */
441 uint8_t * rfcomm_get_outgoing_buffer(void);
442
443 /**
444 * @brief Send packet prepared in outgoing buffer
445 * @note This releases the outgoing rfcomm buffer
446 * @param rfcomm_cid
447 * @param len
448 * @return status
449 */
450 uint8_t rfcomm_send_prepared(uint16_t rfcomm_cid, uint16_t len);
451
452 /**
453 * @brief Release outgoing buffer in case rfcomm_send_prepared was not called
454 */
455 void rfcomm_release_packet_buffer(void);
456
457 /**
458 * @brief Enable L2CAP ERTM mode for RFCOMM. request callback is used to provide ERTM buffer. released callback returns buffer
459 *
460 * @note on request_callback, the app must set the ertm_config, buffer, size fields to enable ERTM for the current connection
461 * @note if buffer is not set, BASIC mode will be used instead
462 *
463 * @note released_callback provides ertm_id from earlier request to match request and release
464 *
465 * @param request_callback
466 * @param released_callback
467 */
468 void rfcomm_enable_l2cap_ertm(void request_callback(rfcomm_ertm_request_t * request), void released_callback(uint16_t ertm_id));
469
470
471 // Event getters for RFCOMM_EVENT_PORT_CONFIGURATION
472
473 /**
474 * @brief Get field rfcomm_cid from event RFCOMM_EVENT_PORT_CONFIGURATION
475 * @param event packet
476 * @return rfcomm_cid
477 */
rfcomm_event_port_configuration_get_rfcomm_cid(const uint8_t * event)478 static inline uint16_t rfcomm_event_port_configuration_get_rfcomm_cid(const uint8_t * event){
479 return little_endian_read_16(event, 2);
480 }
481
482 /**
483 * @brief Get field local from event RFCOMM_EVENT_PORT_CONFIGURATION
484 * @param event packet
485 * @return remote - false for local port, true for remote port
486 */
rfcomm_event_port_configuration_get_remote(const uint8_t * event)487 static inline bool rfcomm_event_port_configuration_get_remote(const uint8_t * event){
488 return event[4] != 0;
489 }
490
491 /**
492 * @brief Get field baud_rate from event RFCOMM_EVENT_PORT_CONFIGURATION
493 * @param event packet
494 * @return baud_rate
495 */
496
rfcomm_event_port_configuration_get_baud_rate(const uint8_t * event)497 static inline rpn_baud_t rfcomm_event_port_configuration_get_baud_rate(const uint8_t * event){
498 return (rpn_baud_t) event[5];
499 }
500
501 /**
502 * @brief Get field data_bits from event RFCOMM_EVENT_PORT_CONFIGURATION
503 * @param event packet
504 * @return data_bits
505 */
506
rfcomm_event_port_configuration_get_data_bits(const uint8_t * event)507 static inline rpn_data_bits_t rfcomm_event_port_configuration_get_data_bits(const uint8_t * event){
508 return (rpn_data_bits_t) (event[6] & 3);
509 }
510 /**
511 * @brief Get field stop_bits from event RFCOMM_EVENT_PORT_CONFIGURATION
512 * @param event packet
513 * @return stop_bits
514 */
rfcomm_event_port_configuration_get_stop_bits(const uint8_t * event)515 static inline rpn_stop_bits_t rfcomm_event_port_configuration_get_stop_bits(const uint8_t * event){
516 return (rpn_stop_bits_t) ((event[6] >> 2) & 1);
517 }
518
519 /**
520 * @brief Get field parity from event RFCOMM_EVENT_PORT_CONFIGURATION
521 * @param event packet
522 * @return parity
523 */
rfcomm_event_port_configuration_get_parity(const uint8_t * event)524 static inline rpn_parity_t rfcomm_event_port_configuration_get_parity(const uint8_t * event){
525 return (rpn_parity_t) ((event[6] >> 3) & 7);
526 }
527
528 /**
529 * @brief Get field flow_control from event RFCOMM_EVENT_PORT_CONFIGURATION
530 * @param event packet
531 * @return flow_control
532 */
533
rfcomm_event_port_configuration_get_flow_control(const uint8_t * event)534 static inline uint8_t rfcomm_event_port_configuration_get_flow_control(const uint8_t * event){
535 return event[7] & 0x3f;
536 }
537
538 /**
539 * @brief Get field xon from event RFCOMM_EVENT_PORT_CONFIGURATION
540 * @param event packet
541 * @return xon
542 */
rfcomm_event_port_configuration_get_xon(const uint8_t * event)543 static inline uint8_t rfcomm_event_port_configuration_get_xon(const uint8_t * event){
544 return event[8];
545 }
546
547 /**
548 * @brief Get field xoff from event RFCOMM_EVENT_PORT_CONFIGURATION
549 * @param event packet
550 * @return xoff
551 */
rfcomm_event_port_configuration_get_xoff(const uint8_t * event)552 static inline uint8_t rfcomm_event_port_configuration_get_xoff(const uint8_t * event){
553 return event[9];
554 }
555
556 /**
557 * @brief De-Init RFCOMM
558 */
559 void rfcomm_deinit(void);
560
561 /* API_END */
562
563 #if defined __cplusplus
564 }
565 #endif
566
567 #endif // RFCOMM_H
568