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