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 ******************************************************************************/
avct_l2c_br_connect_ind_cback(const RawAddress & bd_addr,uint16_t lcid,UNUSED_ATTR uint16_t psm,uint8_t id)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 ******************************************************************************/
avct_l2c_br_connect_cfm_cback(uint16_t lcid,uint16_t result)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 ******************************************************************************/
avct_l2c_br_config_cfm_cback(uint16_t lcid,tL2CAP_CFG_INFO * p_cfg)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 ******************************************************************************/
avct_l2c_br_config_ind_cback(uint16_t lcid,tL2CAP_CFG_INFO * p_cfg)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 ******************************************************************************/
avct_l2c_br_disconnect_ind_cback(uint16_t lcid,bool ack_needed)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 ******************************************************************************/
avct_l2c_br_disconnect_cfm_cback(uint16_t lcid,uint16_t result)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 ******************************************************************************/
avct_l2c_br_congestion_ind_cback(uint16_t lcid,bool is_congested)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 ******************************************************************************/
avct_l2c_br_data_ind_cback(uint16_t lcid,BT_HDR * p_buf)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