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 // internal connection 264 btstack_packet_handler_t packet_handler; 265 266 } rfcomm_service_t; 267 268 // info regarding multiplexer 269 // note: spec mandates single multiplexer per device combination 270 typedef struct { 271 // linked list - assert: first field 272 linked_item_t item; 273 274 timer_source_t timer; 275 int timer_active; 276 277 RFCOMM_MULTIPLEXER_STATE state; 278 279 uint16_t l2cap_cid; 280 uint8_t l2cap_credits; 281 282 uint8_t fcon; // only send if fcon & 1, send rsp if fcon & 0x80 283 284 bd_addr_t remote_addr; 285 hci_con_handle_t con_handle; 286 287 uint8_t outgoing; 288 289 // hack to deal with authentication failure only observed by remote side 290 uint8_t at_least_one_connection; 291 292 uint16_t max_frame_size; 293 294 // send DM for DLCI != 0 295 uint8_t send_dm_for_dlci; 296 297 // non supported command, 0 if not set 298 uint8_t nsc_command; 299 300 // test data - limited to RFCOMM_TEST_DATA_MAX_LEN 301 uint8_t test_data_len; 302 uint8_t test_data[RFCOMM_TEST_DATA_MAX_LEN]; 303 304 } rfcomm_multiplexer_t; 305 306 // info regarding an actual connection 307 typedef struct { 308 // linked list - assert: first field 309 linked_item_t item; 310 311 rfcomm_multiplexer_t *multiplexer; 312 uint16_t rfcomm_cid; 313 uint8_t outgoing; 314 uint8_t dlci; 315 316 // number of packets granted to client 317 uint8_t packets_granted; 318 319 // credits for outgoing traffic 320 uint8_t credits_outgoing; 321 322 // number of packets remote will be granted 323 uint8_t new_credits_incoming; 324 325 // credits for incoming traffic 326 uint8_t credits_incoming; 327 328 // use incoming flow control 329 uint8_t incoming_flow_control; 330 331 // channel state 332 RFCOMM_CHANNEL_STATE state; 333 334 // state variables used in RFCOMM_CHANNEL_INCOMING 335 RFCOMM_CHANNEL_STATE_VAR state_var; 336 337 // priority set by incoming side in PN 338 uint8_t pn_priority; 339 340 // negotiated frame size 341 uint16_t max_frame_size; 342 343 // local rpn data 344 rfcomm_rpn_data_t rpn_data; 345 346 // rls line status. RFCOMM_RLS_STATUS_INVALID if not set 347 uint8_t rls_line_status; 348 349 // msc modem status. 350 uint8_t msc_modem_status; 351 352 // server channel (see rfcomm_service_t) - NULL => outgoing channel 353 rfcomm_service_t * service; 354 355 // internal connection 356 btstack_packet_handler_t packet_handler; 357 358 } rfcomm_channel_t; 359 360 /* API_START */ 361 362 /** 363 * @brief Set up RFCOMM. 364 */ 365 void rfcomm_init(void); 366 367 /** 368 * @brief Set security level required for incoming connections, need to be called before registering services. 369 */ 370 void rfcomm_set_required_security_level(gap_security_level_t security_level); 371 372 /** 373 * @brief Register packet handler. 374 */ 375 void rfcomm_register_packet_handler(void (*handler)(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size)); 376 377 /* 378 * @brief Create RFCOMM connection to a given server channel on a remote deivce. 379 * This channel will automatically provide enough credits to the remote side. 380 * @param addr 381 * @param server_channel 382 * @param out_cid 383 * @result status 384 */ 385 uint8_t rfcomm_create_channel(bd_addr_t addr, uint8_t server_channel, uint16_t * out_cid); 386 387 /* 388 * @brief Create RFCOMM connection to a given server channel on a remote deivce. 389 * This channel will use explicit credit management. During channel establishment, an initial amount of credits is provided. 390 * @param addr 391 * @param server_channel 392 * @param initial_credits 393 * @param out_cid 394 * @result status 395 */ 396 uint8_t rfcomm_create_channel_with_initial_credits(bd_addr_t addr, uint8_t server_channel, uint8_t initial_credits, uint16_t * out_cid); 397 398 /** 399 * @brief Disconnects RFCOMM channel with given identifier. 400 */ 401 void rfcomm_disconnect_internal(uint16_t rfcomm_cid); 402 403 /** 404 * @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. 405 */ 406 uint8_t rfcomm_register_service(uint8_t channel, uint16_t max_frame_size); 407 408 /** 409 * @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. 410 */ 411 uint8_t rfcomm_register_service_with_initial_credits(uint8_t channel, uint16_t max_frame_size, uint8_t initial_credits); 412 413 /** 414 * @brief Unregister RFCOMM service. 415 */ 416 void rfcomm_unregister_service(uint8_t service_channel); 417 418 /** 419 * @brief Accepts/Deny incoming RFCOMM connection. 420 */ 421 void rfcomm_accept_connection_internal(uint16_t rfcomm_cid); 422 void rfcomm_decline_connection_internal(uint16_t rfcomm_cid); 423 424 /** 425 * @brief Grant more incoming credits to the remote side for the given RFCOMM channel identifier. 426 */ 427 void rfcomm_grant_credits(uint16_t rfcomm_cid, uint8_t credits); 428 429 /** 430 * @brief Checks if RFCOMM can send packet. Returns yes if packet can be sent. 431 */ 432 int rfcomm_can_send_packet_now(uint16_t rfcomm_cid); 433 434 /** 435 * @brief Sends RFCOMM data packet to the RFCOMM channel with given identifier. 436 */ 437 int rfcomm_send_internal(uint16_t rfcomm_cid, uint8_t *data, uint16_t len); 438 439 /** 440 * @brief Sends Local Line Status, see LINE_STATUS_.. 441 */ 442 int rfcomm_send_local_line_status(uint16_t rfcomm_cid, uint8_t line_status); 443 444 /** 445 * @brief Send local modem status. see MODEM_STAUS_.. 446 */ 447 int rfcomm_send_modem_status(uint16_t rfcomm_cid, uint8_t modem_status); 448 449 /** 450 * @brief Configure remote port 451 */ 452 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); 453 454 /** 455 * @brief Query remote port 456 */ 457 int rfcomm_query_port_configuration(uint16_t rfcomm_cid); 458 459 /** 460 * @brief Allow to create RFCOMM packet in outgoing buffer. 461 */ 462 int rfcomm_reserve_packet_buffer(void); 463 void rfcomm_release_packet_buffer(void); 464 uint8_t * rfcomm_get_outgoing_buffer(void); 465 uint16_t rfcomm_get_max_frame_size(uint16_t rfcomm_cid); 466 int rfcomm_send_prepared(uint16_t rfcomm_cid, uint16_t len); 467 /* API_END */ 468 469 #if defined __cplusplus 470 } 471 #endif 472 473 #endif // __RFCOMM_H 474