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 "btstack_util.h" 46 47 #include <stdint.h> 48 #include "btstack_run_loop.h" 49 #include "gap.h" 50 51 #if defined __cplusplus 52 extern "C" { 53 #endif 54 55 #define UNLIMITED_INCOMING_CREDITS 0xff 56 57 #define RFCOMM_TEST_DATA_MAX_LEN 4 58 59 #define RFCOMM_RLS_STATUS_INVALID 0xff 60 61 62 // private structs 63 typedef enum { 64 RFCOMM_MULTIPLEXER_CLOSED = 1, 65 RFCOMM_MULTIPLEXER_W4_CONNECT, // outgoing 66 RFCOMM_MULTIPLEXER_SEND_SABM_0, // " 67 RFCOMM_MULTIPLEXER_W4_UA_0, // " 68 RFCOMM_MULTIPLEXER_W4_SABM_0, // incoming 69 RFCOMM_MULTIPLEXER_SEND_UA_0, 70 RFCOMM_MULTIPLEXER_OPEN, 71 RFCOMM_MULTIPLEXER_SEND_UA_0_AND_DISC, 72 RFCOMM_MULTIPLEXER_SHUTTING_DOWN, 73 } RFCOMM_MULTIPLEXER_STATE; 74 75 typedef enum { 76 MULT_EV_READY_TO_SEND = 1, 77 } RFCOMM_MULTIPLEXER_EVENT; 78 79 typedef enum { 80 RFCOMM_CHANNEL_CLOSED = 1, 81 RFCOMM_CHANNEL_W4_MULTIPLEXER, 82 RFCOMM_CHANNEL_SEND_UIH_PN, 83 RFCOMM_CHANNEL_W4_PN_RSP, 84 RFCOMM_CHANNEL_SEND_SABM_W4_UA, 85 RFCOMM_CHANNEL_W4_UA, 86 RFCOMM_CHANNEL_INCOMING_SETUP, 87 RFCOMM_CHANNEL_DLC_SETUP, 88 RFCOMM_CHANNEL_OPEN, 89 RFCOMM_CHANNEL_SEND_UA_AFTER_DISC, 90 RFCOMM_CHANNEL_SEND_DISC, 91 RFCOMM_CHANNEL_W4_UA_AFTER_UA, 92 RFCOMM_CHANNEL_SEND_DM, 93 RFCOMM_CHANNEL_EMIT_OPEN_FAILED_AND_DISCARD, 94 } RFCOMM_CHANNEL_STATE; 95 96 typedef enum { 97 RFCOMM_CHANNEL_STATE_VAR_NONE = 0, 98 RFCOMM_CHANNEL_STATE_VAR_CLIENT_ACCEPTED = 1 << 0, 99 RFCOMM_CHANNEL_STATE_VAR_RCVD_PN = 1 << 1, 100 RFCOMM_CHANNEL_STATE_VAR_RCVD_RPN = 1 << 2, 101 RFCOMM_CHANNEL_STATE_VAR_RCVD_SABM = 1 << 3, 102 103 RFCOMM_CHANNEL_STATE_VAR_RCVD_MSC_CMD = 1 << 4, 104 RFCOMM_CHANNEL_STATE_VAR_RCVD_MSC_RSP = 1 << 5, 105 RFCOMM_CHANNEL_STATE_VAR_SEND_PN_RSP = 1 << 6, 106 RFCOMM_CHANNEL_STATE_VAR_SEND_RPN_INFO = 1 << 7, 107 108 RFCOMM_CHANNEL_STATE_VAR_SEND_RPN_RSP = 1 << 8, 109 RFCOMM_CHANNEL_STATE_VAR_SEND_UA = 1 << 9, 110 RFCOMM_CHANNEL_STATE_VAR_SEND_MSC_CMD = 1 << 10, 111 RFCOMM_CHANNEL_STATE_VAR_SEND_MSC_RSP = 1 << 11, 112 113 RFCOMM_CHANNEL_STATE_VAR_SEND_CREDITS = 1 << 12, 114 RFCOMM_CHANNEL_STATE_VAR_SENT_MSC_CMD = 1 << 13, 115 RFCOMM_CHANNEL_STATE_VAR_SENT_MSC_RSP = 1 << 14, 116 RFCOMM_CHANNEL_STATE_VAR_SENT_CREDITS = 1 << 15, 117 } RFCOMM_CHANNEL_STATE_VAR; 118 119 typedef struct rfcomm_rpn_data { 120 uint8_t baud_rate; 121 uint8_t flags; 122 uint8_t flow_control; 123 uint8_t xon; 124 uint8_t xoff; 125 uint8_t parameter_mask_0; // first byte 126 uint8_t parameter_mask_1; // second byte 127 } rfcomm_rpn_data_t; 128 129 // info regarding potential connections 130 typedef struct { 131 // linked list - assert: first field 132 btstack_linked_item_t item; 133 134 // packet handler 135 btstack_packet_handler_t packet_handler; 136 137 // server channel 138 uint8_t server_channel; 139 140 // incoming max frame size 141 uint16_t max_frame_size; 142 143 // use incoming flow control 144 uint8_t incoming_flow_control; 145 146 // initial incoming credits 147 uint8_t incoming_initial_credits; 148 149 150 } rfcomm_service_t; 151 152 // info regarding multiplexer 153 // note: spec mandates single multiplexer per device combination 154 typedef struct { 155 // linked list - assert: first field 156 btstack_linked_item_t item; 157 158 btstack_timer_source_t timer; 159 int timer_active; 160 161 RFCOMM_MULTIPLEXER_STATE state; 162 163 uint16_t l2cap_cid; 164 165 uint8_t fcon; // only send if fcon & 1, send rsp if fcon & 0x80 166 167 bd_addr_t remote_addr; 168 hci_con_handle_t con_handle; 169 170 uint8_t outgoing; 171 172 // hack to deal with authentication failure only observed by remote side 173 uint8_t at_least_one_connection; 174 175 uint16_t max_frame_size; 176 177 // send DM for DLCI != 0 178 uint8_t send_dm_for_dlci; 179 180 // non supported command, 0 if not set 181 uint8_t nsc_command; 182 183 // test data - limited to RFCOMM_TEST_DATA_MAX_LEN 184 uint8_t test_data_len; 185 uint8_t test_data[RFCOMM_TEST_DATA_MAX_LEN]; 186 187 } rfcomm_multiplexer_t; 188 189 // info regarding an actual connection 190 typedef struct { 191 192 // linked list - assert: first field 193 btstack_linked_item_t item; 194 195 // packet handler 196 btstack_packet_handler_t packet_handler; 197 198 // server channel (see rfcomm_service_t) - NULL => outgoing channel 199 rfcomm_service_t * service; 200 201 // muliplexer for this channel 202 rfcomm_multiplexer_t *multiplexer; 203 204 // RFCOMM Channel ID 205 uint16_t rfcomm_cid; 206 207 // 208 uint8_t dlci; 209 210 // credits for outgoing traffic 211 uint8_t credits_outgoing; 212 213 // number of packets remote will be granted 214 uint8_t new_credits_incoming; 215 216 // credits for incoming traffic 217 uint8_t credits_incoming; 218 219 // use incoming flow control 220 uint8_t incoming_flow_control; 221 222 // channel state 223 RFCOMM_CHANNEL_STATE state; 224 225 // state variables used in RFCOMM_CHANNEL_INCOMING 226 RFCOMM_CHANNEL_STATE_VAR state_var; 227 228 // priority set by incoming side in PN 229 uint8_t pn_priority; 230 231 // negotiated frame size 232 uint16_t max_frame_size; 233 234 // local rpn data 235 rfcomm_rpn_data_t rpn_data; 236 237 // rls line status. RFCOMM_RLS_STATUS_INVALID if not set 238 uint8_t rls_line_status; 239 240 // msc modem status. 241 uint8_t msc_modem_status; 242 243 // 244 uint8_t waiting_for_can_send_now; 245 246 } rfcomm_channel_t; 247 248 /* API_START */ 249 250 /** 251 * @brief Set up RFCOMM. 252 */ 253 void rfcomm_init(void); 254 255 /** 256 * @brief Set security level required for incoming connections, need to be called before registering services. 257 */ 258 void rfcomm_set_required_security_level(gap_security_level_t security_level); 259 260 /* 261 * @brief Create RFCOMM connection to a given server channel on a remote deivce. 262 * This channel will automatically provide enough credits to the remote side. 263 * @param addr 264 * @param server_channel 265 * @param out_cid 266 * @result status 267 */ 268 uint8_t rfcomm_create_channel(btstack_packet_handler_t packet_handler, bd_addr_t addr, uint8_t server_channel, uint16_t * out_cid); 269 270 /* 271 * @brief Create RFCOMM connection to a given server channel on a remote deivce. 272 * This channel will use explicit credit management. During channel establishment, an initial amount of credits is provided. 273 * @param addr 274 * @param server_channel 275 * @param initial_credits 276 * @param out_cid 277 * @result status 278 */ 279 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); 280 281 /** 282 * @brief Disconnects RFCOMM channel with given identifier. 283 */ 284 void rfcomm_disconnect(uint16_t rfcomm_cid); 285 286 /** 287 * @brief Registers RFCOMM service for a server channel and a maximum frame size, and assigns a packet handler. 288 * This channel provides credits automatically to the remote side -> no flow control 289 * @param packet handler for all channels of this service 290 * @param channel 291 * @param max_frame_size 292 */ 293 uint8_t rfcomm_register_service(btstack_packet_handler_t packet_handler, uint8_t channel, uint16_t max_frame_size); 294 295 /** 296 * @brief Registers RFCOMM service for a server channel and a maximum frame size, and assigns a packet handler. 297 * This channel will use explicit credit management. During channel establishment, an initial amount of credits is provided. 298 * @param packet handler for all channels of this service 299 * @param channel 300 * @param max_frame_size 301 * @param initial_credits 302 */ 303 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); 304 305 /** 306 * @brief Unregister RFCOMM service. 307 */ 308 void rfcomm_unregister_service(uint8_t service_channel); 309 310 /** 311 * @brief Accepts incoming RFCOMM connection. 312 */ 313 void rfcomm_accept_connection(uint16_t rfcomm_cid); 314 315 /** 316 * @brief Deny incoming RFCOMM connection. 317 */ 318 void rfcomm_decline_connection(uint16_t rfcomm_cid); 319 320 /** 321 * @brief Grant more incoming credits to the remote side for the given RFCOMM channel identifier. 322 */ 323 void rfcomm_grant_credits(uint16_t rfcomm_cid, uint8_t credits); 324 325 /** 326 * @brief Checks if RFCOMM can send packet. 327 * @param rfcomm_cid 328 * @result != 0 if can send now 329 */ 330 int rfcomm_can_send_packet_now(uint16_t rfcomm_cid); 331 332 /** 333 * @brief Request emission of RFCOMM_EVENT_CAN_SEND_NOW as soon as possible 334 * @note RFCOMM_EVENT_CAN_SEND_NOW might be emitted during call to this function 335 * so packet handler should be ready to handle it 336 * @param rfcomm_cid 337 */ 338 void rfcomm_request_can_send_now_event(uint16_t rfcomm_cid); 339 340 /** 341 * @brief Sends RFCOMM data packet to the RFCOMM channel with given identifier. 342 * @param rfcomm_cid 343 */ 344 int rfcomm_send(uint16_t rfcomm_cid, uint8_t *data, uint16_t len); 345 346 /** 347 * @brief Sends Local Line Status, see LINE_STATUS_.. 348 * @param rfcomm_cid 349 * @param line_status 350 */ 351 int rfcomm_send_local_line_status(uint16_t rfcomm_cid, uint8_t line_status); 352 353 /** 354 * @brief Send local modem status. see MODEM_STAUS_.. 355 * @param rfcomm_cid 356 * @param modem_status 357 */ 358 int rfcomm_send_modem_status(uint16_t rfcomm_cid, uint8_t modem_status); 359 360 /** 361 * @brief Configure remote port 362 * @param rfcomm_cid 363 * @param baud_rate 364 * @param data_bits 365 * @param stop_bits 366 * @param parity 367 * @param flow_control 368 */ 369 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); 370 371 /** 372 * @brief Query remote port 373 * @param rfcomm_cid 374 */ 375 int rfcomm_query_port_configuration(uint16_t rfcomm_cid); 376 377 /** 378 * @brief Query max frame size 379 * @param rfcomm_cid 380 */ 381 uint16_t rfcomm_get_max_frame_size(uint16_t rfcomm_cid); 382 383 /** 384 * @brief Allow to create RFCOMM packet in outgoing buffer. 385 * if (rfcomm_can_send_packet_now(cid)){ 386 * rfcomm_reserve_packet_buffer(); 387 * uint8_t * buffer = rfcomm_get_outgoing_buffer(); 388 * uint16_t buffer_size = rfcomm_get_max_frame_size(cid); 389 * // .. setup data in buffer with len 390 * rfcomm_send_prepared(cid, len) 391 * } 392 */ 393 int rfcomm_reserve_packet_buffer(void); 394 uint8_t * rfcomm_get_outgoing_buffer(void); 395 int rfcomm_send_prepared(uint16_t rfcomm_cid, uint16_t len); 396 void rfcomm_release_packet_buffer(void); 397 398 /* API_END */ 399 400 #if defined __cplusplus 401 } 402 #endif 403 404 #endif // __RFCOMM_H 405