1 /****************************************************************************** 2 * 3 * Copyright (C) 2008-2016 Broadcom Corporation 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at: 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 ******************************************************************************/ 18 19 /***************************************************************************** 20 * 21 * Name: avct_l2c_br.cc 22 * 23 * Description: This AVCTP module interfaces to L2CAP 24 * 25 *****************************************************************************/ 26 27 #include <string.h> 28 #include "avct_api.h" 29 #include "avct_int.h" 30 #include "bt_target.h" 31 #include "bt_utils.h" 32 #include "l2c_api.h" 33 #include "l2cdefs.h" 34 #include "osi/include/osi.h" 35 36 /* Configuration flags. */ 37 #define AVCT_L2C_CFG_IND_DONE (1 << 0) 38 #define AVCT_L2C_CFG_CFM_DONE (1 << 1) 39 40 /* AVCTP Browsing channel FCR Option: 41 * Size of the transmission window when using enhanced retransmission mode. Not 42 * used in basic and streaming modes. Range: 1 - 63 43 */ 44 #define AVCT_BR_FCR_OPT_TX_WINDOW_SIZE 10 45 46 /* AVCTP Browsing channel FCR Option: 47 * Number of transmission attempts for a single I-Frame before taking 48 * Down the connection. Used In ERTM mode only. Value is Ignored in basic and 49 * Streaming modes. 50 * Range: 0, 1-0xFF 51 * 0 - infinite retransmissions 52 * 1 - single transmission 53 */ 54 #define AVCT_BR_FCR_OPT_MAX_TX_B4_DISCNT 20 55 56 /* AVCTP Browsing channel FCR Option: Retransmission Timeout 57 * The AVRCP specification set a value in the range of 300 - 2000 ms 58 * Timeout (in msecs) to detect Lost I-Frames. Only used in Enhanced 59 * retransmission mode. 60 * Range: Minimum 2000 (2 secs) when supporting PBF. 61 */ 62 #define AVCT_BR_FCR_OPT_RETX_TOUT 2000 63 64 /* AVCTP Browsing channel FCR Option: Monitor Timeout 65 * The AVRCP specification set a value in the range of 300 - 2000 ms 66 * Timeout (in msecs) to detect Lost S-Frames. Only used in Enhanced 67 * retransmission mode. 68 * Range: Minimum 12000 (12 secs) when supporting PBF. 69 */ 70 #define AVCT_BR_FCR_OPT_MONITOR_TOUT 12000 71 72 /* callback function declarations */ 73 void avct_l2c_br_connect_ind_cback(BD_ADDR bd_addr, uint16_t lcid, uint16_t psm, 74 uint8_t id); 75 void avct_l2c_br_connect_cfm_cback(uint16_t lcid, uint16_t result); 76 void avct_l2c_br_config_cfm_cback(uint16_t lcid, tL2CAP_CFG_INFO* p_cfg); 77 void avct_l2c_br_config_ind_cback(uint16_t lcid, tL2CAP_CFG_INFO* p_cfg); 78 void avct_l2c_br_disconnect_ind_cback(uint16_t lcid, bool ack_needed); 79 void avct_l2c_br_disconnect_cfm_cback(uint16_t lcid, uint16_t result); 80 void avct_l2c_br_congestion_ind_cback(uint16_t lcid, bool is_congested); 81 void avct_l2c_br_data_ind_cback(uint16_t lcid, BT_HDR* p_buf); 82 83 /* L2CAP callback function structure */ 84 const tL2CAP_APPL_INFO avct_l2c_br_appl = { 85 avct_l2c_br_connect_ind_cback, 86 avct_l2c_br_connect_cfm_cback, 87 NULL, 88 avct_l2c_br_config_ind_cback, 89 avct_l2c_br_config_cfm_cback, 90 avct_l2c_br_disconnect_ind_cback, 91 avct_l2c_br_disconnect_cfm_cback, 92 NULL, 93 avct_l2c_br_data_ind_cback, 94 avct_l2c_br_congestion_ind_cback, 95 NULL /* tL2CA_TX_COMPLETE_CB */ 96 }; 97 98 /* Browsing channel eL2CAP default options */ 99 const tL2CAP_FCR_OPTS avct_l2c_br_fcr_opts_def = { 100 L2CAP_FCR_ERTM_MODE, /* Mandatory for Browsing channel */ 101 AVCT_BR_FCR_OPT_TX_WINDOW_SIZE, /* Tx window size */ 102 AVCT_BR_FCR_OPT_MAX_TX_B4_DISCNT, /* Maximum transmissions before 103 disconnecting */ 104 AVCT_BR_FCR_OPT_RETX_TOUT, /* Retransmission timeout (2 secs) */ 105 AVCT_BR_FCR_OPT_MONITOR_TOUT, /* Monitor timeout (12 secs) */ 106 L2CAP_DEFAULT_ERM_MPS /* MPS segment size */ 107 }; 108 109 /******************************************************************************* 110 * 111 * Function avct_l2c_br_connect_ind_cback 112 * 113 * Description This is the L2CAP connect indication callback function. 114 * 115 * 116 * Returns void 117 * 118 ******************************************************************************/ 119 void avct_l2c_br_connect_ind_cback(BD_ADDR bd_addr, uint16_t lcid, 120 UNUSED_ATTR uint16_t psm, uint8_t id) { 121 tAVCT_LCB* p_lcb; 122 uint16_t result = L2CAP_CONN_NO_RESOURCES; 123 tL2CAP_CFG_INFO cfg; 124 tAVCT_BCB* p_bcb; 125 tL2CAP_ERTM_INFO ertm_info; 126 127 memset(&cfg, 0, sizeof(tL2CAP_CFG_INFO)); 128 cfg.mtu_present = true; 129 130 p_lcb = avct_lcb_by_bd(bd_addr); 131 if (p_lcb != NULL) { 132 /* control channel exists */ 133 p_bcb = avct_bcb_by_lcb(p_lcb); 134 memcpy(p_bcb->peer_addr, bd_addr, BD_ADDR_LEN); 135 136 if (p_bcb->allocated == 0) { 137 /* browsing channel does not exist yet and the browsing channel is 138 * registered 139 * - accept connection */ 140 p_bcb->allocated = p_lcb->allocated; /* copy the index from lcb */ 141 142 result = L2CAP_CONN_OK; 143 cfg.mtu = avct_cb.mtu_br; 144 145 cfg.fcr_present = true; 146 cfg.fcr = avct_l2c_br_fcr_opts_def; 147 } 148 } 149 /* else no control channel yet, reject */ 150 151 /* Set the FCR options: Browsing channel mandates ERTM */ 152 ertm_info.preferred_mode = cfg.fcr.mode; 153 ertm_info.allowed_modes = L2CAP_FCR_CHAN_OPT_ERTM; 154 ertm_info.user_rx_buf_size = BT_DEFAULT_BUFFER_SIZE; 155 ertm_info.user_tx_buf_size = BT_DEFAULT_BUFFER_SIZE; 156 ertm_info.fcr_rx_buf_size = BT_DEFAULT_BUFFER_SIZE; 157 ertm_info.fcr_tx_buf_size = BT_DEFAULT_BUFFER_SIZE; 158 159 /* Send L2CAP connect rsp */ 160 L2CA_ErtmConnectRsp(bd_addr, id, lcid, result, 0, &ertm_info); 161 162 /* if result ok, proceed with connection */ 163 if (result == L2CAP_CONN_OK) { 164 /* store LCID */ 165 p_bcb->ch_lcid = lcid; 166 167 /* transition to configuration state */ 168 p_bcb->ch_state = AVCT_CH_CFG; 169 170 /* Send L2CAP config req */ 171 L2CA_ConfigReq(lcid, &cfg); 172 } 173 } 174 175 /******************************************************************************* 176 * 177 * Function avct_l2c_br_connect_cfm_cback 178 * 179 * Description This is the L2CAP connect confirm callback function. 180 * 181 * 182 * Returns void 183 * 184 ******************************************************************************/ 185 void avct_l2c_br_connect_cfm_cback(uint16_t lcid, uint16_t result) { 186 tAVCT_BCB* p_lcb; 187 tL2CAP_CFG_INFO cfg; 188 189 /* look up lcb for this channel */ 190 p_lcb = avct_bcb_by_lcid(lcid); 191 if ((p_lcb == NULL) || (p_lcb->ch_state != AVCT_CH_CONN)) return; 192 193 if (result != L2CAP_CONN_OK) { 194 /* failure */ 195 avct_bcb_event(p_lcb, AVCT_LCB_LL_CLOSE_EVT, (tAVCT_LCB_EVT*)&result); 196 return; 197 } 198 199 /* result is successful */ 200 /* set channel state */ 201 p_lcb->ch_state = AVCT_CH_CFG; 202 203 /* Send L2CAP config req */ 204 memset(&cfg, 0, sizeof(tL2CAP_CFG_INFO)); 205 206 cfg.mtu_present = true; 207 cfg.mtu = avct_cb.mtu_br; 208 209 cfg.fcr_present = true; 210 cfg.fcr = avct_l2c_br_fcr_opts_def; 211 212 L2CA_ConfigReq(lcid, &cfg); 213 } 214 215 /******************************************************************************* 216 * 217 * Function avct_l2c_br_config_cfm_cback 218 * 219 * Description This is the L2CAP config confirm callback function. 220 * 221 * 222 * Returns void 223 * 224 ******************************************************************************/ 225 void avct_l2c_br_config_cfm_cback(uint16_t lcid, tL2CAP_CFG_INFO* p_cfg) { 226 tAVCT_BCB* p_lcb; 227 228 /* look up lcb for this channel */ 229 p_lcb = avct_bcb_by_lcid(lcid); 230 if ((p_lcb == NULL) || (p_lcb->ch_state != AVCT_CH_CFG)) return; 231 232 /* if result successful */ 233 if (p_cfg->result == L2CAP_CFG_OK) { 234 /* update flags */ 235 p_lcb->ch_flags |= AVCT_L2C_CFG_CFM_DONE; 236 237 /* if configuration complete */ 238 if (p_lcb->ch_flags & AVCT_L2C_CFG_IND_DONE) { 239 p_lcb->ch_state = AVCT_CH_OPEN; 240 avct_bcb_event(p_lcb, AVCT_LCB_LL_OPEN_EVT, NULL); 241 } 242 } 243 /* else failure */ 244 else { 245 /* store result value */ 246 p_lcb->ch_result = p_cfg->result; 247 248 /* Send L2CAP disconnect req */ 249 L2CA_DisconnectReq(lcid); 250 } 251 } 252 253 /******************************************************************************* 254 * 255 * Function avct_l2c_br_config_ind_cback 256 * 257 * Description This is the L2CAP config indication callback function. 258 * 259 * 260 * Returns void 261 * 262 ******************************************************************************/ 263 void avct_l2c_br_config_ind_cback(uint16_t lcid, tL2CAP_CFG_INFO* p_cfg) { 264 tAVCT_BCB* p_lcb; 265 uint16_t max_mtu = BT_DEFAULT_BUFFER_SIZE - L2CAP_MIN_OFFSET - BT_HDR_SIZE; 266 267 /* Don't include QoS nor flush timeout in the response since we 268 currently always accept these values. Note: fcr_present is left 269 untouched since l2cap negotiates this internally 270 */ 271 p_cfg->flush_to_present = false; 272 p_cfg->qos_present = false; 273 274 /* look up lcb for this channel */ 275 p_lcb = avct_bcb_by_lcid(lcid); 276 if (p_lcb == NULL) return; 277 278 /* store the mtu in tbl */ 279 p_lcb->peer_mtu = L2CAP_DEFAULT_MTU; 280 if (p_cfg->mtu_present) { 281 p_lcb->peer_mtu = p_cfg->mtu; 282 } 283 284 if (p_lcb->peer_mtu > max_mtu) { 285 p_lcb->peer_mtu = p_cfg->mtu = max_mtu; 286 287 /* Must tell the peer what the adjusted value is */ 288 p_cfg->mtu_present = true; 289 } else /* Don't include in the response */ 290 p_cfg->mtu_present = false; 291 292 AVCT_TRACE_DEBUG("%s peer_mtu:%d use:%d", __func__, p_lcb->peer_mtu, max_mtu); 293 294 if (p_lcb->peer_mtu >= AVCT_MIN_BROWSE_MTU) 295 p_cfg->result = L2CAP_CFG_OK; 296 else { 297 p_cfg->result = L2CAP_CFG_UNACCEPTABLE_PARAMS; 298 p_cfg->mtu_present = true; 299 p_cfg->mtu = AVCT_MIN_BROWSE_MTU; 300 } 301 302 /* send L2CAP configure response */ 303 L2CA_ConfigRsp(lcid, p_cfg); 304 305 if (p_cfg->result != L2CAP_CFG_OK) { 306 return; 307 } 308 309 /* if first config ind */ 310 if ((p_lcb->ch_flags & AVCT_L2C_CFG_IND_DONE) == 0) { 311 /* update flags */ 312 p_lcb->ch_flags |= AVCT_L2C_CFG_IND_DONE; 313 314 /* if configuration complete */ 315 if (p_lcb->ch_flags & AVCT_L2C_CFG_CFM_DONE) { 316 p_lcb->ch_state = AVCT_CH_OPEN; 317 avct_bcb_event(p_lcb, AVCT_LCB_LL_OPEN_EVT, NULL); 318 } 319 } 320 } 321 322 /******************************************************************************* 323 * 324 * Function avct_l2c_br_disconnect_ind_cback 325 * 326 * Description This is the L2CAP disconnect indication callback function. 327 * 328 * 329 * Returns void 330 * 331 ******************************************************************************/ 332 void avct_l2c_br_disconnect_ind_cback(uint16_t lcid, bool ack_needed) { 333 tAVCT_BCB* p_lcb; 334 uint16_t result = AVCT_RESULT_FAIL; 335 336 /* look up lcb for this channel */ 337 p_lcb = avct_bcb_by_lcid(lcid); 338 if (p_lcb == NULL) return; 339 340 if (ack_needed) { 341 /* send L2CAP disconnect response */ 342 L2CA_DisconnectRsp(lcid); 343 } 344 345 avct_bcb_event(p_lcb, AVCT_LCB_LL_CLOSE_EVT, (tAVCT_LCB_EVT*)&result); 346 } 347 348 /******************************************************************************* 349 * 350 * Function avct_l2c_br_disconnect_cfm_cback 351 * 352 * Description This is the L2CAP disconnect confirm callback function. 353 * 354 * 355 * Returns void 356 * 357 ******************************************************************************/ 358 void avct_l2c_br_disconnect_cfm_cback(uint16_t lcid, uint16_t result) { 359 tAVCT_BCB* p_lcb; 360 uint16_t res; 361 362 /* look up lcb for this channel */ 363 p_lcb = avct_bcb_by_lcid(lcid); 364 if (p_lcb == NULL) return; 365 366 /* result value may be previously stored */ 367 res = (p_lcb->ch_result != 0) ? p_lcb->ch_result : result; 368 p_lcb->ch_result = 0; 369 370 avct_bcb_event(p_lcb, AVCT_LCB_LL_CLOSE_EVT, (tAVCT_LCB_EVT*)&res); 371 } 372 373 /******************************************************************************* 374 * 375 * Function avct_l2c_br_congestion_ind_cback 376 * 377 * Description This is the L2CAP congestion indication callback function. 378 * 379 * 380 * Returns void 381 * 382 ******************************************************************************/ 383 void avct_l2c_br_congestion_ind_cback(uint16_t lcid, bool is_congested) { 384 tAVCT_BCB* p_lcb; 385 386 /* look up lcb for this channel */ 387 p_lcb = avct_bcb_by_lcid(lcid); 388 if (p_lcb == NULL) return; 389 390 avct_bcb_event(p_lcb, AVCT_LCB_LL_CONG_EVT, (tAVCT_LCB_EVT*)&is_congested); 391 } 392 393 /******************************************************************************* 394 * 395 * Function avct_l2c_br_data_ind_cback 396 * 397 * Description This is the L2CAP data indication callback function. 398 * 399 * 400 * Returns void 401 * 402 ******************************************************************************/ 403 void avct_l2c_br_data_ind_cback(uint16_t lcid, BT_HDR* p_buf) { 404 tAVCT_BCB* p_lcb; 405 tAVCT_LCB_EVT evt_data; 406 407 /* look up lcb for this channel */ 408 p_lcb = avct_bcb_by_lcid(lcid); 409 if (p_lcb == NULL) { 410 /* prevent buffer leak */ 411 osi_free(p_buf); 412 return; 413 } 414 415 evt_data.p_buf = p_buf; 416 avct_bcb_event(p_lcb, AVCT_LCB_LL_MSG_EVT, &evt_data); 417 } 418