1 /******************************************************************************
2 *
3 * Copyright (C) 2009-2012 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 * this file contains functions relating to BLE management.
22 *
23 ******************************************************************************/
24
25 #include <string.h>
26 #include "bt_target.h"
27 #include "bt_utils.h"
28 #include "l2cdefs.h"
29 #include "l2c_int.h"
30 #include "btu.h"
31 #include "btm_int.h"
32 #include "hcimsgs.h"
33 #include "device/include/controller.h"
34
35 #if (BLE_INCLUDED == TRUE)
36 static void l2cble_start_conn_update (tL2C_LCB *p_lcb);
37
38 /*******************************************************************************
39 **
40 ** Function L2CA_CancelBleConnectReq
41 **
42 ** Description Cancel a pending connection attempt to a BLE device.
43 **
44 ** Parameters: BD Address of remote
45 **
46 ** Return value: TRUE if connection was cancelled
47 **
48 *******************************************************************************/
L2CA_CancelBleConnectReq(BD_ADDR rem_bda)49 BOOLEAN L2CA_CancelBleConnectReq (BD_ADDR rem_bda)
50 {
51 tL2C_LCB *p_lcb;
52
53 /* There can be only one BLE connection request outstanding at a time */
54 if (btm_ble_get_conn_st() == BLE_CONN_IDLE)
55 {
56 L2CAP_TRACE_WARNING ("L2CA_CancelBleConnectReq - no connection pending");
57 return(FALSE);
58 }
59
60 if (memcmp (rem_bda, l2cb.ble_connecting_bda, BD_ADDR_LEN))
61 {
62 L2CAP_TRACE_WARNING ("L2CA_CancelBleConnectReq - different BDA Connecting: %08x%04x Cancel: %08x%04x",
63 (l2cb.ble_connecting_bda[0]<<24)+(l2cb.ble_connecting_bda[1]<<16)+(l2cb.ble_connecting_bda[2]<<8)+l2cb.ble_connecting_bda[3],
64 (l2cb.ble_connecting_bda[4]<<8)+l2cb.ble_connecting_bda[5],
65 (rem_bda[0]<<24)+(rem_bda[1]<<16)+(rem_bda[2]<<8)+rem_bda[3], (rem_bda[4]<<8)+rem_bda[5]);
66
67 return(FALSE);
68 }
69
70 if (btsnd_hcic_ble_create_conn_cancel())
71 {
72 p_lcb = l2cu_find_lcb_by_bd_addr(rem_bda, BT_TRANSPORT_LE);
73 /* Do not remove lcb if an LE link is already up as a peripheral */
74 if (p_lcb != NULL &&
75 !(p_lcb->link_role == HCI_ROLE_SLAVE && BTM_ACL_IS_CONNECTED(rem_bda)))
76 {
77 p_lcb->disc_reason = L2CAP_CONN_CANCEL;
78 l2cu_release_lcb (p_lcb);
79 }
80 /* update state to be cancel, wait for connection cancel complete */
81 btm_ble_set_conn_st (BLE_CONN_CANCEL);
82
83 return(TRUE);
84 }
85 else
86 return(FALSE);
87 }
88
89 /*******************************************************************************
90 **
91 ** Function L2CA_UpdateBleConnParams
92 **
93 ** Description Update BLE connection parameters.
94 **
95 ** Parameters: BD Address of remote
96 **
97 ** Return value: TRUE if update started
98 **
99 *******************************************************************************/
L2CA_UpdateBleConnParams(BD_ADDR rem_bda,UINT16 min_int,UINT16 max_int,UINT16 latency,UINT16 timeout)100 BOOLEAN L2CA_UpdateBleConnParams (BD_ADDR rem_bda, UINT16 min_int, UINT16 max_int,
101 UINT16 latency, UINT16 timeout)
102 {
103 tL2C_LCB *p_lcb;
104 tACL_CONN *p_acl_cb = btm_bda_to_acl(rem_bda, BT_TRANSPORT_LE);
105
106 /* See if we have a link control block for the remote device */
107 p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda, BT_TRANSPORT_LE);
108
109 /* If we don't have one, create one and accept the connection. */
110 if (!p_lcb || !p_acl_cb)
111 {
112 L2CAP_TRACE_WARNING ("L2CA_UpdateBleConnParams - unknown BD_ADDR %08x%04x",
113 (rem_bda[0]<<24)+(rem_bda[1]<<16)+(rem_bda[2]<<8)+rem_bda[3],
114 (rem_bda[4]<<8)+rem_bda[5]);
115 return(FALSE);
116 }
117
118 if (p_lcb->transport != BT_TRANSPORT_LE)
119 {
120 L2CAP_TRACE_WARNING ("L2CA_UpdateBleConnParams - BD_ADDR %08x%04x not LE",
121 (rem_bda[0]<<24)+(rem_bda[1]<<16)+(rem_bda[2]<<8)+rem_bda[3],
122 (rem_bda[4]<<8)+rem_bda[5]);
123 return(FALSE);
124 }
125
126 p_lcb->min_interval = min_int;
127 p_lcb->max_interval = max_int;
128 p_lcb->latency = latency;
129 p_lcb->timeout = timeout;
130 p_lcb->conn_update_mask |= L2C_BLE_NEW_CONN_PARAM;
131
132 l2cble_start_conn_update(p_lcb);
133
134 return(TRUE);
135 }
136
137
138 /*******************************************************************************
139 **
140 ** Function L2CA_EnableUpdateBleConnParams
141 **
142 ** Description Enable or disable update based on the request from the peer
143 **
144 ** Parameters: BD Address of remote
145 **
146 ** Return value: TRUE if update started
147 **
148 *******************************************************************************/
L2CA_EnableUpdateBleConnParams(BD_ADDR rem_bda,BOOLEAN enable)149 BOOLEAN L2CA_EnableUpdateBleConnParams (BD_ADDR rem_bda, BOOLEAN enable)
150 {
151 tL2C_LCB *p_lcb;
152
153 /* See if we have a link control block for the remote device */
154 p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda, BT_TRANSPORT_LE);
155
156 if (!p_lcb)
157 {
158 L2CAP_TRACE_WARNING ("L2CA_EnableUpdateBleConnParams - unknown BD_ADDR %08x%04x",
159 (rem_bda[0]<<24)+(rem_bda[1]<<16)+(rem_bda[2]<<8)+rem_bda[3],
160 (rem_bda[4]<<8)+rem_bda[5]);
161 return (FALSE);
162 }
163
164 L2CAP_TRACE_API ("%s - BD_ADDR %08x%04x enable %d current upd state 0x%02x",__FUNCTION__,
165 (rem_bda[0]<<24)+(rem_bda[1]<<16)+(rem_bda[2]<<8)+rem_bda[3],
166 (rem_bda[4]<<8)+rem_bda[5], enable, p_lcb->conn_update_mask);
167
168 if (p_lcb->transport != BT_TRANSPORT_LE)
169 {
170 L2CAP_TRACE_WARNING ("%s - BD_ADDR %08x%04x not LE (link role %d)", __FUNCTION__,
171 (rem_bda[0]<<24)+(rem_bda[1]<<16)+(rem_bda[2]<<8)+rem_bda[3],
172 (rem_bda[4]<<8)+rem_bda[5], p_lcb->link_role);
173 return (FALSE);
174 }
175
176 if (enable)
177 p_lcb->conn_update_mask &= ~L2C_BLE_CONN_UPDATE_DISABLE;
178 else
179 p_lcb->conn_update_mask |= L2C_BLE_CONN_UPDATE_DISABLE;
180
181 l2cble_start_conn_update(p_lcb);
182
183 return (TRUE);
184 }
185
186
187 /*******************************************************************************
188 **
189 ** Function L2CA_GetBleConnRole
190 **
191 ** Description This function returns the connection role.
192 **
193 ** Returns link role.
194 **
195 *******************************************************************************/
L2CA_GetBleConnRole(BD_ADDR bd_addr)196 UINT8 L2CA_GetBleConnRole (BD_ADDR bd_addr)
197 {
198 UINT8 role = HCI_ROLE_UNKNOWN;
199
200 tL2C_LCB *p_lcb;
201
202 if ((p_lcb = l2cu_find_lcb_by_bd_addr (bd_addr, BT_TRANSPORT_LE)) != NULL)
203 role = p_lcb->link_role;
204
205 return role;
206 }
207 /*******************************************************************************
208 **
209 ** Function L2CA_GetDisconnectReason
210 **
211 ** Description This function returns the disconnect reason code.
212 **
213 ** Returns disconnect reason
214 **
215 *******************************************************************************/
L2CA_GetDisconnectReason(BD_ADDR remote_bda,tBT_TRANSPORT transport)216 UINT16 L2CA_GetDisconnectReason (BD_ADDR remote_bda, tBT_TRANSPORT transport)
217 {
218 tL2C_LCB *p_lcb;
219 UINT16 reason = 0;
220
221 if ((p_lcb = l2cu_find_lcb_by_bd_addr (remote_bda, transport)) != NULL)
222 reason = p_lcb->disc_reason;
223
224 L2CAP_TRACE_DEBUG ("L2CA_GetDisconnectReason=%d ",reason);
225
226 return reason;
227 }
228
229 /*******************************************************************************
230 **
231 ** Function l2cble_notify_le_connection
232 **
233 ** Description This function notifiy the l2cap connection to the app layer
234 **
235 ** Returns none
236 **
237 *******************************************************************************/
l2cble_notify_le_connection(BD_ADDR bda)238 void l2cble_notify_le_connection (BD_ADDR bda)
239 {
240 tL2C_LCB *p_lcb = l2cu_find_lcb_by_bd_addr (bda, BT_TRANSPORT_LE);
241 tACL_CONN *p_acl = btm_bda_to_acl(bda, BT_TRANSPORT_LE) ;
242
243 if (p_lcb != NULL && p_acl != NULL && p_lcb->link_state != LST_CONNECTED)
244 {
245 /* update link status */
246 btm_establish_continue(p_acl);
247 /* update l2cap link status and send callback */
248 p_lcb->link_state = LST_CONNECTED;
249 l2cu_process_fixed_chnl_resp (p_lcb);
250 }
251 }
252
253 /*******************************************************************************
254 **
255 ** Function l2cble_scanner_conn_comp
256 **
257 ** Description This function is called when an HCI Connection Complete
258 ** event is received while we are a scanner (so we are master).
259 **
260 ** Returns void
261 **
262 *******************************************************************************/
l2cble_scanner_conn_comp(UINT16 handle,BD_ADDR bda,tBLE_ADDR_TYPE type,UINT16 conn_interval,UINT16 conn_latency,UINT16 conn_timeout)263 void l2cble_scanner_conn_comp (UINT16 handle, BD_ADDR bda, tBLE_ADDR_TYPE type,
264 UINT16 conn_interval, UINT16 conn_latency, UINT16 conn_timeout)
265 {
266 int i;
267 tL2C_LCB *p_lcb;
268 tBTM_SEC_DEV_REC *p_dev_rec = btm_find_or_alloc_dev (bda);
269
270 L2CAP_TRACE_DEBUG ("l2cble_scanner_conn_comp: HANDLE=%d addr_type=%d conn_interval=%d slave_latency=%d supervision_tout=%d",
271 handle, type, conn_interval, conn_latency, conn_timeout);
272
273 l2cb.is_ble_connecting = FALSE;
274
275 /* See if we have a link control block for the remote device */
276 p_lcb = l2cu_find_lcb_by_bd_addr (bda, BT_TRANSPORT_LE);
277
278 /* If we don't have one, create one. this is auto connection complete. */
279 if (!p_lcb)
280 {
281 p_lcb = l2cu_allocate_lcb (bda, FALSE, BT_TRANSPORT_LE);
282 if (!p_lcb)
283 {
284 btm_sec_disconnect (handle, HCI_ERR_NO_CONNECTION);
285 L2CAP_TRACE_ERROR ("l2cble_scanner_conn_comp - failed to allocate LCB");
286 return;
287 }
288 else
289 {
290 if (!l2cu_initialize_fixed_ccb (p_lcb, L2CAP_ATT_CID, &l2cb.fixed_reg[L2CAP_ATT_CID - L2CAP_FIRST_FIXED_CHNL].fixed_chnl_opts))
291 {
292 btm_sec_disconnect (handle, HCI_ERR_NO_CONNECTION);
293 L2CAP_TRACE_WARNING ("l2cble_scanner_conn_comp - LCB but no CCB");
294 return ;
295 }
296 }
297 }
298 else if (p_lcb->link_state != LST_CONNECTING)
299 {
300 L2CAP_TRACE_ERROR ("L2CAP got BLE scanner conn_comp in bad state: %d", p_lcb->link_state);
301 return;
302 }
303 btu_stop_timer(&p_lcb->timer_entry);
304
305 /* Save the handle */
306 p_lcb->handle = handle;
307
308 /* Connected OK. Change state to connected, we were scanning so we are master */
309 p_lcb->link_role = HCI_ROLE_MASTER;
310 p_lcb->transport = BT_TRANSPORT_LE;
311
312 /* update link parameter, set slave link as non-spec default upon link up */
313 p_lcb->min_interval = p_lcb->max_interval = conn_interval;
314 p_lcb->timeout = conn_timeout;
315 p_lcb->latency = conn_latency;
316 p_lcb->conn_update_mask = L2C_BLE_NOT_DEFAULT_PARAM;
317
318 /* If there are any preferred connection parameters, set them now */
319 if ( (p_dev_rec->conn_params.min_conn_int >= BTM_BLE_CONN_INT_MIN ) &&
320 (p_dev_rec->conn_params.min_conn_int <= BTM_BLE_CONN_INT_MAX ) &&
321 (p_dev_rec->conn_params.max_conn_int >= BTM_BLE_CONN_INT_MIN ) &&
322 (p_dev_rec->conn_params.max_conn_int <= BTM_BLE_CONN_INT_MAX ) &&
323 (p_dev_rec->conn_params.slave_latency <= BTM_BLE_CONN_LATENCY_MAX ) &&
324 (p_dev_rec->conn_params.supervision_tout >= BTM_BLE_CONN_SUP_TOUT_MIN) &&
325 (p_dev_rec->conn_params.supervision_tout <= BTM_BLE_CONN_SUP_TOUT_MAX) &&
326 ((conn_interval < p_dev_rec->conn_params.min_conn_int &&
327 p_dev_rec->conn_params.min_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ||
328 (conn_interval > p_dev_rec->conn_params.max_conn_int) ||
329 (conn_latency > p_dev_rec->conn_params.slave_latency) ||
330 (conn_timeout > p_dev_rec->conn_params.supervision_tout)))
331 {
332 L2CAP_TRACE_ERROR ("upd_ll_conn_params: HANDLE=%d min_conn_int=%d max_conn_int=%d slave_latency=%d supervision_tout=%d",
333 handle, p_dev_rec->conn_params.min_conn_int, p_dev_rec->conn_params.max_conn_int,
334 p_dev_rec->conn_params.slave_latency, p_dev_rec->conn_params.supervision_tout);
335
336 p_lcb->min_interval = p_dev_rec->conn_params.min_conn_int;
337 p_lcb->max_interval = p_dev_rec->conn_params.max_conn_int;
338 p_lcb->timeout = p_dev_rec->conn_params.supervision_tout;
339 p_lcb->latency = p_dev_rec->conn_params.slave_latency;
340
341 btsnd_hcic_ble_upd_ll_conn_params (handle,
342 p_dev_rec->conn_params.min_conn_int,
343 p_dev_rec->conn_params.max_conn_int,
344 p_dev_rec->conn_params.slave_latency,
345 p_dev_rec->conn_params.supervision_tout,
346 0, 0);
347 }
348
349 /* Tell BTM Acl management about the link */
350 btm_acl_created (bda, NULL, p_dev_rec->sec_bd_name, handle, p_lcb->link_role, BT_TRANSPORT_LE);
351
352 p_lcb->peer_chnl_mask[0] = L2CAP_FIXED_CHNL_ATT_BIT | L2CAP_FIXED_CHNL_BLE_SIG_BIT | L2CAP_FIXED_CHNL_SMP_BIT;
353
354 btm_ble_set_conn_st(BLE_CONN_IDLE);
355
356 #if BLE_PRIVACY_SPT == TRUE
357 btm_ble_disable_resolving_list(BTM_BLE_RL_INIT, TRUE);
358 #endif
359 }
360
361
362 /*******************************************************************************
363 **
364 ** Function l2cble_advertiser_conn_comp
365 **
366 ** Description This function is called when an HCI Connection Complete
367 ** event is received while we are an advertiser (so we are slave).
368 **
369 ** Returns void
370 **
371 *******************************************************************************/
l2cble_advertiser_conn_comp(UINT16 handle,BD_ADDR bda,tBLE_ADDR_TYPE type,UINT16 conn_interval,UINT16 conn_latency,UINT16 conn_timeout)372 void l2cble_advertiser_conn_comp (UINT16 handle, BD_ADDR bda, tBLE_ADDR_TYPE type,
373 UINT16 conn_interval, UINT16 conn_latency, UINT16 conn_timeout)
374 {
375 int i;
376 tL2C_LCB *p_lcb;
377 tBTM_SEC_DEV_REC *p_dev_rec;
378 UNUSED(type);
379 UNUSED(conn_interval);
380 UNUSED(conn_latency);
381 UNUSED(conn_timeout);
382
383 /* See if we have a link control block for the remote device */
384 p_lcb = l2cu_find_lcb_by_bd_addr (bda, BT_TRANSPORT_LE);
385
386 /* If we don't have one, create one and accept the connection. */
387 if (!p_lcb)
388 {
389 p_lcb = l2cu_allocate_lcb (bda, FALSE, BT_TRANSPORT_LE);
390 if (!p_lcb)
391 {
392 btm_sec_disconnect (handle, HCI_ERR_NO_CONNECTION);
393 L2CAP_TRACE_ERROR ("l2cble_advertiser_conn_comp - failed to allocate LCB");
394 return;
395 }
396 else
397 {
398 if (!l2cu_initialize_fixed_ccb (p_lcb, L2CAP_ATT_CID, &l2cb.fixed_reg[L2CAP_ATT_CID - L2CAP_FIRST_FIXED_CHNL].fixed_chnl_opts))
399 {
400 btm_sec_disconnect (handle, HCI_ERR_NO_CONNECTION);
401 L2CAP_TRACE_WARNING ("l2cble_scanner_conn_comp - LCB but no CCB");
402 return ;
403 }
404 }
405 }
406
407 /* Save the handle */
408 p_lcb->handle = handle;
409
410 /* Connected OK. Change state to connected, we were advertising, so we are slave */
411 p_lcb->link_role = HCI_ROLE_SLAVE;
412 p_lcb->transport = BT_TRANSPORT_LE;
413
414 /* update link parameter, set slave link as non-spec default upon link up */
415 p_lcb->min_interval = p_lcb->max_interval = conn_interval;
416 p_lcb->timeout = conn_timeout;
417 p_lcb->latency = conn_latency;
418 p_lcb->conn_update_mask = L2C_BLE_NOT_DEFAULT_PARAM;
419
420 /* Tell BTM Acl management about the link */
421 p_dev_rec = btm_find_or_alloc_dev (bda);
422
423 btm_acl_created (bda, NULL, p_dev_rec->sec_bd_name, handle, p_lcb->link_role, BT_TRANSPORT_LE);
424
425 #if BLE_PRIVACY_SPT == TRUE
426 btm_ble_disable_resolving_list(BTM_BLE_RL_ADV, TRUE);
427 #endif
428
429 p_lcb->peer_chnl_mask[0] = L2CAP_FIXED_CHNL_ATT_BIT | L2CAP_FIXED_CHNL_BLE_SIG_BIT | L2CAP_FIXED_CHNL_SMP_BIT;
430
431 if (!HCI_LE_SLAVE_INIT_FEAT_EXC_SUPPORTED(controller_get_interface()->get_features_ble()->as_array))
432 {
433 p_lcb->link_state = LST_CONNECTED;
434 l2cu_process_fixed_chnl_resp (p_lcb);
435 }
436
437 /* when adv and initiating are both active, cancel the direct connection */
438 if (l2cb.is_ble_connecting && memcmp(bda, l2cb.ble_connecting_bda, BD_ADDR_LEN) == 0)
439 {
440 L2CA_CancelBleConnectReq(bda);
441 }
442 }
443
444 /*******************************************************************************
445 **
446 ** Function l2cble_conn_comp
447 **
448 ** Description This function is called when an HCI Connection Complete
449 ** event is received.
450 **
451 ** Returns void
452 **
453 *******************************************************************************/
l2cble_conn_comp(UINT16 handle,UINT8 role,BD_ADDR bda,tBLE_ADDR_TYPE type,UINT16 conn_interval,UINT16 conn_latency,UINT16 conn_timeout)454 void l2cble_conn_comp(UINT16 handle, UINT8 role, BD_ADDR bda, tBLE_ADDR_TYPE type,
455 UINT16 conn_interval, UINT16 conn_latency, UINT16 conn_timeout)
456 {
457 btm_ble_update_link_topology_mask(role, TRUE);
458
459 if (role == HCI_ROLE_MASTER)
460 {
461 l2cble_scanner_conn_comp(handle, bda, type, conn_interval, conn_latency, conn_timeout);
462 }
463 else
464 {
465 l2cble_advertiser_conn_comp(handle, bda, type, conn_interval, conn_latency, conn_timeout);
466 }
467 }
468
469 /*******************************************************************************
470 **
471 ** Function l2cble_start_conn_update
472 **
473 ** Description start BLE connection parameter update process based on status
474 **
475 ** Parameters: lcb : l2cap link control block
476 **
477 ** Return value: none
478 **
479 *******************************************************************************/
l2cble_start_conn_update(tL2C_LCB * p_lcb)480 static void l2cble_start_conn_update (tL2C_LCB *p_lcb)
481 {
482 UINT16 min_conn_int, max_conn_int, slave_latency, supervision_tout;
483 tBTM_SEC_DEV_REC *p_dev_rec = btm_find_or_alloc_dev(p_lcb->remote_bd_addr);
484 tACL_CONN *p_acl_cb = btm_bda_to_acl(p_lcb->remote_bd_addr, BT_TRANSPORT_LE);
485
486 if (p_lcb->conn_update_mask & L2C_BLE_UPDATE_PENDING) return;
487
488 if (p_lcb->conn_update_mask & L2C_BLE_CONN_UPDATE_DISABLE)
489 {
490 /* application requests to disable parameters update.
491 If parameters are already updated, lets set them
492 up to what has been requested during connection establishement */
493 if (p_lcb->conn_update_mask & L2C_BLE_NOT_DEFAULT_PARAM &&
494 /* current connection interval is greater than default min */
495 p_lcb->min_interval > BTM_BLE_CONN_INT_MIN)
496 {
497 /* use 7.5 ms as fast connection parameter, 0 slave latency */
498 min_conn_int = max_conn_int = BTM_BLE_CONN_INT_MIN;
499 slave_latency = BTM_BLE_CONN_SLAVE_LATENCY_DEF;
500 supervision_tout = BTM_BLE_CONN_TIMEOUT_DEF;
501
502 /* if both side 4.1, or we are master device, send HCI command */
503 if (p_lcb->link_role == HCI_ROLE_MASTER
504 #if (defined BLE_LLT_INCLUDED) && (BLE_LLT_INCLUDED == TRUE)
505 || (HCI_LE_CONN_PARAM_REQ_SUPPORTED(controller_get_interface()->get_features_ble()->as_array) &&
506 HCI_LE_CONN_PARAM_REQ_SUPPORTED(p_acl_cb->peer_le_features))
507 #endif
508 )
509 {
510 btsnd_hcic_ble_upd_ll_conn_params(p_lcb->handle, min_conn_int, max_conn_int,
511 slave_latency, supervision_tout, 0, 0);
512 p_lcb->conn_update_mask |= L2C_BLE_UPDATE_PENDING;
513 }
514 else
515 {
516 l2cu_send_peer_ble_par_req (p_lcb, min_conn_int, max_conn_int, slave_latency, supervision_tout);
517 }
518 p_lcb->conn_update_mask &= ~L2C_BLE_NOT_DEFAULT_PARAM;
519 p_lcb->conn_update_mask |= L2C_BLE_NEW_CONN_PARAM;
520 }
521 }
522 else
523 {
524 /* application allows to do update, if we were delaying one do it now */
525 if (p_lcb->conn_update_mask & L2C_BLE_NEW_CONN_PARAM)
526 {
527 /* if both side 4.1, or we are master device, send HCI command */
528 if (p_lcb->link_role == HCI_ROLE_MASTER
529 #if (defined BLE_LLT_INCLUDED) && (BLE_LLT_INCLUDED == TRUE)
530 || (HCI_LE_CONN_PARAM_REQ_SUPPORTED(controller_get_interface()->get_features_ble()->as_array) &&
531 HCI_LE_CONN_PARAM_REQ_SUPPORTED(p_acl_cb->peer_le_features))
532 #endif
533 )
534 {
535 btsnd_hcic_ble_upd_ll_conn_params(p_lcb->handle, p_lcb->min_interval,
536 p_lcb->max_interval, p_lcb->latency, p_lcb->timeout, 0, 0);
537 p_lcb->conn_update_mask |= L2C_BLE_UPDATE_PENDING;
538 }
539 else
540 {
541 l2cu_send_peer_ble_par_req (p_lcb, p_lcb->min_interval, p_lcb->max_interval,
542 p_lcb->latency, p_lcb->timeout);
543 }
544 p_lcb->conn_update_mask &= ~L2C_BLE_NEW_CONN_PARAM;
545 p_lcb->conn_update_mask |= L2C_BLE_NOT_DEFAULT_PARAM;
546 }
547 }
548 }
549
550 /*******************************************************************************
551 **
552 ** Function l2cble_process_conn_update_evt
553 **
554 ** Description This function enables the connection update request from remote
555 ** after a successful connection update response is received.
556 **
557 ** Returns void
558 **
559 *******************************************************************************/
l2cble_process_conn_update_evt(UINT16 handle,UINT8 status)560 void l2cble_process_conn_update_evt (UINT16 handle, UINT8 status)
561 {
562 tL2C_LCB *p_lcb;
563
564 L2CAP_TRACE_DEBUG("l2cble_process_conn_update_evt");
565
566 /* See if we have a link control block for the remote device */
567 p_lcb = l2cu_find_lcb_by_handle(handle);
568 if (!p_lcb)
569 {
570 L2CAP_TRACE_WARNING("l2cble_process_conn_update_evt: Invalid handle: %d", handle);
571 return;
572 }
573
574 p_lcb->conn_update_mask &= ~L2C_BLE_UPDATE_PENDING;
575
576 if (status != HCI_SUCCESS)
577 {
578 L2CAP_TRACE_WARNING("l2cble_process_conn_update_evt: Error status: %d", status);
579 }
580
581 l2cble_start_conn_update(p_lcb);
582
583 L2CAP_TRACE_DEBUG("l2cble_process_conn_update_evt: conn_update_mask=%d", p_lcb->conn_update_mask);
584 }
585 /*******************************************************************************
586 **
587 ** Function l2cble_process_sig_cmd
588 **
589 ** Description This function is called when a signalling packet is received
590 ** on the BLE signalling CID
591 **
592 ** Returns void
593 **
594 *******************************************************************************/
l2cble_process_sig_cmd(tL2C_LCB * p_lcb,UINT8 * p,UINT16 pkt_len)595 void l2cble_process_sig_cmd (tL2C_LCB *p_lcb, UINT8 *p, UINT16 pkt_len)
596 {
597 UINT8 *p_pkt_end;
598 UINT8 cmd_code, id;
599 UINT16 cmd_len;
600 UINT16 min_interval, max_interval, latency, timeout;
601
602 p_pkt_end = p + pkt_len;
603
604 STREAM_TO_UINT8 (cmd_code, p);
605 STREAM_TO_UINT8 (id, p);
606 STREAM_TO_UINT16 (cmd_len, p);
607
608 /* Check command length does not exceed packet length */
609 if ((p + cmd_len) > p_pkt_end)
610 {
611 L2CAP_TRACE_WARNING ("L2CAP - LE - format error, pkt_len: %d cmd_len: %d code: %d", pkt_len, cmd_len, cmd_code);
612 return;
613 }
614
615 switch (cmd_code)
616 {
617 case L2CAP_CMD_REJECT:
618 case L2CAP_CMD_ECHO_RSP:
619 case L2CAP_CMD_INFO_RSP:
620 p += 2;
621 break;
622 case L2CAP_CMD_ECHO_REQ:
623 case L2CAP_CMD_INFO_REQ:
624 l2cu_send_peer_cmd_reject (p_lcb, L2CAP_CMD_REJ_NOT_UNDERSTOOD, id, 0, 0);
625 break;
626
627 case L2CAP_CMD_BLE_UPDATE_REQ:
628 STREAM_TO_UINT16 (min_interval, p); /* 0x0006 - 0x0C80 */
629 STREAM_TO_UINT16 (max_interval, p); /* 0x0006 - 0x0C80 */
630 STREAM_TO_UINT16 (latency, p); /* 0x0000 - 0x03E8 */
631 STREAM_TO_UINT16 (timeout, p); /* 0x000A - 0x0C80 */
632 /* If we are a master, the slave wants to update the parameters */
633 if (p_lcb->link_role == HCI_ROLE_MASTER)
634 {
635 if (min_interval < BTM_BLE_CONN_INT_MIN_LIMIT)
636 min_interval = BTM_BLE_CONN_INT_MIN_LIMIT;
637
638 if (min_interval < BTM_BLE_CONN_INT_MIN || min_interval > BTM_BLE_CONN_INT_MAX ||
639 max_interval < BTM_BLE_CONN_INT_MIN || max_interval > BTM_BLE_CONN_INT_MAX ||
640 latency > BTM_BLE_CONN_LATENCY_MAX ||
641 /*(timeout >= max_interval && latency > (timeout * 10/(max_interval * 1.25) - 1)) ||*/
642 timeout < BTM_BLE_CONN_SUP_TOUT_MIN || timeout > BTM_BLE_CONN_SUP_TOUT_MAX ||
643 max_interval < min_interval)
644 {
645 l2cu_send_peer_ble_par_rsp (p_lcb, L2CAP_CFG_UNACCEPTABLE_PARAMS, id);
646 }
647 else
648 {
649
650 l2cu_send_peer_ble_par_rsp (p_lcb, L2CAP_CFG_OK, id);
651
652 p_lcb->min_interval = min_interval;
653 p_lcb->max_interval = max_interval;
654 p_lcb->latency = latency;
655 p_lcb->timeout = timeout;
656 p_lcb->conn_update_mask |= L2C_BLE_NEW_CONN_PARAM;
657
658 l2cble_start_conn_update(p_lcb);
659 }
660 }
661 else
662 l2cu_send_peer_cmd_reject (p_lcb, L2CAP_CMD_REJ_NOT_UNDERSTOOD, id, 0, 0);
663 break;
664
665 case L2CAP_CMD_BLE_UPDATE_RSP:
666 p += 2;
667 break;
668
669 default:
670 L2CAP_TRACE_WARNING ("L2CAP - LE - unknown cmd code: %d", cmd_code);
671 l2cu_send_peer_cmd_reject (p_lcb, L2CAP_CMD_REJ_NOT_UNDERSTOOD, id, 0, 0);
672 return;
673 }
674 }
675
676 /*******************************************************************************
677 **
678 ** Function l2cble_init_direct_conn
679 **
680 ** Description This function is to initate a direct connection
681 **
682 ** Returns TRUE connection initiated, FALSE otherwise.
683 **
684 *******************************************************************************/
l2cble_init_direct_conn(tL2C_LCB * p_lcb)685 BOOLEAN l2cble_init_direct_conn (tL2C_LCB *p_lcb)
686 {
687 tBTM_SEC_DEV_REC *p_dev_rec = btm_find_or_alloc_dev (p_lcb->remote_bd_addr);
688 tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
689 UINT16 scan_int;
690 UINT16 scan_win;
691 BD_ADDR peer_addr;
692 UINT8 peer_addr_type = BLE_ADDR_PUBLIC;
693 UINT8 own_addr_type = BLE_ADDR_PUBLIC;
694
695 /* There can be only one BLE connection request outstanding at a time */
696 if (p_dev_rec == NULL)
697 {
698 L2CAP_TRACE_WARNING ("unknown device, can not initate connection");
699 return(FALSE);
700 }
701
702 scan_int = (p_cb->scan_int == BTM_BLE_SCAN_PARAM_UNDEF) ? BTM_BLE_SCAN_FAST_INT : p_cb->scan_int;
703 scan_win = (p_cb->scan_win == BTM_BLE_SCAN_PARAM_UNDEF) ? BTM_BLE_SCAN_FAST_WIN : p_cb->scan_win;
704
705 peer_addr_type = p_lcb->ble_addr_type;
706 memcpy(peer_addr, p_lcb->remote_bd_addr, BD_ADDR_LEN);
707
708 #if ( (defined BLE_PRIVACY_SPT) && (BLE_PRIVACY_SPT == TRUE))
709 own_addr_type = btm_cb.ble_ctr_cb.privacy_mode ? BLE_ADDR_RANDOM : BLE_ADDR_PUBLIC;
710 if (p_dev_rec->ble.in_controller_list & BTM_RESOLVING_LIST_BIT)
711 {
712 if (btm_cb.ble_ctr_cb.privacy_mode >= BTM_PRIVACY_1_2)
713 own_addr_type |= BLE_ADDR_TYPE_ID_BIT;
714
715 btm_ble_enable_resolving_list(BTM_BLE_RL_INIT);
716 btm_random_pseudo_to_identity_addr(peer_addr, &peer_addr_type);
717 }
718 else
719 btm_ble_disable_resolving_list(BTM_BLE_RL_INIT, TRUE);
720 #endif
721
722 if (!btm_ble_topology_check(BTM_BLE_STATE_INIT))
723 {
724 l2cu_release_lcb (p_lcb);
725 L2CAP_TRACE_ERROR("initate direct connection fail, topology limitation");
726 return FALSE;
727 }
728
729 if (!btsnd_hcic_ble_create_ll_conn (scan_int,/* UINT16 scan_int */
730 scan_win, /* UINT16 scan_win */
731 FALSE, /* UINT8 white_list */
732 peer_addr_type, /* UINT8 addr_type_peer */
733 peer_addr, /* BD_ADDR bda_peer */
734 own_addr_type, /* UINT8 addr_type_own */
735 (UINT16) ((p_dev_rec->conn_params.min_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ?
736 p_dev_rec->conn_params.min_conn_int : BTM_BLE_CONN_INT_MIN_DEF), /* UINT16 conn_int_min */
737 (UINT16) ((p_dev_rec->conn_params.max_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ?
738 p_dev_rec->conn_params.max_conn_int : BTM_BLE_CONN_INT_MAX_DEF), /* UINT16 conn_int_max */
739 (UINT16) ((p_dev_rec->conn_params.slave_latency != BTM_BLE_CONN_PARAM_UNDEF) ?
740 p_dev_rec->conn_params.slave_latency : BTM_BLE_CONN_SLAVE_LATENCY_DEF), /* UINT16 conn_latency */
741 (UINT16) ((p_dev_rec->conn_params.supervision_tout != BTM_BLE_CONN_PARAM_UNDEF) ?
742 p_dev_rec->conn_params.supervision_tout : BTM_BLE_CONN_TIMEOUT_DEF), /* conn_timeout */
743 0, /* UINT16 min_len */
744 0)) /* UINT16 max_len */
745 {
746 l2cu_release_lcb (p_lcb);
747 L2CAP_TRACE_ERROR("initate direct connection fail, no resources");
748 return (FALSE);
749 }
750 else
751 {
752 p_lcb->link_state = LST_CONNECTING;
753 l2cb.is_ble_connecting = TRUE;
754 memcpy (l2cb.ble_connecting_bda, p_lcb->remote_bd_addr, BD_ADDR_LEN);
755 btu_start_timer (&p_lcb->timer_entry, BTU_TTYPE_L2CAP_LINK, L2CAP_BLE_LINK_CONNECT_TOUT);
756 btm_ble_set_conn_st (BLE_DIR_CONN);
757
758 return (TRUE);
759 }
760 }
761
762 /*******************************************************************************
763 **
764 ** Function l2cble_create_conn
765 **
766 ** Description This function initiates an acl connection via HCI
767 **
768 ** Returns TRUE if successful, FALSE if connection not started.
769 **
770 *******************************************************************************/
l2cble_create_conn(tL2C_LCB * p_lcb)771 BOOLEAN l2cble_create_conn (tL2C_LCB *p_lcb)
772 {
773 tBTM_BLE_CONN_ST conn_st = btm_ble_get_conn_st();
774 BOOLEAN rt = FALSE;
775
776 /* There can be only one BLE connection request outstanding at a time */
777 if (conn_st == BLE_CONN_IDLE)
778 {
779 rt = l2cble_init_direct_conn(p_lcb);
780 }
781 else
782 {
783 L2CAP_TRACE_WARNING ("L2CAP - LE - cannot start new connection at conn st: %d", conn_st);
784
785 btm_ble_enqueue_direct_conn_req(p_lcb);
786
787 if (conn_st == BLE_BG_CONN)
788 btm_ble_suspend_bg_conn();
789
790 rt = TRUE;
791 }
792 return rt;
793 }
794
795 /*******************************************************************************
796 **
797 ** Function l2c_link_processs_ble_num_bufs
798 **
799 ** Description This function is called when a "controller buffer size"
800 ** event is first received from the controller. It updates
801 ** the L2CAP values.
802 **
803 ** Returns void
804 **
805 *******************************************************************************/
l2c_link_processs_ble_num_bufs(UINT16 num_lm_ble_bufs)806 void l2c_link_processs_ble_num_bufs (UINT16 num_lm_ble_bufs)
807 {
808 if (num_lm_ble_bufs == 0)
809 {
810 num_lm_ble_bufs = L2C_DEF_NUM_BLE_BUF_SHARED;
811 l2cb.num_lm_acl_bufs -= L2C_DEF_NUM_BLE_BUF_SHARED;
812 }
813
814 l2cb.num_lm_ble_bufs = l2cb.controller_le_xmit_window = num_lm_ble_bufs;
815 }
816
817 /*******************************************************************************
818 **
819 ** Function l2c_ble_link_adjust_allocation
820 **
821 ** Description This function is called when a link is created or removed
822 ** to calculate the amount of packets each link may send to
823 ** the HCI without an ack coming back.
824 **
825 ** Currently, this is a simple allocation, dividing the
826 ** number of Controller Packets by the number of links. In
827 ** the future, QOS configuration should be examined.
828 **
829 ** Returns void
830 **
831 *******************************************************************************/
l2c_ble_link_adjust_allocation(void)832 void l2c_ble_link_adjust_allocation (void)
833 {
834 UINT16 qq, yy, qq_remainder;
835 tL2C_LCB *p_lcb;
836 UINT16 hi_quota, low_quota;
837 UINT16 num_lowpri_links = 0;
838 UINT16 num_hipri_links = 0;
839 UINT16 controller_xmit_quota = l2cb.num_lm_ble_bufs;
840 UINT16 high_pri_link_quota = L2CAP_HIGH_PRI_MIN_XMIT_QUOTA_A;
841
842 /* If no links active, reset buffer quotas and controller buffers */
843 if (l2cb.num_ble_links_active == 0)
844 {
845 l2cb.controller_le_xmit_window = l2cb.num_lm_ble_bufs;
846 l2cb.ble_round_robin_quota = l2cb.ble_round_robin_unacked = 0;
847 return;
848 }
849
850 /* First, count the links */
851 for (yy = 0, p_lcb = &l2cb.lcb_pool[0]; yy < MAX_L2CAP_LINKS; yy++, p_lcb++)
852 {
853 if (p_lcb->in_use && p_lcb->transport == BT_TRANSPORT_LE)
854 {
855 if (p_lcb->acl_priority == L2CAP_PRIORITY_HIGH)
856 num_hipri_links++;
857 else
858 num_lowpri_links++;
859 }
860 }
861
862 /* now adjust high priority link quota */
863 low_quota = num_lowpri_links ? 1 : 0;
864 while ( (num_hipri_links * high_pri_link_quota + low_quota) > controller_xmit_quota )
865 high_pri_link_quota--;
866
867
868 /* Work out the xmit quota and buffer quota high and low priorities */
869 hi_quota = num_hipri_links * high_pri_link_quota;
870 low_quota = (hi_quota < controller_xmit_quota) ? controller_xmit_quota - hi_quota : 1;
871
872 /* Work out and save the HCI xmit quota for each low priority link */
873
874 /* If each low priority link cannot have at least one buffer */
875 if (num_lowpri_links > low_quota)
876 {
877 l2cb.ble_round_robin_quota = low_quota;
878 qq = qq_remainder = 0;
879 }
880 /* If each low priority link can have at least one buffer */
881 else if (num_lowpri_links > 0)
882 {
883 l2cb.ble_round_robin_quota = 0;
884 l2cb.ble_round_robin_unacked = 0;
885 qq = low_quota / num_lowpri_links;
886 qq_remainder = low_quota % num_lowpri_links;
887 }
888 /* If no low priority link */
889 else
890 {
891 l2cb.ble_round_robin_quota = 0;
892 l2cb.ble_round_robin_unacked = 0;
893 qq = qq_remainder = 0;
894 }
895 L2CAP_TRACE_EVENT ("l2c_ble_link_adjust_allocation num_hipri: %u num_lowpri: %u low_quota: %u round_robin_quota: %u qq: %u",
896 num_hipri_links, num_lowpri_links, low_quota,
897 l2cb.ble_round_robin_quota, qq);
898
899 /* Now, assign the quotas to each link */
900 for (yy = 0, p_lcb = &l2cb.lcb_pool[0]; yy < MAX_L2CAP_LINKS; yy++, p_lcb++)
901 {
902 if (p_lcb->in_use && p_lcb->transport == BT_TRANSPORT_LE)
903 {
904 if (p_lcb->acl_priority == L2CAP_PRIORITY_HIGH)
905 {
906 p_lcb->link_xmit_quota = high_pri_link_quota;
907 }
908 else
909 {
910 /* Safety check in case we switched to round-robin with something outstanding */
911 /* if sent_not_acked is added into round_robin_unacked then don't add it again */
912 /* l2cap keeps updating sent_not_acked for exiting from round robin */
913 if (( p_lcb->link_xmit_quota > 0 )&&( qq == 0 ))
914 l2cb.ble_round_robin_unacked += p_lcb->sent_not_acked;
915
916 p_lcb->link_xmit_quota = qq;
917 if (qq_remainder > 0)
918 {
919 p_lcb->link_xmit_quota++;
920 qq_remainder--;
921 }
922 }
923
924 L2CAP_TRACE_EVENT("l2c_ble_link_adjust_allocation LCB %d Priority: %d XmitQuota: %d",
925 yy, p_lcb->acl_priority, p_lcb->link_xmit_quota);
926
927 L2CAP_TRACE_EVENT(" SentNotAcked: %d RRUnacked: %d",
928 p_lcb->sent_not_acked, l2cb.round_robin_unacked);
929
930 /* There is a special case where we have readjusted the link quotas and */
931 /* this link may have sent anything but some other link sent packets so */
932 /* so we may need a timer to kick off this link's transmissions. */
933 if ( (p_lcb->link_state == LST_CONNECTED)
934 && (!list_is_empty(p_lcb->link_xmit_data_q))
935 && (p_lcb->sent_not_acked < p_lcb->link_xmit_quota) )
936 btu_start_timer (&p_lcb->timer_entry, BTU_TTYPE_L2CAP_LINK, L2CAP_LINK_FLOW_CONTROL_TOUT);
937 }
938 }
939 }
940
941 #if (defined BLE_LLT_INCLUDED) && (BLE_LLT_INCLUDED == TRUE)
942 /*******************************************************************************
943 **
944 ** Function l2cble_process_rc_param_request_evt
945 **
946 ** Description process LE Remote Connection Parameter Request Event.
947 **
948 ** Returns void
949 **
950 *******************************************************************************/
l2cble_process_rc_param_request_evt(UINT16 handle,UINT16 int_min,UINT16 int_max,UINT16 latency,UINT16 timeout)951 void l2cble_process_rc_param_request_evt(UINT16 handle, UINT16 int_min, UINT16 int_max,
952 UINT16 latency, UINT16 timeout)
953 {
954 tL2C_LCB *p_lcb = l2cu_find_lcb_by_handle (handle);
955
956 if (p_lcb != NULL)
957 {
958 p_lcb->min_interval = int_min;
959 p_lcb->max_interval = int_max;
960 p_lcb->latency = latency;
961 p_lcb->timeout = timeout;
962
963 /* if update is enabled, always accept connection parameter update */
964 if ((p_lcb->conn_update_mask & L2C_BLE_CONN_UPDATE_DISABLE) == 0)
965 {
966 btsnd_hcic_ble_rc_param_req_reply(handle, int_min, int_max, latency, timeout, 0, 0);
967 }
968 else
969 {
970 L2CAP_TRACE_EVENT ("L2CAP - LE - update currently disabled");
971 p_lcb->conn_update_mask |= L2C_BLE_NEW_CONN_PARAM;
972 btsnd_hcic_ble_rc_param_req_neg_reply (handle,HCI_ERR_UNACCEPT_CONN_INTERVAL);
973 }
974
975 }
976 else
977 {
978 L2CAP_TRACE_WARNING("No link to update connection parameter")
979 }
980 }
981 #endif
982
983 /*******************************************************************************
984 **
985 ** Function l2cble_update_data_length
986 **
987 ** Description This function update link tx data length if applicable
988 **
989 ** Returns void
990 **
991 *******************************************************************************/
l2cble_update_data_length(tL2C_LCB * p_lcb)992 void l2cble_update_data_length(tL2C_LCB *p_lcb)
993 {
994 UINT16 tx_mtu = 0;
995 UINT16 i = 0;
996
997 L2CAP_TRACE_DEBUG("%s", __FUNCTION__);
998
999 /* See if we have a link control block for the connection */
1000 if (p_lcb == NULL)
1001 return;
1002
1003 for (i = 0; i < L2CAP_NUM_FIXED_CHNLS; i++)
1004 {
1005 if (i + L2CAP_FIRST_FIXED_CHNL != L2CAP_BLE_SIGNALLING_CID)
1006 {
1007 if ((p_lcb->p_fixed_ccbs[i] != NULL) &&
1008 (tx_mtu < (p_lcb->p_fixed_ccbs[i]->tx_data_len + L2CAP_PKT_OVERHEAD)))
1009 tx_mtu = p_lcb->p_fixed_ccbs[i]->tx_data_len + L2CAP_PKT_OVERHEAD;
1010 }
1011 }
1012
1013 if (tx_mtu > BTM_BLE_DATA_SIZE_MAX)
1014 tx_mtu = BTM_BLE_DATA_SIZE_MAX;
1015
1016 /* update TX data length if changed */
1017 if (p_lcb->tx_data_len != tx_mtu)
1018 BTM_SetBleDataLength(p_lcb->remote_bd_addr, tx_mtu);
1019
1020 }
1021
1022 /*******************************************************************************
1023 **
1024 ** Function l2cble_process_data_length_change_evt
1025 **
1026 ** Description This function process the data length change event
1027 **
1028 ** Returns void
1029 **
1030 *******************************************************************************/
l2cble_process_data_length_change_event(UINT16 handle,UINT16 tx_data_len,UINT16 rx_data_len)1031 void l2cble_process_data_length_change_event(UINT16 handle, UINT16 tx_data_len, UINT16 rx_data_len)
1032 {
1033 tL2C_LCB *p_lcb = l2cu_find_lcb_by_handle(handle);
1034
1035 L2CAP_TRACE_DEBUG("%s TX data len = %d", __FUNCTION__, tx_data_len);
1036 if (p_lcb == NULL)
1037 return;
1038
1039 if (tx_data_len > 0)
1040 p_lcb->tx_data_len = tx_data_len;
1041
1042 /* ignore rx_data len for now */
1043 }
1044
1045 /*******************************************************************************
1046 **
1047 ** Function l2cble_set_fixed_channel_tx_data_length
1048 **
1049 ** Description This function update max fixed channel tx data length if applicable
1050 **
1051 ** Returns void
1052 **
1053 *******************************************************************************/
l2cble_set_fixed_channel_tx_data_length(BD_ADDR remote_bda,UINT16 fix_cid,UINT16 tx_mtu)1054 void l2cble_set_fixed_channel_tx_data_length(BD_ADDR remote_bda, UINT16 fix_cid, UINT16 tx_mtu)
1055 {
1056 tL2C_LCB *p_lcb = l2cu_find_lcb_by_bd_addr(remote_bda, BT_TRANSPORT_LE);
1057 UINT16 cid = fix_cid - L2CAP_FIRST_FIXED_CHNL;
1058
1059 L2CAP_TRACE_DEBUG("%s TX MTU = %d", __FUNCTION__, tx_mtu);
1060
1061 if (!controller_get_interface()->supports_ble_packet_extension())
1062 {
1063 L2CAP_TRACE_WARNING("%s, request not supported", __FUNCTION__);
1064 return;
1065 }
1066
1067 /* See if we have a link control block for the connection */
1068 if (p_lcb == NULL)
1069 return;
1070
1071 if (p_lcb->p_fixed_ccbs[cid] != NULL)
1072 {
1073 if (tx_mtu > BTM_BLE_DATA_SIZE_MAX)
1074 tx_mtu = BTM_BLE_DATA_SIZE_MAX;
1075
1076 p_lcb->p_fixed_ccbs[cid]->tx_data_len = tx_mtu;
1077 }
1078
1079 l2cble_update_data_length(p_lcb);
1080 }
1081
1082 #endif /* (BLE_INCLUDED == TRUE) */
1083