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 * @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_EMIT_OPEN_FAILED_AND_DISCARD, 96 } RFCOMM_CHANNEL_STATE; 97 98 typedef enum { 99 RFCOMM_CHANNEL_STATE_VAR_NONE = 0, 100 RFCOMM_CHANNEL_STATE_VAR_CLIENT_ACCEPTED = 1 << 0, 101 RFCOMM_CHANNEL_STATE_VAR_RCVD_PN = 1 << 1, 102 RFCOMM_CHANNEL_STATE_VAR_RCVD_RPN = 1 << 2, 103 RFCOMM_CHANNEL_STATE_VAR_RCVD_SABM = 1 << 3, 104 105 RFCOMM_CHANNEL_STATE_VAR_RCVD_MSC_CMD = 1 << 4, 106 RFCOMM_CHANNEL_STATE_VAR_RCVD_MSC_RSP = 1 << 5, 107 RFCOMM_CHANNEL_STATE_VAR_SEND_PN_RSP = 1 << 6, 108 RFCOMM_CHANNEL_STATE_VAR_SEND_RPN_INFO = 1 << 7, 109 110 RFCOMM_CHANNEL_STATE_VAR_SEND_RPN_RSP = 1 << 8, 111 RFCOMM_CHANNEL_STATE_VAR_SEND_UA = 1 << 9, 112 RFCOMM_CHANNEL_STATE_VAR_SEND_MSC_CMD = 1 << 10, 113 RFCOMM_CHANNEL_STATE_VAR_SEND_MSC_RSP = 1 << 11, 114 115 RFCOMM_CHANNEL_STATE_VAR_SEND_CREDITS = 1 << 12, 116 RFCOMM_CHANNEL_STATE_VAR_SENT_MSC_CMD = 1 << 13, 117 RFCOMM_CHANNEL_STATE_VAR_SENT_MSC_RSP = 1 << 14, 118 RFCOMM_CHANNEL_STATE_VAR_SENT_CREDITS = 1 << 15, 119 } RFCOMM_CHANNEL_STATE_VAR; 120 121 typedef struct rfcomm_rpn_data { 122 uint8_t baud_rate; 123 uint8_t flags; 124 uint8_t flow_control; 125 uint8_t xon; 126 uint8_t xoff; 127 uint8_t parameter_mask_0; // first byte 128 uint8_t parameter_mask_1; // second byte 129 } rfcomm_rpn_data_t; 130 131 // info regarding potential connections 132 typedef struct { 133 // linked list - assert: first field 134 btstack_linked_item_t item; 135 136 // packet handler 137 btstack_packet_handler_t packet_handler; 138 139 // server channel 140 uint8_t server_channel; 141 142 // incoming max frame size 143 uint16_t max_frame_size; 144 145 // use incoming flow control 146 uint8_t incoming_flow_control; 147 148 // initial incoming credits 149 uint8_t incoming_initial_credits; 150 151 152 } rfcomm_service_t; 153 154 // info regarding multiplexer 155 // note: spec mandates single multiplexer per device combination 156 typedef struct { 157 // linked list - assert: first field 158 btstack_linked_item_t item; 159 160 btstack_timer_source_t timer; 161 int timer_active; 162 163 RFCOMM_MULTIPLEXER_STATE state; 164 165 uint16_t l2cap_cid; 166 167 uint8_t fcon; // only send if fcon & 1, send rsp if fcon & 0x80 168 169 bd_addr_t remote_addr; 170 hci_con_handle_t con_handle; 171 172 uint8_t outgoing; 173 174 // hack to deal with authentication failure only observed by remote side 175 uint8_t at_least_one_connection; 176 177 uint16_t max_frame_size; 178 179 // send DM for DLCI != 0 180 uint8_t send_dm_for_dlci; 181 182 // non supported command, 0 if not set 183 uint8_t nsc_command; 184 185 // ertm id 186 uint16_t ertm_id; 187 188 // test data - limited to RFCOMM_TEST_DATA_MAX_LEN 189 uint8_t test_data_len; 190 uint8_t test_data[RFCOMM_TEST_DATA_MAX_LEN]; 191 192 } rfcomm_multiplexer_t; 193 194 // info regarding an actual connection 195 typedef struct { 196 197 // linked list - assert: first field 198 btstack_linked_item_t item; 199 200 // packet handler 201 btstack_packet_handler_t packet_handler; 202 203 // server channel (see rfcomm_service_t) - NULL => outgoing channel 204 rfcomm_service_t * service; 205 206 // muliplexer for this channel 207 rfcomm_multiplexer_t *multiplexer; 208 209 // RFCOMM Channel ID 210 uint16_t rfcomm_cid; 211 212 // 213 uint8_t dlci; 214 215 // credits for outgoing traffic 216 uint8_t credits_outgoing; 217 218 // number of packets remote will be granted 219 uint8_t new_credits_incoming; 220 221 // credits for incoming traffic 222 uint8_t credits_incoming; 223 224 // use incoming flow control 225 uint8_t incoming_flow_control; 226 227 // channel state 228 RFCOMM_CHANNEL_STATE state; 229 230 // state variables used in RFCOMM_CHANNEL_INCOMING 231 RFCOMM_CHANNEL_STATE_VAR state_var; 232 233 // priority set by incoming side in PN 234 uint8_t pn_priority; 235 236 // negotiated frame size 237 uint16_t max_frame_size; 238 239 // local rpn data 240 rfcomm_rpn_data_t rpn_data; 241 242 // rls line status. RFCOMM_RLS_STATUS_INVALID if not set 243 uint8_t rls_line_status; 244 245 // msc modem status. 246 uint8_t msc_modem_status; 247 248 // 249 uint8_t waiting_for_can_send_now; 250 251 } rfcomm_channel_t; 252 253 // struct used in ERTM callback 254 typedef struct { 255 // remote address 256 bd_addr_t addr; 257 258 // ERTM ID - returned in RFCOMM_EVENT_ERTM_BUFFER_RELEASED. 259 uint16_t ertm_id; 260 261 // ERTM Configuration - needs to stay valid indefinitely 262 l2cap_ertm_config_t * ertm_config; 263 264 // ERTM buffer 265 uint8_t * ertm_buffer; 266 uint32_t ertm_buffer_size; 267 } rfcomm_ertm_request_t; 268 269 /* API_START */ 270 271 /** 272 * @brief Set up RFCOMM. 273 */ 274 void rfcomm_init(void); 275 276 /** 277 * @brief Set security level required for incoming connections, need to be called before registering services. 278 * @deprecated use gap_set_security_level instead 279 */ 280 void rfcomm_set_required_security_level(gap_security_level_t security_level); 281 282 /* 283 * @brief Create RFCOMM connection to a given server channel on a remote deivce. 284 * This channel will automatically provide enough credits to the remote side. 285 * @param addr 286 * @param server_channel 287 * @param out_cid 288 * @result status 289 */ 290 uint8_t rfcomm_create_channel(btstack_packet_handler_t packet_handler, bd_addr_t addr, uint8_t server_channel, uint16_t * out_cid); 291 292 /* 293 * @brief Create RFCOMM connection to a given server channel on a remote deivce. 294 * This channel will use explicit credit management. During channel establishment, an initial amount of credits is provided. 295 * @param addr 296 * @param server_channel 297 * @param initial_credits 298 * @param out_cid 299 * @result status 300 */ 301 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); 302 303 /** 304 * @brief Disconnects RFCOMM channel with given identifier. 305 */ 306 void rfcomm_disconnect(uint16_t rfcomm_cid); 307 308 /** 309 * @brief Registers RFCOMM service for a server channel and a maximum frame size, and assigns a packet handler. 310 * This channel provides credits automatically to the remote side -> no flow control 311 * @param packet handler for all channels of this service 312 * @param channel 313 * @param max_frame_size 314 * @return status ERROR_CODE_SUCCESS if successful, otherwise L2CAP_SERVICE_ALREADY_REGISTERED or BTSTACK_MEMORY_ALLOC_FAILED 315 */ 316 uint8_t rfcomm_register_service(btstack_packet_handler_t packet_handler, uint8_t channel, uint16_t max_frame_size); 317 318 /** 319 * @brief Registers RFCOMM service for a server channel and a maximum frame size, and assigns a packet handler. 320 * This channel will use explicit credit management. During channel establishment, an initial amount of credits is provided. 321 * @param packet handler for all channels of this service 322 * @param channel 323 * @param max_frame_size 324 * @param initial_credits 325 * @return status ERROR_CODE_SUCCESS if successful, otherwise L2CAP_SERVICE_ALREADY_REGISTERED or BTSTACK_MEMORY_ALLOC_FAILED 326 */ 327 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); 328 329 /** 330 * @brief Unregister RFCOMM service. 331 */ 332 void rfcomm_unregister_service(uint8_t service_channel); 333 334 /** 335 * @brief Accepts incoming RFCOMM connection. 336 */ 337 void rfcomm_accept_connection(uint16_t rfcomm_cid); 338 339 /** 340 * @brief Deny incoming RFCOMM connection. 341 */ 342 void rfcomm_decline_connection(uint16_t rfcomm_cid); 343 344 /** 345 * @brief Grant more incoming credits to the remote side for the given RFCOMM channel identifier. 346 */ 347 void rfcomm_grant_credits(uint16_t rfcomm_cid, uint8_t credits); 348 349 /** 350 * @brief Checks if RFCOMM can send packet. 351 * @param rfcomm_cid 352 * @result != 0 if can send now 353 */ 354 int rfcomm_can_send_packet_now(uint16_t rfcomm_cid); 355 356 /** 357 * @brief Request emission of RFCOMM_EVENT_CAN_SEND_NOW as soon as possible 358 * @note RFCOMM_EVENT_CAN_SEND_NOW might be emitted during call to this function 359 * so packet handler should be ready to handle it 360 * @param rfcomm_cid 361 */ 362 void rfcomm_request_can_send_now_event(uint16_t rfcomm_cid); 363 364 /** 365 * @brief Sends RFCOMM data packet to the RFCOMM channel with given identifier. 366 * @param rfcomm_cid 367 */ 368 int rfcomm_send(uint16_t rfcomm_cid, uint8_t *data, uint16_t len); 369 370 /** 371 * @brief Sends Local Line Status, see LINE_STATUS_.. 372 * @param rfcomm_cid 373 * @param line_status 374 */ 375 int rfcomm_send_local_line_status(uint16_t rfcomm_cid, uint8_t line_status); 376 377 /** 378 * @brief Send local modem status. see MODEM_STAUS_.. 379 * @param rfcomm_cid 380 * @param modem_status 381 */ 382 int rfcomm_send_modem_status(uint16_t rfcomm_cid, uint8_t modem_status); 383 384 /** 385 * @brief Configure remote port 386 * @param rfcomm_cid 387 * @param baud_rate 388 * @param data_bits 389 * @param stop_bits 390 * @param parity 391 * @param flow_control 392 */ 393 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); 394 395 /** 396 * @brief Query remote port 397 * @param rfcomm_cid 398 */ 399 int rfcomm_query_port_configuration(uint16_t rfcomm_cid); 400 401 /** 402 * @brief Query max frame size 403 * @param rfcomm_cid 404 */ 405 uint16_t rfcomm_get_max_frame_size(uint16_t rfcomm_cid); 406 407 /** 408 * @brief Allow to create RFCOMM packet in outgoing buffer. 409 * if (rfcomm_can_send_packet_now(cid)){ 410 * rfcomm_reserve_packet_buffer(); 411 * uint8_t * buffer = rfcomm_get_outgoing_buffer(); 412 * uint16_t buffer_size = rfcomm_get_max_frame_size(cid); 413 * .. setup data in buffer with len .. 414 * rfcomm_send_prepared(cid, len) 415 * } 416 */ 417 int rfcomm_reserve_packet_buffer(void); 418 uint8_t * rfcomm_get_outgoing_buffer(void); 419 int rfcomm_send_prepared(uint16_t rfcomm_cid, uint16_t len); 420 void rfcomm_release_packet_buffer(void); 421 422 /** 423 * @brief Enable L2CAP ERTM mode for RFCOMM. request callback is used to provide ERTM buffer. released callback returns buffer 424 * 425 * @note on request_callback, the app must set the ertm_config, buffer, size fields to enable ERTM for the current connection 426 * @note if buffer is not set, BASIC mode will be used instead 427 * 428 * @note released_callback provides ertm_id from earlier request to match request and release 429 * 430 * @param request_callback 431 * @param released_callback 432 */ 433 void rfcomm_enable_l2cap_ertm(void request_callback(rfcomm_ertm_request_t * request), void released_callback(uint16_t ertm_id)); 434 435 /** 436 * @brief De-Init RFCOMM 437 */ 438 void rfcomm_deinit(void); 439 440 /* API_END */ 441 442 #if defined __cplusplus 443 } 444 #endif 445 446 #endif // RFCOMM_H 447