xref: /btstack/src/classic/rfcomm.h (revision 8caefee39d444df6d8908a96a844825f10fbdaa4)
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 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
34  * [email protected]
35  *
36  */
37 
38 /*
39  *  RFCOMM.h
40  */
41 
42 #ifndef __RFCOMM_H
43 #define __RFCOMM_H
44 
45 #include "utils.h"
46 
47 #include <stdint.h>
48 
49 #if defined __cplusplus
50 extern "C" {
51 #endif
52 
53 #define UNLIMITED_INCOMING_CREDITS 0xff
54 
55 #define RFCOMM_TEST_DATA_MAX_LEN 4
56 
57 #define RFCOMM_RLS_STATUS_INVALID 0xff
58 
59 // Line Status
60 #define LINE_STATUS_NO_ERROR       0x00
61 #define LINE_STATUS_OVERRUN_ERROR  0x03
62 #define LINE_STATUS_PARITY_ERORR   0x05
63 #define LINE_STATUS_FRAMING_ERROR  0x09
64 
65 // Modem Status Flags
66 #define MODEM_STATUS_FC   0x02
67 #define MODEM_STATUS_RTC  0x04
68 #define MODEM_STATUS_RTR  0x08
69 #define MODEM_STATUS_IC   0x40
70 #define MODEM_STATUS_DV   0x80
71 
72 typedef enum rpn_baud {
73     RPN_BAUD_2400 = 0,
74     RPN_BAUD_4800,
75     RPN_BAUD_7200,
76     RPN_BAUD_9600,
77     RPN_BAUD_19200,
78     RPN_BAUD_38400,
79     RPN_BAUD_57600,
80     RPN_BAUD_115200,
81     RPN_BAUD_230400
82 } rpn_baud_t;
83 
84 typedef enum rpn_data_bits {
85     RPN_DATA_BITS_5 = 0,
86     RPN_DATA_BITS_6 = 0,
87     RPN_DATA_BITS_7 = 0,
88     RPN_DATA_BITS_8 = 0
89 } rpn_data_bits_t;
90 
91 typedef enum rpn_stop_bits {
92     RPN_STOP_BITS_1_0 = 0,
93     RPN_STOP_BITS_1_5
94 } rpn_stop_bits_t;
95 
96 typedef enum rpn_parity {
97     RPN_PARITY_NONE  = 0,
98     RPN_PARITY_ODD   = 1,
99     RPN_PARITY_EVEN  = 3,
100     RPN_PARITY_MARK  = 5,
101     RPN_PARITY_SPACE = 7,
102 } rpn_parity_t;
103 
104 typedef enum rpn_flow_control {
105     RPN_FLOW_CONTROL_XONXOFF_ON_INPUT  = 1 << 0,
106     RPN_FLOW_CONTROL_XONXOFF_ON_OUTPUT = 1 << 1,
107     RPN_FLOW_CONTROL_RTR_ON_INPUT  = 1 << 2,
108     RPN_FLOW_CONTROL_RTR_ON_OUTPUT = 1 << 3,
109     RPN_FLOW_CONTROL_RTC_ON_INPUT  = 1 << 4,
110     RPN_FLOW_CONTROL_RTC_ON_OUTPUT = 1 << 5,
111 } rpn_flow_control_t;
112 
113 #define RPN_PARAM_MASK_0_BAUD             0x01
114 #define RPN_PARAM_MASK_0_DATA_BITS        0x02
115 #define RPN_PARAM_MASK_0_STOP_BITS        0x04
116 #define RPN_PARAM_MASK_0_PARITY           0x08
117 #define RPN_PARAM_MASK_0_PARITY_TYPE      0x10
118 #define RPN_PARAM_MASK_0_XON_CHAR         0x20
119 #define RPN_PARAM_MASK_0_XOFF_CHAR        0x40
120 #define RPN_PARAM_MASK_0_RESERVED         0x80
121 
122 // @note: values are identical to rpn_flow_control_t
123 #define RPN_PARAM_MASK_1_XONOFF_ON_INPUT  0x01
124 #define RPN_PARAM_MASK_1_XONOFF_ON_OUTPUT 0x02
125 #define RPN_PARAM_MASK_1_RTR_ON_INPUT     0x04
126 #define RPN_PARAM_MASK_1_RTR_ON_OUTPUT    0x08
127 #define RPN_PARAM_MASK_1_RTC_ON_INPUT     0x10
128 #define RPN_PARAM_MASK_1_RTC_ON_OUTPUT    0x20
129 #define RPN_PARAM_MASK_1_RESERVED_0       0x40
130 #define RPN_PARAM_MASK_1_RESERVED_1       0x80
131 
132 
133 // private structs
134 typedef enum {
135 	RFCOMM_MULTIPLEXER_CLOSED = 1,
136 	RFCOMM_MULTIPLEXER_W4_CONNECT,  // outgoing
137 	RFCOMM_MULTIPLEXER_SEND_SABM_0,     //    "
138 	RFCOMM_MULTIPLEXER_W4_UA_0,     //    "
139 	RFCOMM_MULTIPLEXER_W4_SABM_0,   // incoming
140     RFCOMM_MULTIPLEXER_SEND_UA_0,
141 	RFCOMM_MULTIPLEXER_OPEN,
142     RFCOMM_MULTIPLEXER_SEND_UA_0_AND_DISC
143 } RFCOMM_MULTIPLEXER_STATE;
144 
145 typedef enum {
146     MULT_EV_READY_TO_SEND = 1,
147 
148 } RFCOMM_MULTIPLEXER_EVENT;
149 
150 typedef enum {
151 	RFCOMM_CHANNEL_CLOSED = 1,
152 	RFCOMM_CHANNEL_W4_MULTIPLEXER,
153 	RFCOMM_CHANNEL_SEND_UIH_PN,
154     RFCOMM_CHANNEL_W4_PN_RSP,
155 	RFCOMM_CHANNEL_SEND_SABM_W4_UA,
156 	RFCOMM_CHANNEL_W4_UA,
157     RFCOMM_CHANNEL_INCOMING_SETUP,
158     RFCOMM_CHANNEL_DLC_SETUP,
159 	RFCOMM_CHANNEL_OPEN,
160     RFCOMM_CHANNEL_SEND_UA_AFTER_DISC,
161     RFCOMM_CHANNEL_SEND_DISC,
162     RFCOMM_CHANNEL_W4_UA_AFTER_UA,
163     RFCOMM_CHANNEL_SEND_DM,
164 
165 } RFCOMM_CHANNEL_STATE;
166 
167 typedef enum {
168     RFCOMM_CHANNEL_STATE_VAR_NONE            = 0,
169     RFCOMM_CHANNEL_STATE_VAR_CLIENT_ACCEPTED = 1 << 0,
170     RFCOMM_CHANNEL_STATE_VAR_RCVD_PN         = 1 << 1,
171     RFCOMM_CHANNEL_STATE_VAR_RCVD_RPN        = 1 << 2,
172     RFCOMM_CHANNEL_STATE_VAR_RCVD_SABM       = 1 << 3,
173 
174     RFCOMM_CHANNEL_STATE_VAR_RCVD_MSC_CMD    = 1 << 4,
175     RFCOMM_CHANNEL_STATE_VAR_RCVD_MSC_RSP    = 1 << 5,
176     RFCOMM_CHANNEL_STATE_VAR_SEND_PN_RSP     = 1 << 6,
177     RFCOMM_CHANNEL_STATE_VAR_SEND_RPN_INFO   = 1 << 7,
178 
179     RFCOMM_CHANNEL_STATE_VAR_SEND_RPN_RSP    = 1 << 8,
180     RFCOMM_CHANNEL_STATE_VAR_SEND_UA         = 1 << 9,
181     RFCOMM_CHANNEL_STATE_VAR_SEND_MSC_CMD    = 1 << 10,
182     RFCOMM_CHANNEL_STATE_VAR_SEND_MSC_RSP    = 1 << 11,
183 
184     RFCOMM_CHANNEL_STATE_VAR_SEND_CREDITS    = 1 << 12,
185     RFCOMM_CHANNEL_STATE_VAR_SENT_MSC_CMD    = 1 << 13,
186     RFCOMM_CHANNEL_STATE_VAR_SENT_MSC_RSP    = 1 << 14,
187     RFCOMM_CHANNEL_STATE_VAR_SENT_CREDITS    = 1 << 15,
188 } RFCOMM_CHANNEL_STATE_VAR;
189 
190 typedef enum {
191     CH_EVT_RCVD_SABM = 1,
192     CH_EVT_RCVD_UA,
193     CH_EVT_RCVD_PN,
194     CH_EVT_RCVD_PN_RSP,
195     CH_EVT_RCVD_DISC,
196     CH_EVT_RCVD_DM,
197     CH_EVT_RCVD_MSC_CMD,
198     CH_EVT_RCVD_MSC_RSP,
199     CH_EVT_RCVD_NSC_RSP,
200     CH_EVT_RCVD_RLS_CMD,
201     CH_EVT_RCVD_RLS_RSP,
202     CH_EVT_RCVD_RPN_CMD,
203     CH_EVT_RCVD_RPN_REQ,
204     CH_EVT_RCVD_CREDITS,
205     CH_EVT_MULTIPLEXER_READY,
206     CH_EVT_READY_TO_SEND,
207 } RFCOMM_CHANNEL_EVENT;
208 
209 typedef struct rfcomm_channel_event {
210     RFCOMM_CHANNEL_EVENT type;
211     uint16_t dummy; // force rfcomm_channel_event to be 2-byte aligned -> avoid -Wcast-align warning
212 } rfcomm_channel_event_t;
213 
214 typedef struct rfcomm_channel_event_pn {
215     rfcomm_channel_event_t super;
216     uint16_t max_frame_size;
217     uint8_t  priority;
218     uint8_t  credits_outgoing;
219 } rfcomm_channel_event_pn_t;
220 
221 typedef struct rfcomm_rpn_data {
222     uint8_t baud_rate;
223     uint8_t flags;
224     uint8_t flow_control;
225     uint8_t xon;
226     uint8_t xoff;
227     uint8_t parameter_mask_0;   // first byte
228     uint8_t parameter_mask_1;   // second byte
229 } rfcomm_rpn_data_t;
230 
231 typedef struct rfcomm_channel_event_rpn {
232     rfcomm_channel_event_t super;
233     rfcomm_rpn_data_t data;
234 } rfcomm_channel_event_rpn_t;
235 
236 typedef struct rfcomm_channel_event_rls {
237     rfcomm_channel_event_t super;
238     uint8_t line_status;
239 } rfcomm_channel_event_rls_t;
240 
241 typedef struct rfcomm_channel_event_msc {
242     rfcomm_channel_event_t super;
243     uint8_t modem_status;
244 } rfcomm_channel_event_msc_t;
245 
246 // info regarding potential connections
247 typedef struct {
248     // linked list - assert: first field
249     linked_item_t    item;
250 
251     // server channel
252     uint8_t server_channel;
253 
254     // incoming max frame size
255     uint16_t max_frame_size;
256 
257     // use incoming flow control
258     uint8_t incoming_flow_control;
259 
260     // initial incoming credits
261     uint8_t incoming_initial_credits;
262 
263     // client connection
264     void *connection;
265 
266     // internal connection
267     btstack_packet_handler_t packet_handler;
268 
269 } rfcomm_service_t;
270 
271 // info regarding multiplexer
272 // note: spec mandates single multiplexer per device combination
273 typedef struct {
274     // linked list - assert: first field
275     linked_item_t    item;
276 
277     timer_source_t   timer;
278     int              timer_active;
279 
280 	RFCOMM_MULTIPLEXER_STATE state;
281 
282     uint16_t  l2cap_cid;
283     uint8_t   l2cap_credits;
284 
285     uint8_t   fcon; // only send if fcon & 1, send rsp if fcon & 0x80
286 
287 	bd_addr_t remote_addr;
288     hci_con_handle_t con_handle;
289 
290 	uint8_t   outgoing;
291 
292     // hack to deal with authentication failure only observed by remote side
293     uint8_t at_least_one_connection;
294 
295     uint16_t max_frame_size;
296 
297     // send DM for DLCI != 0
298     uint8_t send_dm_for_dlci;
299 
300     // non supported command, 0 if not set
301     uint8_t nsc_command;
302 
303     // test data - limited to RFCOMM_TEST_DATA_MAX_LEN
304     uint8_t test_data_len;
305     uint8_t test_data[RFCOMM_TEST_DATA_MAX_LEN];
306 
307 } rfcomm_multiplexer_t;
308 
309 // info regarding an actual connection
310 typedef struct {
311     // linked list - assert: first field
312     linked_item_t    item;
313 
314 	rfcomm_multiplexer_t *multiplexer;
315 	uint16_t rfcomm_cid;
316     uint8_t  outgoing;
317     uint8_t  dlci;
318 
319     // number of packets granted to client
320     uint8_t packets_granted;
321 
322     // credits for outgoing traffic
323     uint8_t credits_outgoing;
324 
325     // number of packets remote will be granted
326     uint8_t new_credits_incoming;
327 
328     // credits for incoming traffic
329     uint8_t credits_incoming;
330 
331     // use incoming flow control
332     uint8_t incoming_flow_control;
333 
334     // channel state
335     RFCOMM_CHANNEL_STATE state;
336 
337     // state variables used in RFCOMM_CHANNEL_INCOMING
338     RFCOMM_CHANNEL_STATE_VAR state_var;
339 
340     // priority set by incoming side in PN
341     uint8_t pn_priority;
342 
343 	// negotiated frame size
344     uint16_t max_frame_size;
345 
346     // local rpn data
347     rfcomm_rpn_data_t rpn_data;
348 
349     // rls line status. RFCOMM_RLS_STATUS_INVALID if not set
350     uint8_t rls_line_status;
351 
352     // msc modem status.
353     uint8_t msc_modem_status;
354 
355 	// server channel (see rfcomm_service_t) - NULL => outgoing channel
356 	rfcomm_service_t * service;
357 
358     // internal connection
359     btstack_packet_handler_t packet_handler;
360 
361     // client connection
362     void * connection;
363 
364 } rfcomm_channel_t;
365 
366 void rfcomm_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
367 
368 /* API_START */
369 
370 /**
371  * @brief Set up RFCOMM.
372  */
373 void rfcomm_init(void);
374 
375 /**
376  * @brief Set security level required for incoming connections, need to be called before registering services.
377  */
378 void rfcomm_set_required_security_level(gap_security_level_t security_level);
379 
380 /**
381  * @brief Register packet handler.
382  */
383 void rfcomm_register_packet_handler(void (*handler)(void * connection, uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size));
384 
385 /**
386  * @brief Creates RFCOMM connection (channel) to a given server channel on a remote device with baseband address. A new baseband connection will be initiated if necessary. This channel will automatically provide enough credits to the remote side
387  */
388 void rfcomm_create_channel_internal(void * connection, bd_addr_t addr, uint8_t channel);
389 
390 /**
391  * @brief Creates RFCOMM connection (channel) to a given server channel on a remote device with baseband address. new baseband connection will be initiated if necessary. This channel will use explicit credit management. During channel establishment, an initial  amount of credits is provided.
392  */
393 void rfcomm_create_channel_with_initial_credits_internal(void * connection, bd_addr_t addr, uint8_t server_channel, uint8_t initial_credits);
394 
395 /**
396  * @brief Disconnects RFCOMM channel with given identifier.
397  */
398 void rfcomm_disconnect_internal(uint16_t rfcomm_cid);
399 
400 /**
401  * @brief Registers RFCOMM service for a server channel and a maximum frame size, and assigns a packet handler. On embedded systems, use NULL for connection parameter. This channel provides automatically enough credits to the remote side.
402  */
403 void rfcomm_register_service_internal(void * connection, uint8_t channel, uint16_t max_frame_size);
404 
405 /**
406  * @brief Registers RFCOMM service for a server channel and a maximum frame size, and assigns a packet handler. On embedded systems, use NULL for connection parameter. This channel will use explicit credit management. During channel establishment, an initial amount of credits is provided.
407  */
408 void rfcomm_register_service_with_initial_credits_internal(void * connection, uint8_t channel, uint16_t max_frame_size, uint8_t initial_credits);
409 
410 /**
411  * @brief Unregister RFCOMM service.
412  */
413 void rfcomm_unregister_service_internal(uint8_t service_channel);
414 
415 /**
416  * @brief Accepts/Deny incoming RFCOMM connection.
417  */
418 void rfcomm_accept_connection_internal(uint16_t rfcomm_cid);
419 void rfcomm_decline_connection_internal(uint16_t rfcomm_cid);
420 
421 /**
422  * @brief Grant more incoming credits to the remote side for the given RFCOMM channel identifier.
423  */
424 void rfcomm_grant_credits(uint16_t rfcomm_cid, uint8_t credits);
425 
426 /**
427  * @brief Checks if RFCOMM can send packet. Returns yes if packet can be sent.
428  */
429 int rfcomm_can_send_packet_now(uint16_t rfcomm_cid);
430 
431 /**
432  * @brief Sends RFCOMM data packet to the RFCOMM channel with given identifier.
433  */
434 int  rfcomm_send_internal(uint16_t rfcomm_cid, uint8_t *data, uint16_t len);
435 
436 /**
437  * @brief Sends Local Line Status, see LINE_STATUS_..
438  */
439 int rfcomm_send_local_line_status(uint16_t rfcomm_cid, uint8_t line_status);
440 
441 /**
442  * @brief Send local modem status. see MODEM_STAUS_..
443  */
444 int rfcomm_send_modem_status(uint16_t rfcomm_cid, uint8_t modem_status);
445 
446 /**
447  * @brief Configure remote port
448  */
449 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);
450 
451 /**
452  * @brief Query remote port
453  */
454 int rfcomm_query_port_configuration(uint16_t rfcomm_cid);
455 
456 /**
457  * @brief Allow to create RFCOMM packet in outgoing buffer.
458  */
459 int       rfcomm_reserve_packet_buffer(void);
460 void      rfcomm_release_packet_buffer(void);
461 uint8_t * rfcomm_get_outgoing_buffer(void);
462 uint16_t  rfcomm_get_max_frame_size(uint16_t rfcomm_cid);
463 int       rfcomm_send_prepared(uint16_t rfcomm_cid, uint16_t len);
464 /* API_END */
465 
466 #if defined __cplusplus
467 }
468 #endif
469 
470 #endif // __RFCOMM_H
471