1 /****************************************************************************** 2 * 3 * Copyright 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(const RawAddress& bd_addr, uint16_t lcid, 74 uint16_t psm, 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 NULL /* tL2CA_CREDITS_RECEIVED_CB */}; 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(const RawAddress& 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 p_bcb->peer_addr = bd_addr; 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 tAVCT_LCB_EVT avct_lcb_evt; 196 avct_lcb_evt.result = result; 197 avct_bcb_event(p_lcb, AVCT_LCB_LL_CLOSE_EVT, &avct_lcb_evt); 198 return; 199 } 200 201 /* result is successful */ 202 /* set channel state */ 203 p_lcb->ch_state = AVCT_CH_CFG; 204 205 /* Send L2CAP config req */ 206 memset(&cfg, 0, sizeof(tL2CAP_CFG_INFO)); 207 208 cfg.mtu_present = true; 209 cfg.mtu = avct_cb.mtu_br; 210 211 cfg.fcr_present = true; 212 cfg.fcr = avct_l2c_br_fcr_opts_def; 213 214 L2CA_ConfigReq(lcid, &cfg); 215 } 216 217 /******************************************************************************* 218 * 219 * Function avct_l2c_br_config_cfm_cback 220 * 221 * Description This is the L2CAP config confirm callback function. 222 * 223 * 224 * Returns void 225 * 226 ******************************************************************************/ 227 void avct_l2c_br_config_cfm_cback(uint16_t lcid, tL2CAP_CFG_INFO* p_cfg) { 228 tAVCT_BCB* p_lcb; 229 230 /* look up lcb for this channel */ 231 p_lcb = avct_bcb_by_lcid(lcid); 232 if ((p_lcb == NULL) || (p_lcb->ch_state != AVCT_CH_CFG)) return; 233 234 /* if result successful */ 235 if (p_cfg->result == L2CAP_CFG_OK) { 236 /* update flags */ 237 p_lcb->ch_flags |= AVCT_L2C_CFG_CFM_DONE; 238 239 /* if configuration complete */ 240 if (p_lcb->ch_flags & AVCT_L2C_CFG_IND_DONE) { 241 p_lcb->ch_state = AVCT_CH_OPEN; 242 avct_bcb_event(p_lcb, AVCT_LCB_LL_OPEN_EVT, NULL); 243 } 244 } 245 /* else failure */ 246 else { 247 /* store result value */ 248 p_lcb->ch_result = p_cfg->result; 249 250 /* Send L2CAP disconnect req */ 251 L2CA_DisconnectReq(lcid); 252 } 253 } 254 255 /******************************************************************************* 256 * 257 * Function avct_l2c_br_config_ind_cback 258 * 259 * Description This is the L2CAP config indication callback function. 260 * 261 * 262 * Returns void 263 * 264 ******************************************************************************/ 265 void avct_l2c_br_config_ind_cback(uint16_t lcid, tL2CAP_CFG_INFO* p_cfg) { 266 tAVCT_BCB* p_lcb; 267 uint16_t max_mtu = BT_DEFAULT_BUFFER_SIZE - L2CAP_MIN_OFFSET - BT_HDR_SIZE; 268 269 /* Don't include QoS nor flush timeout in the response since we 270 currently always accept these values. Note: fcr_present is left 271 untouched since l2cap negotiates this internally 272 */ 273 p_cfg->flush_to_present = false; 274 p_cfg->qos_present = false; 275 276 /* look up lcb for this channel */ 277 p_lcb = avct_bcb_by_lcid(lcid); 278 if (p_lcb == NULL) return; 279 280 /* store the mtu in tbl */ 281 p_lcb->peer_mtu = L2CAP_DEFAULT_MTU; 282 if (p_cfg->mtu_present) { 283 p_lcb->peer_mtu = p_cfg->mtu; 284 } 285 286 if (p_lcb->peer_mtu > max_mtu) { 287 p_lcb->peer_mtu = p_cfg->mtu = max_mtu; 288 289 /* Must tell the peer what the adjusted value is */ 290 p_cfg->mtu_present = true; 291 } else /* Don't include in the response */ 292 p_cfg->mtu_present = false; 293 294 AVCT_TRACE_DEBUG("%s peer_mtu:%d use:%d", __func__, p_lcb->peer_mtu, max_mtu); 295 296 if (p_lcb->peer_mtu >= AVCT_MIN_BROWSE_MTU) 297 p_cfg->result = L2CAP_CFG_OK; 298 else { 299 p_cfg->result = L2CAP_CFG_UNACCEPTABLE_PARAMS; 300 p_cfg->mtu_present = true; 301 p_cfg->mtu = AVCT_MIN_BROWSE_MTU; 302 } 303 304 /* send L2CAP configure response */ 305 L2CA_ConfigRsp(lcid, p_cfg); 306 307 if (p_cfg->result != L2CAP_CFG_OK) { 308 return; 309 } 310 311 /* if first config ind */ 312 if ((p_lcb->ch_flags & AVCT_L2C_CFG_IND_DONE) == 0) { 313 /* update flags */ 314 p_lcb->ch_flags |= AVCT_L2C_CFG_IND_DONE; 315 316 /* if configuration complete */ 317 if (p_lcb->ch_flags & AVCT_L2C_CFG_CFM_DONE) { 318 p_lcb->ch_state = AVCT_CH_OPEN; 319 avct_bcb_event(p_lcb, AVCT_LCB_LL_OPEN_EVT, NULL); 320 } 321 } 322 } 323 324 /******************************************************************************* 325 * 326 * Function avct_l2c_br_disconnect_ind_cback 327 * 328 * Description This is the L2CAP disconnect indication callback function. 329 * 330 * 331 * Returns void 332 * 333 ******************************************************************************/ 334 void avct_l2c_br_disconnect_ind_cback(uint16_t lcid, bool ack_needed) { 335 tAVCT_BCB* p_lcb; 336 uint16_t result = AVCT_RESULT_FAIL; 337 338 /* look up lcb for this channel */ 339 p_lcb = avct_bcb_by_lcid(lcid); 340 if (p_lcb == NULL) return; 341 342 if (ack_needed) { 343 /* send L2CAP disconnect response */ 344 L2CA_DisconnectRsp(lcid); 345 } 346 347 tAVCT_LCB_EVT avct_lcb_evt; 348 avct_lcb_evt.result = result; 349 avct_bcb_event(p_lcb, AVCT_LCB_LL_CLOSE_EVT, &avct_lcb_evt); 350 } 351 352 /******************************************************************************* 353 * 354 * Function avct_l2c_br_disconnect_cfm_cback 355 * 356 * Description This is the L2CAP disconnect confirm callback function. 357 * 358 * 359 * Returns void 360 * 361 ******************************************************************************/ 362 void avct_l2c_br_disconnect_cfm_cback(uint16_t lcid, uint16_t result) { 363 tAVCT_BCB* p_lcb; 364 uint16_t res; 365 366 /* look up lcb for this channel */ 367 p_lcb = avct_bcb_by_lcid(lcid); 368 if (p_lcb == NULL) return; 369 370 /* result value may be previously stored */ 371 res = (p_lcb->ch_result != 0) ? p_lcb->ch_result : result; 372 p_lcb->ch_result = 0; 373 374 tAVCT_LCB_EVT avct_lcb_evt; 375 avct_lcb_evt.result = res; 376 avct_bcb_event(p_lcb, AVCT_LCB_LL_CLOSE_EVT, &avct_lcb_evt); 377 } 378 379 /******************************************************************************* 380 * 381 * Function avct_l2c_br_congestion_ind_cback 382 * 383 * Description This is the L2CAP congestion indication callback function. 384 * 385 * 386 * Returns void 387 * 388 ******************************************************************************/ 389 void avct_l2c_br_congestion_ind_cback(uint16_t lcid, bool is_congested) { 390 tAVCT_BCB* p_lcb; 391 392 /* look up lcb for this channel */ 393 p_lcb = avct_bcb_by_lcid(lcid); 394 if (p_lcb == NULL) return; 395 396 tAVCT_LCB_EVT avct_lcb_evt; 397 avct_lcb_evt.cong = is_congested; 398 avct_bcb_event(p_lcb, AVCT_LCB_LL_CONG_EVT, &avct_lcb_evt); 399 } 400 401 /******************************************************************************* 402 * 403 * Function avct_l2c_br_data_ind_cback 404 * 405 * Description This is the L2CAP data indication callback function. 406 * 407 * 408 * Returns void 409 * 410 ******************************************************************************/ 411 void avct_l2c_br_data_ind_cback(uint16_t lcid, BT_HDR* p_buf) { 412 tAVCT_BCB* p_lcb; 413 tAVCT_LCB_EVT evt_data; 414 415 /* look up lcb for this channel */ 416 p_lcb = avct_bcb_by_lcid(lcid); 417 if (p_lcb == NULL) { 418 /* prevent buffer leak */ 419 osi_free(p_buf); 420 return; 421 } 422 423 evt_data.p_buf = p_buf; 424 avct_bcb_event(p_lcb, AVCT_LCB_LL_MSG_EVT, &evt_data); 425 } 426