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